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