API 0.9.5
AppKit/CPWebView.j
Go to the documentation of this file.
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
 All Classes Files Functions Variables Defines