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