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