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