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