REGRESSION(PSON, r240660): Navigation over process boundary is flashy when using...
[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.sourceBackForwardItemIdentifier = navigationAction.sourceBackForwardItemIdentifier();
884     navigationActionData.lockHistory = navigationAction.lockHistory();
885     navigationActionData.lockBackForwardList = navigationAction.lockBackForwardList();
886     navigationActionData.adClickAttribution = navigationAction.adClickAttribution();
887
888     WebCore::Frame* coreFrame = m_frame->coreFrame();
889     if (!coreFrame)
890         return function(PolicyAction::Ignore, requestIdentifier);
891     WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader());
892     if (!documentLoader) {
893         // FIXME: When we receive a redirect after the navigation policy has been decided for the initial request,
894         // the provisional load's DocumentLoader needs to receive navigation policy decisions. We need a better model for this state.
895         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader());
896     }
897     if (!documentLoader)
898         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
899
900     navigationActionData.clientRedirectSourceForHistory = documentLoader->clientRedirectSourceForHistory();
901
902     // Notify the UIProcess.
903     Ref<WebFrame> protect(*m_frame);
904
905     if (policyDecisionMode == PolicyDecisionMode::Synchronous) {
906         uint64_t newNavigationID;
907         WebCore::PolicyCheckIdentifier responseIdentifier;
908         PolicyAction policyAction;
909         DownloadID downloadID;
910         Optional<WebsitePoliciesData> websitePolicies;
911
912         if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationActionSync(m_frame->frameID(), m_frame->isMainFrame(), SecurityOriginData::fromFrame(coreFrame),
913             requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request,
914             IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())),
915             Messages::WebPageProxy::DecidePolicyForNavigationActionSync::Reply(responseIdentifier, policyAction, newNavigationID, downloadID, websitePolicies))) {
916             m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { });
917             return;
918         }
919
920         m_frame->didReceivePolicyDecision(listenerID, responseIdentifier, policyAction, 0, downloadID, { });
921         return;
922     }
923
924     ASSERT(policyDecisionMode == PolicyDecisionMode::Asynchronous);
925     if (!webPage->send(Messages::WebPageProxy::DecidePolicyForNavigationActionAsync(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame),
926         requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request,
927         IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()), listenerID)))
928         m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { });
929 }
930
931 void WebFrameLoaderClient::cancelPolicyCheck()
932 {
933     m_frame->invalidatePolicyListener();
934 }
935
936 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
937 {
938     WebPage* webPage = m_frame->page();
939     if (!webPage)
940         return;
941
942     RefPtr<API::Object> userData;
943
944     // Notify the bundle client.
945     webPage->injectedBundlePolicyClient().unableToImplementPolicy(webPage, m_frame, error, userData);
946
947     // Notify the UIProcess.
948     webPage->send(Messages::WebPageProxy::UnableToImplementPolicy(m_frame->frameID(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
949 }
950
951 void WebFrameLoaderClient::dispatchWillSendSubmitEvent(Ref<FormState>&& formState)
952 {
953     auto* webPage = m_frame->page();
954     if (!webPage)
955         return;
956
957     auto& form = formState->form();
958
959     ASSERT(formState->sourceDocument().frame());
960     auto* sourceFrame = WebFrame::fromCoreFrame(*formState->sourceDocument().frame());
961     ASSERT(sourceFrame);
962
963     webPage->injectedBundleFormClient().willSendSubmitEvent(webPage, &form, m_frame, sourceFrame, formState->textFieldValues());
964 }
965
966 void WebFrameLoaderClient::dispatchWillSubmitForm(FormState& formState, CompletionHandler<void()>&& completionHandler)
967 {
968     WebPage* webPage = m_frame->page();
969     if (!webPage) {
970         completionHandler();
971         return;
972     }
973
974     auto& form = formState.form();
975
976     auto* sourceCoreFrame = formState.sourceDocument().frame();
977     if (!sourceCoreFrame)
978         return completionHandler();
979     auto* sourceFrame = WebFrame::fromCoreFrame(*sourceCoreFrame);
980     if (!sourceFrame)
981         return completionHandler();
982
983     auto& values = formState.textFieldValues();
984
985     RefPtr<API::Object> userData;
986     webPage->injectedBundleFormClient().willSubmitForm(webPage, &form, m_frame, sourceFrame, values, userData);
987
988     uint64_t listenerID = m_frame->setUpWillSubmitFormListener(WTFMove(completionHandler));
989
990     webPage->send(Messages::WebPageProxy::WillSubmitForm(m_frame->frameID(), sourceFrame->frameID(), values, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
991 }
992
993 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader*)
994 {
995     notImplemented();
996 }
997
998 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
999 {
1000     if (!m_pluginView)
1001         return;
1002     
1003     m_pluginView->manualLoadDidFail(error);
1004     m_pluginView = nullptr;
1005     m_hasSentResponseToPluginView = false;
1006 }
1007
1008 void WebFrameLoaderClient::setMainFrameDocumentReady(bool)
1009 {
1010     notImplemented();
1011 }
1012
1013 void WebFrameLoaderClient::startDownload(const ResourceRequest& request, const String& suggestedName)
1014 {
1015     m_frame->startDownload(request, suggestedName);
1016 }
1017
1018 void WebFrameLoaderClient::willChangeTitle(DocumentLoader*)
1019 {
1020     notImplemented();
1021 }
1022
1023 void WebFrameLoaderClient::didChangeTitle(DocumentLoader*)
1024 {
1025     notImplemented();
1026 }
1027
1028 void WebFrameLoaderClient::willReplaceMultipartContent()
1029 {
1030     WebPage* webPage = m_frame->page();
1031     if (!webPage)
1032         return;
1033     webPage->willReplaceMultipartContent(*m_frame);
1034 }
1035
1036 void WebFrameLoaderClient::didReplaceMultipartContent()
1037 {
1038     WebPage* webPage = m_frame->page();
1039     if (!webPage)
1040         return;
1041     webPage->didReplaceMultipartContent(*m_frame);
1042 }
1043
1044 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
1045 {
1046     if (!m_pluginView)
1047         loader->commitData(data, length);
1048
1049     // If the document is a stand-alone media document, now is the right time to cancel the WebKit load.
1050     // FIXME: This code should be shared across all ports. <http://webkit.org/b/48762>.
1051     if (m_frame->coreFrame()->document()->isMediaDocument())
1052         loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
1053
1054     // Calling commitData did not create the plug-in view.
1055     if (!m_pluginView)
1056         return;
1057
1058     if (!m_hasSentResponseToPluginView) {
1059         m_pluginView->manualLoadDidReceiveResponse(loader->response());
1060         // manualLoadDidReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
1061         // setting up this stream can cause the main document load to be cancelled, setting m_pluginView
1062         // to null
1063         if (!m_pluginView)
1064             return;
1065         m_hasSentResponseToPluginView = true;
1066     }
1067     m_pluginView->manualLoadDidReceiveData(data, length);
1068 }
1069
1070 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
1071 {
1072     if (!m_pluginView) {
1073         if (m_frameHasCustomContentProvider) {
1074             WebPage* webPage = m_frame->page();
1075             if (!webPage)
1076                 return;
1077
1078             RefPtr<SharedBuffer> mainResourceData = loader->mainResourceData();
1079             IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(mainResourceData ? mainResourceData->data() : 0), mainResourceData ? mainResourceData->size() : 0);
1080             webPage->send(Messages::WebPageProxy::DidFinishLoadingDataForCustomContentProvider(loader->response().suggestedFilename(), dataReference));
1081         }
1082
1083         return;
1084     }
1085
1086     // If we just received an empty response without any data, we won't have sent a response to the plug-in view.
1087     // Make sure to do this before calling manualLoadDidFinishLoading.
1088     if (!m_hasSentResponseToPluginView) {
1089         m_pluginView->manualLoadDidReceiveResponse(loader->response());
1090
1091         // Protect against the above call nulling out the plug-in (by trying to cancel the load for example).
1092         if (!m_pluginView)
1093             return;
1094     }
1095
1096     m_pluginView->manualLoadDidFinishLoading();
1097     m_pluginView = nullptr;
1098     m_hasSentResponseToPluginView = false;
1099 }
1100
1101 void WebFrameLoaderClient::updateGlobalHistory()
1102 {
1103     WebPage* webPage = m_frame->page();
1104     if (!webPage)
1105         return;
1106
1107     DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1108
1109     WebNavigationDataStore data;
1110     data.url = loader->url().string();
1111     // FIXME: Use direction of title.
1112     data.title = loader->title().string;
1113     data.originalRequest = loader->originalRequestCopy();
1114     data.response = loader->response();
1115
1116     webPage->send(Messages::WebPageProxy::DidNavigateWithNavigationData(data, m_frame->frameID()));
1117 }
1118
1119 void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
1120 {
1121     WebPage* webPage = m_frame->page();
1122     if (!webPage)
1123         return;
1124
1125     DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1126     ASSERT(loader->unreachableURL().isEmpty());
1127
1128     // Client redirect
1129     if (!loader->clientRedirectSourceForHistory().isNull()) {
1130         webPage->send(Messages::WebPageProxy::DidPerformClientRedirect(
1131             loader->clientRedirectSourceForHistory(), loader->clientRedirectDestinationForHistory(), m_frame->frameID()));
1132     }
1133
1134     // Server redirect
1135     if (!loader->serverRedirectSourceForHistory().isNull()) {
1136         webPage->send(Messages::WebPageProxy::DidPerformServerRedirect(
1137             loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_frame->frameID()));
1138     }
1139 }
1140
1141 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem& item) const
1142 {
1143     WebPage* webPage = m_frame->page();
1144     if (!webPage)
1145         return false;
1146     webPage->send(Messages::WebPageProxy::WillGoToBackForwardListItem(item.identifier(), item.isInPageCache()));
1147     return true;
1148 }
1149
1150 void WebFrameLoaderClient::didDisplayInsecureContent()
1151 {
1152     WebPage* webPage = m_frame->page();
1153     if (!webPage)
1154         return;
1155
1156     RefPtr<API::Object> userData;
1157
1158     webPage->injectedBundleLoaderClient().didDisplayInsecureContentForFrame(*webPage, *m_frame, userData);
1159
1160     webPage->send(Messages::WebPageProxy::DidDisplayInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1161 }
1162
1163 void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin&, const URL&)
1164 {
1165     WebPage* webPage = m_frame->page();
1166     if (!webPage)
1167         return;
1168
1169     RefPtr<API::Object> userData;
1170
1171     webPage->injectedBundleLoaderClient().didRunInsecureContentForFrame(*webPage, *m_frame, userData);
1172
1173     webPage->send(Messages::WebPageProxy::DidRunInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1174 }
1175
1176 void WebFrameLoaderClient::didDetectXSS(const URL&, bool)
1177 {
1178     WebPage* webPage = m_frame->page();
1179     if (!webPage)
1180         return;
1181
1182     RefPtr<API::Object> userData;
1183
1184     webPage->injectedBundleLoaderClient().didDetectXSSForFrame(*webPage, *m_frame, userData);
1185
1186     webPage->send(Messages::WebPageProxy::DidDetectXSSForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1187 }
1188
1189 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
1190 {
1191     return WebKit::cancelledError(request);
1192 }
1193
1194 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
1195 {
1196     return WebKit::blockedError(request);
1197 }
1198
1199 ResourceError WebFrameLoaderClient::blockedByContentBlockerError(const ResourceRequest& request)
1200 {
1201     return WebKit::blockedByContentBlockerError(request);
1202 }
1203
1204 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1205 {
1206     return WebKit::cannotShowURLError(request);
1207 }
1208
1209 ResourceError WebFrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request)
1210 {
1211     return WebKit::interruptedForPolicyChangeError(request);
1212 }
1213
1214 #if ENABLE(CONTENT_FILTERING)
1215 ResourceError WebFrameLoaderClient::blockedByContentFilterError(const ResourceRequest& request)
1216 {
1217     return WebKit::blockedByContentFilterError(request);
1218 }
1219 #endif
1220
1221 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1222 {
1223     return WebKit::cannotShowMIMETypeError(response);
1224 }
1225
1226 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1227 {
1228     return WebKit::fileDoesNotExistError(response);
1229 }
1230
1231 ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1232 {
1233     return WebKit::pluginWillHandleLoadError(response);
1234 }
1235
1236 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
1237 {
1238     static NeverDestroyed<const ResourceError> cancelledError(this->cancelledError(ResourceRequest()));
1239     static NeverDestroyed<const ResourceError> pluginWillHandleLoadError(this->pluginWillHandleLoadError(ResourceResponse()));
1240
1241     if (error.errorCode() == cancelledError.get().errorCode() && error.domain() == cancelledError.get().domain())
1242         return false;
1243
1244     if (error.errorCode() == pluginWillHandleLoadError.get().errorCode() && error.domain() == pluginWillHandleLoadError.get().domain())
1245         return false;
1246
1247     return true;
1248 }
1249
1250 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest&) const
1251 {
1252     notImplemented();
1253     return true;
1254 }
1255
1256 bool WebFrameLoaderClient::canShowMIMEType(const String& /*MIMEType*/) const
1257 {
1258     notImplemented();
1259     return true;
1260 }
1261
1262 bool WebFrameLoaderClient::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const
1263 {
1264     return true;
1265 }
1266
1267 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& /*URLScheme*/) const
1268 {
1269     notImplemented();
1270     return false;
1271 }
1272
1273 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1274 {
1275     notImplemented();
1276     return String();
1277 }
1278
1279 void WebFrameLoaderClient::frameLoadCompleted()
1280 {
1281     // Note: Can be called multiple times.
1282     WebPage* webPage = m_frame->page();
1283     if (!webPage)
1284         return;
1285
1286     if (m_frame->isMainFrame() && !m_didCompletePageTransition) {
1287         webPage->didCompletePageTransition();
1288         m_didCompletePageTransition = true;
1289     }
1290 }
1291
1292 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem& historyItem)
1293 {
1294 #if PLATFORM(IOS_FAMILY)
1295     if (m_frame->isMainFrame())
1296         m_frame->page()->savePageState(historyItem);
1297 #else
1298     UNUSED_PARAM(historyItem);
1299 #endif
1300 }
1301
1302 void WebFrameLoaderClient::restoreViewState()
1303 {
1304 #if PLATFORM(IOS_FAMILY)
1305     Frame& frame = *m_frame->coreFrame();
1306     HistoryItem* currentItem = frame.loader().history().currentItem();
1307     if (FrameView* view = frame.view()) {
1308         if (m_frame->isMainFrame())
1309             m_frame->page()->restorePageState(*currentItem);
1310         else if (!view->wasScrolledByUser())
1311             view->setScrollPosition(currentItem->scrollPosition());
1312     }
1313 #else
1314     // Inform the UI process of the scale factor.
1315     double scaleFactor = m_frame->coreFrame()->loader().history().currentItem()->pageScaleFactor();
1316
1317     // A scale factor of 0 means the history item has the default scale factor, thus we do not need to update it.
1318     if (scaleFactor)
1319         m_frame->page()->send(Messages::WebPageProxy::PageScaleFactorDidChange(scaleFactor));
1320
1321     // FIXME: This should not be necessary. WebCore should be correctly invalidating
1322     // the view on restores from the back/forward cache.
1323     if (m_frame->page() && m_frame == m_frame->page()->mainWebFrame())
1324         m_frame->page()->drawingArea()->setNeedsDisplay();
1325 #endif
1326 }
1327
1328 void WebFrameLoaderClient::provisionalLoadStarted()
1329 {
1330     WebPage* webPage = m_frame->page();
1331     if (!webPage)
1332         return;
1333
1334     if (m_frame->isMainFrame()) {
1335         webPage->didStartPageTransition();
1336         m_didCompletePageTransition = false;
1337     }
1338 }
1339
1340 void WebFrameLoaderClient::didFinishLoad()
1341 {
1342     // If we have a load listener, notify it.
1343     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
1344         loadListener->didFinishLoad(m_frame);
1345 }
1346
1347 void WebFrameLoaderClient::prepareForDataSourceReplacement()
1348 {
1349     notImplemented();
1350 }
1351
1352 Ref<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
1353 {
1354     return m_frame->page()->createDocumentLoader(*m_frame->coreFrame(), request, substituteData);
1355 }
1356
1357 void WebFrameLoaderClient::updateCachedDocumentLoader(WebCore::DocumentLoader& loader)
1358 {
1359     m_frame->page()->updateCachedDocumentLoader(static_cast<WebDocumentLoader&>(loader), *m_frame->coreFrame());
1360 }
1361
1362 void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const URL& url)
1363 {
1364     WebPage* webPage = m_frame->page();
1365     if (!webPage)
1366         return;
1367
1368     // FIXME: Use direction of title.
1369     webPage->send(Messages::WebPageProxy::DidUpdateHistoryTitle(title.string, url.string(), m_frame->frameID()));
1370 }
1371
1372 String WebFrameLoaderClient::userAgent(const URL& url)
1373 {
1374     auto* webPage = m_frame->page();
1375     if (!webPage)
1376         return String();
1377
1378     return webPage->userAgent(url);
1379 }
1380
1381 String WebFrameLoaderClient::overrideContentSecurityPolicy() const
1382 {
1383     WebPage* webPage = m_frame->page();
1384     if (!webPage)
1385         return String();
1386
1387     return webPage->overrideContentSecurityPolicy();
1388 }
1389
1390 void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1391 {
1392     WebPage* webPage = m_frame->page();
1393     if (!webPage)
1394         return;
1395
1396     HasInsecureContent hasInsecureContent;
1397     if (webPage->sendSync(Messages::WebPageProxy::HasInsecureContent(), Messages::WebPageProxy::HasInsecureContent::Reply(hasInsecureContent)))
1398         cachedFrame->setHasInsecureContent(hasInsecureContent);
1399 }
1400
1401 void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
1402 {
1403     const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1404     m_frameHasCustomContentProvider = m_frame->isMainFrame() && m_frame->page()->shouldUseCustomContentProviderForResponse(response);
1405     m_frameCameFromPageCache = true;
1406 }
1407
1408 void WebFrameLoaderClient::transitionToCommittedForNewPage()
1409 {
1410     WebPage* webPage = m_frame->page();
1411
1412     bool isMainFrame = m_frame->isMainFrame();
1413     bool shouldUseFixedLayout = isMainFrame && webPage->useFixedLayout();
1414     bool shouldDisableScrolling = isMainFrame && !webPage->mainFrameIsScrollable();
1415     bool shouldHideScrollbars = shouldDisableScrolling;
1416     IntRect fixedVisibleContentRect;
1417
1418 #if USE(COORDINATED_GRAPHICS)
1419     if (m_frame->coreFrame()->view())
1420         fixedVisibleContentRect = m_frame->coreFrame()->view()->fixedVisibleContentRect();
1421     if (shouldUseFixedLayout)
1422         shouldHideScrollbars = true;
1423 #endif
1424
1425     const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1426     m_frameHasCustomContentProvider = isMainFrame && webPage->shouldUseCustomContentProviderForResponse(response);
1427     m_frameCameFromPageCache = false;
1428
1429     ScrollbarMode defaultScrollbarMode = shouldHideScrollbars ? ScrollbarAlwaysOff : ScrollbarAuto;
1430
1431     ScrollbarMode horizontalScrollbarMode = webPage->alwaysShowsHorizontalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1432     ScrollbarMode verticalScrollbarMode = webPage->alwaysShowsVerticalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1433
1434     bool horizontalLock = shouldHideScrollbars || webPage->alwaysShowsHorizontalScroller();
1435     bool verticalLock = shouldHideScrollbars || webPage->alwaysShowsVerticalScroller();
1436
1437     m_frame->coreFrame()->createView(webPage->size(), webPage->backgroundColor(),
1438         webPage->fixedLayoutSize(), fixedVisibleContentRect, shouldUseFixedLayout,
1439         horizontalScrollbarMode, horizontalLock, verticalScrollbarMode, verticalLock);
1440
1441     if (int viewLayoutWidth = webPage->viewLayoutSize().width()) {
1442         int viewLayoutHeight = std::max(webPage->viewLayoutSize().height(), 1);
1443         int maximumSize = std::numeric_limits<int>::max();
1444         m_frame->coreFrame()->view()->enableAutoSizeMode(true, IntSize(viewLayoutWidth, viewLayoutHeight), IntSize(maximumSize, maximumSize));
1445
1446         if (webPage->autoSizingShouldExpandToViewHeight())
1447             m_frame->coreFrame()->view()->setAutoSizeFixedMinimumHeight(webPage->size().height());
1448     }
1449
1450     if (auto viewportSizeForViewportUnits = webPage->viewportSizeForCSSViewportUnits())
1451         m_frame->coreFrame()->view()->setViewportSizeForCSSViewportUnits(*viewportSizeForViewportUnits);
1452     m_frame->coreFrame()->view()->setProhibitsScrolling(shouldDisableScrolling);
1453     m_frame->coreFrame()->view()->setVisualUpdatesAllowedByClient(!webPage->shouldExtendIncrementalRenderingSuppression());
1454 #if PLATFORM(COCOA)
1455     m_frame->coreFrame()->view()->setViewExposedRect(webPage->drawingArea()->viewExposedRect());
1456 #endif
1457 #if PLATFORM(IOS_FAMILY)
1458     if (isMainFrame)
1459         m_frame->coreFrame()->view()->setDelegatesScrolling(true);
1460 #endif
1461
1462     if (webPage->scrollPinningBehavior() != DoNotPin)
1463         m_frame->coreFrame()->view()->setScrollPinningBehavior(webPage->scrollPinningBehavior());
1464
1465 #if USE(COORDINATED_GRAPHICS)
1466     if (shouldUseFixedLayout) {
1467         m_frame->coreFrame()->view()->setDelegatesScrolling(shouldUseFixedLayout);
1468         m_frame->coreFrame()->view()->setPaintsEntireContents(shouldUseFixedLayout);
1469         return;
1470     }
1471 #endif
1472 }
1473
1474 void WebFrameLoaderClient::didSaveToPageCache()
1475 {
1476     WebPage* webPage = m_frame->page();
1477     if (!webPage)
1478         return;
1479
1480     if (m_frame->isMainFrame())
1481         webPage->send(Messages::WebPageProxy::DidSaveToPageCache());
1482 }
1483
1484 void WebFrameLoaderClient::didRestoreFromPageCache()
1485 {
1486     m_frameCameFromPageCache = true;
1487 }
1488
1489 void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool value)
1490 {
1491     WebPage* webPage = m_frame->page();
1492     if (!webPage)
1493         return;
1494
1495     webPage->send(Messages::WebPageProxy::FrameDidBecomeFrameSet(m_frame->frameID(), value));
1496 }
1497
1498 bool WebFrameLoaderClient::canCachePage() const
1499 {
1500     // We cannot cache frames that have custom representations because they are
1501     // rendered in the UIProcess.
1502     return !m_frameHasCustomContentProvider;
1503 }
1504
1505 void WebFrameLoaderClient::convertMainResourceLoadToDownload(DocumentLoader *documentLoader, PAL::SessionID sessionID, const ResourceRequest& request, const ResourceResponse& response)
1506 {
1507     m_frame->convertMainResourceLoadToDownload(documentLoader, sessionID, request, response);
1508 }
1509
1510 RefPtr<Frame> WebFrameLoaderClient::createFrame(const URL& url, const String& name, HTMLFrameOwnerElement& ownerElement,
1511     const String& referrer)
1512 {
1513     auto* webPage = m_frame->page();
1514
1515     auto subframe = WebFrame::createSubframe(webPage, name, &ownerElement);
1516     auto* coreSubframe = subframe->coreFrame();
1517     if (!coreSubframe)
1518         return nullptr;
1519
1520     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1521     if (!coreSubframe->page())
1522         return nullptr;
1523
1524     m_frame->coreFrame()->loader().loadURLIntoChildFrame(url, referrer, coreSubframe);
1525
1526     // The frame's onload handler may have removed it from the document.
1527     if (!subframe->coreFrame())
1528         return nullptr;
1529     ASSERT(subframe->coreFrame() == coreSubframe);
1530     if (!coreSubframe->tree().parent())
1531         return nullptr;
1532
1533     return coreSubframe;
1534 }
1535
1536 RefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugInElement& pluginElement, const URL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1537 {
1538     ASSERT(paramNames.size() == paramValues.size());
1539     ASSERT(m_frame->page());
1540
1541     Plugin::Parameters parameters;
1542     parameters.url = url;
1543     parameters.names = paramNames;
1544     parameters.values = paramValues;
1545     parameters.mimeType = mimeType;
1546     parameters.isFullFramePlugin = loadManually;
1547     parameters.shouldUseManualLoader = parameters.isFullFramePlugin && !m_frameCameFromPageCache;
1548 #if PLATFORM(COCOA)
1549     parameters.layerHostingMode = m_frame->page()->layerHostingMode();
1550 #endif
1551
1552 #if ENABLE(NETSCAPE_PLUGIN_API)
1553     auto plugin = m_frame->page()->createPlugin(m_frame, &pluginElement, parameters, parameters.mimeType);
1554     if (!plugin)
1555         return nullptr;
1556
1557     return PluginView::create(pluginElement, plugin.releaseNonNull(), parameters);
1558 #else
1559     UNUSED_PARAM(pluginElement);
1560     return nullptr;
1561 #endif
1562 }
1563
1564 void WebFrameLoaderClient::recreatePlugin(Widget* widget)
1565 {
1566 #if ENABLE(NETSCAPE_PLUGIN_API)
1567     ASSERT(widget);
1568     ASSERT(widget->isPluginViewBase());
1569     ASSERT(m_frame->page());
1570
1571     auto& pluginView = static_cast<PluginView&>(*widget);
1572     String newMIMEType;
1573     auto plugin = m_frame->page()->createPlugin(m_frame, pluginView.pluginElement(), pluginView.initialParameters(), newMIMEType);
1574     pluginView.recreateAndInitialize(plugin.releaseNonNull());
1575 #else
1576     UNUSED_PARAM(widget);
1577 #endif
1578 }
1579
1580 void WebFrameLoaderClient::redirectDataToPlugin(Widget& pluginWidget)
1581 {
1582     m_pluginView = static_cast<PluginView*>(&pluginWidget);
1583 }
1584
1585 #if ENABLE(WEBGL)
1586
1587 WebCore::WebGLLoadPolicy WebFrameLoaderClient::webGLPolicyForURL(const URL& url) const
1588 {
1589     if (auto* webPage = m_frame->page())
1590         return webPage->webGLPolicyForURL(m_frame, url);
1591
1592     return WebGLAllowCreation;
1593 }
1594
1595 WebCore::WebGLLoadPolicy WebFrameLoaderClient::resolveWebGLPolicyForURL(const URL& url) const
1596 {
1597     if (auto* webPage = m_frame->page())
1598         return webPage->resolveWebGLPolicyForURL(m_frame, url);
1599
1600     return WebGLAllowCreation;
1601 }
1602
1603 #endif
1604
1605 RefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement& appletElement, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues)
1606 {
1607 #if ENABLE(NETSCAPE_PLUGIN_API)
1608     auto plugin = createPlugin(pluginSize, appletElement, URL(), paramNames, paramValues, appletElement.serviceType(), false);
1609     if (!plugin) {
1610         if (auto* webPage = m_frame->page()) {
1611             auto frameURLString = m_frame->coreFrame()->loader().documentLoader()->responseURL().string();
1612             auto pageURLString = webPage->corePage()->mainFrame().loader().documentLoader()->responseURL().string();
1613             webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(appletElement.serviceType(), frameURLString, pageURLString));
1614         }
1615     }
1616     return plugin;
1617 #else
1618     UNUSED_PARAM(pluginSize);
1619     UNUSED_PARAM(appletElement);
1620     UNUSED_PARAM(paramNames);
1621     UNUSED_PARAM(paramValues);
1622     return nullptr;
1623 #endif
1624 }
1625
1626 static bool pluginSupportsExtension(const PluginData& pluginData, const String& extension)
1627 {
1628     ASSERT(extension.convertToASCIILowercase() == extension);
1629     Vector<MimeClassInfo> mimes;
1630     Vector<size_t> mimePluginIndices;
1631     pluginData.getWebVisibleMimesAndPluginIndices(mimes, mimePluginIndices);
1632     for (auto& mimeClassInfo : mimes) {
1633         if (mimeClassInfo.extensions.contains(extension))
1634             return true;
1635     }
1636     return false;
1637 }
1638
1639 ObjectContentType WebFrameLoaderClient::objectContentType(const URL& url, const String& mimeTypeIn)
1640 {
1641     // FIXME: This should eventually be merged with WebCore::FrameLoader::defaultObjectContentType.
1642
1643     String mimeType = mimeTypeIn;
1644     if (mimeType.isEmpty()) {
1645         String path = url.path();
1646         auto dotPosition = path.reverseFind('.');
1647         if (dotPosition == notFound)
1648             return ObjectContentType::Frame;
1649         String extension = path.substring(dotPosition + 1).convertToASCIILowercase();
1650
1651         // Try to guess the MIME type from the extension.
1652         mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1653         if (mimeType.isEmpty()) {
1654             // Check if there's a plug-in around that can handle the extension.
1655             if (WebPage* webPage = m_frame->page()) {
1656                 if (pluginSupportsExtension(webPage->corePage()->pluginData(), extension))
1657                     return ObjectContentType::PlugIn;
1658             }
1659             return ObjectContentType::Frame;
1660         }
1661     }
1662
1663     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1664         return ObjectContentType::Image;
1665
1666     if (WebPage* webPage = m_frame->page()) {
1667         auto allowedPluginTypes = webFrame()->coreFrame()->loader().subframeLoader().allowPlugins()
1668             ? PluginData::AllPlugins : PluginData::OnlyApplicationPlugins;
1669         if (webPage->corePage()->pluginData().supportsMimeType(mimeType, allowedPluginTypes))
1670             return ObjectContentType::PlugIn;
1671     }
1672
1673     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1674         return ObjectContentType::Frame;
1675
1676 #if PLATFORM(IOS_FAMILY)
1677     // iOS can render PDF in <object>/<embed> via PDFDocumentImage.
1678     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType))
1679         return ObjectContentType::Image;
1680 #endif
1681
1682     return ObjectContentType::None;
1683 }
1684
1685 String WebFrameLoaderClient::overrideMediaType() const
1686 {
1687     notImplemented();
1688     return String();
1689 }
1690
1691 void WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
1692 {
1693     WebPage* webPage = m_frame->page();
1694     if (!webPage)
1695         return;
1696
1697     webPage->injectedBundleLoaderClient().didClearWindowObjectForFrame(*webPage, *m_frame, world);
1698
1699
1700     WebAutomationSessionProxy* automationSessionProxy = WebProcess::singleton().automationSessionProxy();
1701     if (automationSessionProxy && world.isNormal())
1702         automationSessionProxy->didClearWindowObjectForFrame(*m_frame);
1703
1704 #if HAVE(ACCESSIBILITY) && PLATFORM(GTK)
1705     // Ensure the accessibility hierarchy is updated.
1706     webPage->updateAccessibilityTree();
1707 #endif
1708 }
1709
1710 void WebFrameLoaderClient::dispatchGlobalObjectAvailable(DOMWrapperWorld& world)
1711 {
1712     WebPage* webPage = m_frame->page();
1713     if (!webPage)
1714         return;
1715     
1716     webPage->injectedBundleLoaderClient().globalObjectIsAvailableForFrame(*webPage, *m_frame, world);
1717 }
1718
1719 void WebFrameLoaderClient::willInjectUserScript(DOMWrapperWorld& world)
1720 {
1721     WebPage* webPage = m_frame->page();
1722     if (!webPage)
1723         return;
1724
1725     webPage->injectedBundleLoaderClient().willInjectUserScriptForFrame(*webPage, *m_frame, world);
1726 }
1727
1728 void WebFrameLoaderClient::dispatchWillDisconnectDOMWindowExtensionFromGlobalObject(WebCore::DOMWindowExtension* extension)
1729 {
1730     WebPage* webPage = m_frame->page();
1731     if (!webPage)
1732         return;
1733         
1734     webPage->injectedBundleLoaderClient().willDisconnectDOMWindowExtensionFromGlobalObject(*webPage, extension);
1735 }
1736
1737 void WebFrameLoaderClient::dispatchDidReconnectDOMWindowExtensionToGlobalObject(WebCore::DOMWindowExtension* extension)
1738 {
1739     WebPage* webPage = m_frame->page();
1740     if (!webPage)
1741         return;
1742         
1743     webPage->injectedBundleLoaderClient().didReconnectDOMWindowExtensionToGlobalObject(*webPage, extension);
1744 }
1745
1746 void WebFrameLoaderClient::dispatchWillDestroyGlobalObjectForDOMWindowExtension(WebCore::DOMWindowExtension* extension)
1747 {
1748     WebPage* webPage = m_frame->page();
1749     if (!webPage)
1750         return;
1751         
1752     webPage->injectedBundleLoaderClient().willDestroyGlobalObjectForDOMWindowExtension(*webPage, extension);
1753 }
1754
1755 #if PLATFORM(COCOA)
1756     
1757 RemoteAXObjectRef WebFrameLoaderClient::accessibilityRemoteObject() 
1758 {
1759     WebPage* webPage = m_frame->page();
1760     if (!webPage)
1761         return 0;
1762     
1763     return webPage->accessibilityRemoteObject();
1764 }
1765     
1766 void WebFrameLoaderClient::willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response, CompletionHandler<void(NSCachedURLResponse *)>&& completionHandler) const
1767 {
1768     WebPage* webPage = m_frame->page();
1769     if (!webPage)
1770         return completionHandler(response);
1771
1772     return completionHandler(webPage->injectedBundleResourceLoadClient().shouldCacheResponse(*webPage, *m_frame, identifier) ? response : nil);
1773 }
1774
1775 NSDictionary *WebFrameLoaderClient::dataDetectionContext()
1776 {
1777     WebPage* webPage = m_frame->page();
1778     if (!webPage)
1779         return nil;
1780
1781     return webPage->dataDetectionContext();
1782 }
1783
1784 #endif // PLATFORM(COCOA)
1785
1786 void WebFrameLoaderClient::didChangeScrollOffset()
1787 {
1788     WebPage* webPage = m_frame->page();
1789     if (!webPage)
1790         return;
1791
1792     webPage->didChangeScrollOffsetForFrame(m_frame->coreFrame());
1793 }
1794
1795 bool WebFrameLoaderClient::allowScript(bool enabledPerSettings)
1796 {
1797     if (!enabledPerSettings)
1798         return false;
1799
1800     auto* pluginView = WebPage::pluginViewForFrame(m_frame->coreFrame());
1801     return !pluginView || !pluginView->shouldAllowScripting();
1802 }
1803
1804 bool WebFrameLoaderClient::shouldForceUniversalAccessFromLocalURL(const URL& url)
1805 {
1806     WebPage* webPage = m_frame->page();
1807     if (!webPage)
1808         return false;
1809
1810     return webPage->injectedBundleLoaderClient().shouldForceUniversalAccessFromLocalURL(*webPage, url);
1811 }
1812
1813 Ref<FrameNetworkingContext> WebFrameLoaderClient::createNetworkingContext()
1814 {
1815     ASSERT(!hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
1816     return WebFrameNetworkingContext::create(m_frame);
1817 }
1818
1819 #if ENABLE(CONTENT_FILTERING)
1820
1821 void WebFrameLoaderClient::contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler unblockHandler)
1822 {
1823     if (!unblockHandler.needsUIProcess()) {
1824         m_frame->coreFrame()->loader().policyChecker().setContentFilterUnblockHandler(WTFMove(unblockHandler));
1825         return;
1826     }
1827
1828     if (WebPage* webPage { m_frame->page() })
1829         webPage->send(Messages::WebPageProxy::ContentFilterDidBlockLoadForFrame(unblockHandler, m_frame->frameID()));
1830 }
1831
1832 #endif
1833
1834 void WebFrameLoaderClient::prefetchDNS(const String& hostname)
1835 {
1836     WebProcess::singleton().prefetchDNS(hostname);
1837 }
1838
1839 void WebFrameLoaderClient::didRestoreScrollPosition()
1840 {
1841     WebPage* webPage = m_frame->page();
1842     if (!webPage)
1843         return;
1844
1845     webPage->didRestoreScrollPosition();
1846 }
1847
1848 void WebFrameLoaderClient::getLoadDecisionForIcons(const Vector<std::pair<WebCore::LinkIcon&, uint64_t>>& icons)
1849 {
1850     auto* webPage = m_frame->page();
1851     if (!webPage)
1852         return;
1853
1854     for (auto& icon : icons)
1855         webPage->send(Messages::WebPageProxy::GetLoadDecisionForIcon(icon.first, CallbackID::fromInteger(icon.second)));
1856 }
1857
1858 void WebFrameLoaderClient::finishedLoadingIcon(uint64_t callbackIdentifier, SharedBuffer* data)
1859 {
1860     auto callbackID = CallbackID::fromInteger(callbackIdentifier);
1861     if (WebPage* webPage { m_frame->page() }) {
1862         if (data)
1863             webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { reinterpret_cast<const uint8_t*>(data->data()), data->size() }));
1864         else
1865             webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { nullptr, 0 }));
1866     }
1867 }
1868
1869 void WebFrameLoaderClient::didCreateWindow(DOMWindow& window)
1870 {
1871     auto* webPage = m_frame->page();
1872     if (!webPage)
1873         return;
1874
1875     webPage->send(Messages::WebPageProxy::DidCreateWindow(m_frame->frameID(), window.identifier()));
1876 }
1877
1878 #if ENABLE(APPLICATION_MANIFEST)
1879 void WebFrameLoaderClient::finishedLoadingApplicationManifest(uint64_t callbackIdentifier, const Optional<WebCore::ApplicationManifest>& manifest)
1880 {
1881     WebPage* webPage = m_frame->page();
1882     if (!webPage)
1883         return;
1884
1885     webPage->didFinishLoadingApplicationManifest(callbackIdentifier, manifest);
1886 }
1887 #endif // ENABLE(APPLICATION_MANIFEST)
1888
1889 } // namespace WebKit