[iOS] Upstream PLATFORM(IOS) changes to Source/WebKit/
[WebKit-https.git] / Source / WebKit / mac / WebCoreSupport / WebFrameLoaderClient.mm
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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. 
16  *
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.
27  */
28
29 #import "WebFrameLoaderClient.h"
30
31 // Terrible hack; lets us get at the WebFrame private structure.
32 #define private public
33 #import "WebFrame.h"
34 #undef private
35
36 #import "DOMElementInternal.h"
37 #import "DOMHTMLFormElementInternal.h"
38 #import "WebBackForwardList.h"
39 #import "WebCachedFramePlatformData.h"
40 #import "WebChromeClient.h"
41 #import "WebDataSourceInternal.h"
42 #import "WebDelegateImplementationCaching.h"
43 #import "WebDocumentInternal.h"
44 #import "WebDocumentLoaderMac.h"
45 #import "WebDownloadInternal.h"
46 #import "WebDynamicScrollBarsViewInternal.h"
47 #import "WebElementDictionary.h"
48 #import "WebFormDelegate.h"
49 #import "WebFrameInternal.h"
50 #import "WebFrameLoadDelegate.h"
51 #import "WebFrameNetworkingContext.h"
52 #import "WebFrameViewInternal.h"
53 #import "WebHTMLRepresentationPrivate.h"
54 #import "WebHTMLViewInternal.h"
55 #import "WebHistoryInternal.h"
56 #import "WebHistoryItemInternal.h"
57 #import "WebIconDatabaseInternal.h"
58 #import "WebKitErrorsPrivate.h"
59 #import "WebKitLogging.h"
60 #import "WebKitNSStringExtras.h"
61 #import "WebNSURLExtras.h"
62 #import "WebNavigationData.h"
63 #import "WebNetscapePluginPackage.h"
64 #import "WebNetscapePluginView.h"
65 #import "WebPanelAuthenticationHandler.h"
66 #import "WebPluginController.h"
67 #import "WebPluginPackage.h"
68 #import "WebPluginViewFactoryPrivate.h"
69 #import "WebPolicyDelegate.h"
70 #import "WebPolicyDelegatePrivate.h"
71 #import "WebPreferences.h"
72 #import "WebResourceLoadDelegate.h"
73 #import "WebScriptWorldInternal.h"
74 #import "WebSecurityOriginInternal.h"
75 #import "WebUIDelegate.h"
76 #import "WebUIDelegatePrivate.h"
77 #import "WebViewInternal.h"
78 #import <JavaScriptCore/JSContextInternal.h>
79 #import <WebCore/AuthenticationCF.h>
80 #import <WebCore/AuthenticationMac.h>
81 #import <WebCore/BackForwardController.h>
82 #import <WebCore/BlockExceptions.h>
83 #import <WebCore/CachedFrame.h>
84 #import <WebCore/Chrome.h>
85 #import <WebCore/Document.h>
86 #import <WebCore/DocumentLoader.h>
87 #import <WebCore/EventHandler.h>
88 #import <WebCore/FocusController.h>
89 #import <WebCore/FormState.h>
90 #import <WebCore/FrameLoader.h>
91 #import <WebCore/FrameLoaderStateMachine.h>
92 #import <WebCore/FrameLoaderTypes.h>
93 #import <WebCore/FrameTree.h>
94 #import <WebCore/FrameView.h>
95 #import <WebCore/HTMLAppletElement.h>
96 #import <WebCore/HTMLFormElement.h>
97 #import <WebCore/HTMLFrameElement.h>
98 #import <WebCore/HTMLFrameOwnerElement.h>
99 #import <WebCore/HTMLHeadElement.h>
100 #import <WebCore/HTMLNames.h>
101 #import <WebCore/HTMLParserIdioms.h>
102 #import <WebCore/HTMLPlugInElement.h>
103 #import <WebCore/HistoryController.h>
104 #import <WebCore/HistoryItem.h>
105 #import <WebCore/HitTestResult.h>
106 #import <WebCore/IconDatabase.h>
107 #import <WebCore/LoaderNSURLExtras.h>
108 #import <WebCore/MIMETypeRegistry.h>
109 #import <WebCore/MainFrame.h>
110 #import <WebCore/MouseEvent.h>
111 #import <WebCore/Page.h>
112 #import <WebCore/PluginViewBase.h>
113 #import <WebCore/ProtectionSpace.h>
114 #import <WebCore/ResourceError.h>
115 #import <WebCore/ResourceHandle.h>
116 #import <WebCore/ResourceLoader.h>
117 #import <WebCore/ResourceRequest.h>
118 #import <WebCore/ScriptController.h>
119 #import <WebCore/SharedBuffer.h>
120 #import <WebCore/WebCoreObjCExtras.h>
121 #import <WebCore/WebScriptObjectPrivate.h>
122 #import <WebCore/Widget.h>
123 #import <WebKit/DOMElement.h>
124 #import <WebKit/DOMHTMLFormElement.h>
125 #import <WebKitSystemInterface.h>
126 #import <runtime/InitializeThreading.h>
127 #import <wtf/MainThread.h>
128 #import <wtf/PassRefPtr.h>
129 #import <wtf/RunLoop.h>
130 #import <wtf/text/WTFString.h>
131
132 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
133 #import <WebCore/HTMLMediaElement.h>
134 #endif
135
136 #if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
137 #import "NetscapePluginHostManager.h"
138 #import "WebHostedNetscapePluginView.h"
139 #endif
140
141 #if PLATFORM(IOS)
142 #import <WebCore/HTMLPlugInImageElement.h>
143 #import <WebCore/WAKClipView.h>
144 #import <WebCore/WAKScrollView.h>
145 #import <WebCore/WAKViewPrivate.h>
146 #import <WebCore/WAKWindow.h>
147 #import <WebCore/WebCoreThreadMessage.h>
148 #import "WebKitVersionChecks.h"
149 #import "WebMailDelegate.h"
150 #import "WebUIKitDelegate.h"
151 #endif
152
153 using namespace WebCore;
154 using namespace HTMLNames;
155
156 #if PLATFORM(IOS)
157 @interface WebHTMLView (Init)
158 - (id)initWithFrame:(CGRect)frame;
159 @end
160 #endif
161
162 // For backwards compatibility with older WebKit plug-ins.
163 NSString *WebPluginBaseURLKey = @"WebPluginBaseURL";
164 NSString *WebPluginAttributesKey = @"WebPluginAttributes";
165 NSString *WebPluginContainerKey = @"WebPluginContainer";
166
167 @interface WebFramePolicyListener : NSObject <WebPolicyDecisionListener, WebFormSubmissionListener> {
168     RefPtr<Frame> _frame;
169     FramePolicyFunction _policyFunction;
170 }
171
172 - (id)initWithFrame:(Frame*)frame policyFunction:(FramePolicyFunction)policyFunction;
173 - (void)invalidate;
174
175 @end
176
177 static inline WebDataSource *dataSource(DocumentLoader* loader)
178 {
179     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
180 }
181
182 #if !PLATFORM(IOS)
183 // Quirk for the Apple Dictionary application.
184 //
185 // If a top level frame has a <script> element in its <head> for a script named MainPageJavaScript.js,
186 // then for that frame's document, ignore changes to the scrolling attribute of frames. That script
187 // has a bug in it where it sets the scrolling attribute on frames, and that erroneous scrolling
188 // attribute needs to be ignored to avoid showing extra scroll bars in the window.
189 // This quirk can be removed when Apple Dictionary is fixed (see <rdar://problem/6471058>).
190
191 static void applyAppleDictionaryApplicationQuirkNonInlinePart(WebFrameLoaderClient* client, const ResourceRequest& request)
192 {
193     if (!request.url().isLocalFile())
194         return;
195     if (!request.url().string().endsWith("MainPageJavaScript.js"))
196         return;
197     Frame* frame = core(client->webFrame());
198     if (!frame)
199         return;
200     if (frame->tree().parent())
201         return;
202     Document* document = frame->document();
203     if (!document)
204         return;
205     HTMLHeadElement* head = document->head();
206     if (!head)
207         return;
208     for (Node* c = head->firstChild(); c; c = c->nextSibling()) {
209         if (c->hasTagName(scriptTag) && toElement(c)->getAttribute(srcAttr) == "MainPageJavaScript.js") {
210             document->setFrameElementsShouldIgnoreScrolling(true);
211             return;
212         }
213     }
214 }
215 #endif
216
217 static inline void applyAppleDictionaryApplicationQuirk(WebFrameLoaderClient* client, const ResourceRequest& request)
218 {
219 #if !PLATFORM(IOS)
220     // Use a one-time-initialized global variable so we can quickly determine there's nothing to do in
221     // all applications other than Apple Dictionary.
222     static bool isAppleDictionary = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Dictionary"];
223     if (isAppleDictionary)
224         applyAppleDictionaryApplicationQuirkNonInlinePart(client, request);
225 #endif
226 }
227
228 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame *webFrame)
229     : m_webFrame(webFrame)
230 {
231 }
232
233 void WebFrameLoaderClient::frameLoaderDestroyed()
234 {
235     [m_webFrame.get() _clearCoreFrame];
236     delete this;
237 }
238
239 bool WebFrameLoaderClient::hasWebView() const
240 {
241     return [m_webFrame.get() webView] != nil;
242 }
243
244 void WebFrameLoaderClient::makeRepresentation(DocumentLoader* loader)
245 {
246     [dataSource(loader) _makeRepresentation];
247 }
248
249 bool WebFrameLoaderClient::hasHTMLView() const
250 {
251     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
252     return [view isKindOfClass:[WebHTMLView class]];
253 }
254
255 void WebFrameLoaderClient::forceLayout()
256 {
257     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
258 #if PLATFORM(IOS)
259     // This gets called to lay out a page restored from the page cache.
260     // To work around timing problems with UIKit, restore fixed 
261     // layout settings here.
262     WebView* webView = getWebView(m_webFrame.get());
263     bool isMainFrame = [webView mainFrame] == m_webFrame.get();
264     Frame* coreFrame = core(m_webFrame.get());
265     if (isMainFrame && coreFrame->view()) {
266         IntSize newSize([webView _fixedLayoutSize]);
267         coreFrame->view()->setFixedLayoutSize(newSize);
268         coreFrame->view()->setUseFixedLayout(!newSize.isEmpty()); 
269     }
270 #endif
271     [view setNeedsLayout:YES];
272     [view layout];
273 }
274
275 #if PLATFORM(IOS)
276 void WebFrameLoaderClient::forceLayoutWithoutRecalculatingStyles()
277 {
278     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
279     // This gets called to lay out a page restored from the page cache.
280     // To work around timing problems with UIKit, restore fixed 
281     // layout settings here.
282     WebView* webView = getWebView(m_webFrame.get());
283     bool isMainFrame = [webView mainFrame] == m_webFrame.get();
284     Frame* coreFrame = core(m_webFrame.get());
285     if (isMainFrame && coreFrame->view()) {
286         IntSize newSize([webView _fixedLayoutSize]);
287         coreFrame->view()->setFixedLayoutSize(newSize);
288         coreFrame->view()->setUseFixedLayout(!newSize.isEmpty());
289     }
290     [view setNeedsLayout:YES];
291     [view layout];
292 }
293 #endif
294
295 void WebFrameLoaderClient::forceLayoutForNonHTML()
296 {
297     WebFrameView *thisView = m_webFrame->_private->webFrameView;
298     NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
299     ASSERT(thisDocumentView != nil);
300     
301     // Tell the just loaded document to layout.  This may be necessary
302     // for non-html content that needs a layout message.
303     if (!([[m_webFrame.get() _dataSource] _isDocumentHTML])) {
304         [thisDocumentView setNeedsLayout:YES];
305         [thisDocumentView layout];
306         [thisDocumentView setNeedsDisplay:YES];
307     }
308 }
309
310 void WebFrameLoaderClient::setCopiesOnScroll()
311 {
312     [[[m_webFrame->_private->webFrameView _scrollView] contentView] setCopiesOnScroll:YES];
313 }
314
315 void WebFrameLoaderClient::detachedFromParent2()
316 {
317     //remove any NetScape plugins that are children of this frame because they are about to be detached
318     WebView *webView = getWebView(m_webFrame.get());
319 #if !PLATFORM(IOS)
320     [webView removePluginInstanceViewsFor:(m_webFrame.get())];
321 #endif
322     [m_webFrame->_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
323
324     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
325     if (implementations->didRemoveFrameFromHierarchyFunc)
326         CallFrameLoadDelegate(implementations->didRemoveFrameFromHierarchyFunc, webView, @selector(webView:didRemoveFrameFromHierarchy:), m_webFrame.get());
327 }
328
329 void WebFrameLoaderClient::detachedFromParent3()
330 {
331     [m_webFrame->_private->webFrameView release];
332     m_webFrame->_private->webFrameView = nil;
333 }
334
335 void WebFrameLoaderClient::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, const ResourceRequest& request, const ResourceResponse& response)
336 {
337     WebView *webView = getWebView(m_webFrame.get());
338
339     if (!documentLoader->mainResourceLoader()) {
340         // The resource has already been cached, start a new download.
341         WebDownload *webDownload = [[WebDownload alloc] initWithRequest:request.nsURLRequest(UpdateHTTPBody) delegate:[webView downloadDelegate]];
342         [webDownload autorelease];
343         return;
344     }
345
346     ResourceHandle* handle = documentLoader->mainResourceLoader()->handle();
347
348 #if USE(CFNETWORK)
349     ASSERT([WebDownload respondsToSelector:@selector(_downloadWithLoadingCFURLConnection:request:response:delegate:proxy:)]);
350     CFURLConnectionRef connection = handle->connection();
351     [WebDownload _downloadWithLoadingCFURLConnection:connection
352                                                                      request:request.cfURLRequest(UpdateHTTPBody)
353                                                                     response:response.cfURLResponse()
354                                                                     delegate:[webView downloadDelegate]
355                                                                        proxy:nil];
356
357     // Release the connection since the NSURLDownload (actually CFURLDownload) will retain the connection and use it.
358     handle->releaseConnectionForDownload();
359     CFRelease(connection);
360 #else
361     [WebDownload _downloadWithLoadingConnection:handle->connection()
362                                                                 request:request.nsURLRequest(UpdateHTTPBody)
363                                                                response:response.nsURLResponse()
364                                                                delegate:[webView downloadDelegate]
365                                                                   proxy:nil];
366 #endif
367 }
368
369 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length)
370 {
371     applyAppleDictionaryApplicationQuirk(this, request);
372
373     WebView *webView = getWebView(m_webFrame.get());
374     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
375 #if PLATFORM(IOS)
376     if (implementations->webThreadDidLoadResourceFromMemoryCacheFunc) {
377         CallResourceLoadDelegateInWebThread(implementations->webThreadDidLoadResourceFromMemoryCacheFunc, webView, @selector(webThreadWebView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), request.nsURLRequest(UpdateHTTPBody), response.nsURLResponse(), length, dataSource(loader));
378         return true;
379     } 
380 #endif
381     if (!implementations->didLoadResourceFromMemoryCacheFunc)
382         return false;
383
384     CallResourceLoadDelegate(implementations->didLoadResourceFromMemoryCacheFunc, webView, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), request.nsURLRequest(UpdateHTTPBody), response.nsURLResponse(), length, dataSource(loader));
385     return true;
386 }
387
388 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
389 {
390     WebView *webView = getWebView(m_webFrame.get());
391     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
392
393     id object = nil;
394     BOOL shouldRelease = NO;
395 #if PLATFORM(IOS)
396     if (implementations->webThreadIdentifierForRequestFunc) {
397         object = CallResourceLoadDelegateInWebThread(implementations->webThreadIdentifierForRequestFunc, webView, @selector(webThreadWebView:identifierForInitialRequest:fromDataSource:), request.nsURLRequest(UpdateHTTPBody), dataSource(loader));
398     } else
399 #endif
400     if (implementations->identifierForRequestFunc)
401         object = CallResourceLoadDelegate(implementations->identifierForRequestFunc, webView, @selector(webView:identifierForInitialRequest:fromDataSource:), request.nsURLRequest(UpdateHTTPBody), dataSource(loader));
402     else {
403         object = [[NSObject alloc] init];
404         shouldRelease = YES;
405     }
406
407     [webView _addObject:object forIdentifier:identifier];
408
409     if (shouldRelease)
410         [object release];
411 }
412
413 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
414 {
415     applyAppleDictionaryApplicationQuirk(this, request);
416
417     WebView *webView = getWebView(m_webFrame.get());
418     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
419
420     if (redirectResponse.isNull())
421         static_cast<WebDocumentLoaderMac*>(loader)->increaseLoadCount(identifier);
422
423     NSURLRequest *currentURLRequest = request.nsURLRequest(UpdateHTTPBody);
424     NSURLRequest *newURLRequest = currentURLRequest;
425 #if PLATFORM(IOS)
426     bool isMainResourceRequest = request.isMainResourceRequest();
427     if (implementations->webThreadWillSendRequestFunc) {
428         newURLRequest = (NSURLRequest *)CallResourceLoadDelegateInWebThread(implementations->webThreadWillSendRequestFunc, webView, @selector(webThreadWebView:resource:willSendRequest:redirectResponse:fromDataSource:), [webView _objectForIdentifier:identifier], currentURLRequest, redirectResponse.nsURLResponse(), dataSource(loader));
429     } else
430 #endif
431     if (implementations->willSendRequestFunc)
432         newURLRequest = (NSURLRequest *)CallResourceLoadDelegate(implementations->willSendRequestFunc, webView, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:), [webView _objectForIdentifier:identifier], currentURLRequest, redirectResponse.nsURLResponse(), dataSource(loader));
433
434     if (newURLRequest != currentURLRequest)
435         request = newURLRequest;
436 #if PLATFORM(IOS)
437     request.setMainResourceRequest(isMainResourceRequest);
438 #endif
439 }
440
441 bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader* loader, unsigned long identifier)
442 {
443     WebView *webView = getWebView(m_webFrame.get());
444     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
445
446     if (implementations->shouldUseCredentialStorageFunc) {
447         if (id resource = [webView _objectForIdentifier:identifier])
448             return CallResourceLoadDelegateReturningBoolean(NO, implementations->shouldUseCredentialStorageFunc, webView, @selector(webView:resource:shouldUseCredentialStorageForDataSource:), resource, dataSource(loader));
449     }
450
451     return true;
452 }
453
454 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
455 {
456     WebView *webView = getWebView(m_webFrame.get());
457     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
458
459     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
460
461     if (implementations->didReceiveAuthenticationChallengeFunc) {
462         if (id resource = [webView _objectForIdentifier:identifier]) {
463             CallResourceLoadDelegate(implementations->didReceiveAuthenticationChallengeFunc, webView, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
464             return;
465         }
466     }
467
468 #if !PLATFORM(IOS)
469     NSWindow *window = [webView hostWindow] ? [webView hostWindow] : [webView window];
470     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:webChallenge window:window];
471 #endif
472 }
473
474 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
475 bool WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace(DocumentLoader* loader, unsigned long identifier, const ProtectionSpace& protectionSpace)
476 {
477     WebView *webView = getWebView(m_webFrame.get());
478     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
479     
480     NSURLProtectionSpace *webProtectionSpace = mac(protectionSpace);
481     
482     if (implementations->canAuthenticateAgainstProtectionSpaceFunc) {
483         if (id resource = [webView _objectForIdentifier:identifier]) {
484             return CallResourceLoadDelegateReturningBoolean(NO, implementations->canAuthenticateAgainstProtectionSpaceFunc, webView, @selector(webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:), resource, webProtectionSpace, dataSource(loader));
485         }
486     }
487
488     // If our resource load delegate doesn't handle the question, then only send authentication
489     // challenges for pre-iOS-3.0, pre-10.6 protection spaces.  This is the same as the default implementation
490     // in CFNetwork.
491     return (protectionSpace.authenticationScheme() < ProtectionSpaceAuthenticationSchemeClientCertificateRequested);
492 }
493 #endif
494
495 #if PLATFORM(IOS)
496 RetainPtr<CFDictionaryRef> WebFrameLoaderClient::connectionProperties(DocumentLoader* loader, unsigned long identifier)
497 {
498     WebView *webView = getWebView(m_webFrame.get());
499     id resource = [webView _objectForIdentifier:identifier];
500     if (!resource)
501         return nullptr;
502
503     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
504     if (implementations->connectionPropertiesFunc)
505         return (CFDictionaryRef)CallResourceLoadDelegate(implementations->connectionPropertiesFunc, webView, @selector(webView:connectionPropertiesForResource:dataSource:), resource, dataSource(loader));
506
507     return nullptr;
508 }
509 #endif
510
511 bool WebFrameLoaderClient::shouldPaintBrokenImage(const URL& imageURL) const
512 {
513     WebView *webView = getWebView(m_webFrame.get());
514     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
515
516     if (implementations->shouldPaintBrokenImageForURLFunc) {
517         NSURL* url = imageURL;
518         return CallResourceLoadDelegateReturningBoolean(YES, implementations->shouldPaintBrokenImageForURLFunc, webView, @selector(webView:shouldPaintBrokenImageForURL:), url);
519     }
520     return true;
521 }
522
523 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge&challenge)
524 {
525     WebView *webView = getWebView(m_webFrame.get());
526     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
527     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
528
529     if (implementations->didCancelAuthenticationChallengeFunc) {
530         if (id resource = [webView _objectForIdentifier:identifier]) {
531             CallResourceLoadDelegate(implementations->didCancelAuthenticationChallengeFunc, webView, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
532             return;
533         }
534     }
535
536 #if !PLATFORM(IOS)
537     [(WebPanelAuthenticationHandler *)[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:webChallenge];
538 #endif
539 }
540
541 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
542 {
543     WebView *webView = getWebView(m_webFrame.get());
544     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
545
546 #if PLATFORM(IOS)
547     if (implementations->webThreadDidReceiveResponseFunc) {
548         if (id resource = [webView _objectForIdentifier:identifier])
549             CallResourceLoadDelegateInWebThread(implementations->webThreadDidReceiveResponseFunc, webView, @selector(webThreadWebView:resource:didReceiveResponse:fromDataSource:), resource, response.nsURLResponse(), dataSource(loader));
550         
551     } else
552 #endif
553     if (implementations->didReceiveResponseFunc) {
554         if (id resource = [webView _objectForIdentifier:identifier])
555             CallResourceLoadDelegate(implementations->didReceiveResponseFunc, webView, @selector(webView:resource:didReceiveResponse:fromDataSource:), resource, response.nsURLResponse(), dataSource(loader));
556     }
557 }
558
559 NSCachedURLResponse* WebFrameLoaderClient::willCacheResponse(DocumentLoader* loader, unsigned long identifier, NSCachedURLResponse* response) const
560 {
561     WebView *webView = getWebView(m_webFrame.get());
562     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
563
564 #if PLATFORM(IOS)
565     if (implementations->webThreadWillCacheResponseFunc) {
566         if (id resource = [webView _objectForIdentifier:identifier])
567             return CallResourceLoadDelegateInWebThread(implementations->webThreadWillCacheResponseFunc, webView, @selector(webThreadWebView:resource:willCacheResponse:fromDataSource:), resource, response, dataSource(loader));
568         
569     } else
570 #endif
571     if (implementations->willCacheResponseFunc) {
572         if (id resource = [webView _objectForIdentifier:identifier])
573             return CallResourceLoadDelegate(implementations->willCacheResponseFunc, webView, @selector(webView:resource:willCacheResponse:fromDataSource:), resource, response, dataSource(loader));
574     }
575
576     return response;
577 }
578
579 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int dataLength)
580 {
581     WebView *webView = getWebView(m_webFrame.get());
582     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
583 #if PLATFORM(IOS)
584     if (implementations->webThreadDidReceiveContentLengthFunc) {
585         if (id resource = [webView _objectForIdentifier:identifier])
586             CallResourceLoadDelegateInWebThread(implementations->webThreadDidReceiveContentLengthFunc, webView, @selector(webThreadWebView:resource:didReceiveContentLength:fromDataSource:), resource, (NSInteger)dataLength, dataSource(loader));
587     } else
588 #endif
589     if (implementations->didReceiveContentLengthFunc) {
590         if (id resource = [webView _objectForIdentifier:identifier])
591             CallResourceLoadDelegate(implementations->didReceiveContentLengthFunc, webView, @selector(webView:resource:didReceiveContentLength:fromDataSource:), resource, (NSInteger)dataLength, dataSource(loader));
592     }
593 }
594
595 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
596 {
597     WebView *webView = getWebView(m_webFrame.get());
598     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
599
600 #if PLATFORM(IOS)
601     if (implementations->webThreadDidFinishLoadingFromDataSourceFunc) {
602         if (id resource = [webView _objectForIdentifier:identifier])
603             CallResourceLoadDelegateInWebThread(implementations->webThreadDidFinishLoadingFromDataSourceFunc, webView, @selector(webThreadWebView:resource:didFinishLoadingFromDataSource:), resource, dataSource(loader));
604     } else
605 #endif
606
607     if (implementations->didFinishLoadingFromDataSourceFunc) {
608         if (id resource = [webView _objectForIdentifier:identifier])
609             CallResourceLoadDelegate(implementations->didFinishLoadingFromDataSourceFunc, webView, @selector(webView:resource:didFinishLoadingFromDataSource:), resource, dataSource(loader));
610     }
611
612     [webView _removeObjectForIdentifier:identifier];
613
614     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
615 }
616
617 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
618 {
619     WebView *webView = getWebView(m_webFrame.get());
620     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
621
622 #if PLATFORM(IOS)
623     if (implementations->webThreadDidFailLoadingWithErrorFromDataSourceFunc) {
624         if (id resource = [webView _objectForIdentifier:identifier])
625             CallResourceLoadDelegateInWebThread(implementations->webThreadDidFailLoadingWithErrorFromDataSourceFunc, webView, @selector(webThreadWebView:resource:didFailLoadingWithError:fromDataSource:), resource, (NSError *)error, dataSource(loader));
626     } else
627 #endif
628     if (implementations->didFailLoadingWithErrorFromDataSourceFunc) {
629         if (id resource = [webView _objectForIdentifier:identifier])
630             CallResourceLoadDelegate(implementations->didFailLoadingWithErrorFromDataSourceFunc, webView, @selector(webView:resource:didFailLoadingWithError:fromDataSource:), resource, (NSError *)error, dataSource(loader));
631     }
632
633     [webView _removeObjectForIdentifier:identifier];
634
635     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
636 }
637
638 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
639 {
640     WebView *webView = getWebView(m_webFrame.get());
641     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
642     if (implementations->didHandleOnloadEventsForFrameFunc)
643         CallFrameLoadDelegate(implementations->didHandleOnloadEventsForFrameFunc, webView, @selector(webView:didHandleOnloadEventsForFrame:), m_webFrame.get());
644 }
645
646 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
647 {
648     m_webFrame->_private->provisionalURL = core(m_webFrame.get())->loader().provisionalDocumentLoader()->url().string();
649
650     WebView *webView = getWebView(m_webFrame.get());
651     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
652     if (implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc)
653         CallFrameLoadDelegate(implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc, webView, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:), m_webFrame.get());
654 }
655
656 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
657 {
658     WebView *webView = getWebView(m_webFrame.get());
659     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
660     if (implementations->didCancelClientRedirectForFrameFunc)
661         CallFrameLoadDelegate(implementations->didCancelClientRedirectForFrameFunc, webView, @selector(webView:didCancelClientRedirectForFrame:), m_webFrame.get());
662 }
663
664 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const URL& url, double delay, double fireDate)
665 {
666     WebView *webView = getWebView(m_webFrame.get());
667     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
668     if (implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc) {
669         NSURL *cocoaURL = url;
670         CallFrameLoadDelegate(implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc, webView, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:), cocoaURL, delay, [NSDate dateWithTimeIntervalSince1970:fireDate], m_webFrame.get());
671     }
672 }
673
674 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
675 {
676     m_webFrame->_private->url = core(m_webFrame.get())->document()->url().string();
677
678     WebView *webView = getWebView(m_webFrame.get());
679     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
680     if (implementations->didChangeLocationWithinPageForFrameFunc)
681         CallFrameLoadDelegate(implementations->didChangeLocationWithinPageForFrameFunc, webView, @selector(webView:didChangeLocationWithinPageForFrame:), m_webFrame.get());
682 #if PLATFORM(IOS)
683     [[webView _UIKitDelegateForwarder] webView:webView didChangeLocationWithinPageForFrame:m_webFrame.get()];
684 #endif
685 }
686
687 void WebFrameLoaderClient::dispatchDidPushStateWithinPage()
688 {
689     m_webFrame->_private->url = core(m_webFrame.get())->document()->url().string();
690
691     WebView *webView = getWebView(m_webFrame.get());
692     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
693     if (implementations->didPushStateWithinPageForFrameFunc)
694         CallFrameLoadDelegate(implementations->didPushStateWithinPageForFrameFunc, webView, @selector(webView:didPushStateWithinPageForFrame:), m_webFrame.get());
695 }
696
697 void WebFrameLoaderClient::dispatchDidReplaceStateWithinPage()
698 {
699     m_webFrame->_private->url = core(m_webFrame.get())->document()->url().string();
700
701     WebView *webView = getWebView(m_webFrame.get());
702     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
703     if (implementations->didReplaceStateWithinPageForFrameFunc)
704         CallFrameLoadDelegate(implementations->didReplaceStateWithinPageForFrameFunc, webView, @selector(webView:didReplaceStateWithinPageForFrame:), m_webFrame.get());
705 }
706
707 void WebFrameLoaderClient::dispatchDidPopStateWithinPage()
708 {
709     m_webFrame->_private->url = core(m_webFrame.get())->document()->url().string();
710
711     WebView *webView = getWebView(m_webFrame.get());
712     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
713     if (implementations->didPopStateWithinPageForFrameFunc)
714         CallFrameLoadDelegate(implementations->didPopStateWithinPageForFrameFunc, webView, @selector(webView:didPopStateWithinPageForFrame:), m_webFrame.get());
715 }
716
717 void WebFrameLoaderClient::dispatchWillClose()
718 {
719     WebView *webView = getWebView(m_webFrame.get());   
720     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
721     if (implementations->willCloseFrameFunc)
722         CallFrameLoadDelegate(implementations->willCloseFrameFunc, webView, @selector(webView:willCloseFrame:), m_webFrame.get());
723 #if PLATFORM(IOS)
724     [[webView _UIKitDelegateForwarder] webView:webView willCloseFrame:m_webFrame.get()];
725 #endif
726 }
727
728 void WebFrameLoaderClient::dispatchDidReceiveIcon()
729 {
730 #if ENABLE(ICONDATABASE)
731     WebView *webView = getWebView(m_webFrame.get());   
732     ASSERT(m_webFrame == [webView mainFrame]);
733     [webView _dispatchDidReceiveIconFromWebFrame:m_webFrame.get()];
734 #endif
735 }
736
737 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
738 {
739     ASSERT(!m_webFrame->_private->provisionalURL);
740     m_webFrame->_private->provisionalURL = core(m_webFrame.get())->loader().provisionalDocumentLoader()->url().string();
741
742     WebView *webView = getWebView(m_webFrame.get());
743 #if !PLATFORM(IOS)
744     [webView _didStartProvisionalLoadForFrame:m_webFrame.get()];
745 #endif
746
747 #if PLATFORM(IOS)
748     [[webView _UIKitDelegateForwarder] webView:webView didStartProvisionalLoadForFrame:m_webFrame.get()];
749 #endif
750
751     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
752     if (implementations->didStartProvisionalLoadForFrameFunc)
753         CallFrameLoadDelegate(implementations->didStartProvisionalLoadForFrameFunc, webView, @selector(webView:didStartProvisionalLoadForFrame:), m_webFrame.get());
754 }
755
756 void WebFrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title)
757 {
758     WebView *webView = getWebView(m_webFrame.get());   
759     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
760     if (implementations->didReceiveTitleForFrameFunc)
761         // FIXME: use direction of title.
762         CallFrameLoadDelegate(implementations->didReceiveTitleForFrameFunc, webView, @selector(webView:didReceiveTitle:forFrame:), (NSString *)title.string(), m_webFrame.get());
763 }
764
765 void WebFrameLoaderClient::dispatchDidChangeIcons(WebCore::IconType)
766 {
767      // FIXME: Implement this to allow container to update favicon.
768 }
769
770 void WebFrameLoaderClient::dispatchDidCommitLoad()
771 {
772     // Tell the client we've committed this URL.
773     ASSERT([m_webFrame->_private->webFrameView documentView] != nil);
774     
775     WebView *webView = getWebView(m_webFrame.get());   
776     [webView _didCommitLoadForFrame:m_webFrame.get()];
777
778     m_webFrame->_private->url = m_webFrame->_private->provisionalURL;
779     m_webFrame->_private->provisionalURL = nullptr;
780
781 #if PLATFORM(IOS)
782     [[webView _UIKitDelegateForwarder] webView:webView didCommitLoadForFrame:m_webFrame.get()];
783 #endif
784     
785     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
786     if (implementations->didCommitLoadForFrameFunc)
787         CallFrameLoadDelegate(implementations->didCommitLoadForFrameFunc, webView, @selector(webView:didCommitLoadForFrame:), m_webFrame.get());
788 }
789
790 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
791 {
792     m_webFrame->_private->provisionalURL = nullptr;
793
794     WebView *webView = getWebView(m_webFrame.get());
795 #if !PLATFORM(IOS)
796     [webView _didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
797 #endif
798
799     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
800     if (implementations->didFailProvisionalLoadWithErrorForFrameFunc)
801         CallFrameLoadDelegate(implementations->didFailProvisionalLoadWithErrorForFrameFunc, webView, @selector(webView:didFailProvisionalLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
802
803     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
804 }
805
806 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
807 {
808     ASSERT(!m_webFrame->_private->provisionalURL);
809
810     WebView *webView = getWebView(m_webFrame.get());
811 #if !PLATFORM(IOS)
812     [webView _didFailLoadWithError:error forFrame:m_webFrame.get()];
813 #endif
814
815     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
816     if (implementations->didFailLoadWithErrorForFrameFunc)
817         CallFrameLoadDelegate(implementations->didFailLoadWithErrorForFrameFunc, webView, @selector(webView:didFailLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
818 #if PLATFORM(IOS)
819     [[webView _UIKitDelegateForwarder] webView:webView didFailLoadWithError:((NSError *)error) forFrame:m_webFrame.get()];
820 #endif
821
822     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
823 }
824
825 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
826 {
827     WebView *webView = getWebView(m_webFrame.get());
828
829 #if PLATFORM(IOS)
830     id webThreadDel = [webView _webMailDelegate];
831     if ([webThreadDel respondsToSelector:@selector(_webthread_webView:didFinishDocumentLoadForFrame:)]) {
832         [webThreadDel _webthread_webView:webView didFinishDocumentLoadForFrame:m_webFrame.get()];
833     }
834 #endif
835
836     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
837     if (implementations->didFinishDocumentLoadForFrameFunc)
838         CallFrameLoadDelegate(implementations->didFinishDocumentLoadForFrameFunc, webView, @selector(webView:didFinishDocumentLoadForFrame:), m_webFrame.get());
839 }
840
841 void WebFrameLoaderClient::dispatchDidFinishLoad()
842 {
843     ASSERT(!m_webFrame->_private->provisionalURL);
844
845     WebView *webView = getWebView(m_webFrame.get());
846 #if !PLATFORM(IOS)
847     [webView _didFinishLoadForFrame:m_webFrame.get()];
848 #else
849     [[webView _UIKitDelegateForwarder] webView:webView didFinishLoadForFrame:m_webFrame.get()];
850
851     id webThreadDel = [webView _webMailDelegate];
852     if ([webThreadDel respondsToSelector:@selector(_webthread_webView:didFinishLoadForFrame:)]) {
853         [webThreadDel _webthread_webView:webView didFinishLoadForFrame:m_webFrame.get()];
854     }
855 #endif
856
857     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
858     if (implementations->didFinishLoadForFrameFunc)
859         CallFrameLoadDelegate(implementations->didFinishLoadForFrameFunc, webView, @selector(webView:didFinishLoadForFrame:), m_webFrame.get());
860
861     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];
862 }
863
864 void WebFrameLoaderClient::dispatchDidLayout(LayoutMilestones milestones)
865 {
866     WebView *webView = getWebView(m_webFrame.get());
867     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
868
869 #if PLATFORM(IOS)
870     if (implementations->webThreadDidLayoutFunc)
871         CallFrameLoadDelegateInWebThread(implementations->webThreadDidLayoutFunc, webView, @selector(webThreadWebView:didLayout:), kitLayoutMilestones(milestones));
872 #else
873     if (implementations->didLayoutFunc)
874         CallFrameLoadDelegate(implementations->didLayoutFunc, webView, @selector(webView:didLayout:), kitLayoutMilestones(milestones));
875 #endif
876
877     if (milestones & DidFirstLayout) {
878         // FIXME: We should consider removing the old didFirstLayout API since this is doing double duty with the
879         // new didLayout API.
880         if (implementations->didFirstLayoutInFrameFunc)
881             CallFrameLoadDelegate(implementations->didFirstLayoutInFrameFunc, webView, @selector(webView:didFirstLayoutInFrame:), m_webFrame.get());
882
883 #if PLATFORM(IOS)
884         [[webView _UIKitDelegateForwarder] webView:webView didFirstLayoutInFrame:m_webFrame.get()];
885 #endif
886  
887         // See WebFrameLoaderClient::provisionalLoadStarted.
888         WebDynamicScrollBarsView *scrollView = [m_webFrame->_private->webFrameView _scrollView];
889         if ([getWebView(m_webFrame.get()) drawsBackground])
890             [scrollView setDrawsBackground:YES];
891 #if !PLATFORM(IOS)
892         [scrollView setVerticalScrollElasticity:NSScrollElasticityAutomatic];
893         [scrollView setHorizontalScrollElasticity:NSScrollElasticityAutomatic];
894 #endif
895     }
896
897     if (milestones & DidFirstVisuallyNonEmptyLayout) {
898         // FIXME: We should consider removing the old didFirstVisuallyNonEmptyLayoutForFrame API since this is doing
899         // double duty with the new didLayout API.
900         if (implementations->didFirstVisuallyNonEmptyLayoutInFrameFunc)
901             CallFrameLoadDelegate(implementations->didFirstVisuallyNonEmptyLayoutInFrameFunc, webView, @selector(webView:didFirstVisuallyNonEmptyLayoutInFrame:), m_webFrame.get());
902 #if PLATFORM(IOS)
903         if ([webView mainFrame] == m_webFrame.get())
904             [[webView _UIKitDelegateForwarder] webView:webView didFirstVisuallyNonEmptyLayoutInFrame:m_webFrame.get()];
905 #endif
906     }
907 }
908
909 Frame* WebFrameLoaderClient::dispatchCreatePage(const NavigationAction&)
910 {
911     WebView *currentWebView = getWebView(m_webFrame.get());
912     NSDictionary *features = [[NSDictionary alloc] init];
913     WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView 
914                                                 createWebViewWithRequest:nil
915                                                           windowFeatures:features];
916     [features release];
917     
918 #if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
919     if (newWebView)
920         WebKit::NetscapePluginHostManager::shared().didCreateWindow();
921 #endif
922         
923     return core([newWebView mainFrame]);
924 }
925
926 void WebFrameLoaderClient::dispatchShow()
927 {
928     WebView *webView = getWebView(m_webFrame.get());
929     [[webView _UIDelegateForwarder] webViewShow:webView];
930 }
931
932 void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, FramePolicyFunction function)
933 {
934     WebView *webView = getWebView(m_webFrame.get());
935
936     [[webView _policyDelegateForwarder] webView:webView
937                         decidePolicyForMIMEType:response.mimeType()
938                                         request:request.nsURLRequest(UpdateHTTPBody)
939                                           frame:m_webFrame.get()
940                                decisionListener:setUpPolicyListener(std::move(function)).get()];
941 }
942
943 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, FramePolicyFunction function)
944 {
945     WebView *webView = getWebView(m_webFrame.get());
946     [[webView _policyDelegateForwarder] webView:webView
947             decidePolicyForNewWindowAction:actionDictionary(action, formState)
948                                    request:request.nsURLRequest(UpdateHTTPBody)
949                               newFrameName:frameName
950                           decisionListener:setUpPolicyListener(std::move(function)).get()];
951 }
952
953 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const NavigationAction& action, const ResourceRequest& request, PassRefPtr<FormState> formState, FramePolicyFunction function)
954 {
955     WebView *webView = getWebView(m_webFrame.get());
956     [[webView _policyDelegateForwarder] webView:webView
957                 decidePolicyForNavigationAction:actionDictionary(action, formState)
958                                         request:request.nsURLRequest(UpdateHTTPBody)
959                                           frame:m_webFrame.get()
960                                decisionListener:setUpPolicyListener(std::move(function)).get()];
961 }
962
963 void WebFrameLoaderClient::cancelPolicyCheck()
964 {
965     [m_policyListener invalidate];
966     m_policyListener = nullptr;
967 }
968
969 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
970 {
971     WebView *webView = getWebView(m_webFrame.get());
972     [[webView _policyDelegateForwarder] webView:webView unableToImplementPolicyWithError:error frame:m_webFrame.get()];    
973 }
974
975 static NSDictionary *makeFormFieldValuesDictionary(FormState* formState)
976 {
977     const StringPairVector& textFieldValues = formState->textFieldValues();
978     size_t size = textFieldValues.size();
979     NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:size];
980     for (size_t i = 0; i < size; ++i)
981         [dictionary setObject:textFieldValues[i].second forKey:textFieldValues[i].first];
982
983     return [dictionary autorelease];
984 }
985
986 void WebFrameLoaderClient::dispatchWillSendSubmitEvent(PassRefPtr<WebCore::FormState> formState)
987 {
988     id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate];
989     if (!formDelegate)
990         return;
991
992     DOMHTMLFormElement *formElement = kit(formState->form());
993     NSDictionary *values = makeFormFieldValuesDictionary(formState.get());
994     CallFormDelegate(getWebView(m_webFrame.get()), @selector(willSendSubmitEventToForm:inFrame:withValues:), formElement, m_webFrame.get(), values);
995 }
996
997 void WebFrameLoaderClient::dispatchWillSubmitForm(PassRefPtr<FormState> formState, FramePolicyFunction function)
998 {
999     id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate];
1000     if (!formDelegate) {
1001         function(PolicyUse);
1002         return;
1003     }
1004
1005     NSDictionary *values = makeFormFieldValuesDictionary(formState.get());
1006     CallFormDelegate(getWebView(m_webFrame.get()), @selector(frame:sourceFrame:willSubmitForm:withValues:submissionListener:), m_webFrame.get(), kit(formState->sourceDocument()->frame()), kit(formState->form()), values, setUpPolicyListener(std::move(function)).get());
1007 }
1008
1009 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader)
1010 {
1011     [dataSource(loader) _revertToProvisionalState];
1012 }
1013
1014 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
1015 {
1016     [dataSource(loader) _setMainDocumentError:error];
1017 }
1018
1019 #if !PLATFORM(IOS)
1020 void WebFrameLoaderClient::willChangeEstimatedProgress()
1021 {
1022     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebEstimatedProgressKey];
1023 }
1024
1025 void WebFrameLoaderClient::didChangeEstimatedProgress()
1026 {
1027     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebEstimatedProgressKey];
1028 }
1029 #endif
1030
1031 void WebFrameLoaderClient::postProgressStartedNotification()
1032 {
1033 #if !PLATFORM(IOS)
1034     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:getWebView(m_webFrame.get())];
1035 #else
1036     WebThreadPostNotification(WebViewProgressStartedNotification, getWebView(m_webFrame.get()), nil);
1037 #endif
1038 }
1039
1040 void WebFrameLoaderClient::postProgressEstimateChangedNotification()
1041 {
1042 #if !PLATFORM(IOS)
1043     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:getWebView(m_webFrame.get())];
1044 #else
1045     WebView *webView = getWebView(m_webFrame.get());
1046     NSNumber *progress = [NSNumber numberWithFloat:[webView estimatedProgress]];
1047     CGColorRef bodyBackgroundColor = [[webView mainFrame] _bodyBackgroundColor];
1048
1049     // Use a CFDictionary so we can add the CGColorRef without compile errors. And then thanks to
1050     // toll-free bridging we can pass the CFDictionary as an NSDictionary to postNotification.
1051     CFMutableDictionaryRef userInfo = CFDictionaryCreateMutable(kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1052     CFDictionaryAddValue(userInfo, WebViewProgressEstimatedProgressKey, progress);
1053     if (bodyBackgroundColor)
1054         CFDictionaryAddValue(userInfo, WebViewProgressBackgroundColorKey, bodyBackgroundColor);
1055
1056     WebThreadPostNotification(WebViewProgressEstimateChangedNotification, webView, (NSDictionary *) userInfo);
1057     CFRelease(userInfo);
1058 #endif
1059 }
1060
1061 #if !PLATFORM(IOS)
1062 void WebFrameLoaderClient::postProgressFinishedNotification()
1063 {
1064     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:getWebView(m_webFrame.get())];
1065 }
1066 #endif
1067
1068 void WebFrameLoaderClient::setMainFrameDocumentReady(bool ready)
1069 {
1070     [getWebView(m_webFrame.get()) setMainFrameDocumentReady:ready];
1071 }
1072
1073 void WebFrameLoaderClient::startDownload(const ResourceRequest& request, const String& /* suggestedName */)
1074 {
1075     // FIXME: Should download full request.
1076     [getWebView(m_webFrame.get()) _downloadURL:request.url()];
1077 }
1078
1079 void WebFrameLoaderClient::willChangeTitle(DocumentLoader* loader)
1080 {
1081 #if !PLATFORM(IOS)
1082     // FIXME: Should do this only in main frame case, right?
1083     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebMainFrameTitleKey];
1084 #endif
1085 }
1086
1087 void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader)
1088 {
1089 #if !PLATFORM(IOS)
1090     // FIXME: Should do this only in main frame case, right?
1091     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebMainFrameTitleKey];
1092 #endif
1093 }
1094
1095 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
1096 {
1097     NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO];
1098     [dataSource(loader) _receivedData:nsData];
1099     [nsData release];
1100 }
1101
1102 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
1103 {
1104     [dataSource(loader) _finishedLoading];
1105 }
1106
1107 static inline NSString *nilOrNSString(const String& string)
1108 {
1109     if (string.isNull())
1110         return nil;
1111     return string;
1112 }
1113
1114 void WebFrameLoaderClient::updateGlobalHistory()
1115 {
1116     WebView* view = getWebView(m_webFrame.get());
1117     DocumentLoader* loader = core(m_webFrame.get())->loader().documentLoader();
1118 #if PLATFORM(IOS)
1119     if (loader->urlForHistory() == blankURL())
1120         return;
1121 #endif
1122
1123     if ([view historyDelegate]) {
1124         WebHistoryDelegateImplementationCache* implementations = WebViewGetHistoryDelegateImplementations(view);
1125         if (implementations->navigatedFunc) {
1126             WebNavigationData *data = [[WebNavigationData alloc] initWithURLString:loader->url()
1127                                                                              title:nilOrNSString(loader->title().string())
1128                                                                    originalRequest:loader->originalRequestCopy().nsURLRequest(UpdateHTTPBody)
1129                                                                           response:loader->response().nsURLResponse()
1130                                                                  hasSubstituteData:loader->substituteData().isValid()
1131                                                               clientRedirectSource:loader->clientRedirectSourceForHistory()];
1132
1133             CallHistoryDelegate(implementations->navigatedFunc, view, @selector(webView:didNavigateWithNavigationData:inFrame:), data, m_webFrame.get());
1134             [data release];
1135         }
1136     
1137         return;
1138     }
1139
1140     [[WebHistory optionalSharedHistory] _visitedURL:loader->urlForHistory() 
1141                                           withTitle:loader->title().string()
1142                                              method:loader->originalRequestCopy().httpMethod()
1143                                          wasFailure:loader->urlForHistoryReflectsFailure()
1144                                  increaseVisitCount:!loader->clientRedirectSourceForHistory()]; // Do not increase visit count due to navigations that were not initiated by the user directly, avoiding growth from programmatic reloads.
1145 }
1146
1147 void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
1148 {
1149     WebView* view = getWebView(m_webFrame.get());
1150     WebHistoryDelegateImplementationCache* implementations = [view historyDelegate] ? WebViewGetHistoryDelegateImplementations(view) : 0;
1151     
1152     DocumentLoader* loader = core(m_webFrame.get())->loader().documentLoader();
1153     ASSERT(loader->unreachableURL().isEmpty());
1154
1155     if (!loader->clientRedirectSourceForHistory().isNull()) {
1156         if (implementations) {
1157             if (implementations->clientRedirectFunc) {
1158                 CallHistoryDelegate(implementations->clientRedirectFunc, view, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:), 
1159                     m_webFrame->_private->url.get(), loader->clientRedirectDestinationForHistory(), m_webFrame.get());
1160             }
1161         } else if (WebHistoryItem *item = [[WebHistory optionalSharedHistory] _itemForURLString:loader->clientRedirectSourceForHistory()])
1162             core(item)->addRedirectURL(loader->clientRedirectDestinationForHistory());
1163     }
1164
1165     if (!loader->serverRedirectSourceForHistory().isNull()) {
1166         if (implementations) {
1167             if (implementations->serverRedirectFunc) {
1168                 CallHistoryDelegate(implementations->serverRedirectFunc, view, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:), 
1169                     loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_webFrame.get());
1170             }
1171         } else if (WebHistoryItem *item = [[WebHistory optionalSharedHistory] _itemForURLString:loader->serverRedirectSourceForHistory()])
1172             core(item)->addRedirectURL(loader->serverRedirectDestinationForHistory());
1173     }
1174 }
1175
1176 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
1177 {
1178     WebView* view = getWebView(m_webFrame.get());
1179     WebHistoryItem *webItem = kit(item);
1180     
1181     return [[view _policyDelegateForwarder] webView:view shouldGoToHistoryItem:webItem];
1182 }
1183
1184 bool WebFrameLoaderClient::shouldStopLoadingForHistoryItem(HistoryItem* item) const
1185 {
1186     return true;
1187 }
1188
1189 void WebFrameLoaderClient::updateGlobalHistoryItemForPage()
1190 {
1191     HistoryItem* historyItem = 0;
1192
1193     if (Page* page = core(m_webFrame.get())->page()) {
1194         if (!page->settings().privateBrowsingEnabled())
1195             historyItem = page->backForward().currentItem();
1196     }
1197
1198     WebView *webView = getWebView(m_webFrame.get());
1199     [webView _setGlobalHistoryItem:historyItem];
1200 }
1201
1202 void WebFrameLoaderClient::didDisplayInsecureContent()
1203 {
1204     WebView *webView = getWebView(m_webFrame.get());   
1205     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
1206     if (implementations->didDisplayInsecureContentFunc)
1207         CallFrameLoadDelegate(implementations->didDisplayInsecureContentFunc, webView, @selector(webViewDidDisplayInsecureContent:));
1208 }
1209
1210 void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin* origin, const URL& insecureURL)
1211 {
1212     WebView *webView = getWebView(m_webFrame.get());   
1213     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
1214     if (implementations->didRunInsecureContentFunc) {
1215         RetainPtr<WebSecurityOrigin> webSecurityOrigin = adoptNS([[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:origin]);
1216         CallFrameLoadDelegate(implementations->didRunInsecureContentFunc, webView, @selector(webView:didRunInsecureContent:), webSecurityOrigin.get());
1217     }
1218 }
1219
1220 void WebFrameLoaderClient::didDetectXSS(const URL& insecureURL, bool didBlockEntirePage)
1221 {
1222     WebView *webView = getWebView(m_webFrame.get());   
1223     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
1224     if (implementations->didDetectXSSFunc) {
1225         // FIXME: must pass didBlockEntirePage if we want to do more on mac than just pass tests.
1226         NSURL* insecureNSURL = insecureURL;
1227         CallFrameLoadDelegate(implementations->didDetectXSSFunc, webView, @selector(webView:didDetectXSS:), insecureNSURL);
1228     }
1229 }
1230
1231 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
1232 {
1233     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url()];
1234 }
1235     
1236 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
1237 {
1238     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotUseRestrictedPort URL:request.url()];
1239 }
1240
1241 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1242 {
1243     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotShowURL URL:request.url()];
1244 }
1245
1246 ResourceError WebFrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request)
1247 {
1248     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:request.url()];
1249 }
1250
1251 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1252 {
1253     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:WebKitErrorCannotShowMIMEType URL:response.url()];
1254 }
1255
1256 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1257 {
1258     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:response.url()];    
1259 }
1260
1261 ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1262 {
1263     NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInWillHandleLoad
1264                                                     contentURL:response.url()
1265                                                  pluginPageURL:nil
1266                                                     pluginName:nil
1267                                                       MIMEType:response.mimeType()];
1268     return [error autorelease];
1269 }
1270
1271 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
1272 {
1273     // FIXME: Needs to check domain.
1274     // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent
1275     // loading plugin content twice.  See <rdar://problem/4258008>
1276     return error.errorCode() != NSURLErrorCancelled && error.errorCode() != WebKitErrorPlugInWillHandleLoad;
1277 }
1278
1279 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const
1280 {
1281     return [WebView _canHandleRequest:request.nsURLRequest(UpdateHTTPBody) forMainFrame:core(m_webFrame.get())->isMainFrame()];
1282 }
1283
1284 bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const
1285 {
1286     return [getWebView(m_webFrame.get()) _canShowMIMEType:MIMEType];
1287 }
1288
1289 bool WebFrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const
1290 {
1291     return [WebView canShowMIMETypeAsHTML:MIMEType];
1292 }
1293
1294 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const
1295 {
1296     return [WebView _representationExistsForURLScheme:URLScheme];
1297 }
1298
1299 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const
1300 {
1301     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
1302 }
1303
1304 void WebFrameLoaderClient::frameLoadCompleted()
1305 {
1306     // Note: Can be called multiple times.
1307
1308     // See WebFrameLoaderClient::provisionalLoadStarted.
1309     if ([getWebView(m_webFrame.get()) drawsBackground])
1310         [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:YES];
1311 }
1312
1313 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem* item)
1314 {
1315     if (!item)
1316         return;
1317
1318 #if PLATFORM(IOS)
1319     // Let UIKit handle the scroll point for the main frame.
1320     WebFrame *webFrame = m_webFrame.get();
1321     WebView *webView = getWebView(webFrame);   
1322     if (webFrame == [webView mainFrame]) {
1323         [[webView _UIKitDelegateForwarder] webView:webView saveStateToHistoryItem:kit(item) forFrame:webFrame];
1324         return;
1325     }
1326 #endif                    
1327     
1328     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
1329
1330     // we might already be detached when this is called from detachFromParent, in which
1331     // case we don't want to override real data earlier gathered with (0,0)
1332     if ([docView superview] && [docView conformsToProtocol:@protocol(_WebDocumentViewState)])
1333         item->setViewState([(id <_WebDocumentViewState>)docView viewState]);
1334 }
1335
1336 void WebFrameLoaderClient::restoreViewState()
1337 {
1338     HistoryItem* currentItem = core(m_webFrame.get())->loader().history().currentItem();
1339     ASSERT(currentItem);
1340
1341     // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
1342     // One counterexample is <rdar://problem/4917290>
1343     // For now, to cover this issue in release builds, there is no technical harm to returning
1344     // early and from a user standpoint - as in the above radar - the previous page load failed 
1345     // so there *is* no scroll state to restore!
1346     if (!currentItem)
1347         return;
1348
1349 #if PLATFORM(IOS)
1350     // Let UIKit handle the scroll point for the main frame.
1351     WebFrame *webFrame = m_webFrame.get();
1352     WebView *webView = getWebView(webFrame);   
1353     if (webFrame == [webView mainFrame]) {
1354         [[webView _UIKitDelegateForwarder] webView:webView restoreStateFromHistoryItem:kit(currentItem) forFrame:webFrame force:NO];
1355         return;
1356     }
1357 #endif                    
1358     
1359     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
1360     if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {        
1361         id state = currentItem->viewState();
1362         if (state) {
1363             [(id <_WebDocumentViewState>)docView setViewState:state];
1364         }
1365     }
1366 }
1367
1368 void WebFrameLoaderClient::provisionalLoadStarted()
1369 {    
1370     // Tell the scroll view not to draw a background so we can leave the contents of
1371     // the old page showing during the beginning of the loading process.
1372
1373     // This will stay set to NO until:
1374     //    1) The load gets far enough along: WebFrameLoader::frameLoadCompleted.
1375     //    2) The window is resized: -[WebFrameView setFrameSize:].
1376     // or 3) The view is moved out of the window: -[WebFrameView viewDidMoveToWindow].
1377     // Please keep the comments in these four functions in agreement with each other.
1378
1379     WebDynamicScrollBarsView *scrollView = [m_webFrame->_private->webFrameView _scrollView];
1380     [scrollView setDrawsBackground:NO];
1381 #if !PLATFORM(IOS)
1382     [scrollView setVerticalScrollElasticity:NSScrollElasticityNone];
1383     [scrollView setHorizontalScrollElasticity:NSScrollElasticityNone];
1384 #endif
1385 }
1386
1387 void WebFrameLoaderClient::didFinishLoad()
1388 {
1389     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];    
1390 }
1391
1392 void WebFrameLoaderClient::prepareForDataSourceReplacement()
1393 {
1394     if (![m_webFrame.get() _dataSource]) {
1395         ASSERT(!core(m_webFrame.get())->tree().childCount());
1396         return;
1397     }
1398     
1399 #if !PLATFORM(IOS)
1400     // Make sure that any work that is triggered by resigning first reponder can get done.
1401     // The main example where this came up is the textDidEndEditing that is sent to the
1402     // FormsDelegate (3223413). We need to do this before _detachChildren, since that will
1403     // remove the views as a side-effect of freeing the frame, at which point we can't
1404     // post the FormDelegate messages.
1405     //
1406     // Note that this can also take FirstResponder away from a child of our frameView that
1407     // is not in a child frame's view.  This is OK because we are in the process
1408     // of loading new content, which will blow away all editors in this top frame, and if
1409     // a non-editor is firstReponder it will not be affected by endEditingFor:.
1410     // Potentially one day someone could write a DocView whose editors were not all
1411     // replaced by loading new content, but that does not apply currently.
1412     NSView *frameView = m_webFrame->_private->webFrameView;
1413     NSWindow *window = [frameView window];
1414     NSResponder *firstResp = [window firstResponder];
1415     if ([firstResp isKindOfClass:[NSView class]] && [(NSView *)firstResp isDescendantOf:frameView])
1416         [window endEditingFor:firstResp];
1417 #endif
1418 }
1419
1420 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
1421 {
1422     RefPtr<WebDocumentLoaderMac> loader = WebDocumentLoaderMac::create(request, substituteData);
1423
1424     WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader.get()];
1425     loader->setDataSource(dataSource, getWebView(m_webFrame.get()));
1426     [dataSource release];
1427
1428     return loader.release();
1429 }
1430
1431 void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const URL& url)
1432 {
1433     WebView* view = getWebView(m_webFrame.get());
1434     
1435     if ([view historyDelegate]) {
1436         WebHistoryDelegateImplementationCache* implementations = WebViewGetHistoryDelegateImplementations(view);
1437         // FIXME: use direction of title.
1438         if (implementations->setTitleFunc)
1439             CallHistoryDelegate(implementations->setTitleFunc, view, @selector(webView:updateHistoryTitle:forURL:inFrame:), (NSString *)title.string(), (NSString *)url, m_webFrame.get());
1440         else if (implementations->deprecatedSetTitleFunc)
1441             CallHistoryDelegate(implementations->deprecatedSetTitleFunc, view, @selector(webView:updateHistoryTitle:forURL:), (NSString *)title.string(), (NSString *)url);
1442
1443         return;
1444     }
1445     
1446     NSURL* nsURL = url;
1447     nsURL = [nsURL _webkit_canonicalize];
1448     if(!nsURL)
1449         return;
1450 #if PLATFORM(IOS)
1451     if ([[nsURL absoluteString] isEqualToString:@"about:blank"])
1452         return;
1453 #endif
1454     NSString *titleNSString = title.string();
1455        
1456     [[[WebHistory optionalSharedHistory] itemForURL:nsURL] setTitle:titleNSString];
1457 }
1458
1459 void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1460 {
1461     OwnPtr<WebCachedFramePlatformData> webPlatformData = adoptPtr(new WebCachedFramePlatformData([m_webFrame->_private->webFrameView documentView]));
1462     cachedFrame->setCachedFramePlatformData(webPlatformData.release());
1463
1464 #if PLATFORM(IOS)
1465     // At this point we know this frame is going to be cached. Stop all plugins.
1466     WebView *webView = getWebView(m_webFrame.get());
1467     [webView _stopAllPlugInsForPageCache];
1468 #endif
1469 }
1470
1471 void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame)
1472 {
1473     WebCachedFramePlatformData* platformData = reinterpret_cast<WebCachedFramePlatformData*>(cachedFrame->cachedFramePlatformData());
1474     NSView <WebDocumentView> *cachedView = platformData->webDocumentView();
1475     ASSERT(cachedView != nil);
1476     ASSERT(cachedFrame->documentLoader());
1477     [cachedView setDataSource:dataSource(cachedFrame->documentLoader())];
1478     
1479 #if !PLATFORM(IOS)
1480     // clean up webkit plugin instances before WebHTMLView gets freed.
1481     WebView *webView = getWebView(m_webFrame.get());
1482     [webView removePluginInstanceViewsFor:(m_webFrame.get())];
1483 #endif
1484     
1485     [m_webFrame->_private->webFrameView _setDocumentView:cachedView];
1486 }
1487
1488 #if PLATFORM(IOS)
1489 void WebFrameLoaderClient::didRestoreFrameHierarchyForCachedFrame()
1490 {
1491     // When entering the PageCache the Document is detached and the plugin view may
1492     // have cleaned itself up (removing its webview and layer references). Now, when
1493     // restoring the page we want to recreate whatever is necessary.
1494     WebView *webView = getWebView(m_webFrame.get());
1495     [webView _restorePlugInsFromCache];
1496 }
1497 #endif
1498
1499 void WebFrameLoaderClient::transitionToCommittedForNewPage()
1500 {
1501     WebView *webView = getWebView(m_webFrame.get());
1502     WebDataSource *dataSource = [m_webFrame.get() _dataSource];
1503
1504 #if PLATFORM(IOS)
1505     bool willProduceHTMLView;
1506     // Fast path that skips initialization of objc class objects.
1507     if ([dataSource _documentLoader]->responseMIMEType() == "text/html")
1508         willProduceHTMLView = true;
1509     else
1510         willProduceHTMLView = [m_webFrame->_private->webFrameView _viewClassForMIMEType:[dataSource _responseMIMEType]] == [WebHTMLView class];
1511 #else
1512     // FIXME (Viewless): I assume we want the equivalent of this optimization for viewless mode too.
1513     bool willProduceHTMLView = [m_webFrame->_private->webFrameView _viewClassForMIMEType:[dataSource _responseMIMEType]] == [WebHTMLView class];
1514 #endif
1515     bool canSkipCreation = core(m_webFrame.get())->loader().stateMachine()->committingFirstRealLoad() && willProduceHTMLView;
1516     if (canSkipCreation) {
1517         [[m_webFrame->_private->webFrameView documentView] setDataSource:dataSource];
1518         return;
1519     }
1520
1521 #if !PLATFORM(IOS)
1522     // Don't suppress scrollbars before the view creation if we're making the view for a non-HTML view.
1523     if (!willProduceHTMLView)
1524         [[m_webFrame->_private->webFrameView _scrollView] setScrollBarsSuppressed:NO repaintOnUnsuppress:NO];
1525     
1526     // clean up webkit plugin instances before WebHTMLView gets freed.
1527     [webView removePluginInstanceViewsFor:(m_webFrame.get())];
1528     
1529     NSView <WebDocumentView> *documentView = [m_webFrame->_private->webFrameView _makeDocumentViewForDataSource:dataSource];
1530 #else
1531     NSView <WebDocumentView> *documentView = nil;
1532
1533     // Fast path that skips initialization of objc class objects.
1534     if (willProduceHTMLView) {
1535         documentView = [[WebHTMLView alloc] initWithFrame:[m_webFrame->_private->webFrameView bounds]];
1536         [m_webFrame->_private->webFrameView _setDocumentView:documentView];
1537         [documentView release];
1538     } else
1539         documentView = [m_webFrame->_private->webFrameView _makeDocumentViewForDataSource:dataSource];
1540 #endif
1541     if (!documentView)
1542         return;
1543
1544     // FIXME: Could we skip some of this work for a top-level view that is not a WebHTMLView?
1545
1546     // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
1547     Frame* coreFrame = core(m_webFrame.get());
1548     Page* page = coreFrame->page();
1549     bool isMainFrame = coreFrame->isMainFrame();
1550     if (isMainFrame && coreFrame->view())
1551         coreFrame->view()->setParentVisible(false);
1552     coreFrame->setView(0);
1553     RefPtr<FrameView> coreView = FrameView::create(*coreFrame);
1554     coreFrame->setView(coreView);
1555
1556     [m_webFrame.get() _updateBackgroundAndUpdatesWhileOffscreen];
1557     [m_webFrame->_private->webFrameView _install];
1558
1559     if (isMainFrame) {
1560 #if PLATFORM(IOS)
1561         coreView->setDelegatesScrolling(true);
1562 #endif
1563         coreView->setParentVisible(true);
1564     }
1565
1566     // Call setDataSource on the document view after it has been placed in the view hierarchy.
1567     // This what we for the top-level view, so should do this for views in subframes as well.
1568     [documentView setDataSource:dataSource];
1569
1570     // The following is a no-op for WebHTMLRepresentation, but for custom document types
1571     // like the ones that Safari uses for bookmarks it is the only way the DocumentLoader
1572     // will get the proper title.
1573     if (DocumentLoader* documentLoader = [dataSource _documentLoader])
1574         documentLoader->setTitle(StringWithDirection([dataSource pageTitle], LTR));
1575
1576     if (HTMLFrameOwnerElement* owner = coreFrame->ownerElement())
1577         coreFrame->view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
1578         
1579     // If the document view implicitly became first responder, make sure to set the focused frame properly.
1580     if ([[documentView window] firstResponder] == documentView) {
1581         page->focusController().setFocusedFrame(coreFrame);
1582         page->focusController().setFocused(true);
1583     }
1584 }
1585
1586 void WebFrameLoaderClient::didSaveToPageCache()
1587 {
1588 }
1589
1590 void WebFrameLoaderClient::didRestoreFromPageCache()
1591 {
1592 #if PLATFORM(IOS)
1593     WebView *webView = getWebView(m_webFrame.get());
1594     if ([webView mainFrame] == m_webFrame.get())
1595         [[webView _UIKitDelegateForwarder] webViewDidRestoreFromPageCache:webView];
1596 #endif
1597 }
1598
1599 void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool)
1600 {
1601 }
1602
1603 RetainPtr<WebFramePolicyListener> WebFrameLoaderClient::setUpPolicyListener(FramePolicyFunction function)
1604 {
1605     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
1606     [m_policyListener invalidate];
1607
1608     m_policyListener = adoptNS([[WebFramePolicyListener alloc] initWithFrame:core(m_webFrame.get()) policyFunction:function]);
1609
1610     return m_policyListener;
1611 }
1612
1613 String WebFrameLoaderClient::userAgent(const URL& url)
1614 {
1615     WebView *webView = getWebView(m_webFrame.get());
1616     ASSERT(webView);
1617
1618     // We should never get here with nil for the WebView unless there is a bug somewhere else.
1619     // But if we do, it's better to return the empty string than just crashing on the spot.
1620     // Most other call sites are tolerant of nil because of Objective-C behavior, but this one
1621     // is not because the return value of _userAgentForURL is a const URL&.
1622     if (!webView)
1623         return emptyString();
1624
1625     return [webView _userAgentString];
1626 }
1627
1628 static const MouseEvent* findMouseEvent(const Event* event)
1629 {
1630     for (const Event* e = event; e; e = e->underlyingEvent())
1631         if (e->isMouseEvent())
1632             return static_cast<const MouseEvent*>(e);
1633     return 0;
1634 }
1635
1636 NSDictionary *WebFrameLoaderClient::actionDictionary(const NavigationAction& action, PassRefPtr<FormState> formState) const
1637 {
1638     unsigned modifierFlags = 0;
1639     const Event* event = action.event();
1640 #if !PLATFORM(IOS)
1641     if (const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event))) {
1642         if (keyStateEvent->ctrlKey())
1643             modifierFlags |= NSControlKeyMask;
1644         if (keyStateEvent->altKey())
1645             modifierFlags |= NSAlternateKeyMask;
1646         if (keyStateEvent->shiftKey())
1647             modifierFlags |= NSShiftKeyMask;
1648         if (keyStateEvent->metaKey())
1649             modifierFlags |= NSCommandKeyMask;
1650     }
1651 #else
1652     // No modifier flags on iOS right now
1653     modifierFlags = 0;
1654 #endif
1655
1656     NSURL *originalURL = action.url();
1657
1658     NSMutableDictionary *result = [NSMutableDictionary dictionaryWithObjectsAndKeys:
1659         [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1660         [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1661         originalURL, WebActionOriginalURLKey,
1662         nil];
1663
1664     if (const MouseEvent* mouseEvent = findMouseEvent(event)) {
1665         WebElementDictionary *element = [[WebElementDictionary alloc]
1666             initWithHitTestResult:core(m_webFrame.get())->eventHandler().hitTestResultAtPoint(mouseEvent->absoluteLocation())];
1667         [result setObject:element forKey:WebActionElementKey];
1668         [element release];
1669
1670         [result setObject:[NSNumber numberWithInt:mouseEvent->button()] forKey:WebActionButtonKey];
1671     }
1672
1673     if (formState) {
1674         ASSERT(formState->form());
1675         [result setObject:kit(formState->form()) forKey:WebActionFormKey];
1676     }
1677
1678     return result;
1679 }
1680
1681 bool WebFrameLoaderClient::canCachePage() const
1682 {
1683     // We can only cache HTML pages right now
1684     return [[[m_webFrame.get() _dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]];
1685 }
1686
1687 PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const URL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
1688     const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
1689 {
1690     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1691     
1692     ASSERT(m_webFrame);
1693     
1694     WebFrameView *childView = [[WebFrameView alloc] init];
1695     
1696     RefPtr<Frame> result = [WebFrame _createSubframeWithOwnerElement:ownerElement frameName:name frameView:childView];
1697     [childView release];
1698
1699     WebFrame *newFrame = kit(result.get());
1700
1701     if ([newFrame _dataSource])
1702         [[newFrame _dataSource] _documentLoader]->setOverrideEncoding([[m_webFrame.get() _dataSource] _documentLoader]->overrideEncoding());  
1703
1704     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1705     if (!result->page())
1706         return 0;
1707  
1708     core(m_webFrame.get())->loader().loadURLIntoChildFrame(url, referrer, result.get());
1709
1710     // The frame's onload handler may have removed it from the document.
1711     if (!result->tree().parent())
1712         return 0;
1713
1714     return result.release();
1715
1716     END_BLOCK_OBJC_EXCEPTIONS;
1717
1718     return 0;
1719 }
1720
1721 ObjectContentType WebFrameLoaderClient::objectContentType(const URL& url, const String& mimeType, bool shouldPreferPlugInsForImages)
1722 {
1723     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1724
1725     String type = mimeType;
1726
1727     if (type.isEmpty()) {
1728         // Try to guess the MIME type based off the extension.
1729         NSURL *URL = url;
1730         NSString *extension = [[URL path] pathExtension];
1731         if ([extension length] > 0) {
1732             type = WKGetMIMETypeForExtension(extension);
1733             if (type.isEmpty()) {
1734                 // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
1735                 if (WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForExtension:extension]) {
1736                     if ([package isKindOfClass:[WebPluginPackage class]]) 
1737                         return ObjectContentOtherPlugin;
1738 #if ENABLE(NETSCAPE_PLUGIN_API)
1739                     else {
1740                         ASSERT([package isKindOfClass:[WebNetscapePluginPackage class]]);
1741                         return ObjectContentNetscapePlugin;
1742                     }
1743 #endif
1744                 }
1745             }
1746         }
1747     }
1748
1749     if (type.isEmpty())
1750         return ObjectContentFrame; // Go ahead and hope that we can display the content.
1751
1752     WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForMIMEType:type];
1753     ObjectContentType plugInType = ObjectContentNone;
1754     if (package) {
1755 #if ENABLE(NETSCAPE_PLUGIN_API)
1756         if ([package isKindOfClass:[WebNetscapePluginPackage class]])
1757             plugInType = ObjectContentNetscapePlugin;
1758         else
1759 #endif
1760         {
1761             ASSERT([package isKindOfClass:[WebPluginPackage class]]);
1762             plugInType = ObjectContentOtherPlugin;
1763         }
1764     }
1765     
1766     if (MIMETypeRegistry::isSupportedImageMIMEType(type))
1767         return shouldPreferPlugInsForImages && plugInType != ObjectContentNone ? plugInType : ObjectContentImage;
1768
1769     if (plugInType != ObjectContentNone)
1770         return plugInType;
1771
1772     if ([m_webFrame->_private->webFrameView _viewClassForMIMEType:type])
1773         return ObjectContentFrame;
1774     
1775     return ObjectContentNone;
1776
1777     END_BLOCK_OBJC_EXCEPTIONS;
1778
1779     return ObjectContentNone;
1780 }
1781
1782 static NSMutableArray* kit(const Vector<String>& vector)
1783 {
1784     unsigned len = vector.size();
1785     NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
1786     for (unsigned x = 0; x < len; x++)
1787         [array addObject:vector[x]];
1788     return array;
1789 }
1790
1791 static String parameterValue(const Vector<String>& paramNames, const Vector<String>& paramValues, const String& name)
1792 {
1793     size_t size = paramNames.size();
1794     ASSERT(size == paramValues.size());
1795     for (size_t i = 0; i < size; ++i) {
1796         if (equalIgnoringCase(paramNames[i], name))
1797             return paramValues[i];
1798     }
1799     return String();
1800 }
1801
1802 static NSView *pluginView(WebFrame *frame, WebPluginPackage *pluginPackage,
1803     NSArray *attributeNames, NSArray *attributeValues, NSURL *baseURL,
1804     DOMElement *element, BOOL loadManually)
1805 {
1806     WebHTMLView *docView = (WebHTMLView *)[[frame frameView] documentView];
1807     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1808         
1809     WebPluginController *pluginController = [docView _pluginController];
1810     
1811     // Store attributes in a dictionary so they can be passed to WebPlugins.
1812     NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
1813     
1814     [pluginPackage load];
1815     Class viewFactory = [pluginPackage viewFactory];
1816     
1817     NSView *view = nil;
1818     NSDictionary *arguments = nil;
1819     
1820     if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
1821         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1822             baseURL, WebPlugInBaseURLKey,
1823             attributes, WebPlugInAttributesKey,
1824             pluginController, WebPlugInContainerKey,
1825             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
1826             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
1827             element, WebPlugInContainingElementKey,
1828             nil];
1829         LOG(Plugins, "arguments:\n%@", arguments);
1830     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
1831         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1832             baseURL, WebPluginBaseURLKey,
1833             attributes, WebPluginAttributesKey,
1834             pluginController, WebPluginContainerKey,
1835             element, WebPlugInContainingElementKey,
1836             nil];
1837         LOG(Plugins, "arguments:\n%@", arguments);
1838     }
1839
1840     view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
1841     [attributes release];
1842     return view;
1843 }
1844
1845 class PluginWidget : public PluginViewBase {
1846 public:
1847     PluginWidget(NSView *view = 0)
1848         : PluginViewBase(view)
1849     {
1850     }
1851     
1852 private:
1853     virtual void invalidateRect(const IntRect& rect)
1854     {
1855         [platformWidget() setNeedsDisplayInRect:rect];
1856     }
1857 };
1858
1859 #if PLATFORM(IOS)
1860 @interface WAKView (UIKitSecretsWebKitKnowsAboutSeeUIWebPlugInView)
1861 #if USE(ACCELERATED_COMPOSITING)
1862 - (PlatformLayer *)pluginLayer;
1863 - (BOOL)willProvidePluginLayer;
1864 - (void)attachPluginLayer;
1865 - (void)detachPluginLayer;
1866 #endif
1867 @end
1868
1869 class PluginWidgetIOS : public PluginWidget {
1870 public:
1871     PluginWidgetIOS(WAKView *view)
1872         : PluginWidget(view)
1873     {
1874     }
1875
1876 #if USE(ACCELERATED_COMPOSITING)
1877     virtual PlatformLayer* platformLayer() const
1878     {
1879         if (![platformWidget() respondsToSelector:@selector(pluginLayer)])
1880             return nullptr;
1881
1882         return [platformWidget() pluginLayer];   
1883     }
1884
1885     virtual bool willProvidePluginLayer() const
1886     {
1887         return [platformWidget() respondsToSelector:@selector(willProvidePluginLayer)]
1888             && [platformWidget() willProvidePluginLayer];
1889     }
1890
1891     virtual void attachPluginLayer()
1892     {
1893         if ([platformWidget() respondsToSelector:@selector(attachPluginLayer)])
1894             [platformWidget() attachPluginLayer];
1895     }
1896
1897     virtual void detachPluginLayer()
1898     {
1899         if ([platformWidget() respondsToSelector:@selector(detachPluginLayer)])
1900             [platformWidget() detachPluginLayer];
1901     }
1902 #endif
1903 };
1904 #endif // PLATFORM(IOS)
1905
1906 #if ENABLE(NETSCAPE_PLUGIN_API)
1907
1908 class NetscapePluginWidget : public PluginWidget {
1909 public:
1910     NetscapePluginWidget(WebBaseNetscapePluginView *view)
1911         : PluginWidget(view)
1912     {
1913     }
1914     
1915 #if USE(ACCELERATED_COMPOSITING)
1916     virtual PlatformLayer* platformLayer() const
1917     {
1918         return [(WebBaseNetscapePluginView *)platformWidget() pluginLayer];
1919     }
1920 #endif
1921
1922     virtual bool getFormValue(String& value)
1923     {
1924         NSString* nsValue = 0;
1925         if ([(WebBaseNetscapePluginView *)platformWidget() getFormValue:&nsValue]) {
1926             if (!nsValue)
1927                 return false;
1928             value = String(nsValue);
1929             [nsValue release];
1930             return true;
1931         }
1932         return false;
1933     }
1934
1935     virtual void handleEvent(Event* event)
1936     {
1937         Frame* frame = Frame::frameForWidget(this);
1938         if (!frame)
1939             return;
1940         
1941         NSEvent* currentNSEvent = frame->eventHandler().currentNSEvent();
1942         if (event->type() == eventNames().mousemoveEvent)
1943             [(WebBaseNetscapePluginView *)platformWidget() handleMouseMoved:currentNSEvent];
1944         else if (event->type() == eventNames().mouseoverEvent)
1945             [(WebBaseNetscapePluginView *)platformWidget() handleMouseEntered:currentNSEvent];
1946         else if (event->type() == eventNames().mouseoutEvent)
1947             [(WebBaseNetscapePluginView *)platformWidget() handleMouseExited:currentNSEvent];
1948         else if (event->type() == eventNames().contextmenuEvent)
1949             event->setDefaultHandled(); // We don't know if the plug-in has handled mousedown event by displaying a context menu, so we never want WebKit to show a default one.
1950     }
1951
1952     virtual void clipRectChanged()
1953     {
1954         // Changing the clip rect doesn't affect the view hierarchy, so the plugin must be told about the change directly.
1955         [(WebBaseNetscapePluginView *)platformWidget() updateAndSetWindow];
1956     }
1957
1958 private:
1959     virtual void notifyWidget(WidgetNotification notification)
1960     {
1961         switch (notification) {
1962         case WillPaintFlattened: {
1963             BEGIN_BLOCK_OBJC_EXCEPTIONS;
1964             [(WebBaseNetscapePluginView *)platformWidget() cacheSnapshot];
1965             END_BLOCK_OBJC_EXCEPTIONS;
1966             break;
1967         }
1968         case DidPaintFlattened: {
1969             BEGIN_BLOCK_OBJC_EXCEPTIONS;
1970             [(WebBaseNetscapePluginView *)platformWidget() clearCachedSnapshot];
1971             END_BLOCK_OBJC_EXCEPTIONS;
1972             break;
1973         }
1974         }
1975     }
1976 };
1977
1978 #if USE(PLUGIN_HOST_PROCESS)
1979 #define NETSCAPE_PLUGIN_VIEW WebHostedNetscapePluginView
1980 #else
1981 #define NETSCAPE_PLUGIN_VIEW WebNetscapePluginView
1982 #endif
1983
1984 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1985
1986 PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize& size, HTMLPlugInElement* element, const URL& url,
1987     const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1988 {
1989     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1990
1991     ASSERT(paramNames.size() == paramValues.size());
1992
1993     int errorCode = 0;
1994
1995     WebView *webView = getWebView(m_webFrame.get());
1996 #if !PLATFORM(IOS)
1997     SEL selector = @selector(webView:plugInViewWithArguments:);
1998 #endif
1999
2000     Document* document = core(m_webFrame.get())->document();
2001     NSURL *baseURL = document->baseURL();
2002     NSURL *pluginURL = url;
2003     
2004     // <rdar://problem/8366089>: AppleConnect has a bug where it does not
2005     // understand the parameter names specified in the <object> element that
2006     // embeds its plug-in. This site-specific hack works around the issue by
2007     // converting the parameter names to lowercase before passing them to the
2008     // plug-in.
2009 #if !PLATFORM(IOS)
2010     Frame* frame = core(m_webFrame.get());
2011 #endif
2012     NSMutableArray *attributeKeys = kit(paramNames);
2013 #if !PLATFORM(IOS)
2014     if (frame && frame->settings().needsSiteSpecificQuirks() && equalIgnoringCase(mimeType, "application/x-snkp")) {
2015         for (NSUInteger i = 0; i < [attributeKeys count]; ++i)
2016             [attributeKeys replaceObjectAtIndex:i withObject:[[attributeKeys objectAtIndex:i] lowercaseString]];
2017     }
2018     
2019     if ([[webView UIDelegate] respondsToSelector:selector]) {
2020         NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:kit(paramValues) forKeys:attributeKeys];
2021         NSDictionary *arguments = [[NSDictionary alloc] initWithObjectsAndKeys:
2022             attributes, WebPlugInAttributesKey,
2023             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
2024             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
2025             kit(element), WebPlugInContainingElementKey,
2026             // FIXME: We should be passing base URL, see <https://bugs.webkit.org/show_bug.cgi?id=35215>.
2027             pluginURL, WebPlugInBaseURLKey, // pluginURL might be nil, so add it last
2028             nil];
2029
2030         NSView *view = CallUIDelegate(webView, selector, arguments);
2031
2032         [attributes release];
2033         [arguments release];
2034
2035         if (view)
2036             return adoptRef(new PluginWidget(view));
2037     }
2038 #endif
2039
2040     NSString *MIMEType;
2041     WebBasePluginPackage *pluginPackage;
2042     if (mimeType.isEmpty()) {
2043         MIMEType = nil;
2044         pluginPackage = nil;
2045     } else {
2046         MIMEType = mimeType;
2047         pluginPackage = [webView _pluginForMIMEType:mimeType];
2048     }
2049     
2050     NSString *extension = [[pluginURL path] pathExtension];
2051
2052 #if PLATFORM(IOS)
2053     if (!pluginPackage && [extension length]) {
2054 #else
2055     if (!pluginPackage && [extension length] && ![MIMEType length]) {
2056 #endif
2057         pluginPackage = [webView _pluginForExtension:extension];
2058         if (pluginPackage) {
2059             NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
2060             if ([newMIMEType length] != 0)
2061                 MIMEType = newMIMEType;
2062         }
2063     }
2064
2065     NSView *view = nil;
2066
2067     if (pluginPackage) {
2068         if (WKShouldBlockPlugin([pluginPackage bundleIdentifier], [pluginPackage bundleVersion])) {
2069             errorCode = WebKitErrorBlockedPlugInVersion;
2070             if (element->renderer()->isEmbeddedObject())
2071                 toRenderEmbeddedObject(element->renderer())->setPluginUnavailabilityReason(RenderEmbeddedObject::InsecurePluginVersion);
2072         } else {
2073             if ([pluginPackage isKindOfClass:[WebPluginPackage class]])
2074                 view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, attributeKeys, kit(paramValues), baseURL, kit(element), loadManually);
2075
2076 #if ENABLE(NETSCAPE_PLUGIN_API)
2077             else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
2078                 WebBaseNetscapePluginView *pluginView = [[[NETSCAPE_PLUGIN_VIEW alloc]
2079                     initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
2080                     pluginPackage:(WebNetscapePluginPackage *)pluginPackage
2081                     URL:pluginURL
2082                     baseURL:baseURL
2083                     MIMEType:MIMEType
2084                     attributeKeys:attributeKeys
2085                     attributeValues:kit(paramValues)
2086                     loadManually:loadManually
2087                     element:element] autorelease];
2088
2089                 return adoptRef(new NetscapePluginWidget(pluginView));
2090             }
2091 #endif
2092         }
2093     } else
2094         errorCode = WebKitErrorCannotFindPlugIn;
2095
2096     if (!errorCode && !view)
2097         errorCode = WebKitErrorCannotLoadPlugIn;
2098     
2099     if (errorCode && m_webFrame) {
2100         WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
2101         if (implementations->plugInFailedWithErrorFunc) {
2102             URL pluginPageURL = document->completeURL(stripLeadingAndTrailingHTMLSpaces(parameterValue(paramNames, paramValues, "pluginspage")));
2103             if (!pluginPageURL.protocolIsInHTTPFamily())
2104                 pluginPageURL = URL();
2105             NSString *pluginName = pluginPackage ? (NSString *)[pluginPackage pluginInfo].name : nil;
2106
2107             NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
2108                                                             contentURL:pluginURL pluginPageURL:pluginPageURL pluginName:pluginName MIMEType:MIMEType];
2109             CallResourceLoadDelegate(implementations->plugInFailedWithErrorFunc, [m_webFrame.get() webView],
2110                                      @selector(webView:plugInFailedWithError:dataSource:), error, [m_webFrame.get() _dataSource]);
2111             [error release];
2112         }
2113
2114 #if PLATFORM(IOS)
2115         // See if this is a YouTube Flash plug-in
2116         if ([MIMEType isEqualToString:@"application/x-shockwave-flash"]) {
2117             NSDictionary *attributes = [NSDictionary dictionaryWithObjects:kit(paramValues) forKeys:kit(paramNames)];
2118             NSString *srcString = [attributes objectForKey:@"src"];
2119             if (srcString) {
2120                 NSURL *srcURL = [NSURL URLWithString:srcString];
2121                 NSURL *youtubeURL = [srcURL _webkit_youTubeURL];
2122                 if (srcURL && youtubeURL) {
2123                     // Transform the youtubeURL (youtube:VideoID) to iframe embed url which has the format: http://www.youtube.com/embed/VideoID
2124                     NSString *srcPath = [srcURL path];
2125                     NSString *videoID = [[youtubeURL absoluteString] substringFromIndex:[[youtubeURL scheme] length] + 1];
2126                     NSRange rangeOfVideoIDInPath = [srcPath rangeOfString:videoID];
2127                     NSString *srcURLPrefix = nil;
2128                     if (rangeOfVideoIDInPath.location == NSNotFound && !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_YOUTUBE_EMBED_IFRAME_TRANSFORM)) {
2129                         // If the videoID is not inside srcPath, the embed src url is in wrong format. We still want to support them for apps build against 5.1 and older.
2130                         // For embed src like http://www.youtube.com/watch?v=VideoID, we make srcURLPrefix "http://www.youtube.com".
2131                         // See: <rdar://problem/11517502> youtube videos don't work in FAO Forestry
2132                         srcURLPrefix = [srcString substringToIndex:[srcString rangeOfString:srcPath].location];
2133                     } else {
2134                         ASSERT(rangeOfVideoIDInPath.length);
2135
2136                         // From the original URL, we need to get the part before /path/VideoId.
2137                         NSRange rangeOfPathBeforeVideoID = [srcString rangeOfString:[srcPath substringToIndex:rangeOfVideoIDInPath.location]];
2138                         ASSERT(rangeOfPathBeforeVideoID.length);
2139
2140                         srcURLPrefix = [srcString substringToIndex:rangeOfPathBeforeVideoID.location];
2141                     }
2142                     NSString *query = [srcURL query];
2143                     // By default, the iframe will display information like the video title and uploader on top of the video.  Don't display
2144                     // them if the embeding html doesn't specify it.
2145                     if (query && [query length] && [query rangeOfString:@"showinfo"].location == NSNotFound)
2146                         query = [query stringByAppendingFormat:@"&showinfo=0"];
2147                     else
2148                         query = @"showinfo=0";
2149
2150                     // Append the query string if it is valid.  Some sites apparently forget to add "?" for the query string, in that case,
2151                     // we will discard the parameters in the url.
2152                     // See: <rdar://problem/11535155> [Bincompat] Regression: SC2Casts app: Videos don't play in SC2Casts
2153                     NSString *embedSrc = query ? [srcURLPrefix stringByAppendingFormat:@"/embed/%@?%@", videoID, query] : [srcURLPrefix stringByAppendingFormat:@"/embed/%@", videoID];
2154
2155                     if (element->hasTagName(HTMLNames::embedTag) || element->hasTagName(HTMLNames::objectTag)) {
2156                         // Create a shadow subtree for the plugin element, the iframe player is injected in the shadow tree.
2157                         HTMLPlugInImageElement* pluginElement = static_cast<HTMLPlugInImageElement*>(element);
2158                         pluginElement->createShadowIFrameSubtree(embedSrc);
2159                         return nullptr;
2160                     }
2161
2162                     // If this is a YouTube Flash plug-in.  We don't have Flash.  Create an instance of Apple's special YouTube plug-in instead
2163                     pluginPackage = [webView _pluginForMIMEType:@"application/x-apple-fake-youtube-plugin"];
2164                     if (pluginPackage) {
2165                         view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, kit(paramNames), kit(paramValues), baseURL, kit(element), loadManually);
2166                         if (view)
2167                             return adoptRef(new PluginWidgetIOS(view));
2168                     }
2169                 }
2170             }
2171         }
2172 #endif // PLATFORM(IOS)
2173
2174         return 0;
2175     }
2176     
2177     ASSERT(view);
2178 #if PLATFORM(IOS)
2179     return adoptRef(new PluginWidgetIOS(view));
2180 #else
2181     return adoptRef(new PluginWidget(view));
2182 #endif
2183
2184     END_BLOCK_OBJC_EXCEPTIONS;
2185
2186     return 0;
2187 }
2188
2189 void WebFrameLoaderClient::recreatePlugin(Widget*)
2190 {
2191 }
2192
2193 void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
2194 {
2195     if (!pluginWidget)
2196         return;
2197
2198     BEGIN_BLOCK_OBJC_EXCEPTIONS;
2199
2200     WebHTMLRepresentation *representation = (WebHTMLRepresentation *)[[m_webFrame.get() _dataSource] representation];
2201
2202     NSView *pluginView = pluginWidget->platformWidget();
2203
2204 #if ENABLE(NETSCAPE_PLUGIN_API)
2205     if ([pluginView isKindOfClass:[NETSCAPE_PLUGIN_VIEW class]])
2206         [representation _redirectDataToManualLoader:(NETSCAPE_PLUGIN_VIEW *)pluginView forPluginView:pluginView];
2207     else {
2208 #else
2209     {
2210 #endif
2211         WebHTMLView *documentView = (WebHTMLView *)[[m_webFrame.get() frameView] documentView];
2212         ASSERT([documentView isKindOfClass:[WebHTMLView class]]);
2213         [representation _redirectDataToManualLoader:[documentView _pluginController] forPluginView:pluginView];
2214     }
2215
2216     END_BLOCK_OBJC_EXCEPTIONS;
2217 }
2218     
2219 PassRefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const URL& baseURL, 
2220     const Vector<String>& paramNames, const Vector<String>& paramValues)
2221 {
2222     BEGIN_BLOCK_OBJC_EXCEPTIONS;
2223
2224     NSView *view = nil;
2225
2226     NSString *MIMEType = @"application/x-java-applet";
2227     
2228     WebView *webView = getWebView(m_webFrame.get());
2229
2230     WebBasePluginPackage *pluginPackage = [webView _pluginForMIMEType:MIMEType];
2231
2232     int errorCode = WebKitErrorJavaUnavailable;
2233
2234     if (pluginPackage) {
2235         if (WKShouldBlockPlugin([pluginPackage bundleIdentifier], [pluginPackage bundleVersion])) {
2236             errorCode = WebKitErrorBlockedPlugInVersion;
2237             if (element->renderer()->isEmbeddedObject())
2238                 toRenderEmbeddedObject(element->renderer())->setPluginUnavailabilityReason(RenderEmbeddedObject::InsecurePluginVersion);
2239         } else {
2240     #if ENABLE(NETSCAPE_PLUGIN_API)
2241             if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
2242                 view = [[[NETSCAPE_PLUGIN_VIEW alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
2243                     pluginPackage:(WebNetscapePluginPackage *)pluginPackage
2244                     URL:nil
2245                     baseURL:baseURL
2246                     MIMEType:MIMEType
2247                     attributeKeys:kit(paramNames)
2248                     attributeValues:kit(paramValues)
2249                     loadManually:NO
2250                     element:element] autorelease];
2251                 if (view)
2252                     return adoptRef(new NetscapePluginWidget(static_cast<WebBaseNetscapePluginView *>(view)));
2253             }
2254     #endif
2255         }
2256     }
2257
2258     if (!view) {
2259         WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(getWebView(m_webFrame.get()));
2260         if (implementations->plugInFailedWithErrorFunc) {
2261             NSString *pluginName = pluginPackage ? (NSString *)[pluginPackage pluginInfo].name : nil;
2262             NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode contentURL:nil pluginPageURL:nil pluginName:pluginName MIMEType:MIMEType];
2263             CallResourceLoadDelegate(implementations->plugInFailedWithErrorFunc, [m_webFrame.get() webView],
2264                                      @selector(webView:plugInFailedWithError:dataSource:), error, [m_webFrame.get() _dataSource]);
2265             [error release];
2266         }
2267     }
2268
2269     END_BLOCK_OBJC_EXCEPTIONS;
2270
2271     return 0;
2272 }
2273
2274 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2275 PassRefPtr<Widget> WebFrameLoaderClient::createMediaPlayerProxyPlugin(const IntSize& size, HTMLMediaElement* element, const URL& url,
2276     const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType)
2277 {
2278     BEGIN_BLOCK_OBJC_EXCEPTIONS;
2279
2280     ASSERT(paramNames.size() == paramValues.size());
2281     ASSERT(mimeType);
2282
2283     int errorCode = 0;
2284     WebView *webView = getWebView(m_webFrame.get());
2285     NSURL *URL = url;
2286
2287 #if !PLATFORM(IOS)
2288     SEL selector = @selector(webView:plugInViewWithArguments:);
2289
2290     if ([[webView UIDelegate] respondsToSelector:selector]) {
2291         NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:kit(paramValues) forKeys:kit(paramNames)];
2292         NSDictionary *arguments = [[NSDictionary alloc] initWithObjectsAndKeys:
2293             attributes, WebPlugInAttributesKey,
2294             [NSNumber numberWithInt:WebPlugInModeEmbed], WebPlugInModeKey,
2295             [NSNumber numberWithBool:YES], WebPlugInShouldLoadMainResourceKey,
2296             kit(element), WebPlugInContainingElementKey,
2297             URL, WebPlugInBaseURLKey, // URL might be nil, so add it last
2298             nil];
2299
2300         NSView *view = CallUIDelegate(webView, selector, arguments);
2301
2302         [attributes release];
2303         [arguments release];
2304
2305         if (view)
2306             return adoptRef(new PluginWidget(view));
2307     }
2308 #endif
2309
2310     WebBasePluginPackage *pluginPackage = [webView _videoProxyPluginForMIMEType:mimeType];
2311     Document* document = core(m_webFrame.get())->document();
2312     NSURL *baseURL = document->baseURL();
2313     NSView *view = nil;
2314
2315     if (pluginPackage) {
2316         if ([pluginPackage isKindOfClass:[WebPluginPackage class]])
2317             view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, kit(paramNames), kit(paramValues), baseURL, kit(element), false);
2318     } else
2319         errorCode = WebKitErrorCannotFindPlugIn;
2320
2321     if (!errorCode && !view)
2322         errorCode = WebKitErrorCannotLoadPlugIn;
2323
2324     if (errorCode) {
2325         NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
2326             contentURL:URL pluginPageURL:nil pluginName:[pluginPackage pluginInfo].name MIMEType:mimeType];
2327         WebNullPluginView *nullView = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
2328             error:error DOMElement:kit(element)] autorelease];
2329         view = nullView;
2330         [error release];
2331     }
2332     
2333     ASSERT(view);
2334 #if PLATFORM(IOS)
2335     return adoptRef(new PluginWidgetIOS(view));
2336 #else
2337     return adoptRef(new PluginWidget(view));
2338 #endif
2339
2340     END_BLOCK_OBJC_EXCEPTIONS;
2341
2342     return 0;
2343 }
2344
2345 void WebFrameLoaderClient::hideMediaPlayerProxyPlugin(Widget* widget)
2346 {
2347     [WebPluginController pluginViewHidden:widget->platformWidget()];
2348 }
2349
2350 void WebFrameLoaderClient::showMediaPlayerProxyPlugin(Widget* widget)
2351 {
2352     [WebPluginController addPlugInView:widget->platformWidget()];
2353 }
2354
2355 #endif  // ENABLE(PLUGIN_PROXY_FOR_VIDEO)
2356
2357 String WebFrameLoaderClient::overrideMediaType() const
2358 {
2359     NSString* overrideType = [getWebView(m_webFrame.get()) mediaStyle];
2360     if (overrideType)
2361         return overrideType;
2362     return String();
2363 }
2364
2365 void WebFrameLoaderClient::documentElementAvailable() {
2366 }
2367
2368 void WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
2369 {
2370     WebView *webView = getWebView(m_webFrame.get());
2371     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
2372
2373     if (implementations->didClearWindowObjectForFrameInScriptWorldFunc) {
2374         CallFrameLoadDelegate(implementations->didClearWindowObjectForFrameInScriptWorldFunc,
2375             webView, @selector(webView:didClearWindowObjectForFrame:inScriptWorld:), m_webFrame.get(), [WebScriptWorld findOrCreateWorld:world]);
2376         return;
2377     }
2378
2379     if (&world != &mainThreadNormalWorld())
2380         return;
2381
2382     Frame *frame = core(m_webFrame.get());
2383     ScriptController& script = frame->script();
2384
2385 #if JSC_OBJC_API_ENABLED
2386     if (implementations->didCreateJavaScriptContextForFrameFunc) {
2387         CallFrameLoadDelegate(implementations->didCreateJavaScriptContextForFrameFunc, webView, @selector(webView:didCreateJavaScriptContext:forFrame:),
2388             script.javaScriptContext(), m_webFrame.get());
2389     } else if (implementations->didClearWindowObjectForFrameFunc) {
2390 #else
2391     if (implementations->didClearWindowObjectForFrameFunc) {
2392 #endif
2393         CallFrameLoadDelegate(implementations->didClearWindowObjectForFrameFunc, webView, @selector(webView:didClearWindowObject:forFrame:),
2394             script.windowScriptObject(), m_webFrame.get());
2395     } else if (implementations->windowScriptObjectAvailableFunc) {
2396         CallFrameLoadDelegate(implementations->windowScriptObjectAvailableFunc, webView, @selector(webView:windowScriptObjectAvailable:),
2397             script.windowScriptObject());
2398     }
2399
2400     if ([webView scriptDebugDelegate]) {
2401         [m_webFrame.get() _detachScriptDebugger];
2402         [m_webFrame.get() _attachScriptDebugger];
2403     }
2404 }
2405
2406 void WebFrameLoaderClient::registerForIconNotification(bool listen)
2407 {
2408 #if ENABLE(ICONDATABASE)
2409     [[m_webFrame.get() webView] _registerForIconNotification:listen];
2410 #endif
2411 }
2412
2413 void WebFrameLoaderClient::didPerformFirstNavigation() const
2414 {
2415     WebPreferences *preferences = [[m_webFrame.get() webView] preferences];
2416     if ([preferences automaticallyDetectsCacheModel] && [preferences cacheModel] < WebCacheModelDocumentBrowser)
2417         [preferences setCacheModel:WebCacheModelDocumentBrowser];
2418 }
2419
2420 PassRefPtr<FrameNetworkingContext> WebFrameLoaderClient::createNetworkingContext()
2421 {
2422     return WebFrameNetworkingContext::create(core(m_webFrame.get()));
2423 }
2424
2425 #if PLATFORM(IOS)
2426 bool WebFrameLoaderClient::shouldLoadMediaElementURL(const URL& url) const 
2427 {
2428     WebView *webView = getWebView(m_webFrame.get());
2429     
2430     if (id policyDelegate = [webView policyDelegate]) {
2431         if ([policyDelegate respondsToSelector:@selector(webView:shouldLoadMediaURL:inFrame:)])
2432             return [policyDelegate webView:webView shouldLoadMediaURL:url inFrame:m_webFrame.get()];
2433     }
2434     return true;
2435 }
2436 #endif
2437
2438 @implementation WebFramePolicyListener
2439
2440 + (void)initialize
2441 {
2442 #if !PLATFORM(IOS)
2443     JSC::initializeThreading();
2444     WTF::initializeMainThreadToProcessMainThread();
2445     RunLoop::initializeMainRunLoop();
2446 #endif
2447     WebCoreObjCFinalizeOnMainThread(self);
2448 }
2449
2450 - (id)initWithFrame:(Frame*)frame policyFunction:(FramePolicyFunction)policyFunction
2451 {
2452     self = [self init];
2453     if (!self)
2454         return nil;
2455
2456     _frame = frame;
2457     _policyFunction = std::move(policyFunction);
2458
2459     return self;
2460 }
2461
2462 - (void)invalidate
2463 {
2464     _frame = nullptr;
2465 }
2466
2467 - (void)dealloc
2468 {
2469     if (WebCoreObjCScheduleDeallocateOnMainThread([WebFramePolicyListener class], self))
2470         return;
2471
2472     [super dealloc];
2473 }
2474
2475 - (void)receivedPolicyDecision:(PolicyAction)action
2476 {
2477     RefPtr<Frame> frame = _frame.release();
2478     if (!frame)
2479         return;
2480
2481     FramePolicyFunction policyFunction = std::move(_policyFunction);
2482     _policyFunction = nullptr;
2483
2484     ASSERT(policyFunction);
2485     policyFunction(action);
2486 }
2487
2488 - (void)ignore
2489 {
2490     [self receivedPolicyDecision:PolicyIgnore];
2491 }
2492
2493 - (void)download
2494 {
2495     [self receivedPolicyDecision:PolicyDownload];
2496 }
2497
2498 - (void)use
2499 {
2500     [self receivedPolicyDecision:PolicyUse];
2501 }
2502
2503 - (void)continue
2504 {
2505     [self receivedPolicyDecision:PolicyUse];
2506 }
2507
2508 @end