Add ObjC equivalent of WKPageLoaderClient.pluginDidFail
[WebKit-https.git] / Source / WebKit / UIProcess / Cocoa / NavigationState.mm
1 /*
2  * Copyright (C) 2014-2016 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "NavigationState.h"
28
29 #if WK_API_ENABLED
30
31 #import "APIFrameInfo.h"
32 #import "APINavigationData.h"
33 #import "APINavigationResponse.h"
34 #import "APIString.h"
35 #import "APIURL.h"
36 #import "AuthenticationDecisionListener.h"
37 #import "CompletionHandlerCallChecker.h"
38 #import "Logging.h"
39 #import "NavigationActionData.h"
40 #import "PageLoadState.h"
41 #import "WKBackForwardListInternal.h"
42 #import "WKBackForwardListItemInternal.h"
43 #import "WKFrameInfoInternal.h"
44 #import "WKHistoryDelegatePrivate.h"
45 #import "WKNSDictionary.h"
46 #import "WKNSURLAuthenticationChallenge.h"
47 #import "WKNSURLExtras.h"
48 #import "WKNSURLRequest.h"
49 #import "WKNavigationActionInternal.h"
50 #import "WKNavigationDataInternal.h"
51 #import "WKNavigationDelegatePrivate.h"
52 #import "WKNavigationInternal.h"
53 #import "WKNavigationResponseInternal.h"
54 #import "WKReloadFrameErrorRecoveryAttempter.h"
55 #import "WKWebViewInternal.h"
56 #import "WebCredential.h"
57 #import "WebFrameProxy.h"
58 #import "WebNavigationState.h"
59 #import "WebPageProxy.h"
60 #import "WebProcessProxy.h"
61 #import "WebProtectionSpace.h"
62 #import "_WKErrorRecoveryAttempting.h"
63 #import "_WKFrameHandleInternal.h"
64 #import "_WKRenderingProgressEventsInternal.h"
65 #import "_WKSameDocumentNavigationTypeInternal.h"
66 #import "_WKWebsitePoliciesInternal.h"
67 #import <WebCore/Credential.h>
68 #import <WebCore/SecurityOriginData.h>
69 #import <WebCore/SerializedCryptoKeyWrap.h>
70 #import <WebCore/URL.h>
71 #import <wtf/BlockPtr.h>
72 #import <wtf/NeverDestroyed.h>
73
74 #if HAVE(APP_LINKS)
75 #import <pal/spi/cocoa/LaunchServicesSPI.h>
76 #endif
77
78 #if USE(QUICK_LOOK)
79 #import "QuickLookDocumentData.h"
80 #endif
81
82 using namespace WebCore;
83
84 namespace WebKit {
85
86 static HashMap<WebPageProxy*, NavigationState*>& navigationStates()
87 {
88     static NeverDestroyed<HashMap<WebPageProxy*, NavigationState*>> navigationStates;
89
90     return navigationStates;
91 }
92
93 NavigationState::NavigationState(WKWebView *webView)
94     : m_webView(webView)
95     , m_navigationDelegateMethods()
96     , m_historyDelegateMethods()
97 #if PLATFORM(IOS)
98     , m_releaseActivityTimer(RunLoop::current(), this, &NavigationState::releaseNetworkActivityToken)
99 #endif
100 {
101     ASSERT(m_webView->_page);
102     ASSERT(!navigationStates().contains(m_webView->_page.get()));
103
104     navigationStates().add(m_webView->_page.get(), this);
105     m_webView->_page->pageLoadState().addObserver(*this);
106 }
107
108 NavigationState::~NavigationState()
109 {
110     ASSERT(navigationStates().get(m_webView->_page.get()) == this);
111
112     navigationStates().remove(m_webView->_page.get());
113     m_webView->_page->pageLoadState().removeObserver(*this);
114 }
115
116 NavigationState& NavigationState::fromWebPage(WebPageProxy& webPageProxy)
117 {
118     ASSERT(navigationStates().contains(&webPageProxy));
119
120     return *navigationStates().get(&webPageProxy);
121 }
122
123 std::unique_ptr<API::NavigationClient> NavigationState::createNavigationClient()
124 {
125     return std::make_unique<NavigationClient>(*this);
126 }
127     
128 std::unique_ptr<API::HistoryClient> NavigationState::createHistoryClient()
129 {
130     return std::make_unique<HistoryClient>(*this);
131 }
132
133 RetainPtr<id <WKNavigationDelegate> > NavigationState::navigationDelegate()
134 {
135     return m_navigationDelegate.get();
136 }
137
138 void NavigationState::setNavigationDelegate(id <WKNavigationDelegate> delegate)
139 {
140     m_navigationDelegate = delegate;
141
142     m_navigationDelegateMethods.webViewDecidePolicyForNavigationActionDecisionHandler = [delegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)];
143     m_navigationDelegateMethods.webViewDecidePolicyForNavigationActionDecisionHandlerWebsitePolicies = [delegate respondsToSelector:@selector(_webView:decidePolicyForNavigationAction:decisionHandler:)];
144     m_navigationDelegateMethods.webViewDecidePolicyForNavigationResponseDecisionHandler = [delegate respondsToSelector:@selector(webView:decidePolicyForNavigationResponse:decisionHandler:)];
145
146     m_navigationDelegateMethods.webViewDidStartProvisionalNavigation = [delegate respondsToSelector:@selector(webView:didStartProvisionalNavigation:)];
147     m_navigationDelegateMethods.webViewDidReceiveServerRedirectForProvisionalNavigation = [delegate respondsToSelector:@selector(webView:didReceiveServerRedirectForProvisionalNavigation:)];
148     m_navigationDelegateMethods.webViewDidFailProvisionalNavigationWithError = [delegate respondsToSelector:@selector(webView:didFailProvisionalNavigation:withError:)];
149     m_navigationDelegateMethods.webViewDidCommitNavigation = [delegate respondsToSelector:@selector(webView:didCommitNavigation:)];
150     m_navigationDelegateMethods.webViewDidFinishNavigation = [delegate respondsToSelector:@selector(webView:didFinishNavigation:)];
151     m_navigationDelegateMethods.webViewDidFailNavigationWithError = [delegate respondsToSelector:@selector(webView:didFailNavigation:withError:)];
152
153     m_navigationDelegateMethods.webViewNavigationDidFailProvisionalLoadInSubframeWithError = [delegate respondsToSelector:@selector(_webView:navigation:didFailProvisionalLoadInSubframe:withError:)];
154     m_navigationDelegateMethods.webViewWillPerformClientRedirect = [delegate respondsToSelector:@selector(_webView:willPerformClientRedirectToURL:delay:)];
155     m_navigationDelegateMethods.webViewDidCancelClientRedirect = [delegate respondsToSelector:@selector(_webViewDidCancelClientRedirect:)];
156     m_navigationDelegateMethods.webViewNavigationDidFinishDocumentLoad = [delegate respondsToSelector:@selector(_webView:navigationDidFinishDocumentLoad:)];
157     m_navigationDelegateMethods.webViewNavigationDidSameDocumentNavigation = [delegate respondsToSelector:@selector(_webView:navigation:didSameDocumentNavigation:)];
158     m_navigationDelegateMethods.webViewRenderingProgressDidChange = [delegate respondsToSelector:@selector(_webView:renderingProgressDidChange:)];
159     m_navigationDelegateMethods.webViewDidReceiveAuthenticationChallengeCompletionHandler = [delegate respondsToSelector:@selector(webView:didReceiveAuthenticationChallenge:completionHandler:)];
160     m_navigationDelegateMethods.webViewWebContentProcessDidTerminate = [delegate respondsToSelector:@selector(webViewWebContentProcessDidTerminate:)];
161     m_navigationDelegateMethods.webViewCanAuthenticateAgainstProtectionSpace = [delegate respondsToSelector:@selector(_webView:canAuthenticateAgainstProtectionSpace:)];
162     m_navigationDelegateMethods.webViewDidReceiveAuthenticationChallenge = [delegate respondsToSelector:@selector(_webView:didReceiveAuthenticationChallenge:)];
163     m_navigationDelegateMethods.webViewWebProcessDidCrash = [delegate respondsToSelector:@selector(_webViewWebProcessDidCrash:)];
164     m_navigationDelegateMethods.webViewWebProcessDidBecomeResponsive = [delegate respondsToSelector:@selector(_webViewWebProcessDidBecomeResponsive:)];
165     m_navigationDelegateMethods.webViewWebProcessDidBecomeUnresponsive = [delegate respondsToSelector:@selector(_webViewWebProcessDidBecomeUnresponsive:)];
166     m_navigationDelegateMethods.webCryptoMasterKeyForWebView = [delegate respondsToSelector:@selector(_webCryptoMasterKeyForWebView:)];
167     m_navigationDelegateMethods.webViewDidBeginNavigationGesture = [delegate respondsToSelector:@selector(_webViewDidBeginNavigationGesture:)];
168     m_navigationDelegateMethods.webViewWillEndNavigationGestureWithNavigationToBackForwardListItem = [delegate respondsToSelector:@selector(_webViewWillEndNavigationGesture:withNavigationToBackForwardListItem:)];
169     m_navigationDelegateMethods.webViewDidEndNavigationGestureWithNavigationToBackForwardListItem = [delegate respondsToSelector:@selector(_webViewDidEndNavigationGesture:withNavigationToBackForwardListItem:)];
170     m_navigationDelegateMethods.webViewWillSnapshotBackForwardListItem = [delegate respondsToSelector:@selector(_webView:willSnapshotBackForwardListItem:)];
171     m_navigationDelegateMethods.webViewNavigationGestureSnapshotWasRemoved = [delegate respondsToSelector:@selector(_webViewDidRemoveNavigationGestureSnapshot:)];
172     m_navigationDelegateMethods.webViewURLContentRuleListIdentifiersNotifications = [delegate respondsToSelector:@selector(_webView:URL:contentRuleListIdentifiers:notifications:)];
173 #if USE(QUICK_LOOK)
174     m_navigationDelegateMethods.webViewDidStartLoadForQuickLookDocumentInMainFrame = [delegate respondsToSelector:@selector(_webView:didStartLoadForQuickLookDocumentInMainFrameWithFileName:uti:)];
175     m_navigationDelegateMethods.webViewDidFinishLoadForQuickLookDocumentInMainFrame = [delegate respondsToSelector:@selector(_webView:didFinishLoadForQuickLookDocumentInMainFrame:)];
176     m_navigationDelegateMethods.webViewDidRequestPasswordForQuickLookDocument = [delegate respondsToSelector:@selector(_webViewDidRequestPasswordForQuickLookDocument:)];
177 #endif
178 #if PLATFORM(MAC)
179     m_navigationDelegateMethods.webViewWebGLLoadPolicyForURL = [delegate respondsToSelector:@selector(_webView:webGLLoadPolicyForURL:decisionHandler:)];
180     m_navigationDelegateMethods.webViewResolveWebGLLoadPolicyForURL = [delegate respondsToSelector:@selector(_webView:resolveWebGLLoadPolicyForURL:decisionHandler:)];
181     m_navigationDelegateMethods.webViewWillGoToBackForwardListItemInPageCache = [delegate respondsToSelector:@selector(_webView:willGoToBackForwardListItem:inPageCache:)];
182     m_navigationDelegateMethods.webViewDidFailToInitializePlugInWithInfo = [delegate respondsToSelector:@selector(_webView:didFailToInitializePlugInWithInfo:)];
183 #endif
184 }
185
186 RetainPtr<id <WKHistoryDelegatePrivate> > NavigationState::historyDelegate()
187 {
188     return m_historyDelegate.get();
189 }
190
191 void NavigationState::setHistoryDelegate(id <WKHistoryDelegatePrivate> historyDelegate)
192 {
193     m_historyDelegate = historyDelegate;
194
195     m_historyDelegateMethods.webViewDidNavigateWithNavigationData = [historyDelegate respondsToSelector:@selector(_webView:didNavigateWithNavigationData:)];
196     m_historyDelegateMethods.webViewDidPerformClientRedirectFromURLToURL = [historyDelegate respondsToSelector:@selector(_webView:didPerformClientRedirectFromURL:toURL:)];
197     m_historyDelegateMethods.webViewDidPerformServerRedirectFromURLToURL = [historyDelegate respondsToSelector:@selector(_webView:didPerformServerRedirectFromURL:toURL:)];
198     m_historyDelegateMethods.webViewDidUpdateHistoryTitleForURL = [historyDelegate respondsToSelector:@selector(_webView:didUpdateHistoryTitle:forURL:)];
199 }
200
201 void NavigationState::navigationGestureDidBegin()
202 {
203     if (!m_navigationDelegateMethods.webViewDidBeginNavigationGesture)
204         return;
205
206     auto navigationDelegate = m_navigationDelegate.get();
207     if (!navigationDelegate)
208         return;
209
210     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webViewDidBeginNavigationGesture:m_webView];
211 }
212
213 void NavigationState::navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem& item)
214 {
215     if (!m_navigationDelegateMethods.webViewWillEndNavigationGestureWithNavigationToBackForwardListItem)
216         return;
217
218     auto navigationDelegate = m_navigationDelegate.get();
219     if (!navigationDelegate)
220         return;
221
222     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webViewWillEndNavigationGesture:m_webView withNavigationToBackForwardListItem:willNavigate ? wrapper(item) : nil];
223 }
224
225 void NavigationState::navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem& item)
226 {
227     if (!m_navigationDelegateMethods.webViewDidEndNavigationGestureWithNavigationToBackForwardListItem)
228         return;
229
230     auto navigationDelegate = m_navigationDelegate.get();
231     if (!navigationDelegate)
232         return;
233
234     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webViewDidEndNavigationGesture:m_webView withNavigationToBackForwardListItem:willNavigate ? wrapper(item) : nil];
235 }
236
237 void NavigationState::willRecordNavigationSnapshot(WebBackForwardListItem& item)
238 {
239     if (!m_navigationDelegateMethods.webViewWillSnapshotBackForwardListItem)
240         return;
241
242     auto navigationDelegate = m_navigationDelegate.get();
243     if (!navigationDelegate)
244         return;
245
246     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webView:m_webView willSnapshotBackForwardListItem:wrapper(item)];
247 }
248
249 void NavigationState::navigationGestureSnapshotWasRemoved()
250 {
251     if (!m_navigationDelegateMethods.webViewNavigationGestureSnapshotWasRemoved)
252         return;
253
254     auto navigationDelegate = m_navigationDelegate.get();
255     if (!navigationDelegate)
256         return;
257
258     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webViewDidRemoveNavigationGestureSnapshot:m_webView];
259 }
260
261 #if USE(QUICK_LOOK)
262 void NavigationState::didRequestPasswordForQuickLookDocument()
263 {
264     if (!m_navigationDelegateMethods.webViewDidRequestPasswordForQuickLookDocument)
265         return;
266
267     auto navigationDelegate = m_navigationDelegate.get();
268     if (!navigationDelegate)
269         return;
270
271     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webViewDidRequestPasswordForQuickLookDocument:m_webView];
272 }
273 #endif
274
275 void NavigationState::didFirstPaint()
276 {
277     if (!m_navigationDelegateMethods.webViewRenderingProgressDidChange)
278         return;
279
280     auto navigationDelegate = m_navigationDelegate.get();
281     if (!navigationDelegate)
282         return;
283
284     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webView:m_webView renderingProgressDidChange:_WKRenderingProgressEventFirstPaint];
285 }
286
287 NavigationState::NavigationClient::NavigationClient(NavigationState& navigationState)
288     : m_navigationState(navigationState)
289 {
290 }
291
292 NavigationState::NavigationClient::~NavigationClient()
293 {
294 }
295
296 #if PLATFORM(MAC)
297 bool NavigationState::NavigationClient::didFailToInitializePlugIn(WebKit::WebPageProxy&, API::Dictionary& info)
298 {
299     if (!m_navigationState.m_navigationDelegateMethods.webViewDidFailToInitializePlugInWithInfo)
300         return false;
301     
302     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
303     if (!navigationDelegate)
304         return false;
305     
306     [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView didFailToInitializePlugInWithInfo:wrapper(info)];
307     return true;
308 }
309
310 inline WebCore::WebGLLoadPolicy toWebCoreWebGLLoadPolicy(_WKWebGLLoadPolicy policy)
311 {
312     switch (policy) {
313     case _WKWebGLLoadPolicyAllowCreation:
314         return WebCore::WebGLAllowCreation;
315     case _WKWebGLLoadPolicyBlockCreation:
316         return WebCore::WebGLBlockCreation;
317     case _WKWebGLLoadPolicyPendingCreation:
318         return WebCore::WebGLPendingCreation;
319     }
320     
321     ASSERT_NOT_REACHED();
322     return WebCore::WebGLAllowCreation;
323 }
324
325 void NavigationState::NavigationClient::webGLLoadPolicy(WebPageProxy&, const WebCore::URL& url, WTF::Function<void(WebCore::WebGLLoadPolicy)>&& completionHandler) const
326 {
327     if (!m_navigationState.m_navigationDelegateMethods.webViewWebGLLoadPolicyForURL) {
328         completionHandler(WebGLAllowCreation);
329         return;
330     }
331
332     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
333     Ref<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(navigationDelegate.get(), @selector(_webView:webGLLoadPolicyForURL:decisionHandler:));
334     [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView webGLLoadPolicyForURL:(NSURL *)url decisionHandler:BlockPtr<void(_WKWebGLLoadPolicy)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](_WKWebGLLoadPolicy policy) {
335         if (checker->completionHandlerHasBeenCalled())
336             return;
337         checker->didCallCompletionHandler();
338         completionHandler(toWebCoreWebGLLoadPolicy(policy));
339     }).get()];
340 }
341
342 void NavigationState::NavigationClient::resolveWebGLLoadPolicy(WebPageProxy&, const WebCore::URL& url, WTF::Function<void(WebCore::WebGLLoadPolicy)>&& completionHandler) const
343 {
344     if (!m_navigationState.m_navigationDelegateMethods.webViewResolveWebGLLoadPolicyForURL) {
345         completionHandler(WebGLAllowCreation);
346         return;
347     }
348     
349     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
350     Ref<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(navigationDelegate.get(), @selector(_webView:resolveWebGLLoadPolicyForURL:decisionHandler:));
351     [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView resolveWebGLLoadPolicyForURL:(NSURL *)url decisionHandler:BlockPtr<void(_WKWebGLLoadPolicy)>::fromCallable([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](_WKWebGLLoadPolicy policy) {
352         if (checker->completionHandlerHasBeenCalled())
353             return;
354         checker->didCallCompletionHandler();
355         completionHandler(toWebCoreWebGLLoadPolicy(policy));
356     }).get()];
357 }
358
359 bool NavigationState::NavigationClient::willGoToBackForwardListItem(WebPageProxy&, WebBackForwardListItem& item, bool inPageCache, API::Object*)
360 {
361     if (!m_navigationState.m_navigationDelegateMethods.webViewWillGoToBackForwardListItemInPageCache)
362         return false;
363
364     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
365     if (!navigationDelegate)
366         return false;
367
368     [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView willGoToBackForwardListItem:wrapper(item) inPageCache:inPageCache];
369     return true;
370 }
371 #endif
372
373 static void tryAppLink(RefPtr<API::NavigationAction>&& navigationAction, const String& currentMainFrameURL, WTF::Function<void(bool)>&& completionHandler)
374 {
375 #if HAVE(APP_LINKS)
376     if (!navigationAction->shouldOpenAppLinks()) {
377         completionHandler(false);
378         return;
379     }
380
381     auto* localCompletionHandler = new WTF::Function<void (bool)>(WTFMove(completionHandler));
382     [LSAppLink openWithURL:navigationAction->request().url() completionHandler:[localCompletionHandler](BOOL success, NSError *) {
383         dispatch_async(dispatch_get_main_queue(), [localCompletionHandler, success] {
384             (*localCompletionHandler)(success);
385             delete localCompletionHandler;
386         });
387     }];
388 #else
389     completionHandler(false);
390 #endif
391 }
392
393 void NavigationState::NavigationClient::decidePolicyForNavigationAction(WebPageProxy& webPageProxy, Ref<API::NavigationAction>&& navigationAction, Ref<WebFramePolicyListenerProxy>&& listener, API::Object* userData)
394 {
395     String mainFrameURLString = webPageProxy.mainFrame()->url();
396
397     if (!m_navigationState.m_navigationDelegateMethods.webViewDecidePolicyForNavigationActionDecisionHandler
398         && !m_navigationState.m_navigationDelegateMethods.webViewDecidePolicyForNavigationActionDecisionHandlerWebsitePolicies) {
399         Ref<API::NavigationAction> localNavigationAction = navigationAction.copyRef();
400         RefPtr<WebFramePolicyListenerProxy> localListener = WTFMove(listener);
401
402         tryAppLink(WTFMove(localNavigationAction), mainFrameURLString, [webPage = RefPtr<WebPageProxy>(&webPageProxy), localListener, localNavigationAction = navigationAction.copyRef()] (bool followedLinkToApp) {
403             if (followedLinkToApp) {
404                 localListener->ignore();
405                 return;
406             }
407
408             if (!localNavigationAction->targetFrame()) {
409                 localListener->use({ });
410                 return;
411             }
412
413             RetainPtr<NSURLRequest> nsURLRequest = adoptNS(wrapper(API::URLRequest::create(localNavigationAction->request()).leakRef()));
414             if ([NSURLConnection canHandleRequest:nsURLRequest.get()] || webPage->urlSchemeHandlerForScheme([nsURLRequest URL].scheme)) {
415                 if (localNavigationAction->shouldPerformDownload())
416                     localListener->download();
417                 else
418                     localListener->use({ });
419                 return;
420             }
421
422 #if PLATFORM(MAC)
423             // A file URL shouldn't fall through to here, but if it did,
424             // it would be a security risk to open it.
425             if (![[nsURLRequest URL] isFileURL])
426                 [[NSWorkspace sharedWorkspace] openURL:[nsURLRequest URL]];
427 #endif
428             localListener->ignore();
429         });
430
431         return;
432     }
433
434     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
435     if (!navigationDelegate)
436         return;
437
438     bool delegateHasWebsitePolicies = m_navigationState.m_navigationDelegateMethods.webViewDecidePolicyForNavigationActionDecisionHandlerWebsitePolicies;
439     
440     RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(navigationDelegate.get(), delegateHasWebsitePolicies ? @selector(_webView:decidePolicyForNavigationAction:decisionHandler:) : @selector(webView:decidePolicyForNavigationAction:decisionHandler:));
441     
442     auto decisionHandlerWithPolicies = [localListener = RefPtr<WebFramePolicyListenerProxy>(WTFMove(listener)), localNavigationAction = navigationAction.copyRef(), checker = WTFMove(checker), mainFrameURLString](WKNavigationActionPolicy actionPolicy, _WKWebsitePolicies *websitePolicies) mutable {
443         if (checker->completionHandlerHasBeenCalled())
444             return;
445         checker->didCallCompletionHandler();
446
447         WebsitePolicies policies;
448         if (websitePolicies)
449             policies = websitePolicies->_websitePolicies->websitePolicies();
450
451         switch (actionPolicy) {
452         case WKNavigationActionPolicyAllow:
453             tryAppLink(WTFMove(localNavigationAction), mainFrameURLString, [localListener = WTFMove(localListener), policies = WTFMove(policies)](bool followedLinkToApp) mutable {
454                 if (followedLinkToApp) {
455                     localListener->ignore();
456                     return;
457                 }
458
459                 localListener->use(policies);
460             });
461         
462             break;
463
464         case WKNavigationActionPolicyCancel:
465             localListener->ignore();
466             break;
467
468 // FIXME: Once we have a new enough compiler everywhere we don't need to ignore -Wswitch.
469 #pragma clang diagnostic push
470 #pragma clang diagnostic ignored "-Wswitch"
471         case _WKNavigationActionPolicyDownload:
472             localListener->download();
473             break;
474         case _WKNavigationActionPolicyAllowWithoutTryingAppLink:
475 #pragma clang diagnostic pop
476             localListener->use(policies);
477             break;
478         }
479     };
480     
481     if (delegateHasWebsitePolicies)
482         [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView decidePolicyForNavigationAction:wrapper(navigationAction) decisionHandler:BlockPtr<void(WKNavigationActionPolicy, _WKWebsitePolicies *)>::fromCallable(WTFMove(decisionHandlerWithPolicies)).get()];
483     else {
484         auto decisionHandlerWithoutPolicies = [decisionHandlerWithPolicies = WTFMove(decisionHandlerWithPolicies)] (WKNavigationActionPolicy actionPolicy) mutable {
485             decisionHandlerWithPolicies(actionPolicy, nil);
486         };
487         [navigationDelegate webView:m_navigationState.m_webView decidePolicyForNavigationAction:wrapper(navigationAction) decisionHandler:BlockPtr<void(WKNavigationActionPolicy)>::fromCallable(WTFMove(decisionHandlerWithoutPolicies)).get()];
488     }
489 }
490
491 void NavigationState::NavigationClient::contentRuleListNotification(WebPageProxy&, WebCore::URL&& url, Vector<String>&& listIdentifiers, Vector<String>&& notifications)
492 {
493     if (!m_navigationState.m_navigationDelegateMethods.webViewURLContentRuleListIdentifiersNotifications)
494         return;
495
496     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
497     if (!navigationDelegate)
498         return;
499
500     ASSERT(listIdentifiers.size() == notifications.size());
501
502     auto identifiers = adoptNS([[NSMutableArray alloc] initWithCapacity:listIdentifiers.size()]);
503     for (auto& identifier : listIdentifiers)
504         [identifiers addObject:identifier];
505
506     auto nsNotifications = adoptNS([[NSMutableArray alloc] initWithCapacity:notifications.size()]);
507     for (auto& notification : notifications)
508         [nsNotifications addObject:notification];
509     
510     [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView URL:url contentRuleListIdentifiers:identifiers.get() notifications:nsNotifications.get()];
511 }
512     
513 void NavigationState::NavigationClient::decidePolicyForNavigationResponse(WebPageProxy&, API::NavigationResponse& navigationResponse, Ref<WebFramePolicyListenerProxy>&& listener, API::Object* userData)
514 {
515     if (!m_navigationState.m_navigationDelegateMethods.webViewDecidePolicyForNavigationResponseDecisionHandler) {
516         NSURL *url = navigationResponse.response().nsURLResponse().URL;
517         if ([url isFileURL]) {
518             BOOL isDirectory = NO;
519             BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDirectory];
520
521             if (exists && !isDirectory && navigationResponse.canShowMIMEType())
522                 listener->use({ });
523             else
524                 listener->ignore();
525             return;
526         }
527
528         if (navigationResponse.canShowMIMEType())
529             listener->use({ });
530         else
531             listener->ignore();
532         return;
533     }
534
535     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
536     if (!navigationDelegate)
537         return;
538
539     RefPtr<WebFramePolicyListenerProxy> localListener = WTFMove(listener);
540     RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(navigationDelegate.get(), @selector(webView:decidePolicyForNavigationResponse:decisionHandler:));
541     [navigationDelegate webView:m_navigationState.m_webView decidePolicyForNavigationResponse:wrapper(navigationResponse) decisionHandler:[localListener, checker](WKNavigationResponsePolicy responsePolicy) {
542         if (checker->completionHandlerHasBeenCalled())
543             return;
544         checker->didCallCompletionHandler();
545
546         switch (responsePolicy) {
547         case WKNavigationResponsePolicyAllow:
548             localListener->use({ });
549             break;
550
551         case WKNavigationResponsePolicyCancel:
552             localListener->ignore();
553             break;
554
555 // FIXME: Once we have a new enough compiler everywhere we don't need to ignore -Wswitch.
556 #pragma clang diagnostic push
557 #pragma clang diagnostic ignored "-Wswitch"
558         case _WKNavigationResponsePolicyBecomeDownload:
559 #pragma clang diagnostic pop
560             localListener->download();
561             break;
562         }
563     }];
564 }
565
566 void NavigationState::NavigationClient::didStartProvisionalNavigation(WebPageProxy& page, API::Navigation* navigation, API::Object*)
567 {
568     if (!m_navigationState.m_navigationDelegateMethods.webViewDidStartProvisionalNavigation)
569         return;
570
571     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
572     if (!navigationDelegate)
573         return;
574
575     // FIXME: We should assert that navigation is not null here, but it's currently null for some navigations through the page cache.
576     WKNavigation *wkNavigation = nil;
577     if (navigation)
578         wkNavigation = wrapper(*navigation);
579
580     [navigationDelegate webView:m_navigationState.m_webView didStartProvisionalNavigation:wkNavigation];
581 }
582
583 void NavigationState::NavigationClient::didReceiveServerRedirectForProvisionalNavigation(WebPageProxy& page, API::Navigation* navigation, API::Object*)
584 {
585     if (!m_navigationState.m_navigationDelegateMethods.webViewDidReceiveServerRedirectForProvisionalNavigation)
586         return;
587
588     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
589     if (!navigationDelegate)
590         return;
591
592     // FIXME: We should assert that navigation is not null here, but it's currently null for some navigations through the page cache.
593     WKNavigation *wkNavigation = nil;
594     if (navigation)
595         wkNavigation = wrapper(*navigation);
596
597     [navigationDelegate webView:m_navigationState.m_webView didReceiveServerRedirectForProvisionalNavigation:wkNavigation];
598 }
599
600 void NavigationState::NavigationClient::willPerformClientRedirect(WebKit::WebPageProxy& page, const WTF::String& urlString, double delay)
601 {
602     if (!m_navigationState.m_navigationDelegateMethods.webViewWillPerformClientRedirect)
603         return;
604
605     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
606     if (!navigationDelegate)
607         return;
608
609     WebCore::URL url(WebCore::URL(), urlString);
610
611     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webView:m_navigationState.m_webView willPerformClientRedirectToURL:url delay:delay];
612 }
613
614 void NavigationState::NavigationClient::didCancelClientRedirect(WebKit::WebPageProxy& page)
615 {
616     if (!m_navigationState.m_navigationDelegateMethods.webViewDidCancelClientRedirect)
617         return;
618
619     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
620     if (!navigationDelegate)
621         return;
622
623     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webViewDidCancelClientRedirect:m_navigationState.m_webView];
624 }
625
626 static RetainPtr<NSError> createErrorWithRecoveryAttempter(WKWebView *webView, WebFrameProxy& webFrameProxy, NSError *originalError)
627 {
628     RefPtr<API::FrameHandle> frameHandle = API::FrameHandle::create(webFrameProxy.frameID());
629
630     auto recoveryAttempter = adoptNS([[WKReloadFrameErrorRecoveryAttempter alloc] initWithWebView:webView frameHandle:wrapper(*frameHandle) urlString:originalError.userInfo[NSURLErrorFailingURLStringErrorKey]]);
631
632     auto userInfo = adoptNS([[NSMutableDictionary alloc] initWithObjectsAndKeys:recoveryAttempter.get(), _WKRecoveryAttempterErrorKey, nil]);
633
634     if (NSDictionary *originalUserInfo = originalError.userInfo)
635         [userInfo addEntriesFromDictionary:originalUserInfo];
636
637     return adoptNS([[NSError alloc] initWithDomain:originalError.domain code:originalError.code userInfo:userInfo.get()]);
638 }
639
640 // FIXME: Shouldn't need to pass the WebFrameProxy in here. At most, a FrameHandle.
641 void NavigationState::NavigationClient::didFailProvisionalNavigationWithError(WebPageProxy& page, WebFrameProxy& webFrameProxy, API::Navigation* navigation, const WebCore::ResourceError& error, API::Object*)
642 {
643     // FIXME: We should assert that navigation is not null here, but it's currently null for some navigations through the page cache.
644     RetainPtr<WKNavigation> wkNavigation;
645     if (navigation)
646         wkNavigation = wrapper(*navigation);
647     
648     // FIXME: Set the error on the navigation object.
649
650     if (!m_navigationState.m_navigationDelegateMethods.webViewDidFailProvisionalNavigationWithError)
651         return;
652
653     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
654     if (!navigationDelegate)
655         return;
656
657     auto errorWithRecoveryAttempter = createErrorWithRecoveryAttempter(m_navigationState.m_webView, webFrameProxy, error);
658     [navigationDelegate webView:m_navigationState.m_webView didFailProvisionalNavigation:wkNavigation.get() withError:errorWithRecoveryAttempter.get()];
659 }
660
661 // FIXME: Shouldn't need to pass the WebFrameProxy in here. At most, a FrameHandle.
662 void NavigationState::NavigationClient::didFailProvisionalLoadInSubframeWithError(WebPageProxy& page, WebFrameProxy& webFrameProxy, const SecurityOriginData& securityOrigin, API::Navigation* navigation, const WebCore::ResourceError& error, API::Object*)
663 {
664     // FIXME: We should assert that navigation is not null here, but it's currently null because WebPageProxy::didFailProvisionalLoadForFrame passes null.
665     RetainPtr<WKNavigation> wkNavigation;
666     if (navigation)
667         wkNavigation = wrapper(*navigation);
668
669     if (!m_navigationState.m_navigationDelegateMethods.webViewNavigationDidFailProvisionalLoadInSubframeWithError)
670         return;
671
672     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
673     auto errorWithRecoveryAttempter = createErrorWithRecoveryAttempter(m_navigationState.m_webView, webFrameProxy, error);
674
675     [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView navigation:nil didFailProvisionalLoadInSubframe:wrapper(API::FrameInfo::create(webFrameProxy, securityOrigin.securityOrigin())) withError:errorWithRecoveryAttempter.get()];
676 }
677
678 void NavigationState::NavigationClient::didCommitNavigation(WebPageProxy& page, API::Navigation* navigation, API::Object*)
679 {
680     if (!m_navigationState.m_navigationDelegateMethods.webViewDidCommitNavigation)
681         return;
682
683     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
684     if (!navigationDelegate)
685         return;
686
687     // FIXME: We should assert that navigation is not null here, but it's currently null for some navigations through the page cache.
688     WKNavigation *wkNavigation = nil;
689     if (navigation)
690         wkNavigation = wrapper(*navigation);
691
692     [navigationDelegate webView:m_navigationState.m_webView didCommitNavigation:wkNavigation];
693 }
694
695 void NavigationState::NavigationClient::didFinishDocumentLoad(WebPageProxy& page, API::Navigation* navigation, API::Object*)
696 {
697     if (!m_navigationState.m_navigationDelegateMethods.webViewNavigationDidFinishDocumentLoad)
698         return;
699
700     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
701     if (!navigationDelegate)
702         return;
703
704     // FIXME: We should assert that navigation is not null here, but it's currently null for some navigations through the page cache.
705     WKNavigation *wkNavigation = nil;
706     if (navigation)
707         wkNavigation = wrapper(*navigation);
708
709     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webView:m_navigationState.m_webView navigationDidFinishDocumentLoad:wkNavigation];
710 }
711
712 void NavigationState::NavigationClient::didFinishNavigation(WebPageProxy& page, API::Navigation* navigation, API::Object*)
713 {
714     if (!m_navigationState.m_navigationDelegateMethods.webViewDidFinishNavigation)
715         return;
716
717     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
718     if (!navigationDelegate)
719         return;
720
721     // FIXME: We should assert that navigation is not null here, but it's currently null for some navigations through the page cache.
722     WKNavigation *wkNavigation = nil;
723     if (navigation)
724         wkNavigation = wrapper(*navigation);
725
726     [navigationDelegate webView:m_navigationState.m_webView didFinishNavigation:wkNavigation];
727 }
728
729 // FIXME: Shouldn't need to pass the WebFrameProxy in here. At most, a FrameHandle.
730 void NavigationState::NavigationClient::didFailNavigationWithError(WebPageProxy& page, WebFrameProxy& webFrameProxy, API::Navigation* navigation, const WebCore::ResourceError& error, API::Object* userData)
731 {
732     if (!m_navigationState.m_navigationDelegateMethods.webViewDidFailNavigationWithError)
733         return;
734
735     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
736     if (!navigationDelegate)
737         return;
738
739     // FIXME: We should assert that navigation is not null here, but it's currently null for some navigations through the page cache.
740     WKNavigation *wkNavigation = nil;
741     if (navigation)
742         wkNavigation = wrapper(*navigation);
743
744     auto errorWithRecoveryAttempter = createErrorWithRecoveryAttempter(m_navigationState.m_webView, webFrameProxy, error);
745     [navigationDelegate webView:m_navigationState.m_webView didFailNavigation:wkNavigation withError:errorWithRecoveryAttempter.get()];
746 }
747
748 void NavigationState::NavigationClient::didSameDocumentNavigation(WebPageProxy&, API::Navigation* navigation, SameDocumentNavigationType navigationType, API::Object*)
749 {
750     if (!m_navigationState.m_navigationDelegateMethods.webViewNavigationDidSameDocumentNavigation)
751         return;
752
753     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
754     if (!navigationDelegate)
755         return;
756
757     // FIXME: We should assert that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
758     WKNavigation *wkNavigation = nil;
759     if (navigation)
760         wkNavigation = wrapper(*navigation);
761
762     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webView:m_navigationState.m_webView navigation:wkNavigation didSameDocumentNavigation:toWKSameDocumentNavigationType(navigationType)];
763 }
764
765 void NavigationState::NavigationClient::renderingProgressDidChange(WebKit::WebPageProxy&, WebCore::LayoutMilestones layoutMilestones)
766 {
767     if (!m_navigationState.m_navigationDelegateMethods.webViewRenderingProgressDidChange)
768         return;
769
770     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
771     if (!navigationDelegate)
772         return;
773
774     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webView:m_navigationState.m_webView renderingProgressDidChange:renderingProgressEvents(layoutMilestones)];
775 }
776
777 bool NavigationState::NavigationClient::canAuthenticateAgainstProtectionSpace(WebKit::WebPageProxy&, WebKit::WebProtectionSpace* protectionSpace)
778 {
779     if (m_navigationState.m_navigationDelegateMethods.webViewDidReceiveAuthenticationChallengeCompletionHandler)
780         return true;
781
782     if (!m_navigationState.m_navigationDelegateMethods.webViewCanAuthenticateAgainstProtectionSpace)
783         return false;
784
785     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
786     if (!navigationDelegate)
787         return false;
788
789     return [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webView:m_navigationState.m_webView canAuthenticateAgainstProtectionSpace:protectionSpace->protectionSpace().nsSpace()];
790 }
791
792 void NavigationState::NavigationClient::didReceiveAuthenticationChallenge(WebPageProxy&, AuthenticationChallengeProxy* authenticationChallenge)
793 {
794     if (m_navigationState.m_navigationDelegateMethods.webViewDidReceiveAuthenticationChallengeCompletionHandler) {
795         auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
796         if (!navigationDelegate) {
797             authenticationChallenge->listener()->performDefaultHandling();
798             return;
799         }
800
801         RefPtr<AuthenticationChallengeProxy> challenge = authenticationChallenge;
802         RefPtr<CompletionHandlerCallChecker> checker = CompletionHandlerCallChecker::create(navigationDelegate.get(), @selector(webView:didReceiveAuthenticationChallenge:completionHandler:));
803         [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) webView:m_navigationState.m_webView didReceiveAuthenticationChallenge:wrapper(*authenticationChallenge)
804             completionHandler:[challenge, checker](NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential) {
805                 if (checker->completionHandlerHasBeenCalled())
806                     return;
807                 checker->didCallCompletionHandler();
808
809                 switch (disposition) {
810                 case NSURLSessionAuthChallengeUseCredential: {
811                     RefPtr<WebCredential> webCredential;
812                     if (credential)
813                         webCredential = WebCredential::create(WebCore::Credential(credential));
814
815                     challenge->listener()->useCredential(webCredential.get());
816                     break;
817                 }
818
819                 case NSURLSessionAuthChallengePerformDefaultHandling:
820                     challenge->listener()->performDefaultHandling();
821                     break;
822
823                 case NSURLSessionAuthChallengeCancelAuthenticationChallenge:
824                     challenge->listener()->cancel();
825                     break;
826
827                 case NSURLSessionAuthChallengeRejectProtectionSpace:
828                     challenge->listener()->rejectProtectionSpaceAndContinue();
829                     break;
830
831                 default:
832                     [NSException raise:NSInvalidArgumentException format:@"Invalid NSURLSessionAuthChallengeDisposition (%ld)", (long)disposition];
833                 }
834             }
835         ];
836         return;
837     }
838
839     if (!m_navigationState.m_navigationDelegateMethods.webViewDidReceiveAuthenticationChallenge)
840         return;
841
842     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
843     if (!navigationDelegate)
844         return;
845
846     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webView:m_navigationState.m_webView didReceiveAuthenticationChallenge:wrapper(*authenticationChallenge)];
847 }
848
849 void NavigationState::NavigationClient::processDidTerminate(WebKit::WebPageProxy& page, WebKit::ProcessTerminationReason)
850 {
851     if (!m_navigationState.m_navigationDelegateMethods.webViewWebContentProcessDidTerminate && !m_navigationState.m_navigationDelegateMethods.webViewWebProcessDidCrash)
852         return;
853
854     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
855     if (!navigationDelegate)
856         return;
857
858     // We prefer webViewWebContentProcessDidTerminate: over _webViewWebProcessDidCrash:.
859     if (m_navigationState.m_navigationDelegateMethods.webViewWebContentProcessDidTerminate) {
860         [navigationDelegate webViewWebContentProcessDidTerminate:m_navigationState.m_webView];
861         return;
862     }
863
864     if (m_navigationState.m_navigationDelegateMethods.webViewWebProcessDidCrash)
865         [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webViewWebProcessDidCrash:m_navigationState.m_webView];
866 }
867
868 void NavigationState::NavigationClient::processDidBecomeResponsive(WebKit::WebPageProxy& page)
869 {
870     if (!m_navigationState.m_navigationDelegateMethods.webViewWebProcessDidBecomeResponsive)
871         return;
872
873     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
874     if (!navigationDelegate)
875         return;
876
877     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webViewWebProcessDidBecomeResponsive:m_navigationState.m_webView];
878 }
879
880 void NavigationState::NavigationClient::processDidBecomeUnresponsive(WebKit::WebPageProxy& page)
881 {
882     if (!m_navigationState.m_navigationDelegateMethods.webViewWebProcessDidBecomeUnresponsive)
883         return;
884
885     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
886     if (!navigationDelegate)
887         return;
888
889     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webViewWebProcessDidBecomeUnresponsive:m_navigationState.m_webView];
890 }
891
892 RefPtr<API::Data> NavigationState::NavigationClient::webCryptoMasterKey(WebKit::WebPageProxy&)
893 {
894     if (!m_navigationState.m_navigationDelegateMethods.webCryptoMasterKeyForWebView) {
895         Vector<uint8_t> masterKey;
896         if (!getDefaultWebCryptoMasterKey(masterKey))
897             return nullptr;
898
899         return API::Data::create(masterKey.data(), masterKey.size());
900     }
901
902     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
903     if (!navigationDelegate)
904         return nullptr;
905
906     RetainPtr<NSData> data = [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webCryptoMasterKeyForWebView:m_navigationState.m_webView];
907
908     return API::Data::createWithoutCopying((const unsigned char*)[data bytes], [data length], [] (unsigned char*, const void* data) {
909         [(NSData *)data release];
910     }, data.leakRef());
911 }
912
913 #if USE(QUICK_LOOK)
914 void NavigationState::NavigationClient::didStartLoadForQuickLookDocumentInMainFrame(const String& fileName, const String& uti)
915 {
916     if (!m_navigationState.m_navigationDelegateMethods.webViewDidStartLoadForQuickLookDocumentInMainFrame)
917         return;
918
919     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
920     if (!navigationDelegate)
921         return;
922
923     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webView:m_navigationState.m_webView didStartLoadForQuickLookDocumentInMainFrameWithFileName:fileName uti:uti];
924 }
925
926 void NavigationState::NavigationClient::didFinishLoadForQuickLookDocumentInMainFrame(const WebKit::QuickLookDocumentData& data)
927 {
928     if (!m_navigationState.m_navigationDelegateMethods.webViewDidFinishLoadForQuickLookDocumentInMainFrame)
929         return;
930
931     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
932     if (!navigationDelegate)
933         return;
934
935     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webView:m_navigationState.m_webView didFinishLoadForQuickLookDocumentInMainFrame:(NSData *)data.decodedData()];
936 }
937 #endif
938
939 // HistoryDelegatePrivate support
940     
941 NavigationState::HistoryClient::HistoryClient(NavigationState& navigationState)
942     : m_navigationState(navigationState)
943 {
944 }
945
946 NavigationState::HistoryClient::~HistoryClient()
947 {
948 }
949
950 void NavigationState::HistoryClient::didNavigateWithNavigationData(WebKit::WebPageProxy&, const WebKit::WebNavigationDataStore& navigationDataStore)
951 {
952     if (!m_navigationState.m_historyDelegateMethods.webViewDidNavigateWithNavigationData)
953         return;
954
955     auto historyDelegate = m_navigationState.m_historyDelegate.get();
956     if (!historyDelegate)
957         return;
958
959     [historyDelegate _webView:m_navigationState.m_webView didNavigateWithNavigationData:wrapper(API::NavigationData::create(navigationDataStore))];
960 }
961
962 void NavigationState::HistoryClient::didPerformClientRedirect(WebKit::WebPageProxy&, const WTF::String& sourceURL, const WTF::String& destinationURL)
963 {
964     if (!m_navigationState.m_historyDelegateMethods.webViewDidPerformClientRedirectFromURLToURL)
965         return;
966
967     auto historyDelegate = m_navigationState.m_historyDelegate.get();
968     if (!historyDelegate)
969         return;
970
971     [historyDelegate _webView:m_navigationState.m_webView didPerformClientRedirectFromURL:[NSURL _web_URLWithWTFString:sourceURL] toURL:[NSURL _web_URLWithWTFString:destinationURL]];
972 }
973
974 void NavigationState::HistoryClient::didPerformServerRedirect(WebKit::WebPageProxy&, const WTF::String& sourceURL, const WTF::String& destinationURL)
975 {
976     if (!m_navigationState.m_historyDelegateMethods.webViewDidPerformServerRedirectFromURLToURL)
977         return;
978
979     auto historyDelegate = m_navigationState.m_historyDelegate.get();
980     if (!historyDelegate)
981         return;
982
983     [historyDelegate _webView:m_navigationState.m_webView didPerformServerRedirectFromURL:[NSURL _web_URLWithWTFString:sourceURL] toURL:[NSURL _web_URLWithWTFString:destinationURL]];
984 }
985
986 void NavigationState::HistoryClient::didUpdateHistoryTitle(WebKit::WebPageProxy&, const WTF::String& title, const WTF::String& url)
987 {
988     if (!m_navigationState.m_historyDelegateMethods.webViewDidUpdateHistoryTitleForURL)
989         return;
990
991     auto historyDelegate = m_navigationState.m_historyDelegate.get();
992     if (!historyDelegate)
993         return;
994
995     [historyDelegate _webView:m_navigationState.m_webView didUpdateHistoryTitle:title forURL:[NSURL _web_URLWithWTFString:url]];
996 }
997
998 void NavigationState::willChangeIsLoading()
999 {
1000     [m_webView willChangeValueForKey:@"loading"];
1001 }
1002
1003 #if PLATFORM(IOS)
1004 void NavigationState::releaseNetworkActivityToken()
1005 {
1006     RELEASE_LOG_IF(m_webView->_page->isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p UIProcess is releasing a background assertion because a page load completed", this);
1007     ASSERT(m_activityToken);
1008     m_activityToken = nullptr;
1009 }
1010 #endif
1011
1012 void NavigationState::didChangeIsLoading()
1013 {
1014 #if PLATFORM(IOS)
1015     if (m_webView->_page->pageLoadState().isLoading()) {
1016         if (m_releaseActivityTimer.isActive())
1017             m_releaseActivityTimer.stop();
1018         else {
1019             RELEASE_LOG_IF(m_webView->_page->isAlwaysOnLoggingAllowed(), ProcessSuspension, "%p - UIProcess is taking a background assertion because a page load started", this);
1020             ASSERT(!m_activityToken);
1021             m_activityToken = m_webView->_page->process().throttler().backgroundActivityToken();
1022         }
1023     } else {
1024         // Delay releasing the background activity for 3 seconds to give the application a chance to start another navigation
1025         // before suspending the WebContent process <rdar://problem/27910964>.
1026         m_releaseActivityTimer.startOneShot(3_s);
1027     }
1028 #endif
1029
1030     [m_webView didChangeValueForKey:@"loading"];
1031 }
1032
1033 void NavigationState::willChangeTitle()
1034 {
1035     [m_webView willChangeValueForKey:@"title"];
1036 }
1037
1038 void NavigationState::didChangeTitle()
1039 {
1040     [m_webView didChangeValueForKey:@"title"];
1041 }
1042
1043 void NavigationState::willChangeActiveURL()
1044 {
1045     [m_webView willChangeValueForKey:@"URL"];
1046 }
1047
1048 void NavigationState::didChangeActiveURL()
1049 {
1050     [m_webView didChangeValueForKey:@"URL"];
1051 }
1052
1053 void NavigationState::willChangeHasOnlySecureContent()
1054 {
1055     [m_webView willChangeValueForKey:@"hasOnlySecureContent"];
1056 }
1057
1058 void NavigationState::didChangeHasOnlySecureContent()
1059 {
1060     [m_webView didChangeValueForKey:@"hasOnlySecureContent"];
1061 }
1062
1063 void NavigationState::willChangeEstimatedProgress()
1064 {
1065     [m_webView willChangeValueForKey:@"estimatedProgress"];
1066 }
1067
1068 void NavigationState::didChangeEstimatedProgress()
1069 {
1070     [m_webView didChangeValueForKey:@"estimatedProgress"];
1071 }
1072
1073 void NavigationState::willChangeCanGoBack()
1074 {
1075     [m_webView willChangeValueForKey:@"canGoBack"];
1076 }
1077
1078 void NavigationState::didChangeCanGoBack()
1079 {
1080     [m_webView didChangeValueForKey:@"canGoBack"];
1081 }
1082
1083 void NavigationState::willChangeCanGoForward()
1084 {
1085     [m_webView willChangeValueForKey:@"canGoForward"];
1086 }
1087
1088 void NavigationState::didChangeCanGoForward()
1089 {
1090     [m_webView didChangeValueForKey:@"canGoForward"];
1091 }
1092
1093 void NavigationState::willChangeNetworkRequestsInProgress()
1094 {
1095     [m_webView willChangeValueForKey:@"_networkRequestsInProgress"];
1096 }
1097
1098 void NavigationState::didChangeNetworkRequestsInProgress()
1099 {
1100     [m_webView didChangeValueForKey:@"_networkRequestsInProgress"];
1101 }
1102
1103 void NavigationState::willChangeCertificateInfo()
1104 {
1105     [m_webView willChangeValueForKey:@"serverTrust"];
1106     [m_webView willChangeValueForKey:@"certificateChain"];
1107 }
1108
1109 void NavigationState::didChangeCertificateInfo()
1110 {
1111     [m_webView didChangeValueForKey:@"certificateChain"];
1112     [m_webView didChangeValueForKey:@"serverTrust"];
1113 }
1114
1115 void NavigationState::willChangeWebProcessIsResponsive()
1116 {
1117     [m_webView willChangeValueForKey:@"_webProcessIsResponsive"];
1118 }
1119
1120 void NavigationState::didChangeWebProcessIsResponsive()
1121 {
1122     [m_webView didChangeValueForKey:@"_webProcessIsResponsive"];
1123 }
1124
1125 } // namespace WebKit
1126
1127 #endif