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