2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #import "WebFrameLoaderClient.h"
31 // Terrible hack; lets us get at the WebFrame private structure.
32 #define private public
36 #import "DOMElementInternal.h"
37 #import "WebBackForwardList.h"
38 #import "WebCachedFramePlatformData.h"
39 #import "WebChromeClient.h"
40 #import "WebDataSourceInternal.h"
41 #import "WebDocumentInternal.h"
42 #import "WebDocumentLoaderMac.h"
43 #import "WebDownloadInternal.h"
44 #import "WebDynamicScrollBarsViewInternal.h"
45 #import "WebElementDictionary.h"
46 #import "WebFormDelegate.h"
47 #import "WebFrameInternal.h"
48 #import "WebFrameLoadDelegate.h"
49 #import "WebFrameViewInternal.h"
50 #import "WebHTMLRepresentationPrivate.h"
51 #import "WebHTMLViewInternal.h"
52 #import "WebHistoryItemInternal.h"
53 #import "WebHistoryInternal.h"
54 #import "WebIconDatabaseInternal.h"
55 #import "WebKitErrorsPrivate.h"
56 #import "WebKitLogging.h"
57 #import "WebKitNSStringExtras.h"
58 #import "WebNSURLExtras.h"
59 #import "WebNetscapePluginView.h"
60 #import "WebNetscapePluginPackage.h"
61 #import "WebNullPluginView.h"
62 #import "WebPanelAuthenticationHandler.h"
63 #import "WebPluginController.h"
64 #import "WebPluginPackage.h"
65 #import "WebPluginViewFactoryPrivate.h"
66 #import "WebPolicyDelegate.h"
67 #import "WebPolicyDelegatePrivate.h"
68 #import "WebPreferences.h"
69 #import "WebResourceLoadDelegate.h"
70 #import "WebUIDelegate.h"
71 #import "WebUIDelegatePrivate.h"
72 #import "WebViewInternal.h"
73 #import <WebKitSystemInterface.h>
74 #import <WebCore/AuthenticationMac.h>
75 #import <WebCore/BlockExceptions.h>
76 #import <WebCore/CachedFrame.h>
77 #import <WebCore/Chrome.h>
78 #import <WebCore/Document.h>
79 #import <WebCore/DocumentLoader.h>
80 #import <WebCore/EventHandler.h>
81 #import <WebCore/FormState.h>
82 #import <WebCore/Frame.h>
83 #import <WebCore/FrameLoader.h>
84 #import <WebCore/FrameLoaderTypes.h>
85 #import <WebCore/FrameTree.h>
86 #import <WebCore/FrameView.h>
87 #import <WebCore/HTMLAppletElement.h>
88 #import <WebCore/HTMLHeadElement.h>
89 #import <WebCore/HTMLFormElement.h>
90 #import <WebCore/HTMLFrameElement.h>
91 #import <WebCore/HTMLFrameOwnerElement.h>
92 #import <WebCore/HTMLNames.h>
93 #import <WebCore/HTMLPlugInElement.h>
94 #import <WebCore/HistoryItem.h>
95 #import <WebCore/HitTestResult.h>
96 #import <WebCore/IconDatabase.h>
97 #import <WebCore/LoaderNSURLExtras.h>
98 #import <WebCore/MIMETypeRegistry.h>
99 #import <WebCore/MouseEvent.h>
100 #import <WebCore/Page.h>
101 #import <WebCore/PlatformString.h>
102 #import <WebCore/ResourceError.h>
103 #import <WebCore/ResourceHandle.h>
104 #import <WebCore/ResourceLoader.h>
105 #import <WebCore/ResourceRequest.h>
106 #import <WebCore/ScriptController.h>
107 #import <WebCore/SharedBuffer.h>
108 #import <WebCore/WebCoreObjCExtras.h>
109 #import <WebCore/Widget.h>
110 #import <WebKit/DOMElement.h>
111 #import <WebKit/DOMHTMLFormElement.h>
112 #import <runtime/InitializeThreading.h>
113 #import <wtf/PassRefPtr.h>
115 #if ENABLE(MAC_JAVA_BRIDGE)
116 #import "WebJavaPlugIn.h"
119 #if USE(PLUGIN_HOST_PROCESS)
120 #import "WebHostedNetscapePluginView.h"
123 using namespace WebCore;
124 using namespace HTMLNames;
126 #if ENABLE(MAC_JAVA_BRIDGE)
127 @interface NSView (WebJavaPluginDetails)
128 - (jobject)pollForAppletInWindow:(NSWindow *)window;
132 @interface NSURLDownload (WebNSURLDownloadDetails)
133 - (void)_setOriginatingURL:(NSURL *)originatingURL;
136 // For backwards compatibility with older WebKit plug-ins.
137 NSString *WebPluginBaseURLKey = @"WebPluginBaseURL";
138 NSString *WebPluginAttributesKey = @"WebPluginAttributes";
139 NSString *WebPluginContainerKey = @"WebPluginContainer";
141 @interface WebFramePolicyListener : NSObject <WebPolicyDecisionListener, WebFormSubmissionListener> {
144 - (id)initWithWebCoreFrame:(Frame*)frame;
148 static inline WebDataSource *dataSource(DocumentLoader* loader)
150 return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
153 // Quirk for the Apple Dictionary application.
155 // If a top level frame has a <script> element in its <head> for a script named MainPageJavaScript.js,
156 // then for that frame's document, ignore changes to the scrolling attribute of frames. That script
157 // has a bug in it where it sets the scrolling attribute on frames, and that erroneous scrolling
158 // attribute needs to be ignored to avoid showing extra scroll bars in the window.
159 // This quirk can be removed when Apple Dictionary is fixed (see <rdar://problem/6471058>).
161 static void applyAppleDictionaryApplicationQuirkNonInlinePart(WebFrameLoaderClient* client, const ResourceRequest& request)
163 if (!request.url().isLocalFile())
165 if (!request.url().string().endsWith("MainPageJavaScript.js"))
167 Frame* frame = core(client->webFrame());
170 if (frame->tree()->parent())
172 Document* document = frame->document();
175 HTMLHeadElement* head = document->head();
178 for (Node* c = head->firstChild(); c; c = c->nextSibling()) {
179 if (c->hasTagName(scriptTag) && static_cast<Element*>(c)->getAttribute(srcAttr) == "MainPageJavaScript.js") {
180 document->setFrameElementsShouldIgnoreScrolling(true);
186 static inline void applyAppleDictionaryApplicationQuirk(WebFrameLoaderClient* client, const ResourceRequest& request)
188 // Use a one-time-initialized global variable so we can quickly determine there's nothing to do in
189 // all applications other than Apple Dictionary.
190 static bool isAppleDictionary = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Dictionary"];
191 if (isAppleDictionary)
192 applyAppleDictionaryApplicationQuirkNonInlinePart(client, request);
195 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame *webFrame)
196 : m_webFrame(webFrame)
197 , m_policyFunction(0)
201 void WebFrameLoaderClient::frameLoaderDestroyed()
203 [m_webFrame.get() _clearCoreFrame];
207 bool WebFrameLoaderClient::hasWebView() const
209 return [m_webFrame.get() webView] != nil;
212 void WebFrameLoaderClient::makeRepresentation(DocumentLoader* loader)
214 [dataSource(loader) _makeRepresentation];
217 bool WebFrameLoaderClient::hasHTMLView() const
219 NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
220 return [view isKindOfClass:[WebHTMLView class]];
223 void WebFrameLoaderClient::forceLayout()
225 NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
226 if ([view isKindOfClass:[WebHTMLView class]])
227 [(WebHTMLView *)view setNeedsToApplyStyles:YES];
228 [view setNeedsLayout:YES];
232 void WebFrameLoaderClient::forceLayoutForNonHTML()
234 WebFrameView *thisView = m_webFrame->_private->webFrameView;
235 if (!thisView) // Viewless mode.
237 NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
238 ASSERT(thisDocumentView != nil);
240 // Tell the just loaded document to layout. This may be necessary
241 // for non-html content that needs a layout message.
242 if (!([[m_webFrame.get() _dataSource] _isDocumentHTML])) {
243 [thisDocumentView setNeedsLayout:YES];
244 [thisDocumentView layout];
245 [thisDocumentView setNeedsDisplay:YES];
249 void WebFrameLoaderClient::setCopiesOnScroll()
251 [[[m_webFrame->_private->webFrameView _scrollView] contentView] setCopiesOnScroll:YES];
254 void WebFrameLoaderClient::detachedFromParent2()
256 //remove any NetScape plugins that are children of this frame because they are about to be detached
257 WebView *webView = getWebView(m_webFrame.get());
258 [webView removePluginInstanceViewsFor:(m_webFrame.get())];
259 [m_webFrame->_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
262 void WebFrameLoaderClient::detachedFromParent3()
264 [m_webFrame->_private->webFrameView release];
265 m_webFrame->_private->webFrameView = nil;
268 void WebFrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest& initialRequest, const ResourceResponse& response)
270 id proxy = handle->releaseProxy();
273 WebView *webView = getWebView(m_webFrame.get());
274 WebDownload *download = [WebDownload _downloadWithLoadingConnection:handle->connection()
275 request:request.nsURLRequest()
276 response:response.nsURLResponse()
277 delegate:[webView downloadDelegate]
280 setOriginalURLForDownload(download, initialRequest);
283 void WebFrameLoaderClient::setOriginalURLForDownload(WebDownload *download, const ResourceRequest& initialRequest) const
285 NSURLRequest *initialURLRequest = initialRequest.nsURLRequest();
286 NSURL *originalURL = nil;
288 // If there was no referrer, don't traverse the back/forward history
289 // since this download was initiated directly. <rdar://problem/5294691>
290 if ([initialURLRequest valueForHTTPHeaderField:@"Referer"]) {
291 // find the first item in the history that was originated by the user
292 WebView *webView = getWebView(m_webFrame.get());
293 WebBackForwardList *history = [webView backForwardList];
294 int backListCount = [history backListCount];
295 for (int backIndex = 0; backIndex <= backListCount && !originalURL; backIndex++) {
296 // FIXME: At one point we had code here to check a "was user gesture" flag.
297 // Do we need to restore that logic?
298 originalURL = [[history itemAtIndex:-backIndex] URL];
303 originalURL = [initialURLRequest URL];
305 if ([download respondsToSelector:@selector(_setOriginatingURL:)]) {
306 NSString *scheme = [originalURL scheme];
307 NSString *host = [originalURL host];
308 if (scheme && host && [scheme length] && [host length]) {
309 NSNumber *port = [originalURL port];
310 if (port && [port intValue] < 0)
312 NSString *hostOnlyURLString;
314 hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@:%d", scheme, host, [port intValue]];
316 hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@", scheme, host];
317 NSURL *hostOnlyURL = [[NSURL alloc] initWithString:hostOnlyURLString];
318 [hostOnlyURLString release];
319 [download _setOriginatingURL:hostOnlyURL];
320 [hostOnlyURL release];
325 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length)
327 applyAppleDictionaryApplicationQuirk(this, request);
329 WebView *webView = getWebView(m_webFrame.get());
330 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
331 if (!implementations->didLoadResourceFromMemoryCacheFunc)
334 CallResourceLoadDelegate(implementations->didLoadResourceFromMemoryCacheFunc, webView, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), request.nsURLRequest(), response.nsURLResponse(), length, dataSource(loader));
338 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
340 WebView *webView = getWebView(m_webFrame.get());
341 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
344 BOOL shouldRelease = NO;
345 if (implementations->identifierForRequestFunc)
346 object = CallResourceLoadDelegate(implementations->identifierForRequestFunc, webView, @selector(webView:identifierForInitialRequest:fromDataSource:), request.nsURLRequest(), dataSource(loader));
348 object = [[NSObject alloc] init];
352 [webView _addObject:object forIdentifier:identifier];
358 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
360 applyAppleDictionaryApplicationQuirk(this, request);
362 WebView *webView = getWebView(m_webFrame.get());
363 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
365 if (redirectResponse.isNull())
366 static_cast<WebDocumentLoaderMac*>(loader)->increaseLoadCount(identifier);
368 if (implementations->willSendRequestFunc)
369 request = (NSURLRequest *)CallResourceLoadDelegate(implementations->willSendRequestFunc, webView, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:), [webView _objectForIdentifier:identifier], request.nsURLRequest(), redirectResponse.nsURLResponse(), dataSource(loader));
372 bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader* loader, unsigned long identifier)
374 WebView *webView = getWebView(m_webFrame.get());
375 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
377 if (implementations->shouldUseCredentialStorageFunc) {
378 if (id resource = [webView _objectForIdentifier:identifier])
379 return CallResourceLoadDelegateReturningBoolean(NO, implementations->shouldUseCredentialStorageFunc, webView, @selector(webView:resource:shouldUseCredentialStorageForDataSource:), resource, dataSource(loader));
385 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
387 WebView *webView = getWebView(m_webFrame.get());
388 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
390 NSURLAuthenticationChallenge *webChallenge = mac(challenge);
392 if (implementations->didReceiveAuthenticationChallengeFunc) {
393 if (id resource = [webView _objectForIdentifier:identifier]) {
394 CallResourceLoadDelegate(implementations->didReceiveAuthenticationChallengeFunc, webView, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
399 NSWindow *window = [webView hostWindow] ? [webView hostWindow] : [webView window];
400 [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:webChallenge window:window];
403 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge&challenge)
405 WebView *webView = getWebView(m_webFrame.get());
406 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
407 NSURLAuthenticationChallenge *webChallenge = mac(challenge);
409 if (implementations->didCancelAuthenticationChallengeFunc) {
410 if (id resource = [webView _objectForIdentifier:identifier]) {
411 CallResourceLoadDelegate(implementations->didCancelAuthenticationChallengeFunc, webView, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
416 [(WebPanelAuthenticationHandler *)[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:webChallenge];
419 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
421 WebView *webView = getWebView(m_webFrame.get());
422 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
423 if (implementations->didReceiveResponseFunc) {
424 if (id resource = [webView _objectForIdentifier:identifier])
425 CallResourceLoadDelegate(implementations->didReceiveResponseFunc, webView, @selector(webView:resource:didReceiveResponse:fromDataSource:), resource, response.nsURLResponse(), dataSource(loader));
429 NSCachedURLResponse* WebFrameLoaderClient::willCacheResponse(DocumentLoader* loader, unsigned long identifier, NSCachedURLResponse* response) const
431 WebView *webView = getWebView(m_webFrame.get());
432 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
434 if (implementations->willCacheResponseFunc) {
435 if (id resource = [webView _objectForIdentifier:identifier])
436 return CallResourceLoadDelegate(implementations->willCacheResponseFunc, webView, @selector(webView:resource:willCacheResponse:fromDataSource:), resource, response, dataSource(loader));
442 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int lengthReceived)
444 WebView *webView = getWebView(m_webFrame.get());
445 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
446 if (implementations->didReceiveContentLengthFunc) {
447 if (id resource = [webView _objectForIdentifier:identifier])
448 CallResourceLoadDelegate(implementations->didReceiveContentLengthFunc, webView, @selector(webView:resource:didReceiveContentLength:fromDataSource:), resource, (NSInteger)lengthReceived, dataSource(loader));
452 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
454 WebView *webView = getWebView(m_webFrame.get());
455 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
457 if (implementations->didFinishLoadingFromDataSourceFunc) {
458 if (id resource = [webView _objectForIdentifier:identifier])
459 CallResourceLoadDelegate(implementations->didFinishLoadingFromDataSourceFunc, webView, @selector(webView:resource:didFinishLoadingFromDataSource:), resource, dataSource(loader));
462 [webView _removeObjectForIdentifier:identifier];
464 static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
467 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
469 WebView *webView = getWebView(m_webFrame.get());
470 WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
472 if (implementations->didFailLoadingWithErrorFromDataSourceFunc) {
473 if (id resource = [webView _objectForIdentifier:identifier])
474 CallResourceLoadDelegate(implementations->didFailLoadingWithErrorFromDataSourceFunc, webView, @selector(webView:resource:didFailLoadingWithError:fromDataSource:), resource, (NSError *)error, dataSource(loader));
477 [webView _removeObjectForIdentifier:identifier];
479 static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
482 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
484 WebView *webView = getWebView(m_webFrame.get());
485 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
486 if (implementations->didHandleOnloadEventsForFrameFunc)
487 CallFrameLoadDelegate(implementations->didHandleOnloadEventsForFrameFunc, webView, @selector(webView:didHandleOnloadEventsForFrame:), m_webFrame.get());
490 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
492 WebView *webView = getWebView(m_webFrame.get());
493 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
494 if (implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc)
495 CallFrameLoadDelegate(implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc, webView, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:), m_webFrame.get());
498 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
500 WebView *webView = getWebView(m_webFrame.get());
501 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
502 if (implementations->didCancelClientRedirectForFrameFunc)
503 CallFrameLoadDelegate(implementations->didCancelClientRedirectForFrameFunc, webView, @selector(webView:didCancelClientRedirectForFrame:), m_webFrame.get());
506 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate)
508 WebView *webView = getWebView(m_webFrame.get());
509 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
510 if (implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc) {
511 NSURL *cocoaURL = url;
512 CallFrameLoadDelegate(implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc, webView, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:), cocoaURL, delay, [NSDate dateWithTimeIntervalSince1970:fireDate], m_webFrame.get());
516 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
518 WebView *webView = getWebView(m_webFrame.get());
519 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
520 if (implementations->didChangeLocationWithinPageForFrameFunc)
521 CallFrameLoadDelegate(implementations->didChangeLocationWithinPageForFrameFunc, webView, @selector(webView:didChangeLocationWithinPageForFrame:), m_webFrame.get());
524 void WebFrameLoaderClient::dispatchWillClose()
526 WebView *webView = getWebView(m_webFrame.get());
527 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
528 if (implementations->willCloseFrameFunc)
529 CallFrameLoadDelegate(implementations->willCloseFrameFunc, webView, @selector(webView:willCloseFrame:), m_webFrame.get());
532 void WebFrameLoaderClient::dispatchDidReceiveIcon()
534 WebView *webView = getWebView(m_webFrame.get());
535 ASSERT(m_webFrame == [webView mainFrame]);
536 [webView _dispatchDidReceiveIconFromWebFrame:m_webFrame.get()];
539 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
541 WebView *webView = getWebView(m_webFrame.get());
542 [webView _didStartProvisionalLoadForFrame:m_webFrame.get()];
544 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
545 if (implementations->didStartProvisionalLoadForFrameFunc)
546 CallFrameLoadDelegate(implementations->didStartProvisionalLoadForFrameFunc, webView, @selector(webView:didStartProvisionalLoadForFrame:), m_webFrame.get());
549 void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title)
551 WebView *webView = getWebView(m_webFrame.get());
552 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
553 if (implementations->didReceiveTitleForFrameFunc)
554 CallFrameLoadDelegate(implementations->didReceiveTitleForFrameFunc, webView, @selector(webView:didReceiveTitle:forFrame:), (NSString *)title, m_webFrame.get());
557 void WebFrameLoaderClient::dispatchDidCommitLoad()
559 // Tell the client we've committed this URL.
560 ASSERT([m_webFrame->_private->webFrameView documentView] != nil || ![getWebView(m_webFrame.get()) _usesDocumentViews]);
562 WebView *webView = getWebView(m_webFrame.get());
563 [webView _didCommitLoadForFrame:m_webFrame.get()];
565 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
566 if (implementations->didCommitLoadForFrameFunc)
567 CallFrameLoadDelegate(implementations->didCommitLoadForFrameFunc, webView, @selector(webView:didCommitLoadForFrame:), m_webFrame.get());
570 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
572 WebView *webView = getWebView(m_webFrame.get());
573 [webView _didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
575 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
576 if (implementations->didFailProvisionalLoadWithErrorForFrameFunc)
577 CallFrameLoadDelegate(implementations->didFailProvisionalLoadWithErrorForFrameFunc, webView, @selector(webView:didFailProvisionalLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
579 [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
582 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
584 WebView *webView = getWebView(m_webFrame.get());
585 [webView _didFailLoadWithError:error forFrame:m_webFrame.get()];
587 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
588 if (implementations->didFailLoadWithErrorForFrameFunc)
589 CallFrameLoadDelegate(implementations->didFailLoadWithErrorForFrameFunc, webView, @selector(webView:didFailLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
591 [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
594 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
596 WebView *webView = getWebView(m_webFrame.get());
597 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
598 if (implementations->didFinishDocumentLoadForFrameFunc)
599 CallFrameLoadDelegate(implementations->didFinishDocumentLoadForFrameFunc, webView, @selector(webView:didFinishDocumentLoadForFrame:), m_webFrame.get());
602 void WebFrameLoaderClient::dispatchDidFinishLoad()
604 WebView *webView = getWebView(m_webFrame.get());
605 [webView _didFinishLoadForFrame:m_webFrame.get()];
607 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
608 if (implementations->didFinishLoadForFrameFunc)
609 CallFrameLoadDelegate(implementations->didFinishLoadForFrameFunc, webView, @selector(webView:didFinishLoadForFrame:), m_webFrame.get());
611 [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];
614 void WebFrameLoaderClient::dispatchDidFirstLayout()
616 WebView *webView = getWebView(m_webFrame.get());
617 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
618 if (implementations->didFirstLayoutInFrameFunc)
619 CallFrameLoadDelegate(implementations->didFirstLayoutInFrameFunc, webView, @selector(webView:didFirstLayoutInFrame:), m_webFrame.get());
622 void WebFrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
624 WebView *webView = getWebView(m_webFrame.get());
625 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
626 if (implementations->didFirstVisuallyNonEmptyLayoutInFrameFunc)
627 CallFrameLoadDelegate(implementations->didFirstVisuallyNonEmptyLayoutInFrameFunc, webView, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:), m_webFrame.get());
630 Frame* WebFrameLoaderClient::dispatchCreatePage()
632 WebView *currentWebView = getWebView(m_webFrame.get());
633 NSDictionary *features = [[NSDictionary alloc] init];
634 WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView
635 createWebViewWithRequest:nil
636 windowFeatures:features];
638 return core([newWebView mainFrame]);
641 void WebFrameLoaderClient::dispatchShow()
643 WebView *webView = getWebView(m_webFrame.get());
644 [[webView _UIDelegateForwarder] webViewShow:webView];
647 void WebFrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction function,
648 const String& MIMEType, const ResourceRequest& request)
650 WebView *webView = getWebView(m_webFrame.get());
652 [[webView _policyDelegateForwarder] webView:webView
653 decidePolicyForMIMEType:MIMEType
654 request:request.nsURLRequest()
655 frame:m_webFrame.get()
656 decisionListener:setUpPolicyListener(function).get()];
659 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function,
660 const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName)
662 WebView *webView = getWebView(m_webFrame.get());
663 [[webView _policyDelegateForwarder] webView:webView
664 decidePolicyForNewWindowAction:actionDictionary(action, formState)
665 request:request.nsURLRequest()
666 newFrameName:frameName
667 decisionListener:setUpPolicyListener(function).get()];
670 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function,
671 const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState)
673 WebView *webView = getWebView(m_webFrame.get());
674 [[webView _policyDelegateForwarder] webView:webView
675 decidePolicyForNavigationAction:actionDictionary(action, formState)
676 request:request.nsURLRequest()
677 frame:m_webFrame.get()
678 decisionListener:setUpPolicyListener(function).get()];
681 void WebFrameLoaderClient::cancelPolicyCheck()
683 [m_policyListener.get() invalidate];
684 m_policyListener = nil;
685 m_policyFunction = 0;
688 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
690 WebView *webView = getWebView(m_webFrame.get());
691 [[webView _policyDelegateForwarder] webView:webView unableToImplementPolicyWithError:error frame:m_webFrame.get()];
694 void WebFrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
696 id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate];
698 (core(m_webFrame.get())->loader()->*function)(PolicyUse);
702 NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:formState->values().size()];
703 HashMap<String, String>::const_iterator end = formState->values().end();
704 for (HashMap<String, String>::const_iterator it = formState->values().begin(); it != end; ++it)
705 [dictionary setObject:it->second forKey:it->first];
707 CallFormDelegate(getWebView(m_webFrame.get()), @selector(frame:sourceFrame:willSubmitForm:withValues:submissionListener:), m_webFrame.get(), kit(formState->sourceFrame()), kit(formState->form()), dictionary, setUpPolicyListener(function).get());
709 [dictionary release];
712 void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader* loader)
716 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader)
718 [dataSource(loader) _revertToProvisionalState];
721 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
723 [dataSource(loader) _setMainDocumentError:error];
726 void WebFrameLoaderClient::willChangeEstimatedProgress()
728 [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebEstimatedProgressKey];
731 void WebFrameLoaderClient::didChangeEstimatedProgress()
733 [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebEstimatedProgressKey];
736 void WebFrameLoaderClient::postProgressStartedNotification()
738 [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:getWebView(m_webFrame.get())];
741 void WebFrameLoaderClient::postProgressEstimateChangedNotification()
743 [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:getWebView(m_webFrame.get())];
746 void WebFrameLoaderClient::postProgressFinishedNotification()
748 [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:getWebView(m_webFrame.get())];
751 void WebFrameLoaderClient::setMainFrameDocumentReady(bool ready)
753 [getWebView(m_webFrame.get()) setMainFrameDocumentReady:ready];
756 void WebFrameLoaderClient::startDownload(const ResourceRequest& request)
758 // FIXME: Should download full request.
759 WebDownload *download = [getWebView(m_webFrame.get()) _downloadURL:request.url()];
761 setOriginalURLForDownload(download, request);
764 void WebFrameLoaderClient::willChangeTitle(DocumentLoader* loader)
766 // FIXME: Should do this only in main frame case, right?
767 [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebMainFrameTitleKey];
770 void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader)
772 // FIXME: Should do this only in main frame case, right?
773 [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebMainFrameTitleKey];
776 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
778 NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO];
779 [dataSource(loader) _receivedData:nsData];
783 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
785 [dataSource(loader) _finishedLoading];
788 void WebFrameLoaderClient::updateGlobalHistory()
790 DocumentLoader* loader = core(m_webFrame.get())->loader()->documentLoader();
791 [[WebHistory optionalSharedHistory] _visitedURL:loader->urlForHistory()
792 withTitle:loader->title()
793 method:loader->originalRequestCopy().httpMethod()
794 wasFailure:loader->urlForHistoryReflectsFailure()];
797 void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
799 DocumentLoader* loader = core(m_webFrame.get())->loader()->documentLoader();
800 ASSERT(loader->unreachableURL().isEmpty());
802 if (!loader->clientRedirectSourceForHistory().isNull()) {
803 if (WebHistoryItem *item = [[WebHistory optionalSharedHistory] _itemForURLString:loader->clientRedirectSourceForHistory()])
804 core(item)->addRedirectURL(loader->clientRedirectDestinationForHistory());
807 if (!loader->serverRedirectSourceForHistory().isNull()) {
808 if (WebHistoryItem *item = [[WebHistory optionalSharedHistory] _itemForURLString:loader->serverRedirectSourceForHistory()])
809 core(item)->addRedirectURL(loader->serverRedirectDestinationForHistory());
813 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
815 WebView* view = getWebView(m_webFrame.get());
816 WebHistoryItem *webItem = kit(item);
818 return [[view _policyDelegateForwarder] webView:view shouldGoToHistoryItem:webItem];
821 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
823 return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url()];
826 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
828 return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotUseRestrictedPort URL:request.url()];
831 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
833 return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotShowURL URL:request.url()];
836 ResourceError WebFrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
838 return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:request.url()];
841 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
843 return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:WebKitErrorCannotShowMIMEType URL:response.url()];
846 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
848 return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:response.url()];
851 ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
853 NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInWillHandleLoad
854 contentURL:response.url()
857 MIMEType:response.mimeType()];
858 return [error autorelease];
861 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
863 // FIXME: Needs to check domain.
864 // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent
865 // loading plugin content twice. See <rdar://problem/4258008>
866 return error.errorCode() != NSURLErrorCancelled && error.errorCode() != WebKitErrorPlugInWillHandleLoad;
869 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const
871 Frame* frame = core(m_webFrame.get());
872 Page* page = frame->page();
873 BOOL forMainFrame = page && page->mainFrame() == frame;
874 return [WebView _canHandleRequest:request.nsURLRequest() forMainFrame:forMainFrame];
877 bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const
879 return [WebView canShowMIMEType:MIMEType];
882 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const
884 return [WebView _representationExistsForURLScheme:URLScheme];
887 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const
889 return [WebView _generatedMIMETypeForURLScheme:URLScheme];
892 void WebFrameLoaderClient::frameLoadCompleted()
894 // Note: Can be called multiple times.
896 // See WebFrameLoaderClient::provisionalLoadStarted.
897 if ([getWebView(m_webFrame.get()) drawsBackground])
898 [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:YES];
901 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem* item)
906 NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
908 // we might already be detached when this is called from detachFromParent, in which
909 // case we don't want to override real data earlier gathered with (0,0)
910 if ([docView superview] && [docView conformsToProtocol:@protocol(_WebDocumentViewState)])
911 item->setViewState([(id <_WebDocumentViewState>)docView viewState]);
914 void WebFrameLoaderClient::restoreViewState()
916 HistoryItem* currentItem = core(m_webFrame.get())->loader()->currentHistoryItem();
919 // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
920 // One counterexample is <rdar://problem/4917290>
921 // For now, to cover this issue in release builds, there is no technical harm to returning
922 // early and from a user standpoint - as in the above radar - the previous page load failed
923 // so there *is* no scroll state to restore!
927 NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
928 if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {
929 id state = currentItem->viewState();
931 [(id <_WebDocumentViewState>)docView setViewState:state];
936 void WebFrameLoaderClient::provisionalLoadStarted()
938 // Tell the scroll view not to draw a background so we can leave the contents of
939 // the old page showing during the beginning of the loading process.
941 // This will stay set to NO until:
942 // 1) The load gets far enough along: WebFrameLoader::frameLoadCompleted.
943 // 2) The window is resized: -[WebFrameView setFrameSize:].
944 // or 3) The view is moved out of the window: -[WebFrameView viewDidMoveToWindow].
945 // Please keep the comments in these four functions in agreement with each other.
947 [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:NO];
950 void WebFrameLoaderClient::didFinishLoad()
952 [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];
955 void WebFrameLoaderClient::prepareForDataSourceReplacement()
957 if (![m_webFrame.get() _dataSource]) {
958 ASSERT(!core(m_webFrame.get())->tree()->childCount());
962 // Make sure that any work that is triggered by resigning first reponder can get done.
963 // The main example where this came up is the textDidEndEditing that is sent to the
964 // FormsDelegate (3223413). We need to do this before _detachChildren, since that will
965 // remove the views as a side-effect of freeing the frame, at which point we can't
966 // post the FormDelegate messages.
968 // Note that this can also take FirstResponder away from a child of our frameView that
969 // is not in a child frame's view. This is OK because we are in the process
970 // of loading new content, which will blow away all editors in this top frame, and if
971 // a non-editor is firstReponder it will not be affected by endEditingFor:.
972 // Potentially one day someone could write a DocView whose editors were not all
973 // replaced by loading new content, but that does not apply currently.
974 NSView *frameView = m_webFrame->_private->webFrameView;
975 NSWindow *window = [frameView window];
976 NSResponder *firstResp = [window firstResponder];
977 if ([firstResp isKindOfClass:[NSView class]] && [(NSView *)firstResp isDescendantOf:frameView])
978 [window endEditingFor:firstResp];
981 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
983 RefPtr<WebDocumentLoaderMac> loader = WebDocumentLoaderMac::create(request, substituteData);
985 WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader.get()];
986 loader->setDataSource(dataSource, getWebView(m_webFrame.get()));
987 [dataSource release];
989 return loader.release();
992 // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
993 // Once that task is complete, this will go away
994 void WebFrameLoaderClient::setTitle(const String& title, const KURL& URL)
997 nsURL = [nsURL _webkit_canonicalize];
1000 NSString *titleNSString = title;
1001 [[[WebHistory optionalSharedHistory] itemForURL:nsURL] setTitle:titleNSString];
1004 void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1006 WebCachedFramePlatformData* webPlatformData = new WebCachedFramePlatformData([m_webFrame->_private->webFrameView documentView]);
1007 cachedFrame->setCachedFramePlatformData(webPlatformData);
1010 void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame)
1012 WebCachedFramePlatformData* platformData = reinterpret_cast<WebCachedFramePlatformData*>(cachedFrame->cachedFramePlatformData());
1013 NSView <WebDocumentView> *cachedView = platformData->webDocumentView();
1014 ASSERT(cachedView != nil);
1015 ASSERT(cachedFrame->documentLoader());
1016 [cachedView setDataSource:dataSource(cachedFrame->documentLoader())];
1018 // clean up webkit plugin instances before WebHTMLView gets freed.
1019 WebView *webView = getWebView(m_webFrame.get());
1020 [webView removePluginInstanceViewsFor:(m_webFrame.get())];
1022 [m_webFrame->_private->webFrameView _setDocumentView:cachedView];
1025 void WebFrameLoaderClient::transitionToCommittedForNewPage()
1027 WebFrameView *v = m_webFrame->_private->webFrameView;
1028 WebDataSource *ds = [m_webFrame.get() _dataSource];
1030 bool willProduceHTMLView = [[WebFrameView class] _viewClassForMIMEType:[ds _responseMIMEType]] == [WebHTMLView class];
1031 bool canSkipCreation = core(m_webFrame.get())->loader()->committingFirstRealLoad() && willProduceHTMLView;
1032 if (canSkipCreation) {
1033 [[v documentView] setDataSource:ds];
1037 // Don't suppress scrollbars before the view creation if we're making the view for a non-HTML view.
1038 if (!willProduceHTMLView)
1039 [[v _scrollView] setScrollBarsSuppressed:NO repaintOnUnsuppress:NO];
1041 // clean up webkit plugin instances before WebHTMLView gets freed.
1042 WebView *webView = getWebView(m_webFrame.get());
1043 [webView removePluginInstanceViewsFor:(m_webFrame.get())];
1045 BOOL useDocumentViews = [webView _usesDocumentViews];
1046 NSView <WebDocumentView> *documentView = nil;
1047 if (useDocumentViews) {
1048 documentView = [v _makeDocumentViewForDataSource:ds];
1053 // FIXME: Could we skip some of this work for a top-level view that is not a WebHTMLView?
1055 // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
1056 Frame* coreFrame = core(m_webFrame.get());
1057 Page* page = coreFrame->page();
1058 bool isMainFrame = coreFrame == page->mainFrame();
1059 if (isMainFrame && coreFrame->view())
1060 coreFrame->view()->setParentVisible(false);
1061 coreFrame->setView(0);
1062 FrameView* coreView;
1063 if (useDocumentViews)
1064 coreView = new FrameView(coreFrame);
1066 coreView = new FrameView(coreFrame, IntSize([webView bounds].size));
1067 coreFrame->setView(coreView);
1068 coreView->deref(); // FIXME: Eliminate this crazy refcounting!
1070 [m_webFrame.get() _updateBackgroundAndUpdatesWhileOffscreen];
1075 coreView->setParentVisible(true);
1077 // Call setDataSource on the document view after it has been placed in the view hierarchy.
1078 // This what we for the top-level view, so should do this for views in subframes as well.
1079 [documentView setDataSource:ds];
1081 if (HTMLFrameOwnerElement* owner = coreFrame->ownerElement())
1082 coreFrame->view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
1086 RetainPtr<WebFramePolicyListener> WebFrameLoaderClient::setUpPolicyListener(FramePolicyFunction function)
1088 // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
1090 [m_policyListener.get() invalidate];
1092 WebFramePolicyListener *listener = [[WebFramePolicyListener alloc] initWithWebCoreFrame:core(m_webFrame.get())];
1093 m_policyListener = listener;
1095 m_policyFunction = function;
1100 void WebFrameLoaderClient::receivedPolicyDecison(PolicyAction action)
1102 ASSERT(m_policyListener);
1103 ASSERT(m_policyFunction);
1105 FramePolicyFunction function = m_policyFunction;
1107 m_policyListener = nil;
1108 m_policyFunction = 0;
1110 (core(m_webFrame.get())->loader()->*function)(action);
1113 String WebFrameLoaderClient::userAgent(const KURL& url)
1115 WebView *webView = getWebView(m_webFrame.get());
1118 // We should never get here with nil for the WebView unless there is a bug somewhere else.
1119 // But if we do, it's better to return the empty string than just crashing on the spot.
1120 // Most other call sites are tolerant of nil because of Objective-C behavior, but this one
1121 // is not because the return value of _userAgentForURL is a const KURL&.
1125 return [webView _userAgentForURL:url];
1128 static const MouseEvent* findMouseEvent(const Event* event)
1130 for (const Event* e = event; e; e = e->underlyingEvent())
1131 if (e->isMouseEvent())
1132 return static_cast<const MouseEvent*>(e);
1136 NSDictionary *WebFrameLoaderClient::actionDictionary(const NavigationAction& action, PassRefPtr<FormState> formState) const
1138 unsigned modifierFlags = 0;
1139 const Event* event = action.event();
1140 if (const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event))) {
1141 if (keyStateEvent->ctrlKey())
1142 modifierFlags |= NSControlKeyMask;
1143 if (keyStateEvent->altKey())
1144 modifierFlags |= NSAlternateKeyMask;
1145 if (keyStateEvent->shiftKey())
1146 modifierFlags |= NSShiftKeyMask;
1147 if (keyStateEvent->metaKey())
1148 modifierFlags |= NSCommandKeyMask;
1151 NSURL *originalURL = action.url();
1153 NSMutableDictionary *result = [NSMutableDictionary dictionaryWithObjectsAndKeys:
1154 [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1155 [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1156 originalURL, WebActionOriginalURLKey,
1159 if (const MouseEvent* mouseEvent = findMouseEvent(event)) {
1160 IntPoint point(mouseEvent->pageX(), mouseEvent->pageY());
1161 WebElementDictionary *element = [[WebElementDictionary alloc]
1162 initWithHitTestResult:core(m_webFrame.get())->eventHandler()->hitTestResultAtPoint(point, false)];
1163 [result setObject:element forKey:WebActionElementKey];
1166 [result setObject:[NSNumber numberWithInt:mouseEvent->button()] forKey:WebActionButtonKey];
1170 ASSERT(formState->form());
1171 [result setObject:kit(formState->form()) forKey:WebActionFormKey];
1177 bool WebFrameLoaderClient::canCachePage() const
1179 // We can only cache HTML pages right now
1180 return [[[m_webFrame.get() _dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]];
1183 PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
1184 const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
1186 BEGIN_BLOCK_OBJC_EXCEPTIONS;
1190 WebFrameView *childView = [getWebView(m_webFrame.get()) _usesDocumentViews] ? [[WebFrameView alloc] init] : nil;
1192 RefPtr<Frame> result = [WebFrame _createSubframeWithOwnerElement:ownerElement frameName:name frameView:childView];
1193 [childView release];
1195 WebFrame *newFrame = kit(result.get());
1197 if ([newFrame _dataSource])
1198 [[newFrame _dataSource] _documentLoader]->setOverrideEncoding([[m_webFrame.get() _dataSource] _documentLoader]->overrideEncoding());
1200 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1201 if (!result->page())
1204 core(m_webFrame.get())->loader()->loadURLIntoChildFrame(url, referrer, result.get());
1206 // The frame's onload handler may have removed it from the document.
1207 if (!result->tree()->parent())
1210 return result.release();
1212 END_BLOCK_OBJC_EXCEPTIONS;
1217 ObjectContentType WebFrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
1219 BEGIN_BLOCK_OBJC_EXCEPTIONS;
1221 // This is a quirk that ensures Tiger Mail's WebKit plug-in will load during layout
1222 // and not attach time. (5520541)
1223 static BOOL isTigerMail = WKAppVersionCheckLessThan(@"com.apple.mail", -1, 3.0);
1224 if (isTigerMail && mimeType == "application/x-apple-msg-attachment")
1225 return ObjectContentNetscapePlugin;
1227 String type = mimeType;
1229 if (type.isEmpty()) {
1230 // Try to guess the MIME type based off the extension.
1232 NSString *extension = [[URL path] pathExtension];
1233 if ([extension length] > 0) {
1234 type = WKGetMIMETypeForExtension(extension);
1235 if (type.isEmpty()) {
1236 // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
1237 if (WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForExtension:extension]) {
1238 if ([package isKindOfClass:[WebPluginPackage class]])
1239 return ObjectContentOtherPlugin;
1240 #if ENABLE(NETSCAPE_PLUGIN_API)
1242 ASSERT([package isKindOfClass:[WebNetscapePluginPackage class]]);
1243 return ObjectContentNetscapePlugin;
1252 return ObjectContentFrame; // Go ahead and hope that we can display the content.
1254 if (MIMETypeRegistry::isSupportedImageMIMEType(type))
1255 return ObjectContentImage;
1257 WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForMIMEType:type];
1259 #if ENABLE(NETSCAPE_PLUGIN_API)
1260 if ([package isKindOfClass:[WebNetscapePluginPackage class]])
1261 return ObjectContentNetscapePlugin;
1263 ASSERT([package isKindOfClass:[WebPluginPackage class]]);
1264 return ObjectContentOtherPlugin;
1267 if ([WebFrameView _viewClassForMIMEType:type])
1268 return ObjectContentFrame;
1270 return ObjectContentNone;
1272 END_BLOCK_OBJC_EXCEPTIONS;
1274 return ObjectContentNone;
1277 static NSMutableArray* kit(const Vector<String>& vector)
1279 unsigned len = vector.size();
1280 NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
1281 for (unsigned x = 0; x < len; x++)
1282 [array addObject:vector[x]];
1286 static String parameterValue(const Vector<String>& paramNames, const Vector<String>& paramValues, const String& name)
1288 size_t size = paramNames.size();
1289 ASSERT(size == paramValues.size());
1290 for (size_t i = 0; i < size; ++i) {
1291 if (equalIgnoringCase(paramNames[i], name))
1292 return paramValues[i];
1297 static NSView *pluginView(WebFrame *frame, WebPluginPackage *pluginPackage,
1298 NSArray *attributeNames, NSArray *attributeValues, NSURL *baseURL,
1299 DOMElement *element, BOOL loadManually)
1301 WebHTMLView *docView = (WebHTMLView *)[[frame frameView] documentView];
1302 ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1304 WebPluginController *pluginController = [docView _pluginController];
1306 // Store attributes in a dictionary so they can be passed to WebPlugins.
1307 NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
1309 [pluginPackage load];
1310 Class viewFactory = [pluginPackage viewFactory];
1313 NSDictionary *arguments = nil;
1315 if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
1316 arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1317 baseURL, WebPlugInBaseURLKey,
1318 attributes, WebPlugInAttributesKey,
1319 pluginController, WebPlugInContainerKey,
1320 [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
1321 [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
1322 element, WebPlugInContainingElementKey,
1324 LOG(Plugins, "arguments:\n%@", arguments);
1325 } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
1326 arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1327 baseURL, WebPluginBaseURLKey,
1328 attributes, WebPluginAttributesKey,
1329 pluginController, WebPluginContainerKey,
1330 element, WebPlugInContainingElementKey,
1332 LOG(Plugins, "arguments:\n%@", arguments);
1335 view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
1336 [attributes release];
1340 class PluginWidget : public Widget {
1342 PluginWidget(NSView *view = 0)
1347 virtual void invalidateRect(const IntRect& rect)
1349 [platformWidget() setNeedsDisplayInRect:rect];
1353 #if ENABLE(NETSCAPE_PLUGIN_API)
1355 class NetscapePluginWidget : public PluginWidget {
1357 NetscapePluginWidget(WebBaseNetscapePluginView *view)
1358 : PluginWidget(view)
1362 virtual void handleEvent(Event*)
1364 Frame* frame = Frame::frameForWidget(this);
1368 NSEvent* event = frame->eventHandler()->currentNSEvent();
1369 if ([event type] == NSMouseMoved)
1370 [(WebBaseNetscapePluginView *)platformWidget() handleMouseMoved:event];
1375 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1377 static Class netscapePluginViewClass()
1379 #if USE(PLUGIN_HOST_PROCESS)
1380 return [WebHostedNetscapePluginView class];
1382 return [WebNetscapePluginView class];
1386 Widget* WebFrameLoaderClient::createPlugin(const IntSize& size, HTMLPlugInElement* element, const KURL& url,
1387 const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1389 BEGIN_BLOCK_OBJC_EXCEPTIONS;
1391 ASSERT(paramNames.size() == paramValues.size());
1395 WebView *webView = getWebView(m_webFrame.get());
1396 SEL selector = @selector(webView:plugInViewWithArguments:);
1399 if ([[webView UIDelegate] respondsToSelector:selector]) {
1400 NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:kit(paramValues) forKeys:kit(paramNames)];
1401 NSDictionary *arguments = [[NSDictionary alloc] initWithObjectsAndKeys:
1402 attributes, WebPlugInAttributesKey,
1403 [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
1404 [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
1405 kit(element), WebPlugInContainingElementKey,
1406 URL, WebPlugInBaseURLKey, // URL might be nil, so add it last
1409 NSView *view = CallUIDelegate(webView, selector, arguments);
1411 [attributes release];
1412 [arguments release];
1415 return new PluginWidget(view);
1419 WebBasePluginPackage *pluginPackage;
1420 if (mimeType.isEmpty()) {
1422 pluginPackage = nil;
1424 MIMEType = mimeType;
1425 pluginPackage = [webView _pluginForMIMEType:mimeType];
1428 NSString *extension = [[URL path] pathExtension];
1429 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1430 // don't allow proxy plug-in selection by file extension
1431 if (element->hasTagName(videoTag) || element->hasTagName(audioTag))
1435 if (!pluginPackage && [extension length] != 0) {
1436 pluginPackage = [webView _pluginForExtension:extension];
1437 if (pluginPackage) {
1438 NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
1439 if ([newMIMEType length] != 0)
1440 MIMEType = newMIMEType;
1446 Document* document = core(m_webFrame.get())->document();
1447 NSURL *baseURL = document->baseURL();
1448 if (pluginPackage) {
1449 if ([pluginPackage isKindOfClass:[WebPluginPackage class]])
1450 view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, kit(paramNames), kit(paramValues), baseURL, kit(element), loadManually);
1452 #if ENABLE(NETSCAPE_PLUGIN_API)
1453 else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
1454 WebBaseNetscapePluginView *pluginView = [[[netscapePluginViewClass() alloc]
1455 initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1456 pluginPackage:(WebNetscapePluginPackage *)pluginPackage
1460 attributeKeys:kit(paramNames)
1461 attributeValues:kit(paramValues)
1462 loadManually:loadManually
1463 element:element] autorelease];
1465 return new NetscapePluginWidget(pluginView);
1469 errorCode = WebKitErrorCannotFindPlugIn;
1471 if (!errorCode && !view)
1472 errorCode = WebKitErrorCannotLoadPlugIn;
1475 NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
1477 pluginPageURL:document->completeURL(parseURL(parameterValue(paramNames, paramValues, "pluginspage")))
1478 pluginName:[pluginPackage name]
1480 WebNullPluginView *nullView = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1481 error:error DOMElement:kit(element)] autorelease];
1487 return new PluginWidget(view);
1489 END_BLOCK_OBJC_EXCEPTIONS;
1494 void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
1496 BEGIN_BLOCK_OBJC_EXCEPTIONS;
1498 WebHTMLRepresentation *representation = (WebHTMLRepresentation *)[[m_webFrame.get() _dataSource] representation];
1500 NSView *pluginView = pluginWidget->platformWidget();
1502 #if ENABLE(NETSCAPE_PLUGIN_API)
1503 if ([pluginView isKindOfClass:[WebNetscapePluginView class]])
1504 [representation _redirectDataToManualLoader:(WebNetscapePluginView *)pluginView forPluginView:pluginView];
1509 WebHTMLView *documentView = (WebHTMLView *)[[m_webFrame.get() frameView] documentView];
1510 ASSERT([documentView isKindOfClass:[WebHTMLView class]]);
1511 [representation _redirectDataToManualLoader:[documentView _pluginController] forPluginView:pluginView];
1514 END_BLOCK_OBJC_EXCEPTIONS;
1517 Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const KURL& baseURL,
1518 const Vector<String>& paramNames, const Vector<String>& paramValues)
1520 BEGIN_BLOCK_OBJC_EXCEPTIONS;
1524 NSString *MIMEType = @"application/x-java-applet";
1526 WebView *webView = getWebView(m_webFrame.get());
1528 WebBasePluginPackage *pluginPackage = [webView _pluginForMIMEType:MIMEType];
1530 if (pluginPackage) {
1531 if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
1532 // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes.
1533 NSMutableArray *names = kit(paramNames);
1534 NSMutableArray *values = kit(paramValues);
1535 if (parameterValue(paramNames, paramValues, "width").isNull()) {
1536 [names addObject:@"width"];
1537 [values addObject:[NSString stringWithFormat:@"%d", size.width()]];
1539 if (parameterValue(paramNames, paramValues, "height").isNull()) {
1540 [names addObject:@"height"];
1541 [values addObject:[NSString stringWithFormat:@"%d", size.height()]];
1543 view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, names, values, baseURL, kit(element), NO);
1545 #if ENABLE(NETSCAPE_PLUGIN_API)
1546 else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
1547 view = [[[netscapePluginViewClass() alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1548 pluginPackage:(WebNetscapePluginPackage *)pluginPackage
1552 attributeKeys:kit(paramNames)
1553 attributeValues:kit(paramValues)
1555 element:element] autorelease];
1557 ASSERT_NOT_REACHED();
1563 NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorJavaUnavailable
1566 pluginName:[pluginPackage name]
1568 view = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1569 error:error DOMElement:kit(element)] autorelease];
1574 return new PluginWidget(view);
1576 END_BLOCK_OBJC_EXCEPTIONS;
1578 return new PluginWidget;
1581 String WebFrameLoaderClient::overrideMediaType() const
1583 NSString* overrideType = [getWebView(m_webFrame.get()) mediaStyle];
1585 return overrideType;
1589 void WebFrameLoaderClient::documentElementAvailable() {
1592 void WebFrameLoaderClient::windowObjectCleared()
1594 Frame *frame = core(m_webFrame.get());
1595 ScriptController *script = frame->script();
1596 WebView *webView = getWebView(m_webFrame.get());
1597 WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
1598 if (implementations->didClearWindowObjectForFrameFunc) {
1599 CallFrameLoadDelegate(implementations->didClearWindowObjectForFrameFunc, webView, @selector(webView:didClearWindowObject:forFrame:),
1600 script->windowScriptObject(), m_webFrame.get());
1601 } else if (implementations->windowScriptObjectAvailableFunc) {
1602 CallFrameLoadDelegate(implementations->windowScriptObjectAvailableFunc, webView, @selector(webView:windowScriptObjectAvailable:),
1603 script->windowScriptObject());
1606 if ([webView scriptDebugDelegate]) {
1607 [m_webFrame.get() _detachScriptDebugger];
1608 [m_webFrame.get() _attachScriptDebugger];
1612 void WebFrameLoaderClient::registerForIconNotification(bool listen)
1614 [[m_webFrame.get() webView] _registerForIconNotification:listen];
1617 void WebFrameLoaderClient::didPerformFirstNavigation() const
1619 WebPreferences *preferences = [[m_webFrame.get() webView] preferences];
1620 if ([preferences automaticallyDetectsCacheModel] && [preferences cacheModel] < WebCacheModelDocumentBrowser)
1621 [preferences setCacheModel:WebCacheModelDocumentBrowser];
1624 #if ENABLE(MAC_JAVA_BRIDGE)
1625 jobject WebFrameLoaderClient::javaApplet(NSView* view)
1627 if ([view respondsToSelector:@selector(webPlugInGetApplet)])
1628 return [view webPlugInGetApplet];
1630 // Compatibility with older versions of Java.
1631 // FIXME: Do we still need this?
1632 if ([view respondsToSelector:@selector(pollForAppletInWindow:)])
1633 return [view pollForAppletInWindow:[[m_webFrame.get() frameView] window]];
1639 @implementation WebFramePolicyListener
1643 JSC::initializeThreading();
1644 #ifndef BUILDING_ON_TIGER
1645 WebCoreObjCFinalizeOnMainThread(self);
1649 - (id)initWithWebCoreFrame:(Frame*)frame
1669 if (WebCoreObjCScheduleDeallocateOnMainThread([WebFramePolicyListener class], self))
1679 ASSERT_MAIN_THREAD();
1685 - (void)receivedPolicyDecision:(PolicyAction)action
1687 RefPtr<Frame> frame = adoptRef(m_frame);
1690 static_cast<WebFrameLoaderClient*>(frame->loader()->client())->receivedPolicyDecison(action);
1695 [self receivedPolicyDecision:PolicyIgnore];
1700 [self receivedPolicyDecision:PolicyDownload];
1705 [self receivedPolicyDecision:PolicyUse];
1710 [self receivedPolicyDecision:PolicyUse];