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