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