![]() |
API 0.9.5
|
00001 /* 00002 * CPWebView.j 00003 * AppKit 00004 * 00005 * Created by Thomas Robinson. 00006 * Copyright 2008, 280 North, Inc. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 00024 00025 // FIXME: implement these where possible: 00026 /* 00027 CPWebViewDidBeginEditingNotification = "CPWebViewDidBeginEditingNotification"; 00028 CPWebViewDidChangeNotification = "CPWebViewDidChangeNotification"; 00029 CPWebViewDidChangeSelectionNotification = "CPWebViewDidChangeSelectionNotification"; 00030 CPWebViewDidChangeTypingStyleNotification = "CPWebViewDidChangeTypingStyleNotification"; 00031 CPWebViewDidEndEditingNotification = "CPWebViewDidEndEditingNotification"; 00032 CPWebViewProgressEstimateChangedNotification = "CPWebViewProgressEstimateChangedNotification"; 00033 */ 00034 CPWebViewProgressStartedNotification = "CPWebViewProgressStartedNotification"; 00035 CPWebViewProgressFinishedNotification = "CPWebViewProgressFinishedNotification"; 00036 00043 CPWebViewScrollAuto = 0; 00049 CPWebViewScrollAppKit = 1; 00053 CPWebViewScrollNative = 2; 00057 CPWebViewScrollNone = 3; 00058 00063 CPWebViewAppKitScrollPollInterval = 1.0; 00064 00073 CPWebViewAppKitScrollMaxPollCount = 3; 00074 00089 @implementation CPWebView : CPView 00090 { 00091 CPScrollView _scrollView; 00092 CPView _frameView; 00093 00094 IFrame _iframe; 00095 CPString _mainFrameURL; 00096 CPArray _backwardStack; 00097 CPArray _forwardStack; 00098 00099 BOOL _ignoreLoadStart; 00100 BOOL _ignoreLoadEnd; 00101 BOOL _isLoading; 00102 00103 id _downloadDelegate; 00104 id _frameLoadDelegate; 00105 id _policyDelegate; 00106 id _resourceLoadDelegate; 00107 id _UIDelegate; 00108 00109 CPWebScriptObject _wso; 00110 00111 CPString _url; 00112 CPString _html; 00113 00114 Function _loadCallback; 00115 00116 int _scrollMode; 00117 int _effectiveScrollMode; 00118 BOOL _contentIsAccessible; 00119 CPTimer _contentSizeCheckTimer; 00120 int _contentSizePollCount; 00121 00122 int _loadHTMLStringTimer; 00123 00124 BOOL _drawsBackground; 00125 } 00126 00127 - (id)initWithFrame:(CPRect)frameRect frameName:(CPString)frameName groupName:(CPString)groupName 00128 { 00129 if (self = [self initWithFrame:frameRect]) 00130 { 00131 _iframe.name = frameName; 00132 } 00133 00134 return self; 00135 } 00136 00137 - (id)initWithFrame:(CPRect)aFrame 00138 { 00139 if (self = [super initWithFrame:aFrame]) 00140 { 00141 _mainFrameURL = nil; 00142 _backwardStack = []; 00143 _forwardStack = []; 00144 _scrollMode = CPWebViewScrollAuto; 00145 _contentIsAccessible = YES; 00146 _isLoading = NO; 00147 00148 _drawsBackground = YES; 00149 00150 [self setBackgroundColor:[CPColor whiteColor]]; 00151 00152 [self _initDOMWithFrame:aFrame]; 00153 } 00154 00155 return self; 00156 } 00157 00158 - (id)_initDOMWithFrame:(CPRect)aFrame 00159 { 00160 _ignoreLoadStart = YES; 00161 _ignoreLoadEnd = YES; 00162 00163 _iframe = document.createElement("iframe"); 00164 _iframe.name = "iframe_" + FLOOR(RAND() * 10000); 00165 _iframe.style.width = "100%"; 00166 _iframe.style.height = "100%"; 00167 _iframe.style.borderWidth = "0px"; 00168 _iframe.frameBorder = "0"; 00169 00170 [self _applyBackgroundColor]; 00171 00172 _loadCallback = function() 00173 { 00174 // HACK: this block handles the case where we don't know about loads initiated by the user clicking a link 00175 if (!_ignoreLoadStart) 00176 { 00177 // post the start load notification 00178 [self _startedLoading]; 00179 00180 if (_mainFrameURL) 00181 [_backwardStack addObject:_mainFrameURL]; 00182 00183 // FIXME: this doesn't actually get the right URL for different domains. Not possible due to browser security restrictions. 00184 _mainFrameURL = _iframe.src; 00185 00186 // clear the forward 00187 [_forwardStack removeAllObjects]; 00188 } 00189 else 00190 _ignoreLoadStart = NO; 00191 00192 if (!_ignoreLoadEnd) 00193 { 00194 [self _finishedLoading]; 00195 } 00196 else 00197 _ignoreLoadEnd = NO; 00198 00199 [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; 00200 } 00201 00202 if (_iframe.addEventListener) 00203 _iframe.addEventListener("load", _loadCallback, false); 00204 else if (_iframe.attachEvent) 00205 _iframe.attachEvent("onload", _loadCallback); 00206 00207 _frameView = [[CPView alloc] initWithFrame:[self bounds]]; 00208 [_frameView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; 00209 00210 _scrollView = [[CPScrollView alloc] initWithFrame:[self bounds]]; 00211 [_scrollView setAutohidesScrollers:YES]; 00212 [_scrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable]; 00213 [_scrollView setDocumentView:_frameView]; 00214 00215 _frameView._DOMElement.appendChild(_iframe); 00216 00217 [self _updateEffectiveScrollMode]; 00218 00219 [self addSubview:_scrollView]; 00220 } 00221 00222 - (void)setFrameSize:(CPSize)aSize 00223 { 00224 [super setFrameSize:aSize]; 00225 [self _resizeWebFrame]; 00226 } 00227 00228 - (void)viewDidUnhide 00229 { 00230 // Sizing cannot properly happen while we're hidden because the iframe is inaccessible. 00231 // So now that it is accessible again, make sure to catch up. 00232 [_frameView setFrameSize:[_scrollView contentSize]]; 00233 [self _resizeWebFrame]; 00234 [self _scheduleContentSizeCheck]; 00235 } 00236 00237 - (void)_attachScrollEventIfNecessary 00238 { 00239 if (_effectiveScrollMode !== CPWebViewScrollAppKit) 00240 return; 00241 00242 var win = null; 00243 try { win = [self DOMWindow]; } catch (e) {} 00244 00245 if (win && win.addEventListener) 00246 { 00247 var scrollEventHandler = function(anEvent) 00248 { 00249 var frameBounds = [self bounds], 00250 frameCenter = CGPointMake(CGRectGetMidX(frameBounds), CGRectGetMidY(frameBounds)), 00251 windowOrigin = [self convertPoint:frameCenter toView:nil], 00252 globalOrigin = [[self window] convertBaseToBridge:windowOrigin]; 00253 00254 anEvent._overrideLocation = globalOrigin; 00255 [[[self window] platformWindow] scrollEvent:anEvent]; 00256 }; 00257 00258 win.addEventListener("DOMMouseScroll", scrollEventHandler, false); 00259 } 00260 } 00261 00262 - (void)_resizeWebFrame 00263 { 00264 // When a webview is not in the DOM we can't inspect its contents for sizing information. 00265 // If we try, we might end up setting the fallback frame size which will then become 00266 // somewhat sticky. 00267 if (![self _isVisible]) 00268 { 00269 return; 00270 } 00271 00272 if (_effectiveScrollMode === CPWebViewScrollAppKit) 00273 { 00274 var visibleRect = [_frameView visibleRect]; 00275 [_frameView setFrameSize:CGSizeMake(CGRectGetMaxX(visibleRect), CGRectGetMaxY(visibleRect))]; 00276 00277 // try to get the document size so we can correctly set the frame 00278 var win = null; 00279 try { win = [self DOMWindow]; } catch (e) {} 00280 00281 if (win && win.document && win.document.body) 00282 { 00283 var width = win.document.body.scrollWidth, 00284 height = win.document.body.scrollHeight; 00285 00286 _iframe.setAttribute("width", width); 00287 _iframe.setAttribute("height", height); 00288 00289 [_frameView setFrameSize:CGSizeMake(width, height)]; 00290 } 00291 else 00292 { 00293 // If we do have access to the content, it might be that the 'body' element simply hasn't loaded yet. 00294 // The size will be updated by the content size timer in this case. 00295 if (!win || !win.document) 00296 { 00297 CPLog.warn("using default size 800*1600"); 00298 [_frameView setFrameSize:CGSizeMake(800, 1600)]; 00299 } 00300 } 00301 00302 [_frameView scrollRectToVisible:visibleRect]; 00303 } 00304 } 00305 00317 - (void)setScrollMode:(int)aScrollMode 00318 { 00319 if (_scrollMode == aScrollMode) 00320 return; 00321 00322 _scrollMode = aScrollMode; 00323 00324 [self _updateEffectiveScrollMode]; 00325 } 00326 00336 - (int)effectiveScrollMode 00337 { 00338 return _effectiveScrollMode; 00339 } 00340 00341 - (void)_updateEffectiveScrollMode 00342 { 00343 var _newScrollMode = CPWebViewScrollAppKit; 00344 00345 if (_scrollMode == CPWebViewScrollNative 00346 || (_scrollMode == CPWebViewScrollAuto && !_contentIsAccessible) 00347 || CPBrowserIsEngine(CPInternetExplorerBrowserEngine)) 00348 { 00349 _newScrollMode = CPWebViewScrollNative; 00350 } 00351 else if (_scrollMode == CPWebViewScrollAppKit && !_contentIsAccessible) 00352 { 00353 // Same behaviour as the previous case except that a warning is logged when AppKit 00354 // scrollers can't be used. 00355 CPLog.warn(self + " unable to use CPWebViewScrollAppKit scroll mode due to same origin policy."); 00356 _newScrollMode = CPWebViewScrollNative; 00357 } 00358 00359 if (_newScrollMode !== _effectiveScrollMode) 00360 [self _setEffectiveScrollMode:_newScrollMode]; 00361 } 00362 00363 - (void)_setEffectiveScrollMode:(int)aScrollMode 00364 { 00365 _effectiveScrollMode = aScrollMode; 00366 00367 _ignoreLoadStart = YES; 00368 _ignoreLoadEnd = YES; 00369 00370 var parent = _iframe.parentNode; 00371 // FIXME "scrolling" can't be changed without readding the iframe. Unfortunately this causes a reload. 00372 parent.removeChild(_iframe); 00373 00374 if (_effectiveScrollMode === CPWebViewScrollAppKit) 00375 { 00376 [_scrollView setHasHorizontalScroller:YES]; 00377 [_scrollView setHasVerticalScroller:YES]; 00378 00379 _iframe.setAttribute("scrolling", "no"); 00380 } 00381 else if (_effectiveScrollMode === CPWebViewScrollNone) 00382 { 00383 [_scrollView setHasHorizontalScroller:NO]; 00384 [_scrollView setHasVerticalScroller:NO]; 00385 00386 _iframe.setAttribute("scrolling", "no"); 00387 } 00388 else 00389 { 00390 [_scrollView setHasHorizontalScroller:NO]; 00391 [_scrollView setHasVerticalScroller:NO]; 00392 00393 _iframe.setAttribute("scrolling", "auto"); 00394 00395 [_frameView setFrameSize:[_scrollView bounds].size]; 00396 } 00397 00398 parent.appendChild(_iframe); 00399 [self _applyBackgroundColor]; 00400 00401 [self _resizeWebFrame]; 00402 } 00403 00404 - (void)_maybePollWebFrameSize 00405 { 00406 if (CPWebViewAppKitScrollMaxPollCount == 0 || _contentSizePollCount++ < CPWebViewAppKitScrollMaxPollCount) 00407 [self _resizeWebFrame]; 00408 else 00409 [_contentSizeCheckTimer invalidate]; 00410 } 00411 00417 - (void)loadHTMLString:(CPString)aString 00418 { 00419 [self loadHTMLString:aString baseURL:nil]; 00420 } 00421 00428 - (void)loadHTMLString:(CPString)aString baseURL:(CPURL)URL 00429 { 00430 // FIXME: do something with baseURL? 00431 [_frameView setFrameSize:[_scrollView contentSize]]; 00432 00433 [self _startedLoading]; 00434 00435 _ignoreLoadStart = YES; 00436 00437 _url = nil; 00438 _html = aString; 00439 00440 [self _load]; 00441 } 00442 00443 - (void)_loadMainFrameURL 00444 { 00445 [self _startedLoading]; 00446 00447 _ignoreLoadStart = YES; 00448 00449 _url = _mainFrameURL; 00450 _html = nil; 00451 00452 [self _load]; 00453 } 00454 00455 - (void)_load 00456 { 00457 if (_url) 00458 { 00459 // Try to figure out if this URL will pass the same origin policy and hence allow us to potentially 00460 // use appkit scrollbars. 00461 var cpurl = [CPURL URLWithString:_url]; 00462 _contentIsAccessible = [cpurl _passesSameOriginPolicy]; 00463 [self _updateEffectiveScrollMode]; 00464 00465 _ignoreLoadEnd = NO; 00466 00467 _iframe.src = _url; 00468 } 00469 else if (_html !== nil) 00470 { 00471 // clear the iframe 00472 _iframe.src = ""; 00473 00474 _contentIsAccessible = YES; 00475 [self _updateEffectiveScrollMode]; 00476 00477 _ignoreLoadEnd = NO; 00478 00479 if (_loadHTMLStringTimer !== nil) 00480 { 00481 window.clearTimeout(_loadHTMLStringTimer); 00482 _loadHTMLStringTimer = nil; 00483 } 00484 00485 // need to give the browser a chance to reset iframe, otherwise we'll be document.write()-ing the previous document 00486 _loadHTMLStringTimer = window.setTimeout(function() 00487 { 00488 var win = [self DOMWindow]; 00489 00490 /* 00491 If _html is the empty string, subtitute in an empty HTML structure. Just leaving the contents entirely empty prompts the browser to subtitute in a white page which would interfere with any custom background colours in use by this web view. 00492 */ 00493 if (win) 00494 win.document.write(_html || "<html><body></body></html>"); 00495 00496 window.setTimeout(_loadCallback, 1); 00497 }, 0); 00498 } 00499 } 00500 00501 - (void)_startedLoading 00502 { 00503 _isLoading = YES; 00504 00505 [[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressStartedNotification object:self]; 00506 00507 if ([_frameLoadDelegate respondsToSelector:@selector(webView:didStartProvisionalLoadForFrame:)]) 00508 [_frameLoadDelegate webView:self didStartProvisionalLoadForFrame:nil]; // FIXME: give this a frame somehow? 00509 } 00510 00511 - (void)_finishedLoading 00512 { 00513 _isLoading = NO; 00514 00515 [self _resizeWebFrame]; 00516 [self _attachScrollEventIfNecessary]; 00517 00518 [self _scheduleContentSizeCheck]; 00519 00520 [[CPNotificationCenter defaultCenter] postNotificationName:CPWebViewProgressFinishedNotification object:self]; 00521 00522 if ([_frameLoadDelegate respondsToSelector:@selector(webView:didFinishLoadForFrame:)]) 00523 [_frameLoadDelegate webView:self didFinishLoadForFrame:nil]; // FIXME: give this a frame somehow? 00524 } 00525 00526 - (void)_scheduleContentSizeCheck 00527 { 00528 [_contentSizeCheckTimer invalidate]; 00529 if (_effectiveScrollMode == CPWebViewScrollAppKit) 00530 { 00531 /* 00532 FIXME Need better method. 00533 We don't know when the content of the iframe changes size (e.g. a 00534 picture finishes loading, dynamic content is loaded). Often when a 00535 page has initially 'loaded', it does not yet have its final size. In 00536 lieu of any resize events we will simply check back in a few times 00537 some time after loading. 00538 00539 We run these checks only a limited number of times as to not deplete 00540 battery life and slow down the software needlessly. This does mean 00541 there are situations where the content changes size and the AppKit 00542 scrollbars will be out of sync. Users who have dynamic content 00543 in their web view will, for now, have to implement domain specific 00544 fixes. 00545 */ 00546 00547 _contentSizePollCount = 0; 00548 _contentSizeCheckTimer = [CPTimer scheduledTimerWithTimeInterval:CPWebViewAppKitScrollPollInterval target:self selector:@selector(_maybePollWebFrameSize) userInfo:nil repeats:YES]; 00549 } 00550 } 00551 00556 - (BOOL)isLoading 00557 { 00558 return _isLoading; 00559 } 00560 00566 - (CPString)mainFrameURL 00567 { 00568 return _mainFrameURL; 00569 } 00570 00576 - (void)setMainFrameURL:(CPString)URLString 00577 { 00578 if (_mainFrameURL) 00579 [_backwardStack addObject:_mainFrameURL]; 00580 _mainFrameURL = URLString; 00581 [_forwardStack removeAllObjects]; 00582 00583 [self _loadMainFrameURL]; 00584 } 00585 00591 - (BOOL)goBack 00592 { 00593 if (_backwardStack.length > 0) 00594 { 00595 if (_mainFrameURL) 00596 [_forwardStack addObject:_mainFrameURL]; 00597 _mainFrameURL = [_backwardStack lastObject]; 00598 [_backwardStack removeLastObject]; 00599 00600 [self _loadMainFrameURL]; 00601 00602 return YES; 00603 } 00604 return NO; 00605 } 00606 00612 - (BOOL)goForward 00613 { 00614 if (_forwardStack.length > 0) 00615 { 00616 if (_mainFrameURL) 00617 [_backwardStack addObject:_mainFrameURL]; 00618 _mainFrameURL = [_forwardStack lastObject]; 00619 [_forwardStack removeLastObject]; 00620 00621 [self _loadMainFrameURL]; 00622 00623 return YES; 00624 } 00625 return NO; 00626 } 00627 00634 - (BOOL)canGoBack 00635 { 00636 return (_backwardStack.length > 0); 00637 } 00638 00645 - (BOOL)canGoForward 00646 { 00647 return (_forwardStack.length > 0); 00648 } 00649 00650 - (WebBackForwardList)backForwardList 00651 { 00652 // FIXME: return a real WebBackForwardList? 00653 return { back: _backwardStack, forward: _forwardStack }; 00654 } 00655 00660 - (void)close 00661 { 00662 _iframe.parentNode.removeChild(_iframe); 00663 } 00664 00670 - (DOMWindow)DOMWindow 00671 { 00672 return (_iframe.contentDocument && _iframe.contentDocument.defaultView) || _iframe.contentWindow; 00673 } 00674 00680 - (CPWebScriptObject)windowScriptObject 00681 { 00682 var win = [self DOMWindow]; 00683 if (!_wso || win != [_wso window]) 00684 { 00685 if (win) 00686 _wso = [[CPWebScriptObject alloc] initWithWindow:win]; 00687 else 00688 _wso = nil; 00689 } 00690 return _wso; 00691 } 00692 00700 - (CPString)stringByEvaluatingJavaScriptFromString:(CPString)script 00701 { 00702 var result = [self objectByEvaluatingJavaScriptFromString:script]; 00703 return result ? String(result) : nil; 00704 } 00705 00712 - (JSObject)objectByEvaluatingJavaScriptFromString:(CPString)script 00713 { 00714 return [[self windowScriptObject] evaluateWebScript:script]; 00715 } 00716 00724 - (DOMCSSStyleDeclaration)computedStyleForElement:(DOMElement)element pseudoElement:(CPString)pseudoElement 00725 { 00726 var win = [[self windowScriptObject] window]; 00727 if (win) 00728 { 00729 // FIXME: IE version? 00730 return win.document.defaultView.getComputedStyle(element, pseudoElement); 00731 } 00732 return nil; 00733 } 00734 00735 00739 - (BOOL)drawsBackground 00740 { 00741 return _drawsBackground; 00742 } 00743 00755 - (void)setDrawsBackground:(BOOL)drawsBackground 00756 { 00757 if (drawsBackground == _drawsBackground) 00758 return; 00759 _drawsBackground = drawsBackground; 00760 00761 [self _applyBackgroundColor]; 00762 } 00763 00764 - (void)setBackgroundColor:(CPColor)aColor 00765 { 00766 [super setBackgroundColor:aColor]; 00767 [self _applyBackgroundColor]; 00768 } 00769 00770 - (void)_applyBackgroundColor 00771 { 00772 if (_iframe) 00773 { 00774 var bgColor = [self backgroundColor] || [CPColor whiteColor]; 00775 _iframe.allowtransparency = !_drawsBackground; 00776 _iframe.style.backgroundColor = _drawsBackground ? [bgColor cssString] : "transparent"; 00777 } 00778 } 00779 00780 // IBActions 00781 00788 - (@action)takeStringURLFrom:(id)sender 00789 { 00790 [self setMainFrameURL:[sender stringValue]]; 00791 } 00792 00798 - (@action)goBack:(id)sender 00799 { 00800 [self goBack]; 00801 } 00802 00808 - (@action)goForward:(id)sender 00809 { 00810 [self goForward]; 00811 } 00812 00818 - (@action)stopLoading:(id)sender 00819 { 00820 // FIXME: what to do? 00821 } 00822 00828 - (@action)reload:(id)sender 00829 { 00830 // If we're displaying pure HTML, redisplay it. 00831 if(!_url && (_html !== nil)) 00832 [self loadHTMLString:_html]; 00833 else 00834 [self _loadMainFrameURL]; 00835 } 00836 00843 - (@action)print:(id)sender 00844 { 00845 try 00846 { 00847 [self DOMWindow].print(); 00848 } 00849 catch (e) 00850 { 00851 alert('Please click the webpage and select "Print" from the "File" menu'); 00852 } 00853 } 00854 00855 00856 // Delegates: 00857 00858 // FIXME: implement more delegates, though most of these will likely never work with the iframe implementation 00859 00860 - (id)downloadDelegate 00861 { 00862 return _downloadDelegate; 00863 } 00864 - (void)setDownloadDelegate:(id)anObject 00865 { 00866 _downloadDelegate = anObject; 00867 } 00868 - (id)frameLoadDelegate 00869 { 00870 return _frameLoadDelegate; 00871 } 00872 - (void)setFrameLoadDelegate:(id)anObject 00873 { 00874 _frameLoadDelegate = anObject; 00875 } 00876 - (id)policyDelegate 00877 { 00878 return _policyDelegate; 00879 } 00880 - (void)setPolicyDelegate:(id)anObject 00881 { 00882 _policyDelegate = anObject; 00883 } 00884 - (id)resourceLoadDelegate 00885 { 00886 return _resourceLoadDelegate; 00887 } 00888 - (void)setResourceLoadDelegate:(id)anObject 00889 { 00890 _resourceLoadDelegate = anObject; 00891 } 00892 - (id)UIDelegate 00893 { 00894 return _UIDelegate; 00895 } 00896 - (void)setUIDelegate:(id)anObject 00897 { 00898 _UIDelegate = anObject; 00899 } 00900 00901 @end 00902 00908 @implementation CPWebScriptObject : CPObject 00909 { 00910 Window _window; 00911 } 00912 00916 - (id)initWithWindow:(Window)aWindow 00917 { 00918 if (self = [super init]) 00919 { 00920 _window = aWindow; 00921 } 00922 return self; 00923 } 00924 00931 - (id)callWebScriptMethod:(CPString)methodName withArguments:(CPArray)args 00932 { 00933 // Would using "with" be better here? 00934 if (typeof _window[methodName] == "function") 00935 { 00936 try { 00937 return _window[methodName].apply(args); 00938 } catch (e) { 00939 } 00940 } 00941 return undefined; 00942 } 00943 00950 - (id)evaluateWebScript:(CPString)script 00951 { 00952 try { 00953 return _window.eval(script); 00954 } catch (e) { 00955 // FIX ME: if we fail inside here, shouldn't we return an exception? 00956 } 00957 return undefined; 00958 } 00959 00963 - (Window)window 00964 { 00965 return _window; 00966 } 00967 00968 @end 00969 00970 00971 @implementation CPWebView (CPCoding) 00972 00979 - (id)initWithCoder:(CPCoder)aCoder 00980 { 00981 self = [super initWithCoder:aCoder]; 00982 00983 if (self) 00984 { 00985 // FIXME: encode/decode these? 00986 _mainFrameURL = nil; 00987 _backwardStack = []; 00988 _forwardStack = []; 00989 _scrollMode = CPWebViewScrollAuto; 00990 00991 #if PLATFORM(DOM) 00992 [self _initDOMWithFrame:[self frame]]; 00993 #endif 00994 00995 if (![self backgroundColor]) 00996 [self setBackgroundColor:[CPColor whiteColor]]; 00997 00998 [self _updateEffectiveScrollMode]; 00999 } 01000 01001 return self; 01002 } 01003 01009 - (void)encodeWithCoder:(CPCoder)aCoder 01010 { 01011 var actualSubviews = _subviews; 01012 _subviews = []; 01013 [super encodeWithCoder:aCoder]; 01014 _subviews = actualSubviews; 01015 } 01016 01017 @end 01018 01019 @implementation CPURL(SOP) 01020 01028 - (BOOL)_passesSameOriginPolicy 01029 { 01030 var documentURL = [CPURL URLWithString:window.location.href]; 01031 if ([documentURL isFileURL] && CPFeatureIsCompatible(CPSOPDisabledFromFileURLs)) 01032 return YES; 01033 return ([documentURL scheme] == [self scheme] && [documentURL host] == [self host] && [documentURL port] == [self port]); 01034 } 01035 01036 @end