c54f7df91f2d5f45e0e07f091ec1b09a5c591e47
[WebKit-https.git] / Source / WebKit / WebProcess / WebCoreSupport / WebFrameLoaderClient.cpp
1 /*
2  * Copyright (C) 2010-2018 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 #include "config.h"
27 #include "WebFrameLoaderClient.h"
28
29 #include "AuthenticationManager.h"
30 #include "DataReference.h"
31 #include "DrawingArea.h"
32 #include "FindController.h"
33 #include "FormDataReference.h"
34 #include "FrameInfoData.h"
35 #include "InjectedBundle.h"
36 #include "InjectedBundleDOMWindowExtension.h"
37 #include "InjectedBundleNavigationAction.h"
38 #include "Logging.h"
39 #include "NavigationActionData.h"
40 #include "NetworkConnectionToWebProcessMessages.h"
41 #include "NetworkProcessConnection.h"
42 #include "PluginView.h"
43 #include "UserData.h"
44 #include "WKBundleAPICast.h"
45 #include "WebAutomationSessionProxy.h"
46 #include "WebBackForwardListProxy.h"
47 #include "WebCoreArgumentCoders.h"
48 #include "WebDocumentLoader.h"
49 #include "WebErrors.h"
50 #include "WebEvent.h"
51 #include "WebFrame.h"
52 #include "WebFrameNetworkingContext.h"
53 #include "WebFullScreenManager.h"
54 #include "WebNavigationDataStore.h"
55 #include "WebPage.h"
56 #include "WebPageGroupProxy.h"
57 #include "WebPageProxyMessages.h"
58 #include "WebProcess.h"
59 #include "WebProcessPoolMessages.h"
60 #include "WebsitePoliciesData.h"
61 #include <JavaScriptCore/APICast.h>
62 #include <JavaScriptCore/JSObject.h>
63 #include <WebCore/CachedFrame.h>
64 #include <WebCore/CertificateInfo.h>
65 #include <WebCore/Chrome.h>
66 #include <WebCore/DOMWrapperWorld.h>
67 #include <WebCore/DocumentLoader.h>
68 #include <WebCore/FormState.h>
69 #include <WebCore/Frame.h>
70 #include <WebCore/FrameLoadRequest.h>
71 #include <WebCore/FrameLoader.h>
72 #include <WebCore/FrameLoaderTypes.h>
73 #include <WebCore/FrameView.h>
74 #include <WebCore/HTMLAppletElement.h>
75 #include <WebCore/HTMLFormElement.h>
76 #include <WebCore/HistoryController.h>
77 #include <WebCore/HistoryItem.h>
78 #include <WebCore/MIMETypeRegistry.h>
79 #include <WebCore/MouseEvent.h>
80 #include <WebCore/NotImplemented.h>
81 #include <WebCore/Page.h>
82 #include <WebCore/PluginData.h>
83 #include <WebCore/PluginDocument.h>
84 #include <WebCore/PolicyChecker.h>
85 #include <WebCore/ProgressTracker.h>
86 #include <WebCore/ResourceError.h>
87 #include <WebCore/ResourceRequest.h>
88 #include <WebCore/ScriptController.h>
89 #include <WebCore/SecurityOriginData.h>
90 #include <WebCore/Settings.h>
91 #include <WebCore/SubframeLoader.h>
92 #include <WebCore/UIEventWithKeyState.h>
93 #include <WebCore/Widget.h>
94 #include <WebCore/WindowFeatures.h>
95 #include <wtf/NeverDestroyed.h>
96 #include <wtf/ProcessID.h>
97 #include <wtf/ProcessPrivilege.h>
98
99 namespace WebKit {
100 using namespace WebCore;
101
102 WebFrameLoaderClient::WebFrameLoaderClient()
103     : m_frame(0)
104     , m_hasSentResponseToPluginView(false)
105     , m_didCompletePageTransition(false)
106     , m_frameHasCustomContentProvider(false)
107     , m_frameCameFromPageCache(false)
108 {
109 }
110
111 WebFrameLoaderClient::~WebFrameLoaderClient()
112 {
113 }
114
115 Optional<WebPageProxyIdentifier> WebFrameLoaderClient::webPageProxyID() const
116 {
117     if (m_frame && m_frame->page())
118         return m_frame->page()->webPageProxyIdentifier();
119
120     return WTF::nullopt;
121 }
122
123 Optional<PageIdentifier> WebFrameLoaderClient::pageID() const
124 {
125     if (m_frame && m_frame->page())
126         return m_frame->page()->identifier();
127
128     return WTF::nullopt;
129 }
130
131 Optional<FrameIdentifier> WebFrameLoaderClient::frameID() const
132 {
133     if (m_frame)
134         return m_frame->frameID();
135
136     return WTF::nullopt;
137 }
138
139 PAL::SessionID WebFrameLoaderClient::sessionID() const
140 {
141     WebPage* page = m_frame ? m_frame->page() : nullptr;
142     if (!page || !page->corePage()) {
143         ASSERT_NOT_REACHED();
144         return PAL::SessionID::defaultSessionID();
145     }
146     return page->sessionID();
147 }
148
149 #if ENABLE(RESOURCE_LOAD_STATISTICS)
150 void WebFrameLoaderClient::setHasFrameSpecificStorageAccess(FrameSpecificStorageAccessIdentifier&& frameSpecificStorageAccessIdentifier )
151 {
152     ASSERT(!m_frameSpecificStorageAccessIdentifier);
153
154     m_frameSpecificStorageAccessIdentifier = WTFMove(frameSpecificStorageAccessIdentifier);
155 }
156 #endif
157
158 void WebFrameLoaderClient::frameLoaderDestroyed()
159 {
160     m_frame->invalidate();
161
162     // Balances explicit ref() in WebFrame::create().
163     m_frame->deref();
164 }
165
166 bool WebFrameLoaderClient::hasHTMLView() const
167 {
168     return !m_frameHasCustomContentProvider;
169 }
170
171 bool WebFrameLoaderClient::hasWebView() const
172 {
173     return m_frame->page();
174 }
175
176 void WebFrameLoaderClient::makeRepresentation(DocumentLoader*)
177 {
178     notImplemented();
179 }
180
181 void WebFrameLoaderClient::forceLayoutForNonHTML()
182 {
183     notImplemented();
184 }
185
186 void WebFrameLoaderClient::setCopiesOnScroll()
187 {
188     notImplemented();
189 }
190
191 void WebFrameLoaderClient::detachedFromParent2()
192 {
193     WebPage* webPage = m_frame->page();
194     if (!webPage)
195         return;
196
197 #if ENABLE(RESOURCE_LOAD_STATISTICS)
198     if (m_frameSpecificStorageAccessIdentifier) {
199         WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RemoveStorageAccessForFrame(
200             m_frameSpecificStorageAccessIdentifier->frameID, m_frameSpecificStorageAccessIdentifier->pageID), 0);
201         m_frameSpecificStorageAccessIdentifier = WTF::nullopt;
202     }
203 #endif
204
205     RefPtr<API::Object> userData;
206
207     // Notify the bundle client.
208     webPage->injectedBundleLoaderClient().didRemoveFrameFromHierarchy(*webPage, *m_frame, userData);
209 }
210
211 void WebFrameLoaderClient::detachedFromParent3()
212 {
213     notImplemented();
214 }
215
216 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
217 {
218     WebPage* webPage = m_frame->page();
219     if (!webPage)
220         return;
221
222     bool pageIsProvisionallyLoading = false;
223     if (FrameLoader* frameLoader = loader ? loader->frameLoader() : nullptr)
224         pageIsProvisionallyLoading = frameLoader->provisionalDocumentLoader() == loader;
225
226     webPage->injectedBundleResourceLoadClient().didInitiateLoadForResource(*webPage, *m_frame, identifier, request, pageIsProvisionallyLoading);
227     webPage->addResourceRequest(identifier, request);
228 }
229
230 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
231 {
232     WebPage* webPage = m_frame->page();
233     if (!webPage)
234         return;
235
236     // The API can return a completely new request. We should ensure that at least the requester
237     // is kept, so that if this is a main resource load it's still considered as such.
238     auto requester = request.requester();
239     webPage->injectedBundleResourceLoadClient().willSendRequestForFrame(*webPage, *m_frame, identifier, request, redirectResponse);
240     if (!request.isNull())
241         request.setRequester(requester);
242 }
243
244 bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier)
245 {
246     WebPage* webPage = m_frame->page();
247     if (!webPage)
248         return true;
249
250     return webPage->injectedBundleResourceLoadClient().shouldUseCredentialStorage(*webPage, *m_frame, identifier);
251 }
252
253 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&)
254 {
255     ASSERT_NOT_REACHED();
256 }
257
258 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
259 bool WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long, const ProtectionSpace& protectionSpace)
260 {
261     // The WebKit 2 Networking process asks the UIProcess directly, so the WebContent process should never receive this callback.
262     ASSERT_NOT_REACHED();
263     return false;
264 }
265 #endif
266
267 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse& response)
268 {
269     WebPage* webPage = m_frame->page();
270     if (!webPage)
271         return;
272
273     webPage->injectedBundleResourceLoadClient().didReceiveResponseForResource(*webPage, *m_frame, identifier, response);
274 }
275
276 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int dataLength)
277 {
278     WebPage* webPage = m_frame->page();
279     if (!webPage)
280         return;
281
282     webPage->injectedBundleResourceLoadClient().didReceiveContentLengthForResource(*webPage, *m_frame, identifier, dataLength);
283 }
284
285 #if ENABLE(DATA_DETECTION)
286 void WebFrameLoaderClient::dispatchDidFinishDataDetection(NSArray *detectionResults)
287 {
288     WebPage* webPage = m_frame->page();
289     if (!webPage)
290         return;
291     webPage->setDataDetectionResults(detectionResults);
292 }
293 #endif
294
295 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier)
296 {
297     WebPage* webPage = m_frame->page();
298     if (!webPage)
299         return;
300
301     webPage->injectedBundleResourceLoadClient().didFinishLoadForResource(*webPage, *m_frame, identifier);
302     webPage->removeResourceRequest(identifier);
303 }
304
305 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError& error)
306 {
307     WebPage* webPage = m_frame->page();
308     if (!webPage)
309         return;
310
311     webPage->injectedBundleResourceLoadClient().didFailLoadForResource(*webPage, *m_frame, identifier, error);
312     webPage->removeResourceRequest(identifier);
313 }
314
315 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/)
316 {
317     notImplemented();
318     return false;
319 }
320
321 void WebFrameLoaderClient::dispatchDidDispatchOnloadEvents()
322 {
323     WebPage* webPage = m_frame->page();
324     if (!webPage)
325         return;
326
327     // Notify the bundle client.
328     webPage->injectedBundleLoaderClient().didHandleOnloadEventsForFrame(*webPage, *m_frame);
329 }
330
331 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
332 {
333     WebPage* webPage = m_frame->page();
334     if (!webPage)
335         return;
336
337     WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(m_frame->coreFrame()->loader().provisionalDocumentLoader());
338     if (!documentLoader) {
339         RELEASE_LOG_FAULT(Loading, "WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad called with no provisional DocumentLoader. FrameState is %i. FrameLoaderStateMachine stateForDebugging - %i", m_frame->coreFrame()->loader().state(), m_frame->coreFrame()->loader().stateMachine().stateForDebugging());
340         return;
341     }
342
343     RefPtr<API::Object> userData;
344
345     LOG(Loading, "WebProcess %i - dispatchDidReceiveServerRedirectForProvisionalLoad to request url %s", getCurrentProcessID(), documentLoader->request().url().string().utf8().data());
346
347     // Notify the bundle client.
348     webPage->injectedBundleLoaderClient().didReceiveServerRedirectForProvisionalLoadForFrame(*webPage, *m_frame, userData);
349
350     // Notify the UIProcess.
351     webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader->navigationID(), documentLoader->request(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
352 }
353
354 void WebFrameLoaderClient::dispatchDidChangeProvisionalURL()
355 {
356     WebPage* webPage = m_frame->page();
357     if (!webPage)
358         return;
359
360     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader());
361     webPage->send(Messages::WebPageProxy::DidChangeProvisionalURLForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.url()));
362 }
363
364 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
365 {
366     WebPage* webPage = m_frame->page();
367     if (!webPage)
368         return;
369
370     // Notify the bundle client.
371     webPage->injectedBundleLoaderClient().didCancelClientRedirectForFrame(*webPage, *m_frame);
372
373     // Notify the UIProcess.
374     webPage->send(Messages::WebPageProxy::DidCancelClientRedirectForFrame(m_frame->frameID()));
375 }
376
377 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const URL& url, double interval, WallTime fireDate, LockBackForwardList lockBackForwardList)
378 {
379     WebPage* webPage = m_frame->page();
380     if (!webPage)
381         return;
382
383     // Notify the bundle client.
384     webPage->injectedBundleLoaderClient().willPerformClientRedirectForFrame(*webPage, *m_frame, url, interval, fireDate);
385
386     // Notify the UIProcess.
387     webPage->send(Messages::WebPageProxy::WillPerformClientRedirectForFrame(m_frame->frameID(), url.string(), interval, lockBackForwardList));
388 }
389
390 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
391 {
392     WebPage* webPage = m_frame->page();
393     if (!webPage)
394         return;
395
396     RefPtr<API::Object> userData;
397
398     auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
399
400     // Notify the bundle client.
401     webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationAnchorNavigation, userData);
402
403     // Notify the UIProcess.
404     webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationAnchorNavigation, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
405 }
406
407 void WebFrameLoaderClient::dispatchDidChangeMainDocument()
408 {
409     WebPage* webPage = m_frame->page();
410     if (!webPage)
411         return;
412
413     webPage->send(Messages::WebPageProxy::DidChangeMainDocument(m_frame->frameID()));
414 }
415
416 void WebFrameLoaderClient::dispatchWillChangeDocument(const URL& currentUrl, const URL& newUrl)
417 {
418 #if ENABLE(RESOURCE_LOAD_STATISTICS)
419     if (m_frame->isMainFrame())
420         return;
421
422     WebPage* webPage = m_frame->page();
423     if (!webPage)
424         return;
425
426     if (m_frameSpecificStorageAccessIdentifier && !WebCore::areRegistrableDomainsEqual(currentUrl, newUrl)) {
427         WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RemoveStorageAccessForFrame(
428             m_frameSpecificStorageAccessIdentifier->frameID, m_frameSpecificStorageAccessIdentifier->pageID), 0);
429         m_frameSpecificStorageAccessIdentifier = WTF::nullopt;
430     }
431 #endif
432 }
433
434 void WebFrameLoaderClient::dispatchDidPushStateWithinPage()
435 {
436     WebPage* webPage = m_frame->page();
437     if (!webPage)
438         return;
439
440     RefPtr<API::Object> userData;
441
442     auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
443
444     // Notify the bundle client.
445     webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationSessionStatePush, userData);
446
447     // Notify the UIProcess.
448     webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStatePush, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
449 }
450
451 void WebFrameLoaderClient::dispatchDidReplaceStateWithinPage()
452 {
453     WebPage* webPage = m_frame->page();
454     if (!webPage)
455         return;
456
457     RefPtr<API::Object> userData;
458
459     auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
460
461     // Notify the bundle client.
462     webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationSessionStateReplace, userData);
463
464     // Notify the UIProcess.
465     webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStateReplace, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
466 }
467
468 void WebFrameLoaderClient::dispatchDidPopStateWithinPage()
469 {
470     WebPage* webPage = m_frame->page();
471     if (!webPage)
472         return;
473
474     RefPtr<API::Object> userData;
475
476     auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
477
478     // Notify the bundle client.
479     webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationSessionStatePop, userData);
480
481     // Notify the UIProcess.
482     webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStatePop, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
483 }
484
485 void WebFrameLoaderClient::dispatchWillClose()
486 {
487     notImplemented();
488 }
489
490 void WebFrameLoaderClient::dispatchDidExplicitOpen(const URL& url)
491 {
492     auto* webPage = m_frame->page();
493     if (!webPage)
494         return;
495
496     // Notify the UIProcess.
497     webPage->send(Messages::WebPageProxy::DidExplicitOpenForFrame(m_frame->frameID(), url));
498 }
499
500 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
501 {
502     WebPage* webPage = m_frame->page();
503     if (!webPage)
504         return;
505
506 #if ENABLE(FULLSCREEN_API)
507     Element* documentElement = m_frame->coreFrame()->document()->documentElement();
508     if (documentElement && documentElement->containsFullScreenElement())
509         webPage->fullScreenManager()->exitFullScreenForElement(webPage->fullScreenManager()->element());
510 #endif
511
512     webPage->findController().hideFindUI();
513     webPage->sandboxExtensionTracker().didStartProvisionalLoad(m_frame);
514
515     WebDocumentLoader& provisionalLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader());
516     auto& url = provisionalLoader.url();
517     RefPtr<API::Object> userData;
518
519     // Notify the bundle client.
520     webPage->injectedBundleLoaderClient().didStartProvisionalLoadForFrame(*webPage, *m_frame, userData);
521
522     auto& unreachableURL = provisionalLoader.unreachableURL();
523
524     // Notify the UIProcess.
525     webPage->send(Messages::WebPageProxy::DidStartProvisionalLoadForFrame(m_frame->frameID(), provisionalLoader.navigationID(), url, unreachableURL, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
526 }
527
528 static constexpr unsigned maxTitleLength = 1000; // Closest power of 10 above the W3C recommendation for Title length.
529
530 void WebFrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title)
531 {
532     WebPage* webPage = m_frame->page();
533     if (!webPage)
534         return;
535
536     auto truncatedTitle = truncateFromEnd(title, maxTitleLength);
537     
538     RefPtr<API::Object> userData;
539
540     // Notify the bundle client.
541     // FIXME: Use direction of title.
542     webPage->injectedBundleLoaderClient().didReceiveTitleForFrame(*webPage, truncatedTitle.string, *m_frame, userData);
543
544     // Notify the UIProcess.
545     webPage->send(Messages::WebPageProxy::DidReceiveTitleForFrame(m_frame->frameID(), truncatedTitle.string, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
546 }
547
548 void WebFrameLoaderClient::dispatchDidCommitLoad(Optional<HasInsecureContent> hasInsecureContent)
549 {
550     WebPage* webPage = m_frame->page();
551     if (!webPage)
552         return;
553
554     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
555     RefPtr<API::Object> userData;
556
557     // Notify the bundle client.
558     webPage->injectedBundleLoaderClient().didCommitLoadForFrame(*webPage, *m_frame, userData);
559
560     webPage->sandboxExtensionTracker().didCommitProvisionalLoad(m_frame);
561
562     // Notify the UIProcess.
563     webPage->send(Messages::WebPageProxy::DidCommitLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.response().mimeType(), m_frameHasCustomContentProvider, static_cast<uint32_t>(m_frame->coreFrame()->loader().loadType()), valueOrCompute(documentLoader.response().certificateInfo(), [] { return CertificateInfo(); }), m_frame->coreFrame()->document()->isPluginDocument(), hasInsecureContent, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
564     webPage->didCommitLoad(m_frame);
565 }
566
567 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error, WillContinueLoading willContinueLoading)
568 {
569     WebPage* webPage = m_frame->page();
570     if (!webPage)
571         return;
572
573     RELEASE_LOG(Network, "%p - WebFrameLoaderClient::dispatchDidFailProvisionalLoad: (pageID = %" PRIu64 ", frameID = %" PRIu64 ")", this, webPage->identifier().toUInt64(), m_frame->frameID().toUInt64());
574
575     RefPtr<API::Object> userData;
576
577     // Notify the bundle client.
578     webPage->injectedBundleLoaderClient().didFailProvisionalLoadWithErrorForFrame(*webPage, *m_frame, error, userData);
579
580     webPage->sandboxExtensionTracker().didFailProvisionalLoad(m_frame);
581
582     // FIXME: This is gross. This is necessary because if the client calls WKBundlePageStopLoading() from within the didFailProvisionalLoadWithErrorForFrame
583     // injected bundle client call, that will cause the provisional DocumentLoader to be disconnected from the Frame, and didDistroyNavigation message
584     // to be sent to the UIProcess (and the destruction of the DocumentLoader). If that happens, and we had captured the navigationID before injected bundle 
585     // client call, the DidFailProvisionalLoadForFrame would send a navigationID of a destroyed Navigation, and the UIProcess would not be able to find it
586     // in its table.
587     //
588     // A better solution to this problem would be find a clean way to postpone the disconnection of the DocumentLoader from the Frame until
589     // the entire FrameLoaderClient function was complete.
590     uint64_t navigationID = 0;
591     if (auto documentLoader = m_frame->coreFrame()->loader().provisionalDocumentLoader())
592         navigationID = static_cast<WebDocumentLoader*>(documentLoader)->navigationID();
593
594     // Notify the UIProcess.
595     WebCore::Frame* coreFrame = m_frame ? m_frame->coreFrame() : nullptr;
596     webPage->send(Messages::WebPageProxy::DidFailProvisionalLoadForFrame(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), navigationID, m_frame->coreFrame()->loader().provisionalLoadErrorBeingHandledURL(), error, willContinueLoading, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
597
598     // If we have a load listener, notify it.
599     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
600         loadListener->didFailLoad(m_frame, error.isCancellation());
601 }
602
603 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
604 {
605     WebPage* webPage = m_frame->page();
606     if (!webPage)
607         return;
608
609     RELEASE_LOG(Network, "%p - WebFrameLoaderClient::dispatchDidFailLoad: (pageID = %" PRIu64 ", frameID = %" PRIu64 ")", this, webPage->identifier().toUInt64(), m_frame->frameID().toUInt64());
610
611     RefPtr<API::Object> userData;
612
613     auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
614
615     // Notify the bundle client.
616     webPage->injectedBundleLoaderClient().didFailLoadWithErrorForFrame(*webPage, *m_frame, error, userData);
617
618     // Notify the UIProcess.
619     webPage->send(Messages::WebPageProxy::DidFailLoadForFrame(m_frame->frameID(), navigationID, error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
620
621     // If we have a load listener, notify it.
622     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
623         loadListener->didFailLoad(m_frame, error.isCancellation());
624 }
625
626 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
627 {
628     WebPage* webPage = m_frame->page();
629     if (!webPage)
630         return;
631
632     RefPtr<API::Object> userData;
633
634     auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
635
636     // Notify the bundle client.
637     webPage->injectedBundleLoaderClient().didFinishDocumentLoadForFrame(*webPage, *m_frame, userData);
638
639     // Notify the UIProcess.
640     webPage->send(Messages::WebPageProxy::DidFinishDocumentLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
641
642     webPage->didFinishDocumentLoad(*m_frame);
643 }
644
645 void WebFrameLoaderClient::dispatchDidFinishLoad()
646 {
647     WebPage* webPage = m_frame->page();
648     if (!webPage)
649         return;
650
651     RefPtr<API::Object> userData;
652
653     auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
654
655     // Notify the bundle client.
656     webPage->injectedBundleLoaderClient().didFinishLoadForFrame(*webPage, *m_frame, userData);
657
658     // Notify the UIProcess.
659     webPage->send(Messages::WebPageProxy::DidFinishLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
660
661     // If we have a load listener, notify it.
662     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
663         loadListener->didFinishLoad(m_frame);
664
665     webPage->didFinishLoad(*m_frame);
666 }
667
668 void WebFrameLoaderClient::forcePageTransitionIfNeeded()
669 {
670     if (m_didCompletePageTransition)
671         return;
672
673     WebPage* webPage = m_frame->page();
674     if (!webPage)
675         return;
676
677     webPage->didCompletePageTransition();
678     m_didCompletePageTransition = true;
679 }
680
681 void WebFrameLoaderClient::dispatchDidReachLayoutMilestone(OptionSet<WebCore::LayoutMilestone> milestones)
682 {
683     WebPage* webPage = m_frame->page();
684     if (!webPage)
685         return;
686
687     RefPtr<API::Object> userData;
688
689     if (milestones & DidFirstLayout) {
690         RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching DidFirstLayoutForFrame, page = %p", this, webPage);
691
692         // FIXME: We should consider removing the old didFirstLayout API since this is doing double duty with the
693         // new didLayout API.
694         webPage->injectedBundleLoaderClient().didFirstLayoutForFrame(*webPage, *m_frame, userData);
695         webPage->send(Messages::WebPageProxy::DidFirstLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
696
697 #if PLATFORM(MAC)
698         // FIXME: Do this on DidFirstVisuallyNonEmptyLayout when Mac Safari is able to handle it (<rdar://problem/17580021>)
699         if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) {
700             RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching didCompletePageTransition, page = %p", this, webPage);
701             webPage->didCompletePageTransition();
702             m_didCompletePageTransition = true;
703         }
704 #endif
705
706 #if USE(COORDINATED_GRAPHICS)
707         // Make sure viewport properties are dispatched on the main frame by the time the first layout happens.
708         ASSERT(!webPage->useFixedLayout() || m_frame != m_frame->page()->mainWebFrame() || m_frame->coreFrame()->document()->didDispatchViewportPropertiesChanged());
709 #endif
710     }
711
712 #if !RELEASE_LOG_DISABLED
713     StringBuilder builder;
714     auto addIfSet = [&milestones, &builder] (WebCore::LayoutMilestone milestone, const String& toAdd) {
715         if (milestones.contains(milestone)) {
716             if (!builder.isEmpty())
717                 builder.append(", ");
718             builder.append(toAdd);
719         }
720     };
721
722     addIfSet(DidFirstLayout, "DidFirstLayout"_s);
723     addIfSet(DidFirstVisuallyNonEmptyLayout, "DidFirstVisuallyNonEmptyLayout"_s);
724     addIfSet(DidHitRelevantRepaintedObjectsAreaThreshold, "DidHitRelevantRepaintedObjectsAreaThreshold"_s);
725     addIfSet(DidFirstFlushForHeaderLayer, "DidFirstFlushForHeaderLayer"_s);
726     addIfSet(DidFirstLayoutAfterSuppressedIncrementalRendering, "DidFirstLayoutAfterSuppressedIncrementalRendering"_s);
727     addIfSet(DidFirstPaintAfterSuppressedIncrementalRendering, "DidFirstPaintAfterSuppressedIncrementalRendering"_s);
728     addIfSet(ReachedSessionRestorationRenderTreeSizeThreshold, "ReachedSessionRestorationRenderTreeSizeThreshold"_s);
729     addIfSet(DidRenderSignificantAmountOfText, "DidRenderSignificantAmountOfText"_s);
730     addIfSet(DidFirstMeaningfulPaint, "DidFirstMeaningfulPaint"_s);
731
732     RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching DidReachLayoutMilestone, page = %p, milestones = %{public}s", this, webPage, builder.toString().utf8().data());
733 #endif
734
735     // Send this after DidFirstLayout-specific calls since some clients expect to get those messages first.
736     webPage->dispatchDidReachLayoutMilestone(milestones);
737
738     if (milestones & DidFirstVisuallyNonEmptyLayout) {
739         if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) {
740             RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching didCompletePageTransition, page = %p", this, webPage);
741             webPage->didCompletePageTransition();
742             m_didCompletePageTransition = true;
743         }
744
745         // FIXME: We should consider removing the old didFirstVisuallyNonEmptyLayoutForFrame API since this is doing
746         // double duty with the new didLayout API.
747         RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching DidFirstVisuallyNonEmptyLayoutForFrame, page = %p", this, webPage);
748         webPage->injectedBundleLoaderClient().didFirstVisuallyNonEmptyLayoutForFrame(*webPage, *m_frame, userData);
749         webPage->send(Messages::WebPageProxy::DidFirstVisuallyNonEmptyLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
750     }
751 }
752
753 void WebFrameLoaderClient::dispatchDidLayout()
754 {
755     WebPage* webPage = m_frame->page();
756     if (!webPage)
757         return;
758
759     // Notify the bundle client.
760     webPage->injectedBundleLoaderClient().didLayoutForFrame(*webPage, *m_frame);
761
762     webPage->recomputeShortCircuitHorizontalWheelEventsState();
763
764 #if PLATFORM(IOS_FAMILY)
765     webPage->updateSelectionAppearance();
766 #endif
767
768     // NOTE: Unlike the other layout notifications, this does not notify the
769     // the UIProcess for every call.
770
771     if (m_frame == m_frame->page()->mainWebFrame()) {
772         // FIXME: Remove at the soonest possible time.
773         webPage->send(Messages::WebPageProxy::SetRenderTreeSize(webPage->renderTreeSize()));
774         webPage->mainFrameDidLayout();
775     }
776 }
777
778 Frame* WebFrameLoaderClient::dispatchCreatePage(const NavigationAction& navigationAction)
779 {
780     WebPage* webPage = m_frame->page();
781     if (!webPage)
782         return nullptr;
783
784     // Just call through to the chrome client.
785     FrameLoadRequest frameLoadRequest { *m_frame->coreFrame()->document(), m_frame->coreFrame()->document()->securityOrigin(), navigationAction.resourceRequest(), { }, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, navigationAction.shouldOpenExternalURLsPolicy(), InitiatedByMainFrame::Unknown };
786     Page* newPage = webPage->corePage()->chrome().createWindow(*m_frame->coreFrame(), frameLoadRequest, { }, navigationAction);
787     if (!newPage)
788         return nullptr;
789     
790     return &newPage->mainFrame();
791 }
792
793 void WebFrameLoaderClient::dispatchShow()
794 {
795     WebPage* webPage = m_frame->page();
796     if (!webPage)
797         return;
798
799     webPage->show();
800 }
801
802 void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, WebCore::PolicyCheckIdentifier identifier, const String& downloadAttribute, FramePolicyFunction&& function)
803 {
804     WebPage* webPage = m_frame ? m_frame->page() : nullptr;
805     if (!webPage) {
806         function(PolicyAction::Ignore, identifier);
807         return;
808     }
809
810     if (!request.url().string()) {
811         function(PolicyAction::Use, identifier);
812         return;
813     }
814
815     RefPtr<API::Object> userData;
816
817     // Notify the bundle client.
818     WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForResponse(webPage, m_frame, response, request, userData);
819     if (policy == WKBundlePagePolicyActionUse) {
820         function(PolicyAction::Use, identifier);
821         return;
822     }
823
824     bool canShowResponse = webPage->canShowResponse(response);
825
826     WebCore::Frame* coreFrame = m_frame->coreFrame();
827     auto* policyDocumentLoader = coreFrame ? coreFrame->loader().provisionalDocumentLoader() : nullptr;
828     auto navigationID = policyDocumentLoader ? static_cast<WebDocumentLoader&>(*policyDocumentLoader).navigationID() : 0;
829     
830     Ref<WebFrame> protector(*m_frame);
831     uint64_t listenerID = m_frame->setUpPolicyListener(identifier, WTFMove(function), WebFrame::ForNavigationAction::No);
832     if (!webPage->send(Messages::WebPageProxy::DecidePolicyForResponse(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), identifier, navigationID, response, request,
833         canShowResponse, downloadAttribute, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))))
834         m_frame->didReceivePolicyDecision(listenerID, identifier, PolicyAction::Ignore, 0, { }, { });
835 }
836
837 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(const NavigationAction& navigationAction, const ResourceRequest& request,
838     FormState* formState, const String& frameName, WebCore::PolicyCheckIdentifier identifier, FramePolicyFunction&& function)
839 {
840     WebPage* webPage = m_frame ? m_frame->page() : nullptr;
841     if (!webPage) {
842         function(PolicyAction::Ignore, identifier);
843         return;
844     }
845
846     RefPtr<API::Object> userData;
847
848     auto action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
849
850     // Notify the bundle client.
851     WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNewWindowAction(webPage, m_frame, action.ptr(), request, frameName, userData);
852     if (policy == WKBundlePagePolicyActionUse) {
853         function(PolicyAction::Use, identifier);
854         return;
855     }
856
857     uint64_t listenerID = m_frame->setUpPolicyListener(identifier, WTFMove(function), WebFrame::ForNavigationAction::No);
858
859     NavigationActionData navigationActionData;
860     navigationActionData.navigationType = action->navigationType();
861     navigationActionData.modifiers = action->modifiers();
862     navigationActionData.mouseButton = action->mouseButton();
863     navigationActionData.syntheticClickType = action->syntheticClickType();
864     navigationActionData.clickLocationInRootViewCoordinates = action->clickLocationInRootViewCoordinates();
865     navigationActionData.userGestureTokenIdentifier = WebProcess::singleton().userGestureTokenIdentifier(navigationAction.userGestureToken());
866     navigationActionData.canHandleRequest = webPage->canHandleRequest(request);
867     navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy();
868     navigationActionData.downloadAttribute = navigationAction.downloadAttribute();
869
870     WebCore::Frame* coreFrame = m_frame ? m_frame->coreFrame() : nullptr;
871     webPage->send(Messages::WebPageProxy::DecidePolicyForNewWindowAction(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), identifier, navigationActionData, request,
872         frameName, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
873 }
874
875 void WebFrameLoaderClient::applyToDocumentLoader(WebsitePoliciesData&& websitePolicies)
876 {
877     if (!m_frame)
878         return;
879     auto* coreFrame = m_frame->coreFrame();
880     if (!coreFrame)
881         return;
882     WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader());
883     if (!documentLoader)
884         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader());
885     if (!documentLoader)
886         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
887     if (!documentLoader)
888         return;
889
890     WebsitePoliciesData::applyToDocumentLoader(WTFMove(websitePolicies), *documentLoader);
891 }
892
893 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const NavigationAction& navigationAction, const ResourceRequest& request, const ResourceResponse& redirectResponse,
894     FormState* formState, PolicyDecisionMode policyDecisionMode, WebCore::PolicyCheckIdentifier requestIdentifier, FramePolicyFunction&& function)
895 {
896     WebPage* webPage = m_frame ? m_frame->page() : nullptr;
897     if (!webPage) {
898         function(PolicyAction::Ignore, requestIdentifier);
899         return;
900     }
901
902     LOG(Loading, "WebProcess %i - dispatchDecidePolicyForNavigationAction to request url %s", getCurrentProcessID(), request.url().string().utf8().data());
903
904     // Always ignore requests with empty URLs. 
905     if (request.isEmpty()) {
906         function(PolicyAction::Ignore, requestIdentifier);
907         return;
908     }
909
910     RefPtr<API::Object> userData;
911
912     Ref<InjectedBundleNavigationAction> action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
913
914     // Notify the bundle client.
915     WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNavigationAction(webPage, m_frame, action.ptr(), request, userData);
916     if (policy == WKBundlePagePolicyActionUse) {
917         function(PolicyAction::Use, requestIdentifier);
918         return;
919     }
920
921     uint64_t listenerID = m_frame->setUpPolicyListener(requestIdentifier, WTFMove(function), WebFrame::ForNavigationAction::Yes);
922
923     ASSERT(navigationAction.requester());
924     auto requester = navigationAction.requester().value();
925
926     FrameInfoData originatingFrameInfoData;
927     originatingFrameInfoData.isMainFrame = navigationAction.initiatedByMainFrame() == InitiatedByMainFrame::Yes;
928     originatingFrameInfoData.request = ResourceRequest { requester.url() };
929     originatingFrameInfoData.securityOrigin = requester.securityOrigin().data();
930     if (requester.frameID() && WebProcess::singleton().webFrame(requester.frameID()))
931         originatingFrameInfoData.frameID = requester.frameID();
932
933     Optional<WebPageProxyIdentifier> originatingPageID;
934     if (requester.pageID()) {
935         if (auto* webPage = WebProcess::singleton().webPage(requester.pageID()))
936             originatingPageID = webPage->webPageProxyIdentifier();
937     }
938
939     NavigationActionData navigationActionData;
940     navigationActionData.navigationType = action->navigationType();
941     navigationActionData.modifiers = action->modifiers();
942     navigationActionData.mouseButton = action->mouseButton();
943     navigationActionData.syntheticClickType = action->syntheticClickType();
944     navigationActionData.clickLocationInRootViewCoordinates = action->clickLocationInRootViewCoordinates();
945     navigationActionData.userGestureTokenIdentifier = WebProcess::singleton().userGestureTokenIdentifier(navigationAction.userGestureToken());
946     navigationActionData.canHandleRequest = webPage->canHandleRequest(request);
947     navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy();
948     navigationActionData.downloadAttribute = navigationAction.downloadAttribute();
949     navigationActionData.isRedirect = !redirectResponse.isNull();
950     navigationActionData.treatAsSameOriginNavigation = navigationAction.treatAsSameOriginNavigation();
951     navigationActionData.hasOpenedFrames = navigationAction.hasOpenedFrames();
952     navigationActionData.openedByDOMWithOpener = navigationAction.openedByDOMWithOpener();
953     if (auto& requester = navigationAction.requester())
954         navigationActionData.requesterOrigin = requester->securityOrigin().data();
955     navigationActionData.targetBackForwardItemIdentifier = navigationAction.targetBackForwardItemIdentifier();
956     navigationActionData.sourceBackForwardItemIdentifier = navigationAction.sourceBackForwardItemIdentifier();
957     navigationActionData.lockHistory = navigationAction.lockHistory();
958     navigationActionData.lockBackForwardList = navigationAction.lockBackForwardList();
959     navigationActionData.adClickAttribution = navigationAction.adClickAttribution();
960
961     WebCore::Frame* coreFrame = m_frame->coreFrame();
962     if (!coreFrame)
963         return function(PolicyAction::Ignore, requestIdentifier);
964     WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader());
965     if (!documentLoader) {
966         // FIXME: When we receive a redirect after the navigation policy has been decided for the initial request,
967         // the provisional load's DocumentLoader needs to receive navigation policy decisions. We need a better model for this state.
968         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader());
969     }
970     if (!documentLoader)
971         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
972
973     navigationActionData.clientRedirectSourceForHistory = documentLoader->clientRedirectSourceForHistory();
974
975     // Notify the UIProcess.
976     Ref<WebFrame> protect(*m_frame);
977
978     if (policyDecisionMode == PolicyDecisionMode::Synchronous) {
979         uint64_t newNavigationID;
980         WebCore::PolicyCheckIdentifier responseIdentifier;
981         PolicyAction policyAction;
982         DownloadID downloadID;
983         Optional<WebsitePoliciesData> websitePolicies;
984
985         if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationActionSync(m_frame->frameID(), m_frame->isMainFrame(), SecurityOriginData::fromFrame(coreFrame),
986             requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request,
987             IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())),
988             Messages::WebPageProxy::DecidePolicyForNavigationActionSync::Reply(responseIdentifier, policyAction, newNavigationID, downloadID, websitePolicies))) {
989             m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { });
990             return;
991         }
992
993         m_frame->didReceivePolicyDecision(listenerID, responseIdentifier, policyAction, 0, downloadID, { });
994         return;
995     }
996
997     ASSERT(policyDecisionMode == PolicyDecisionMode::Asynchronous);
998     if (!webPage->send(Messages::WebPageProxy::DecidePolicyForNavigationActionAsync(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame),
999         requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request,
1000         IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()), listenerID)))
1001         m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { });
1002 }
1003
1004 void WebFrameLoaderClient::cancelPolicyCheck()
1005 {
1006     m_frame->invalidatePolicyListener();
1007 }
1008
1009 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
1010 {
1011     WebPage* webPage = m_frame->page();
1012     if (!webPage)
1013         return;
1014
1015     RefPtr<API::Object> userData;
1016
1017     // Notify the bundle client.
1018     webPage->injectedBundlePolicyClient().unableToImplementPolicy(webPage, m_frame, error, userData);
1019
1020     // Notify the UIProcess.
1021     webPage->send(Messages::WebPageProxy::UnableToImplementPolicy(m_frame->frameID(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1022 }
1023
1024 void WebFrameLoaderClient::dispatchWillSendSubmitEvent(Ref<FormState>&& formState)
1025 {
1026     auto* webPage = m_frame->page();
1027     if (!webPage)
1028         return;
1029
1030     auto& form = formState->form();
1031
1032     ASSERT(formState->sourceDocument().frame());
1033     auto* sourceFrame = WebFrame::fromCoreFrame(*formState->sourceDocument().frame());
1034     ASSERT(sourceFrame);
1035
1036     webPage->injectedBundleFormClient().willSendSubmitEvent(webPage, &form, m_frame, sourceFrame, formState->textFieldValues());
1037 }
1038
1039 void WebFrameLoaderClient::dispatchWillSubmitForm(FormState& formState, CompletionHandler<void()>&& completionHandler)
1040 {
1041     WebPage* webPage = m_frame->page();
1042     if (!webPage) {
1043         completionHandler();
1044         return;
1045     }
1046
1047     auto& form = formState.form();
1048
1049     auto* sourceCoreFrame = formState.sourceDocument().frame();
1050     if (!sourceCoreFrame)
1051         return completionHandler();
1052     auto* sourceFrame = WebFrame::fromCoreFrame(*sourceCoreFrame);
1053     if (!sourceFrame)
1054         return completionHandler();
1055
1056     auto& values = formState.textFieldValues();
1057
1058     RefPtr<API::Object> userData;
1059     webPage->injectedBundleFormClient().willSubmitForm(webPage, &form, m_frame, sourceFrame, values, userData);
1060
1061     uint64_t listenerID = m_frame->setUpWillSubmitFormListener(WTFMove(completionHandler));
1062
1063     webPage->send(Messages::WebPageProxy::WillSubmitForm(m_frame->frameID(), sourceFrame->frameID(), values, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1064 }
1065
1066 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader*)
1067 {
1068     notImplemented();
1069 }
1070
1071 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
1072 {
1073     if (!m_pluginView)
1074         return;
1075     
1076     m_pluginView->manualLoadDidFail(error);
1077     m_pluginView = nullptr;
1078     m_hasSentResponseToPluginView = false;
1079 }
1080
1081 void WebFrameLoaderClient::setMainFrameDocumentReady(bool)
1082 {
1083     notImplemented();
1084 }
1085
1086 void WebFrameLoaderClient::startDownload(const ResourceRequest& request, const String& suggestedName)
1087 {
1088     m_frame->startDownload(request, suggestedName);
1089 }
1090
1091 void WebFrameLoaderClient::willChangeTitle(DocumentLoader*)
1092 {
1093     notImplemented();
1094 }
1095
1096 void WebFrameLoaderClient::didChangeTitle(DocumentLoader*)
1097 {
1098     notImplemented();
1099 }
1100
1101 void WebFrameLoaderClient::willReplaceMultipartContent()
1102 {
1103     WebPage* webPage = m_frame->page();
1104     if (!webPage)
1105         return;
1106     webPage->willReplaceMultipartContent(*m_frame);
1107 }
1108
1109 void WebFrameLoaderClient::didReplaceMultipartContent()
1110 {
1111     WebPage* webPage = m_frame->page();
1112     if (!webPage)
1113         return;
1114     webPage->didReplaceMultipartContent(*m_frame);
1115 }
1116
1117 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
1118 {
1119     if (!m_pluginView)
1120         loader->commitData(data, length);
1121
1122     // If the document is a stand-alone media document, now is the right time to cancel the WebKit load.
1123     // FIXME: This code should be shared across all ports. <http://webkit.org/b/48762>.
1124     if (m_frame->coreFrame()->document()->isMediaDocument())
1125         loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
1126
1127     // Calling commitData did not create the plug-in view.
1128     if (!m_pluginView)
1129         return;
1130
1131     if (!m_hasSentResponseToPluginView) {
1132         m_pluginView->manualLoadDidReceiveResponse(loader->response());
1133         // manualLoadDidReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
1134         // setting up this stream can cause the main document load to be cancelled, setting m_pluginView
1135         // to null
1136         if (!m_pluginView)
1137             return;
1138         m_hasSentResponseToPluginView = true;
1139     }
1140     m_pluginView->manualLoadDidReceiveData(data, length);
1141 }
1142
1143 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
1144 {
1145     if (!m_pluginView) {
1146         if (m_frameHasCustomContentProvider) {
1147             WebPage* webPage = m_frame->page();
1148             if (!webPage)
1149                 return;
1150
1151             RefPtr<SharedBuffer> mainResourceData = loader->mainResourceData();
1152             IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(mainResourceData ? mainResourceData->data() : 0), mainResourceData ? mainResourceData->size() : 0);
1153             webPage->send(Messages::WebPageProxy::DidFinishLoadingDataForCustomContentProvider(loader->response().suggestedFilename(), dataReference));
1154         }
1155
1156         return;
1157     }
1158
1159     // If we just received an empty response without any data, we won't have sent a response to the plug-in view.
1160     // Make sure to do this before calling manualLoadDidFinishLoading.
1161     if (!m_hasSentResponseToPluginView) {
1162         m_pluginView->manualLoadDidReceiveResponse(loader->response());
1163
1164         // Protect against the above call nulling out the plug-in (by trying to cancel the load for example).
1165         if (!m_pluginView)
1166             return;
1167     }
1168
1169     m_pluginView->manualLoadDidFinishLoading();
1170     m_pluginView = nullptr;
1171     m_hasSentResponseToPluginView = false;
1172 }
1173
1174 void WebFrameLoaderClient::updateGlobalHistory()
1175 {
1176     WebPage* webPage = m_frame->page();
1177     if (!webPage)
1178         return;
1179
1180     DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1181
1182     WebNavigationDataStore data;
1183     data.url = loader->url().string();
1184     // FIXME: Use direction of title.
1185     data.title = loader->title().string;
1186     data.originalRequest = loader->originalRequestCopy();
1187     data.response = loader->response();
1188
1189     webPage->send(Messages::WebPageProxy::DidNavigateWithNavigationData(data, m_frame->frameID()));
1190 }
1191
1192 void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
1193 {
1194     WebPage* webPage = m_frame->page();
1195     if (!webPage)
1196         return;
1197
1198     DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1199     ASSERT(loader->unreachableURL().isEmpty());
1200
1201     // Client redirect
1202     if (!loader->clientRedirectSourceForHistory().isNull()) {
1203         webPage->send(Messages::WebPageProxy::DidPerformClientRedirect(
1204             loader->clientRedirectSourceForHistory(), loader->clientRedirectDestinationForHistory(), m_frame->frameID()));
1205     }
1206
1207     // Server redirect
1208     if (!loader->serverRedirectSourceForHistory().isNull()) {
1209         webPage->send(Messages::WebPageProxy::DidPerformServerRedirect(
1210             loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_frame->frameID()));
1211     }
1212 }
1213
1214 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem& item) const
1215 {
1216     WebPage* webPage = m_frame->page();
1217     if (!webPage)
1218         return false;
1219     webPage->send(Messages::WebPageProxy::WillGoToBackForwardListItem(item.identifier(), item.isInPageCache()));
1220     return true;
1221 }
1222
1223 void WebFrameLoaderClient::didDisplayInsecureContent()
1224 {
1225     WebPage* webPage = m_frame->page();
1226     if (!webPage)
1227         return;
1228
1229     RefPtr<API::Object> userData;
1230
1231     webPage->injectedBundleLoaderClient().didDisplayInsecureContentForFrame(*webPage, *m_frame, userData);
1232
1233     webPage->send(Messages::WebPageProxy::DidDisplayInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1234 }
1235
1236 void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin&, const URL&)
1237 {
1238     WebPage* webPage = m_frame->page();
1239     if (!webPage)
1240         return;
1241
1242     RefPtr<API::Object> userData;
1243
1244     webPage->injectedBundleLoaderClient().didRunInsecureContentForFrame(*webPage, *m_frame, userData);
1245
1246     webPage->send(Messages::WebPageProxy::DidRunInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1247 }
1248
1249 void WebFrameLoaderClient::didDetectXSS(const URL&, bool)
1250 {
1251     WebPage* webPage = m_frame->page();
1252     if (!webPage)
1253         return;
1254
1255     RefPtr<API::Object> userData;
1256
1257     webPage->injectedBundleLoaderClient().didDetectXSSForFrame(*webPage, *m_frame, userData);
1258
1259     webPage->send(Messages::WebPageProxy::DidDetectXSSForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1260 }
1261
1262 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
1263 {
1264     return WebKit::cancelledError(request);
1265 }
1266
1267 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
1268 {
1269     return WebKit::blockedError(request);
1270 }
1271
1272 ResourceError WebFrameLoaderClient::blockedByContentBlockerError(const ResourceRequest& request)
1273 {
1274     return WebKit::blockedByContentBlockerError(request);
1275 }
1276
1277 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1278 {
1279     return WebKit::cannotShowURLError(request);
1280 }
1281
1282 ResourceError WebFrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request)
1283 {
1284     return WebKit::interruptedForPolicyChangeError(request);
1285 }
1286
1287 #if ENABLE(CONTENT_FILTERING)
1288 ResourceError WebFrameLoaderClient::blockedByContentFilterError(const ResourceRequest& request)
1289 {
1290     return WebKit::blockedByContentFilterError(request);
1291 }
1292 #endif
1293
1294 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1295 {
1296     return WebKit::cannotShowMIMETypeError(response);
1297 }
1298
1299 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1300 {
1301     return WebKit::fileDoesNotExistError(response);
1302 }
1303
1304 ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1305 {
1306     return WebKit::pluginWillHandleLoadError(response);
1307 }
1308
1309 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
1310 {
1311     static NeverDestroyed<const ResourceError> cancelledError(this->cancelledError(ResourceRequest()));
1312     static NeverDestroyed<const ResourceError> pluginWillHandleLoadError(this->pluginWillHandleLoadError(ResourceResponse()));
1313
1314     if (error.errorCode() == cancelledError.get().errorCode() && error.domain() == cancelledError.get().domain())
1315         return false;
1316
1317     if (error.errorCode() == pluginWillHandleLoadError.get().errorCode() && error.domain() == pluginWillHandleLoadError.get().domain())
1318         return false;
1319
1320     return true;
1321 }
1322
1323 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest&) const
1324 {
1325     notImplemented();
1326     return true;
1327 }
1328
1329 bool WebFrameLoaderClient::canShowMIMEType(const String& /*MIMEType*/) const
1330 {
1331     notImplemented();
1332     return true;
1333 }
1334
1335 bool WebFrameLoaderClient::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const
1336 {
1337     return true;
1338 }
1339
1340 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& /*URLScheme*/) const
1341 {
1342     notImplemented();
1343     return false;
1344 }
1345
1346 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1347 {
1348     notImplemented();
1349     return String();
1350 }
1351
1352 void WebFrameLoaderClient::frameLoadCompleted()
1353 {
1354     // Note: Can be called multiple times.
1355     WebPage* webPage = m_frame->page();
1356     if (!webPage)
1357         return;
1358
1359     if (m_frame->isMainFrame() && !m_didCompletePageTransition) {
1360         webPage->didCompletePageTransition();
1361         m_didCompletePageTransition = true;
1362     }
1363 }
1364
1365 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem& historyItem)
1366 {
1367 #if PLATFORM(IOS_FAMILY)
1368     if (m_frame->isMainFrame())
1369         m_frame->page()->savePageState(historyItem);
1370 #else
1371     UNUSED_PARAM(historyItem);
1372 #endif
1373 }
1374
1375 void WebFrameLoaderClient::restoreViewState()
1376 {
1377 #if PLATFORM(IOS_FAMILY)
1378     Frame& frame = *m_frame->coreFrame();
1379     HistoryItem* currentItem = frame.loader().history().currentItem();
1380     if (FrameView* view = frame.view()) {
1381         if (m_frame->isMainFrame())
1382             m_frame->page()->restorePageState(*currentItem);
1383         else if (!view->wasScrolledByUser())
1384             view->setScrollPosition(currentItem->scrollPosition());
1385     }
1386 #else
1387     // Inform the UI process of the scale factor.
1388     double scaleFactor = m_frame->coreFrame()->loader().history().currentItem()->pageScaleFactor();
1389
1390     // A scale factor of 0 means the history item has the default scale factor, thus we do not need to update it.
1391     if (scaleFactor)
1392         m_frame->page()->send(Messages::WebPageProxy::PageScaleFactorDidChange(scaleFactor));
1393
1394     // FIXME: This should not be necessary. WebCore should be correctly invalidating
1395     // the view on restores from the back/forward cache.
1396     if (m_frame->page() && m_frame == m_frame->page()->mainWebFrame())
1397         m_frame->page()->drawingArea()->setNeedsDisplay();
1398 #endif
1399 }
1400
1401 void WebFrameLoaderClient::provisionalLoadStarted()
1402 {
1403     WebPage* webPage = m_frame->page();
1404     if (!webPage)
1405         return;
1406
1407     if (m_frame->isMainFrame()) {
1408         webPage->didStartPageTransition();
1409         m_didCompletePageTransition = false;
1410     }
1411 }
1412
1413 void WebFrameLoaderClient::didFinishLoad()
1414 {
1415     // If we have a load listener, notify it.
1416     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
1417         loadListener->didFinishLoad(m_frame);
1418 }
1419
1420 void WebFrameLoaderClient::prepareForDataSourceReplacement()
1421 {
1422     notImplemented();
1423 }
1424
1425 Ref<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
1426 {
1427     return m_frame->page()->createDocumentLoader(*m_frame->coreFrame(), request, substituteData);
1428 }
1429
1430 void WebFrameLoaderClient::updateCachedDocumentLoader(WebCore::DocumentLoader& loader)
1431 {
1432     m_frame->page()->updateCachedDocumentLoader(static_cast<WebDocumentLoader&>(loader), *m_frame->coreFrame());
1433 }
1434
1435 void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const URL& url)
1436 {
1437     WebPage* webPage = m_frame->page();
1438     if (!webPage)
1439         return;
1440
1441     // FIXME: Use direction of title.
1442     webPage->send(Messages::WebPageProxy::DidUpdateHistoryTitle(title.string, url.string(), m_frame->frameID()));
1443 }
1444
1445 String WebFrameLoaderClient::userAgent(const URL& url)
1446 {
1447     auto* webPage = m_frame->page();
1448     if (!webPage)
1449         return String();
1450
1451     return webPage->userAgent(url);
1452 }
1453
1454 String WebFrameLoaderClient::overrideContentSecurityPolicy() const
1455 {
1456     WebPage* webPage = m_frame->page();
1457     if (!webPage)
1458         return String();
1459
1460     return webPage->overrideContentSecurityPolicy();
1461 }
1462
1463 void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1464 {
1465     WebPage* webPage = m_frame->page();
1466     if (!webPage)
1467         return;
1468
1469     HasInsecureContent hasInsecureContent;
1470     if (webPage->sendSync(Messages::WebPageProxy::HasInsecureContent(), Messages::WebPageProxy::HasInsecureContent::Reply(hasInsecureContent)))
1471         cachedFrame->setHasInsecureContent(hasInsecureContent);
1472 }
1473
1474 void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
1475 {
1476     const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1477     m_frameHasCustomContentProvider = m_frame->isMainFrame() && m_frame->page()->shouldUseCustomContentProviderForResponse(response);
1478     m_frameCameFromPageCache = true;
1479 }
1480
1481 void WebFrameLoaderClient::transitionToCommittedForNewPage()
1482 {
1483     WebPage* webPage = m_frame->page();
1484
1485     bool isMainFrame = m_frame->isMainFrame();
1486     bool shouldUseFixedLayout = isMainFrame && webPage->useFixedLayout();
1487     bool shouldDisableScrolling = isMainFrame && !webPage->mainFrameIsScrollable();
1488     bool shouldHideScrollbars = shouldDisableScrolling;
1489     IntRect fixedVisibleContentRect;
1490
1491 #if USE(COORDINATED_GRAPHICS)
1492     if (m_frame->coreFrame()->view())
1493         fixedVisibleContentRect = m_frame->coreFrame()->view()->fixedVisibleContentRect();
1494     if (shouldUseFixedLayout)
1495         shouldHideScrollbars = true;
1496 #endif
1497
1498     const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1499     m_frameHasCustomContentProvider = isMainFrame && webPage->shouldUseCustomContentProviderForResponse(response);
1500     m_frameCameFromPageCache = false;
1501
1502     ScrollbarMode defaultScrollbarMode = shouldHideScrollbars ? ScrollbarAlwaysOff : ScrollbarAuto;
1503
1504     ScrollbarMode horizontalScrollbarMode = webPage->alwaysShowsHorizontalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1505     ScrollbarMode verticalScrollbarMode = webPage->alwaysShowsVerticalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1506
1507     bool horizontalLock = shouldHideScrollbars || webPage->alwaysShowsHorizontalScroller();
1508     bool verticalLock = shouldHideScrollbars || webPage->alwaysShowsVerticalScroller();
1509
1510     m_frame->coreFrame()->createView(webPage->size(), webPage->backgroundColor(),
1511         webPage->fixedLayoutSize(), fixedVisibleContentRect, shouldUseFixedLayout,
1512         horizontalScrollbarMode, horizontalLock, verticalScrollbarMode, verticalLock);
1513
1514     if (int width = webPage->minimumSizeForAutoLayout().width()) {
1515         int height = std::max(webPage->minimumSizeForAutoLayout().height(), 1);
1516         m_frame->coreFrame()->view()->enableAutoSizeMode(true, { width, height });
1517
1518         if (webPage->autoSizingShouldExpandToViewHeight())
1519             m_frame->coreFrame()->view()->setAutoSizeFixedMinimumHeight(webPage->size().height());
1520     }
1521
1522     if (auto viewportSizeForViewportUnits = webPage->viewportSizeForCSSViewportUnits())
1523         m_frame->coreFrame()->view()->setViewportSizeForCSSViewportUnits(*viewportSizeForViewportUnits);
1524     m_frame->coreFrame()->view()->setProhibitsScrolling(shouldDisableScrolling);
1525     m_frame->coreFrame()->view()->setVisualUpdatesAllowedByClient(!webPage->shouldExtendIncrementalRenderingSuppression());
1526 #if PLATFORM(COCOA)
1527     m_frame->coreFrame()->view()->setViewExposedRect(webPage->drawingArea()->viewExposedRect());
1528 #endif
1529 #if PLATFORM(IOS_FAMILY)
1530     if (isMainFrame)
1531         m_frame->coreFrame()->view()->setDelegatesScrolling(true);
1532 #endif
1533
1534     if (webPage->scrollPinningBehavior() != DoNotPin)
1535         m_frame->coreFrame()->view()->setScrollPinningBehavior(webPage->scrollPinningBehavior());
1536
1537 #if USE(COORDINATED_GRAPHICS)
1538     if (shouldUseFixedLayout) {
1539         m_frame->coreFrame()->view()->setDelegatesScrolling(shouldUseFixedLayout);
1540         m_frame->coreFrame()->view()->setPaintsEntireContents(shouldUseFixedLayout);
1541         return;
1542     }
1543 #endif
1544 }
1545
1546 void WebFrameLoaderClient::didSaveToPageCache()
1547 {
1548     WebPage* webPage = m_frame->page();
1549     if (!webPage)
1550         return;
1551
1552     if (m_frame->isMainFrame())
1553         webPage->send(Messages::WebPageProxy::DidSaveToPageCache());
1554 }
1555
1556 void WebFrameLoaderClient::didRestoreFromPageCache()
1557 {
1558     m_frameCameFromPageCache = true;
1559 }
1560
1561 void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool value)
1562 {
1563     WebPage* webPage = m_frame->page();
1564     if (!webPage)
1565         return;
1566
1567     webPage->send(Messages::WebPageProxy::FrameDidBecomeFrameSet(m_frame->frameID(), value));
1568 }
1569
1570 bool WebFrameLoaderClient::canCachePage() const
1571 {
1572     // We cannot cache frames that have custom representations because they are
1573     // rendered in the UIProcess.
1574     return !m_frameHasCustomContentProvider;
1575 }
1576
1577 void WebFrameLoaderClient::convertMainResourceLoadToDownload(DocumentLoader *documentLoader, PAL::SessionID sessionID, const ResourceRequest& request, const ResourceResponse& response)
1578 {
1579     m_frame->convertMainResourceLoadToDownload(documentLoader, sessionID, request, response);
1580 }
1581
1582 RefPtr<Frame> WebFrameLoaderClient::createFrame(const URL& url, const String& name, HTMLFrameOwnerElement& ownerElement,
1583     const String& referrer)
1584 {
1585     auto* webPage = m_frame->page();
1586
1587     auto subframe = WebFrame::createSubframe(webPage, name, &ownerElement);
1588     auto* coreSubframe = subframe->coreFrame();
1589     if (!coreSubframe)
1590         return nullptr;
1591
1592     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1593     if (!coreSubframe->page())
1594         return nullptr;
1595
1596     m_frame->coreFrame()->loader().loadURLIntoChildFrame(url, referrer, coreSubframe);
1597
1598     // The frame's onload handler may have removed it from the document.
1599     if (!subframe->coreFrame())
1600         return nullptr;
1601     ASSERT(subframe->coreFrame() == coreSubframe);
1602     if (!coreSubframe->tree().parent())
1603         return nullptr;
1604
1605     return coreSubframe;
1606 }
1607
1608 RefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugInElement& pluginElement, const URL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1609 {
1610     ASSERT(paramNames.size() == paramValues.size());
1611     ASSERT(m_frame->page());
1612
1613     Plugin::Parameters parameters;
1614     parameters.url = url;
1615     parameters.names = paramNames;
1616     parameters.values = paramValues;
1617     parameters.mimeType = mimeType;
1618     parameters.isFullFramePlugin = loadManually;
1619     parameters.shouldUseManualLoader = parameters.isFullFramePlugin && !m_frameCameFromPageCache;
1620 #if PLATFORM(COCOA)
1621     parameters.layerHostingMode = m_frame->page()->layerHostingMode();
1622 #endif
1623
1624 #if ENABLE(NETSCAPE_PLUGIN_API)
1625     auto plugin = m_frame->page()->createPlugin(m_frame, &pluginElement, parameters, parameters.mimeType);
1626     if (!plugin)
1627         return nullptr;
1628
1629     return PluginView::create(pluginElement, plugin.releaseNonNull(), parameters);
1630 #else
1631     UNUSED_PARAM(pluginElement);
1632     return nullptr;
1633 #endif
1634 }
1635
1636 void WebFrameLoaderClient::redirectDataToPlugin(Widget& pluginWidget)
1637 {
1638     m_pluginView = static_cast<PluginView*>(&pluginWidget);
1639 }
1640
1641 #if ENABLE(WEBGL)
1642
1643 WebCore::WebGLLoadPolicy WebFrameLoaderClient::webGLPolicyForURL(const URL& url) const
1644 {
1645     if (auto* webPage = m_frame->page())
1646         return webPage->webGLPolicyForURL(m_frame, url);
1647
1648     return WebGLAllowCreation;
1649 }
1650
1651 WebCore::WebGLLoadPolicy WebFrameLoaderClient::resolveWebGLPolicyForURL(const URL& url) const
1652 {
1653     if (auto* webPage = m_frame->page())
1654         return webPage->resolveWebGLPolicyForURL(m_frame, url);
1655
1656     return WebGLAllowCreation;
1657 }
1658
1659 #endif
1660
1661 RefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement& appletElement, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues)
1662 {
1663 #if ENABLE(NETSCAPE_PLUGIN_API)
1664     auto plugin = createPlugin(pluginSize, appletElement, URL(), paramNames, paramValues, appletElement.serviceType(), false);
1665     if (!plugin) {
1666         if (auto* webPage = m_frame->page()) {
1667             auto frameURLString = m_frame->coreFrame()->loader().documentLoader()->responseURL().string();
1668             auto pageURLString = webPage->corePage()->mainFrame().loader().documentLoader()->responseURL().string();
1669             webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(appletElement.serviceType(), frameURLString, pageURLString));
1670         }
1671     }
1672     return plugin;
1673 #else
1674     UNUSED_PARAM(pluginSize);
1675     UNUSED_PARAM(appletElement);
1676     UNUSED_PARAM(paramNames);
1677     UNUSED_PARAM(paramValues);
1678     return nullptr;
1679 #endif
1680 }
1681
1682 static bool pluginSupportsExtension(const PluginData& pluginData, const String& extension)
1683 {
1684     ASSERT(extension.convertToASCIILowercase() == extension);
1685     Vector<MimeClassInfo> mimes;
1686     Vector<size_t> mimePluginIndices;
1687     pluginData.getWebVisibleMimesAndPluginIndices(mimes, mimePluginIndices);
1688     for (auto& mimeClassInfo : mimes) {
1689         if (mimeClassInfo.extensions.contains(extension))
1690             return true;
1691     }
1692     return false;
1693 }
1694
1695 ObjectContentType WebFrameLoaderClient::objectContentType(const URL& url, const String& mimeTypeIn)
1696 {
1697     // FIXME: This should eventually be merged with WebCore::FrameLoader::defaultObjectContentType.
1698
1699     String mimeType = mimeTypeIn;
1700     if (mimeType.isEmpty()) {
1701         String path = url.path();
1702         auto dotPosition = path.reverseFind('.');
1703         if (dotPosition == notFound)
1704             return ObjectContentType::Frame;
1705         String extension = path.substring(dotPosition + 1).convertToASCIILowercase();
1706
1707         // Try to guess the MIME type from the extension.
1708         mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1709         if (mimeType.isEmpty()) {
1710             // Check if there's a plug-in around that can handle the extension.
1711             if (WebPage* webPage = m_frame->page()) {
1712                 if (pluginSupportsExtension(webPage->corePage()->pluginData(), extension))
1713                     return ObjectContentType::PlugIn;
1714             }
1715             return ObjectContentType::Frame;
1716         }
1717     }
1718
1719     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1720         return ObjectContentType::Image;
1721
1722     if (WebPage* webPage = m_frame->page()) {
1723         auto allowedPluginTypes = webFrame()->coreFrame()->loader().subframeLoader().allowPlugins()
1724             ? PluginData::AllPlugins : PluginData::OnlyApplicationPlugins;
1725         if (webPage->corePage()->pluginData().supportsMimeType(mimeType, allowedPluginTypes))
1726             return ObjectContentType::PlugIn;
1727     }
1728
1729     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1730         return ObjectContentType::Frame;
1731
1732 #if PLATFORM(IOS_FAMILY)
1733     // iOS can render PDF in <object>/<embed> via PDFDocumentImage.
1734     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType))
1735         return ObjectContentType::Image;
1736 #endif
1737
1738     return ObjectContentType::None;
1739 }
1740
1741 String WebFrameLoaderClient::overrideMediaType() const
1742 {
1743     notImplemented();
1744     return String();
1745 }
1746
1747 void WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
1748 {
1749     WebPage* webPage = m_frame->page();
1750     if (!webPage)
1751         return;
1752
1753     webPage->injectedBundleLoaderClient().didClearWindowObjectForFrame(*webPage, *m_frame, world);
1754
1755     WebAutomationSessionProxy* automationSessionProxy = WebProcess::singleton().automationSessionProxy();
1756     if (automationSessionProxy && world.isNormal())
1757         automationSessionProxy->didClearWindowObjectForFrame(*m_frame);
1758 }
1759
1760 void WebFrameLoaderClient::dispatchGlobalObjectAvailable(DOMWrapperWorld& world)
1761 {
1762     WebPage* webPage = m_frame->page();
1763     if (!webPage)
1764         return;
1765     
1766     webPage->injectedBundleLoaderClient().globalObjectIsAvailableForFrame(*webPage, *m_frame, world);
1767 }
1768
1769 void WebFrameLoaderClient::willInjectUserScript(DOMWrapperWorld& world)
1770 {
1771     WebPage* webPage = m_frame->page();
1772     if (!webPage)
1773         return;
1774
1775     webPage->injectedBundleLoaderClient().willInjectUserScriptForFrame(*webPage, *m_frame, world);
1776 }
1777
1778 void WebFrameLoaderClient::dispatchWillDisconnectDOMWindowExtensionFromGlobalObject(WebCore::DOMWindowExtension* extension)
1779 {
1780     WebPage* webPage = m_frame->page();
1781     if (!webPage)
1782         return;
1783         
1784     webPage->injectedBundleLoaderClient().willDisconnectDOMWindowExtensionFromGlobalObject(*webPage, extension);
1785 }
1786
1787 void WebFrameLoaderClient::dispatchDidReconnectDOMWindowExtensionToGlobalObject(WebCore::DOMWindowExtension* extension)
1788 {
1789     WebPage* webPage = m_frame->page();
1790     if (!webPage)
1791         return;
1792         
1793     webPage->injectedBundleLoaderClient().didReconnectDOMWindowExtensionToGlobalObject(*webPage, extension);
1794 }
1795
1796 void WebFrameLoaderClient::dispatchWillDestroyGlobalObjectForDOMWindowExtension(WebCore::DOMWindowExtension* extension)
1797 {
1798     WebPage* webPage = m_frame->page();
1799     if (!webPage)
1800         return;
1801         
1802     webPage->injectedBundleLoaderClient().willDestroyGlobalObjectForDOMWindowExtension(*webPage, extension);
1803 }
1804
1805 #if PLATFORM(COCOA)
1806     
1807 RemoteAXObjectRef WebFrameLoaderClient::accessibilityRemoteObject() 
1808 {
1809     WebPage* webPage = m_frame->page();
1810     if (!webPage)
1811         return 0;
1812     
1813     return webPage->accessibilityRemoteObject();
1814 }
1815     
1816 void WebFrameLoaderClient::willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response, CompletionHandler<void(NSCachedURLResponse *)>&& completionHandler) const
1817 {
1818     WebPage* webPage = m_frame->page();
1819     if (!webPage)
1820         return completionHandler(response);
1821
1822     return completionHandler(webPage->injectedBundleResourceLoadClient().shouldCacheResponse(*webPage, *m_frame, identifier) ? response : nil);
1823 }
1824
1825 NSDictionary *WebFrameLoaderClient::dataDetectionContext()
1826 {
1827     WebPage* webPage = m_frame->page();
1828     if (!webPage)
1829         return nil;
1830
1831     return webPage->dataDetectionContext();
1832 }
1833
1834 #endif // PLATFORM(COCOA)
1835
1836 void WebFrameLoaderClient::didChangeScrollOffset()
1837 {
1838     WebPage* webPage = m_frame->page();
1839     if (!webPage)
1840         return;
1841
1842     webPage->didChangeScrollOffsetForFrame(m_frame->coreFrame());
1843 }
1844
1845 bool WebFrameLoaderClient::allowScript(bool enabledPerSettings)
1846 {
1847     if (!enabledPerSettings)
1848         return false;
1849
1850     auto* pluginView = WebPage::pluginViewForFrame(m_frame->coreFrame());
1851     return !pluginView || !pluginView->shouldAllowScripting();
1852 }
1853
1854 bool WebFrameLoaderClient::shouldForceUniversalAccessFromLocalURL(const URL& url)
1855 {
1856     WebPage* webPage = m_frame->page();
1857     if (!webPage)
1858         return false;
1859
1860     return webPage->injectedBundleLoaderClient().shouldForceUniversalAccessFromLocalURL(*webPage, url);
1861 }
1862
1863 Ref<FrameNetworkingContext> WebFrameLoaderClient::createNetworkingContext()
1864 {
1865     ASSERT(!hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
1866     return WebFrameNetworkingContext::create(m_frame);
1867 }
1868
1869 #if ENABLE(CONTENT_FILTERING)
1870
1871 void WebFrameLoaderClient::contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler unblockHandler)
1872 {
1873     if (!unblockHandler.needsUIProcess()) {
1874         m_frame->coreFrame()->loader().policyChecker().setContentFilterUnblockHandler(WTFMove(unblockHandler));
1875         return;
1876     }
1877
1878     if (WebPage* webPage { m_frame->page() })
1879         webPage->send(Messages::WebPageProxy::ContentFilterDidBlockLoadForFrame(unblockHandler, m_frame->frameID()));
1880 }
1881
1882 #endif
1883
1884 void WebFrameLoaderClient::prefetchDNS(const String& hostname)
1885 {
1886     WebProcess::singleton().prefetchDNS(hostname);
1887 }
1888
1889 void WebFrameLoaderClient::didRestoreScrollPosition()
1890 {
1891     WebPage* webPage = m_frame->page();
1892     if (!webPage)
1893         return;
1894
1895     webPage->didRestoreScrollPosition();
1896 }
1897
1898 void WebFrameLoaderClient::getLoadDecisionForIcons(const Vector<std::pair<WebCore::LinkIcon&, uint64_t>>& icons)
1899 {
1900     auto* webPage = m_frame->page();
1901     if (!webPage)
1902         return;
1903
1904     for (auto& icon : icons)
1905         webPage->send(Messages::WebPageProxy::GetLoadDecisionForIcon(icon.first, CallbackID::fromInteger(icon.second)));
1906 }
1907
1908 void WebFrameLoaderClient::finishedLoadingIcon(uint64_t callbackIdentifier, SharedBuffer* data)
1909 {
1910     auto callbackID = CallbackID::fromInteger(callbackIdentifier);
1911     if (WebPage* webPage { m_frame->page() }) {
1912         if (data)
1913             webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { reinterpret_cast<const uint8_t*>(data->data()), data->size() }));
1914         else
1915             webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { nullptr, 0 }));
1916     }
1917 }
1918
1919 void WebFrameLoaderClient::didCreateWindow(DOMWindow& window)
1920 {
1921     auto* webPage = m_frame->page();
1922     if (!webPage)
1923         return;
1924
1925     webPage->send(Messages::WebPageProxy::DidCreateWindow(m_frame->frameID(), window.identifier()));
1926 }
1927
1928 #if ENABLE(APPLICATION_MANIFEST)
1929 void WebFrameLoaderClient::finishedLoadingApplicationManifest(uint64_t callbackIdentifier, const Optional<WebCore::ApplicationManifest>& manifest)
1930 {
1931     WebPage* webPage = m_frame->page();
1932     if (!webPage)
1933         return;
1934
1935     webPage->didFinishLoadingApplicationManifest(callbackIdentifier, manifest);
1936 }
1937 #endif // ENABLE(APPLICATION_MANIFEST)
1938
1939 } // namespace WebKit