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