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