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
99namespace WebKit {
100using namespace WebCore;
101
102WebFrameLoaderClient::WebFrameLoaderClient()
103 : m_frame(0)
104 , m_hasSentResponseToPluginView(false)
105 , m_didCompletePageTransition(false)
106 , m_frameHasCustomContentProvider(false)
107 , m_frameCameFromPageCache(false)
108{
109}
110
111WebFrameLoaderClient::~WebFrameLoaderClient()
112{
113}
114
115Optional<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
123Optional<uint64_t> WebFrameLoaderClient::frameID() const
124{
125 if (m_frame)
126 return m_frame->frameID();
127
128 return WTF::nullopt;
129}
130
131PAL::SessionID WebFrameLoaderClient::sessionID() const
132{
133 return m_frame && m_frame->page() ? m_frame->page()->sessionID() : PAL::SessionID::defaultSessionID();
134}
135
136void WebFrameLoaderClient::frameLoaderDestroyed()
137{
138 m_frame->invalidate();
139
140 // Balances explicit ref() in WebFrame::create().
141 m_frame->deref();
142}
143
144bool WebFrameLoaderClient::hasHTMLView() const
145{
146 return !m_frameHasCustomContentProvider;
147}
148
149bool WebFrameLoaderClient::hasWebView() const
150{
151 return m_frame->page();
152}
153
154void WebFrameLoaderClient::makeRepresentation(DocumentLoader*)
155{
156 notImplemented();
157}
158
159void WebFrameLoaderClient::forceLayoutForNonHTML()
160{
161 notImplemented();
162}
163
164void WebFrameLoaderClient::setCopiesOnScroll()
165{
166 notImplemented();
167}
168
169void 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
188void WebFrameLoaderClient::detachedFromParent3()
189{
190 notImplemented();
191}
192
193void 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
207void 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
221bool 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
230void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&)
231{
232 ASSERT_NOT_REACHED();
233}
234
235#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
236bool 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
244void 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
253void 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)
263void WebFrameLoaderClient::dispatchDidFinishDataDetection(NSArray *detectionResults)
264{
265 WebPage* webPage = m_frame->page();
266 if (!webPage)
267 return;
268 webPage->setDataDetectionResults(detectionResults);
269}
270#endif
271
272void 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
282void 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
292bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/)
293{
294 notImplemented();
295 return false;
296}
297
298void 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
308void 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
326void 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
336void 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
349void 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
362void 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
379void 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
388void 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
405void 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
422void 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
439void 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
456void WebFrameLoaderClient::dispatchWillClose()
457{
458 notImplemented();
459}
460
461void 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
471void 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
499static constexpr unsigned maxTitleLength = 1000; // Closest power of 10 above the W3C recommendation for Title length.
500
501void 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
519void 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
538void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error, WillContinueLoading willContinueLoading)
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, willContinueLoading, 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
574void 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
597void 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 webPage->didFinishDocumentLoad(*m_frame);
614}
615
616void WebFrameLoaderClient::dispatchDidFinishLoad()
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().didFinishLoadForFrame(*webPage, *m_frame, userData);
628
629 // Notify the UIProcess.
630 webPage->send(Messages::WebPageProxy::DidFinishLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
631
632 // If we have a load listener, notify it.
633 if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
634 loadListener->didFinishLoad(m_frame);
635
636 webPage->didFinishLoad(*m_frame);
637}
638
639void WebFrameLoaderClient::forcePageTransitionIfNeeded()
640{
641 if (m_didCompletePageTransition)
642 return;
643
644 WebPage* webPage = m_frame->page();
645 if (!webPage)
646 return;
647
648 webPage->didCompletePageTransition();
649 m_didCompletePageTransition = true;
650}
651
652void WebFrameLoaderClient::dispatchDidReachLayoutMilestone(OptionSet<WebCore::LayoutMilestone> milestones)
653{
654 WebPage* webPage = m_frame->page();
655 if (!webPage)
656 return;
657
658 RefPtr<API::Object> userData;
659
660 if (milestones & DidFirstLayout) {
661 RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching DidFirstLayoutForFrame, page = %p", this, webPage);
662
663 // FIXME: We should consider removing the old didFirstLayout API since this is doing double duty with the
664 // new didLayout API.
665 webPage->injectedBundleLoaderClient().didFirstLayoutForFrame(*webPage, *m_frame, userData);
666 webPage->send(Messages::WebPageProxy::DidFirstLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
667
668#if PLATFORM(MAC)
669 // FIXME: Do this on DidFirstVisuallyNonEmptyLayout when Mac Safari is able to handle it (<rdar://problem/17580021>)
670 if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) {
671 RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching didCompletePageTransition, page = %p", this, webPage);
672 webPage->didCompletePageTransition();
673 m_didCompletePageTransition = true;
674 }
675#endif
676
677#if USE(COORDINATED_GRAPHICS)
678 // Make sure viewport properties are dispatched on the main frame by the time the first layout happens.
679 ASSERT(!webPage->useFixedLayout() || m_frame != m_frame->page()->mainWebFrame() || m_frame->coreFrame()->document()->didDispatchViewportPropertiesChanged());
680#endif
681 }
682
683#if !RELEASE_LOG_DISABLED
684 StringBuilder builder;
685 auto addIfSet = [&milestones, &builder] (WebCore::LayoutMilestone milestone, const String& toAdd) {
686 if (milestones.contains(milestone)) {
687 if (!builder.isEmpty())
688 builder.append(", ");
689 builder.append(toAdd);
690 }
691 };
692
693 addIfSet(DidFirstLayout, "DidFirstLayout"_s);
694 addIfSet(DidFirstVisuallyNonEmptyLayout, "DidFirstVisuallyNonEmptyLayout"_s);
695 addIfSet(DidHitRelevantRepaintedObjectsAreaThreshold, "DidHitRelevantRepaintedObjectsAreaThreshold"_s);
696 addIfSet(DidFirstFlushForHeaderLayer, "DidFirstFlushForHeaderLayer"_s);
697 addIfSet(DidFirstLayoutAfterSuppressedIncrementalRendering, "DidFirstLayoutAfterSuppressedIncrementalRendering"_s);
698 addIfSet(DidFirstPaintAfterSuppressedIncrementalRendering, "DidFirstPaintAfterSuppressedIncrementalRendering"_s);
699 addIfSet(ReachedSessionRestorationRenderTreeSizeThreshold, "ReachedSessionRestorationRenderTreeSizeThreshold"_s);
700 addIfSet(DidRenderSignificantAmountOfText, "DidRenderSignificantAmountOfText"_s);
701 addIfSet(DidFirstMeaningfulPaint, "DidFirstMeaningfulPaint"_s);
702
703 RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching DidReachLayoutMilestone, page = %p, milestones = %{public}s", this, webPage, builder.toString().utf8().data());
704#endif
705
706 // Send this after DidFirstLayout-specific calls since some clients expect to get those messages first.
707 webPage->dispatchDidReachLayoutMilestone(milestones);
708
709 if (milestones & DidFirstVisuallyNonEmptyLayout) {
710 if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) {
711 RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching didCompletePageTransition, page = %p", this, webPage);
712 webPage->didCompletePageTransition();
713 m_didCompletePageTransition = true;
714 }
715
716 // FIXME: We should consider removing the old didFirstVisuallyNonEmptyLayoutForFrame API since this is doing
717 // double duty with the new didLayout API.
718 RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching DidFirstVisuallyNonEmptyLayoutForFrame, page = %p", this, webPage);
719 webPage->injectedBundleLoaderClient().didFirstVisuallyNonEmptyLayoutForFrame(*webPage, *m_frame, userData);
720 webPage->send(Messages::WebPageProxy::DidFirstVisuallyNonEmptyLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
721 }
722}
723
724void WebFrameLoaderClient::dispatchDidLayout()
725{
726 WebPage* webPage = m_frame->page();
727 if (!webPage)
728 return;
729
730 // Notify the bundle client.
731 webPage->injectedBundleLoaderClient().didLayoutForFrame(*webPage, *m_frame);
732
733 webPage->recomputeShortCircuitHorizontalWheelEventsState();
734
735#if PLATFORM(IOS_FAMILY)
736 webPage->updateSelectionAppearance();
737#endif
738
739 // NOTE: Unlike the other layout notifications, this does not notify the
740 // the UIProcess for every call.
741
742 if (m_frame == m_frame->page()->mainWebFrame()) {
743 // FIXME: Remove at the soonest possible time.
744 webPage->send(Messages::WebPageProxy::SetRenderTreeSize(webPage->renderTreeSize()));
745 webPage->mainFrameDidLayout();
746 }
747}
748
749Frame* WebFrameLoaderClient::dispatchCreatePage(const NavigationAction& navigationAction)
750{
751 WebPage* webPage = m_frame->page();
752 if (!webPage)
753 return nullptr;
754
755 // Just call through to the chrome client.
756 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 };
757 Page* newPage = webPage->corePage()->chrome().createWindow(*m_frame->coreFrame(), frameLoadRequest, { }, navigationAction);
758 if (!newPage)
759 return nullptr;
760
761 return &newPage->mainFrame();
762}
763
764void WebFrameLoaderClient::dispatchShow()
765{
766 WebPage* webPage = m_frame->page();
767 if (!webPage)
768 return;
769
770 webPage->show();
771}
772
773void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, WebCore::PolicyCheckIdentifier identifier, const String& downloadAttribute, FramePolicyFunction&& function)
774{
775 WebPage* webPage = m_frame ? m_frame->page() : nullptr;
776 if (!webPage) {
777 function(PolicyAction::Ignore, identifier);
778 return;
779 }
780
781 if (!request.url().string()) {
782 function(PolicyAction::Use, identifier);
783 return;
784 }
785
786 RefPtr<API::Object> userData;
787
788 // Notify the bundle client.
789 WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForResponse(webPage, m_frame, response, request, userData);
790 if (policy == WKBundlePagePolicyActionUse) {
791 function(PolicyAction::Use, identifier);
792 return;
793 }
794
795 bool canShowResponse = webPage->canShowResponse(response);
796
797 WebCore::Frame* coreFrame = m_frame->coreFrame();
798 auto* policyDocumentLoader = coreFrame ? coreFrame->loader().provisionalDocumentLoader() : nullptr;
799 auto navigationID = policyDocumentLoader ? static_cast<WebDocumentLoader&>(*policyDocumentLoader).navigationID() : 0;
800
801 Ref<WebFrame> protector(*m_frame);
802 uint64_t listenerID = m_frame->setUpPolicyListener(identifier, WTFMove(function), WebFrame::ForNavigationAction::No);
803 if (!webPage->send(Messages::WebPageProxy::DecidePolicyForResponse(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), identifier, navigationID, response, request,
804 canShowResponse, downloadAttribute, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))))
805 m_frame->didReceivePolicyDecision(listenerID, identifier, PolicyAction::Ignore, 0, { }, { });
806}
807
808void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(const NavigationAction& navigationAction, const ResourceRequest& request,
809 FormState* formState, const String& frameName, WebCore::PolicyCheckIdentifier identifier, FramePolicyFunction&& function)
810{
811 WebPage* webPage = m_frame ? m_frame->page() : nullptr;
812 if (!webPage) {
813 function(PolicyAction::Ignore, identifier);
814 return;
815 }
816
817 RefPtr<API::Object> userData;
818
819 auto action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
820
821 // Notify the bundle client.
822 WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNewWindowAction(webPage, m_frame, action.ptr(), request, frameName, userData);
823 if (policy == WKBundlePagePolicyActionUse) {
824 function(PolicyAction::Use, identifier);
825 return;
826 }
827
828 uint64_t listenerID = m_frame->setUpPolicyListener(identifier, WTFMove(function), WebFrame::ForNavigationAction::No);
829
830 NavigationActionData navigationActionData;
831 navigationActionData.navigationType = action->navigationType();
832 navigationActionData.modifiers = action->modifiers();
833 navigationActionData.mouseButton = action->mouseButton();
834 navigationActionData.syntheticClickType = action->syntheticClickType();
835 navigationActionData.clickLocationInRootViewCoordinates = action->clickLocationInRootViewCoordinates();
836 navigationActionData.userGestureTokenIdentifier = WebProcess::singleton().userGestureTokenIdentifier(navigationAction.userGestureToken());
837 navigationActionData.canHandleRequest = webPage->canHandleRequest(request);
838 navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy();
839 navigationActionData.downloadAttribute = navigationAction.downloadAttribute();
840
841 WebCore::Frame* coreFrame = m_frame ? m_frame->coreFrame() : nullptr;
842 webPage->send(Messages::WebPageProxy::DecidePolicyForNewWindowAction(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), identifier, navigationActionData, request,
843 frameName, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
844}
845
846void WebFrameLoaderClient::applyToDocumentLoader(WebsitePoliciesData&& websitePolicies)
847{
848 if (!m_frame)
849 return;
850 auto* coreFrame = m_frame->coreFrame();
851 if (!coreFrame)
852 return;
853 WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader());
854 if (!documentLoader)
855 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader());
856 if (!documentLoader)
857 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
858 if (!documentLoader)
859 return;
860
861 WebsitePoliciesData::applyToDocumentLoader(WTFMove(websitePolicies), *documentLoader);
862}
863
864void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const NavigationAction& navigationAction, const ResourceRequest& request, const ResourceResponse& redirectResponse,
865 FormState* formState, PolicyDecisionMode policyDecisionMode, WebCore::PolicyCheckIdentifier requestIdentifier, FramePolicyFunction&& function)
866{
867 WebPage* webPage = m_frame ? m_frame->page() : nullptr;
868 if (!webPage) {
869 function(PolicyAction::Ignore, requestIdentifier);
870 return;
871 }
872
873 LOG(Loading, "WebProcess %i - dispatchDecidePolicyForNavigationAction to request url %s", getCurrentProcessID(), request.url().string().utf8().data());
874
875 // Always ignore requests with empty URLs.
876 if (request.isEmpty()) {
877 function(PolicyAction::Ignore, requestIdentifier);
878 return;
879 }
880
881 RefPtr<API::Object> userData;
882
883 Ref<InjectedBundleNavigationAction> action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
884
885 // Notify the bundle client.
886 WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNavigationAction(webPage, m_frame, action.ptr(), request, userData);
887 if (policy == WKBundlePagePolicyActionUse) {
888 function(PolicyAction::Use, requestIdentifier);
889 return;
890 }
891
892 uint64_t listenerID = m_frame->setUpPolicyListener(requestIdentifier, WTFMove(function), WebFrame::ForNavigationAction::Yes);
893
894 ASSERT(navigationAction.requester());
895 auto requester = navigationAction.requester().value();
896
897 FrameInfoData originatingFrameInfoData;
898 originatingFrameInfoData.isMainFrame = navigationAction.initiatedByMainFrame() == InitiatedByMainFrame::Yes;
899 originatingFrameInfoData.request = ResourceRequest { requester.url() };
900 originatingFrameInfoData.securityOrigin = requester.securityOrigin().data();
901 if (requester.frameID() && WebProcess::singleton().webFrame(requester.frameID()))
902 originatingFrameInfoData.frameID = requester.frameID();
903
904 uint64_t originatingPageID = requester.pageID() && WebProcess::singleton().webPage(requester.pageID()) ? requester.pageID() : 0;
905
906 NavigationActionData navigationActionData;
907 navigationActionData.navigationType = action->navigationType();
908 navigationActionData.modifiers = action->modifiers();
909 navigationActionData.mouseButton = action->mouseButton();
910 navigationActionData.syntheticClickType = action->syntheticClickType();
911 navigationActionData.clickLocationInRootViewCoordinates = action->clickLocationInRootViewCoordinates();
912 navigationActionData.userGestureTokenIdentifier = WebProcess::singleton().userGestureTokenIdentifier(navigationAction.userGestureToken());
913 navigationActionData.canHandleRequest = webPage->canHandleRequest(request);
914 navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy();
915 navigationActionData.downloadAttribute = navigationAction.downloadAttribute();
916 navigationActionData.isRedirect = !redirectResponse.isNull();
917 navigationActionData.treatAsSameOriginNavigation = navigationAction.treatAsSameOriginNavigation();
918 navigationActionData.hasOpenedFrames = navigationAction.hasOpenedFrames();
919 navigationActionData.openedByDOMWithOpener = navigationAction.openedByDOMWithOpener();
920 if (auto& requester = navigationAction.requester())
921 navigationActionData.requesterOrigin = requester->securityOrigin().data();
922 navigationActionData.targetBackForwardItemIdentifier = navigationAction.targetBackForwardItemIdentifier();
923 navigationActionData.sourceBackForwardItemIdentifier = navigationAction.sourceBackForwardItemIdentifier();
924 navigationActionData.lockHistory = navigationAction.lockHistory();
925 navigationActionData.lockBackForwardList = navigationAction.lockBackForwardList();
926 navigationActionData.adClickAttribution = navigationAction.adClickAttribution();
927
928 WebCore::Frame* coreFrame = m_frame->coreFrame();
929 if (!coreFrame)
930 return function(PolicyAction::Ignore, requestIdentifier);
931 WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader());
932 if (!documentLoader) {
933 // FIXME: When we receive a redirect after the navigation policy has been decided for the initial request,
934 // the provisional load's DocumentLoader needs to receive navigation policy decisions. We need a better model for this state.
935 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader());
936 }
937 if (!documentLoader)
938 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
939
940 navigationActionData.clientRedirectSourceForHistory = documentLoader->clientRedirectSourceForHistory();
941
942 // Notify the UIProcess.
943 Ref<WebFrame> protect(*m_frame);
944
945 if (policyDecisionMode == PolicyDecisionMode::Synchronous) {
946 uint64_t newNavigationID;
947 WebCore::PolicyCheckIdentifier responseIdentifier;
948 PolicyAction policyAction;
949 DownloadID downloadID;
950 Optional<WebsitePoliciesData> websitePolicies;
951
952 if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationActionSync(m_frame->frameID(), m_frame->isMainFrame(), SecurityOriginData::fromFrame(coreFrame),
953 requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request,
954 IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())),
955 Messages::WebPageProxy::DecidePolicyForNavigationActionSync::Reply(responseIdentifier, policyAction, newNavigationID, downloadID, websitePolicies))) {
956 m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { });
957 return;
958 }
959
960 m_frame->didReceivePolicyDecision(listenerID, responseIdentifier, policyAction, 0, downloadID, { });
961 return;
962 }
963
964 ASSERT(policyDecisionMode == PolicyDecisionMode::Asynchronous);
965 if (!webPage->send(Messages::WebPageProxy::DecidePolicyForNavigationActionAsync(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame),
966 requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request,
967 IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()), listenerID)))
968 m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { });
969}
970
971void WebFrameLoaderClient::cancelPolicyCheck()
972{
973 m_frame->invalidatePolicyListener();
974}
975
976void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
977{
978 WebPage* webPage = m_frame->page();
979 if (!webPage)
980 return;
981
982 RefPtr<API::Object> userData;
983
984 // Notify the bundle client.
985 webPage->injectedBundlePolicyClient().unableToImplementPolicy(webPage, m_frame, error, userData);
986
987 // Notify the UIProcess.
988 webPage->send(Messages::WebPageProxy::UnableToImplementPolicy(m_frame->frameID(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
989}
990
991void WebFrameLoaderClient::dispatchWillSendSubmitEvent(Ref<FormState>&& formState)
992{
993 auto* webPage = m_frame->page();
994 if (!webPage)
995 return;
996
997 auto& form = formState->form();
998
999 ASSERT(formState->sourceDocument().frame());
1000 auto* sourceFrame = WebFrame::fromCoreFrame(*formState->sourceDocument().frame());
1001 ASSERT(sourceFrame);
1002
1003 webPage->injectedBundleFormClient().willSendSubmitEvent(webPage, &form, m_frame, sourceFrame, formState->textFieldValues());
1004}
1005
1006void WebFrameLoaderClient::dispatchWillSubmitForm(FormState& formState, CompletionHandler<void()>&& completionHandler)
1007{
1008 WebPage* webPage = m_frame->page();
1009 if (!webPage) {
1010 completionHandler();
1011 return;
1012 }
1013
1014 auto& form = formState.form();
1015
1016 auto* sourceCoreFrame = formState.sourceDocument().frame();
1017 if (!sourceCoreFrame)
1018 return completionHandler();
1019 auto* sourceFrame = WebFrame::fromCoreFrame(*sourceCoreFrame);
1020 if (!sourceFrame)
1021 return completionHandler();
1022
1023 auto& values = formState.textFieldValues();
1024
1025 RefPtr<API::Object> userData;
1026 webPage->injectedBundleFormClient().willSubmitForm(webPage, &form, m_frame, sourceFrame, values, userData);
1027
1028 uint64_t listenerID = m_frame->setUpWillSubmitFormListener(WTFMove(completionHandler));
1029
1030 webPage->send(Messages::WebPageProxy::WillSubmitForm(m_frame->frameID(), sourceFrame->frameID(), values, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1031}
1032
1033void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader*)
1034{
1035 notImplemented();
1036}
1037
1038void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
1039{
1040 if (!m_pluginView)
1041 return;
1042
1043 m_pluginView->manualLoadDidFail(error);
1044 m_pluginView = nullptr;
1045 m_hasSentResponseToPluginView = false;
1046}
1047
1048void WebFrameLoaderClient::setMainFrameDocumentReady(bool)
1049{
1050 notImplemented();
1051}
1052
1053void WebFrameLoaderClient::startDownload(const ResourceRequest& request, const String& suggestedName)
1054{
1055 m_frame->startDownload(request, suggestedName);
1056}
1057
1058void WebFrameLoaderClient::willChangeTitle(DocumentLoader*)
1059{
1060 notImplemented();
1061}
1062
1063void WebFrameLoaderClient::didChangeTitle(DocumentLoader*)
1064{
1065 notImplemented();
1066}
1067
1068void WebFrameLoaderClient::willReplaceMultipartContent()
1069{
1070 WebPage* webPage = m_frame->page();
1071 if (!webPage)
1072 return;
1073 webPage->willReplaceMultipartContent(*m_frame);
1074}
1075
1076void WebFrameLoaderClient::didReplaceMultipartContent()
1077{
1078 WebPage* webPage = m_frame->page();
1079 if (!webPage)
1080 return;
1081 webPage->didReplaceMultipartContent(*m_frame);
1082}
1083
1084void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
1085{
1086 if (!m_pluginView)
1087 loader->commitData(data, length);
1088
1089 // If the document is a stand-alone media document, now is the right time to cancel the WebKit load.
1090 // FIXME: This code should be shared across all ports. <http://webkit.org/b/48762>.
1091 if (m_frame->coreFrame()->document()->isMediaDocument())
1092 loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
1093
1094 // Calling commitData did not create the plug-in view.
1095 if (!m_pluginView)
1096 return;
1097
1098 if (!m_hasSentResponseToPluginView) {
1099 m_pluginView->manualLoadDidReceiveResponse(loader->response());
1100 // manualLoadDidReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
1101 // setting up this stream can cause the main document load to be cancelled, setting m_pluginView
1102 // to null
1103 if (!m_pluginView)
1104 return;
1105 m_hasSentResponseToPluginView = true;
1106 }
1107 m_pluginView->manualLoadDidReceiveData(data, length);
1108}
1109
1110void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
1111{
1112 if (!m_pluginView) {
1113 if (m_frameHasCustomContentProvider) {
1114 WebPage* webPage = m_frame->page();
1115 if (!webPage)
1116 return;
1117
1118 RefPtr<SharedBuffer> mainResourceData = loader->mainResourceData();
1119 IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(mainResourceData ? mainResourceData->data() : 0), mainResourceData ? mainResourceData->size() : 0);
1120 webPage->send(Messages::WebPageProxy::DidFinishLoadingDataForCustomContentProvider(loader->response().suggestedFilename(), dataReference));
1121 }
1122
1123 return;
1124 }
1125
1126 // If we just received an empty response without any data, we won't have sent a response to the plug-in view.
1127 // Make sure to do this before calling manualLoadDidFinishLoading.
1128 if (!m_hasSentResponseToPluginView) {
1129 m_pluginView->manualLoadDidReceiveResponse(loader->response());
1130
1131 // Protect against the above call nulling out the plug-in (by trying to cancel the load for example).
1132 if (!m_pluginView)
1133 return;
1134 }
1135
1136 m_pluginView->manualLoadDidFinishLoading();
1137 m_pluginView = nullptr;
1138 m_hasSentResponseToPluginView = false;
1139}
1140
1141void WebFrameLoaderClient::updateGlobalHistory()
1142{
1143 WebPage* webPage = m_frame->page();
1144 if (!webPage)
1145 return;
1146
1147 DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1148
1149 WebNavigationDataStore data;
1150 data.url = loader->url().string();
1151 // FIXME: Use direction of title.
1152 data.title = loader->title().string;
1153 data.originalRequest = loader->originalRequestCopy();
1154 data.response = loader->response();
1155
1156 webPage->send(Messages::WebPageProxy::DidNavigateWithNavigationData(data, m_frame->frameID()));
1157}
1158
1159void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
1160{
1161 WebPage* webPage = m_frame->page();
1162 if (!webPage)
1163 return;
1164
1165 DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1166 ASSERT(loader->unreachableURL().isEmpty());
1167
1168 // Client redirect
1169 if (!loader->clientRedirectSourceForHistory().isNull()) {
1170 webPage->send(Messages::WebPageProxy::DidPerformClientRedirect(
1171 loader->clientRedirectSourceForHistory(), loader->clientRedirectDestinationForHistory(), m_frame->frameID()));
1172 }
1173
1174 // Server redirect
1175 if (!loader->serverRedirectSourceForHistory().isNull()) {
1176 webPage->send(Messages::WebPageProxy::DidPerformServerRedirect(
1177 loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_frame->frameID()));
1178 }
1179}
1180
1181bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem& item) const
1182{
1183 WebPage* webPage = m_frame->page();
1184 if (!webPage)
1185 return false;
1186 webPage->send(Messages::WebPageProxy::WillGoToBackForwardListItem(item.identifier(), item.isInPageCache()));
1187 return true;
1188}
1189
1190void WebFrameLoaderClient::didDisplayInsecureContent()
1191{
1192 WebPage* webPage = m_frame->page();
1193 if (!webPage)
1194 return;
1195
1196 RefPtr<API::Object> userData;
1197
1198 webPage->injectedBundleLoaderClient().didDisplayInsecureContentForFrame(*webPage, *m_frame, userData);
1199
1200 webPage->send(Messages::WebPageProxy::DidDisplayInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1201}
1202
1203void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin&, const URL&)
1204{
1205 WebPage* webPage = m_frame->page();
1206 if (!webPage)
1207 return;
1208
1209 RefPtr<API::Object> userData;
1210
1211 webPage->injectedBundleLoaderClient().didRunInsecureContentForFrame(*webPage, *m_frame, userData);
1212
1213 webPage->send(Messages::WebPageProxy::DidRunInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1214}
1215
1216void WebFrameLoaderClient::didDetectXSS(const URL&, bool)
1217{
1218 WebPage* webPage = m_frame->page();
1219 if (!webPage)
1220 return;
1221
1222 RefPtr<API::Object> userData;
1223
1224 webPage->injectedBundleLoaderClient().didDetectXSSForFrame(*webPage, *m_frame, userData);
1225
1226 webPage->send(Messages::WebPageProxy::DidDetectXSSForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1227}
1228
1229ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
1230{
1231 return WebKit::cancelledError(request);
1232}
1233
1234ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
1235{
1236 return WebKit::blockedError(request);
1237}
1238
1239ResourceError WebFrameLoaderClient::blockedByContentBlockerError(const ResourceRequest& request)
1240{
1241 return WebKit::blockedByContentBlockerError(request);
1242}
1243
1244ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1245{
1246 return WebKit::cannotShowURLError(request);
1247}
1248
1249ResourceError WebFrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request)
1250{
1251 return WebKit::interruptedForPolicyChangeError(request);
1252}
1253
1254#if ENABLE(CONTENT_FILTERING)
1255ResourceError WebFrameLoaderClient::blockedByContentFilterError(const ResourceRequest& request)
1256{
1257 return WebKit::blockedByContentFilterError(request);
1258}
1259#endif
1260
1261ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1262{
1263 return WebKit::cannotShowMIMETypeError(response);
1264}
1265
1266ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1267{
1268 return WebKit::fileDoesNotExistError(response);
1269}
1270
1271ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1272{
1273 return WebKit::pluginWillHandleLoadError(response);
1274}
1275
1276bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
1277{
1278 static NeverDestroyed<const ResourceError> cancelledError(this->cancelledError(ResourceRequest()));
1279 static NeverDestroyed<const ResourceError> pluginWillHandleLoadError(this->pluginWillHandleLoadError(ResourceResponse()));
1280
1281 if (error.errorCode() == cancelledError.get().errorCode() && error.domain() == cancelledError.get().domain())
1282 return false;
1283
1284 if (error.errorCode() == pluginWillHandleLoadError.get().errorCode() && error.domain() == pluginWillHandleLoadError.get().domain())
1285 return false;
1286
1287 return true;
1288}
1289
1290bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest&) const
1291{
1292 notImplemented();
1293 return true;
1294}
1295
1296bool WebFrameLoaderClient::canShowMIMEType(const String& /*MIMEType*/) const
1297{
1298 notImplemented();
1299 return true;
1300}
1301
1302bool WebFrameLoaderClient::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const
1303{
1304 return true;
1305}
1306
1307bool WebFrameLoaderClient::representationExistsForURLScheme(const String& /*URLScheme*/) const
1308{
1309 notImplemented();
1310 return false;
1311}
1312
1313String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1314{
1315 notImplemented();
1316 return String();
1317}
1318
1319void WebFrameLoaderClient::frameLoadCompleted()
1320{
1321 // Note: Can be called multiple times.
1322 WebPage* webPage = m_frame->page();
1323 if (!webPage)
1324 return;
1325
1326 if (m_frame->isMainFrame() && !m_didCompletePageTransition) {
1327 webPage->didCompletePageTransition();
1328 m_didCompletePageTransition = true;
1329 }
1330}
1331
1332void WebFrameLoaderClient::saveViewStateToItem(HistoryItem& historyItem)
1333{
1334#if PLATFORM(IOS_FAMILY)
1335 if (m_frame->isMainFrame())
1336 m_frame->page()->savePageState(historyItem);
1337#else
1338 UNUSED_PARAM(historyItem);
1339#endif
1340}
1341
1342void WebFrameLoaderClient::restoreViewState()
1343{
1344#if PLATFORM(IOS_FAMILY)
1345 Frame& frame = *m_frame->coreFrame();
1346 HistoryItem* currentItem = frame.loader().history().currentItem();
1347 if (FrameView* view = frame.view()) {
1348 if (m_frame->isMainFrame())
1349 m_frame->page()->restorePageState(*currentItem);
1350 else if (!view->wasScrolledByUser())
1351 view->setScrollPosition(currentItem->scrollPosition());
1352 }
1353#else
1354 // Inform the UI process of the scale factor.
1355 double scaleFactor = m_frame->coreFrame()->loader().history().currentItem()->pageScaleFactor();
1356
1357 // A scale factor of 0 means the history item has the default scale factor, thus we do not need to update it.
1358 if (scaleFactor)
1359 m_frame->page()->send(Messages::WebPageProxy::PageScaleFactorDidChange(scaleFactor));
1360
1361 // FIXME: This should not be necessary. WebCore should be correctly invalidating
1362 // the view on restores from the back/forward cache.
1363 if (m_frame->page() && m_frame == m_frame->page()->mainWebFrame())
1364 m_frame->page()->drawingArea()->setNeedsDisplay();
1365#endif
1366}
1367
1368void WebFrameLoaderClient::provisionalLoadStarted()
1369{
1370 WebPage* webPage = m_frame->page();
1371 if (!webPage)
1372 return;
1373
1374 if (m_frame->isMainFrame()) {
1375 webPage->didStartPageTransition();
1376 m_didCompletePageTransition = false;
1377 }
1378}
1379
1380void WebFrameLoaderClient::didFinishLoad()
1381{
1382 // If we have a load listener, notify it.
1383 if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
1384 loadListener->didFinishLoad(m_frame);
1385}
1386
1387void WebFrameLoaderClient::prepareForDataSourceReplacement()
1388{
1389 notImplemented();
1390}
1391
1392Ref<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
1393{
1394 return m_frame->page()->createDocumentLoader(*m_frame->coreFrame(), request, substituteData);
1395}
1396
1397void WebFrameLoaderClient::updateCachedDocumentLoader(WebCore::DocumentLoader& loader)
1398{
1399 m_frame->page()->updateCachedDocumentLoader(static_cast<WebDocumentLoader&>(loader), *m_frame->coreFrame());
1400}
1401
1402void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const URL& url)
1403{
1404 WebPage* webPage = m_frame->page();
1405 if (!webPage)
1406 return;
1407
1408 // FIXME: Use direction of title.
1409 webPage->send(Messages::WebPageProxy::DidUpdateHistoryTitle(title.string, url.string(), m_frame->frameID()));
1410}
1411
1412String WebFrameLoaderClient::userAgent(const URL& url)
1413{
1414 auto* webPage = m_frame->page();
1415 if (!webPage)
1416 return String();
1417
1418 return webPage->userAgent(url);
1419}
1420
1421String WebFrameLoaderClient::overrideContentSecurityPolicy() const
1422{
1423 WebPage* webPage = m_frame->page();
1424 if (!webPage)
1425 return String();
1426
1427 return webPage->overrideContentSecurityPolicy();
1428}
1429
1430void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1431{
1432 WebPage* webPage = m_frame->page();
1433 if (!webPage)
1434 return;
1435
1436 HasInsecureContent hasInsecureContent;
1437 if (webPage->sendSync(Messages::WebPageProxy::HasInsecureContent(), Messages::WebPageProxy::HasInsecureContent::Reply(hasInsecureContent)))
1438 cachedFrame->setHasInsecureContent(hasInsecureContent);
1439}
1440
1441void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
1442{
1443 const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1444 m_frameHasCustomContentProvider = m_frame->isMainFrame() && m_frame->page()->shouldUseCustomContentProviderForResponse(response);
1445 m_frameCameFromPageCache = true;
1446}
1447
1448void WebFrameLoaderClient::transitionToCommittedForNewPage()
1449{
1450 WebPage* webPage = m_frame->page();
1451
1452 bool isMainFrame = m_frame->isMainFrame();
1453 bool shouldUseFixedLayout = isMainFrame && webPage->useFixedLayout();
1454 bool shouldDisableScrolling = isMainFrame && !webPage->mainFrameIsScrollable();
1455 bool shouldHideScrollbars = shouldDisableScrolling;
1456 IntRect fixedVisibleContentRect;
1457
1458#if USE(COORDINATED_GRAPHICS)
1459 if (m_frame->coreFrame()->view())
1460 fixedVisibleContentRect = m_frame->coreFrame()->view()->fixedVisibleContentRect();
1461 if (shouldUseFixedLayout)
1462 shouldHideScrollbars = true;
1463#endif
1464
1465 const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1466 m_frameHasCustomContentProvider = isMainFrame && webPage->shouldUseCustomContentProviderForResponse(response);
1467 m_frameCameFromPageCache = false;
1468
1469 ScrollbarMode defaultScrollbarMode = shouldHideScrollbars ? ScrollbarAlwaysOff : ScrollbarAuto;
1470
1471 ScrollbarMode horizontalScrollbarMode = webPage->alwaysShowsHorizontalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1472 ScrollbarMode verticalScrollbarMode = webPage->alwaysShowsVerticalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1473
1474 bool horizontalLock = shouldHideScrollbars || webPage->alwaysShowsHorizontalScroller();
1475 bool verticalLock = shouldHideScrollbars || webPage->alwaysShowsVerticalScroller();
1476
1477 m_frame->coreFrame()->createView(webPage->size(), webPage->backgroundColor(),
1478 webPage->fixedLayoutSize(), fixedVisibleContentRect, shouldUseFixedLayout,
1479 horizontalScrollbarMode, horizontalLock, verticalScrollbarMode, verticalLock);
1480
1481 if (int viewLayoutWidth = webPage->viewLayoutSize().width()) {
1482 int viewLayoutHeight = std::max(webPage->viewLayoutSize().height(), 1);
1483 m_frame->coreFrame()->view()->enableAutoSizeMode(true, { viewLayoutWidth, viewLayoutHeight });
1484
1485 if (webPage->autoSizingShouldExpandToViewHeight())
1486 m_frame->coreFrame()->view()->setAutoSizeFixedMinimumHeight(webPage->size().height());
1487 }
1488
1489 if (auto viewportSizeForViewportUnits = webPage->viewportSizeForCSSViewportUnits())
1490 m_frame->coreFrame()->view()->setViewportSizeForCSSViewportUnits(*viewportSizeForViewportUnits);
1491 m_frame->coreFrame()->view()->setProhibitsScrolling(shouldDisableScrolling);
1492 m_frame->coreFrame()->view()->setVisualUpdatesAllowedByClient(!webPage->shouldExtendIncrementalRenderingSuppression());
1493#if PLATFORM(COCOA)
1494 m_frame->coreFrame()->view()->setViewExposedRect(webPage->drawingArea()->viewExposedRect());
1495#endif
1496#if PLATFORM(IOS_FAMILY)
1497 if (isMainFrame)
1498 m_frame->coreFrame()->view()->setDelegatesScrolling(true);
1499#endif
1500
1501 if (webPage->scrollPinningBehavior() != DoNotPin)
1502 m_frame->coreFrame()->view()->setScrollPinningBehavior(webPage->scrollPinningBehavior());
1503
1504#if USE(COORDINATED_GRAPHICS)
1505 if (shouldUseFixedLayout) {
1506 m_frame->coreFrame()->view()->setDelegatesScrolling(shouldUseFixedLayout);
1507 m_frame->coreFrame()->view()->setPaintsEntireContents(shouldUseFixedLayout);
1508 return;
1509 }
1510#endif
1511}
1512
1513void WebFrameLoaderClient::didSaveToPageCache()
1514{
1515 WebPage* webPage = m_frame->page();
1516 if (!webPage)
1517 return;
1518
1519 if (m_frame->isMainFrame())
1520 webPage->send(Messages::WebPageProxy::DidSaveToPageCache());
1521}
1522
1523void WebFrameLoaderClient::didRestoreFromPageCache()
1524{
1525 m_frameCameFromPageCache = true;
1526}
1527
1528void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool value)
1529{
1530 WebPage* webPage = m_frame->page();
1531 if (!webPage)
1532 return;
1533
1534 webPage->send(Messages::WebPageProxy::FrameDidBecomeFrameSet(m_frame->frameID(), value));
1535}
1536
1537bool WebFrameLoaderClient::canCachePage() const
1538{
1539 // We cannot cache frames that have custom representations because they are
1540 // rendered in the UIProcess.
1541 return !m_frameHasCustomContentProvider;
1542}
1543
1544void WebFrameLoaderClient::convertMainResourceLoadToDownload(DocumentLoader *documentLoader, PAL::SessionID sessionID, const ResourceRequest& request, const ResourceResponse& response)
1545{
1546 m_frame->convertMainResourceLoadToDownload(documentLoader, sessionID, request, response);
1547}
1548
1549RefPtr<Frame> WebFrameLoaderClient::createFrame(const URL& url, const String& name, HTMLFrameOwnerElement& ownerElement,
1550 const String& referrer)
1551{
1552 auto* webPage = m_frame->page();
1553
1554 auto subframe = WebFrame::createSubframe(webPage, name, &ownerElement);
1555 auto* coreSubframe = subframe->coreFrame();
1556 if (!coreSubframe)
1557 return nullptr;
1558
1559 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1560 if (!coreSubframe->page())
1561 return nullptr;
1562
1563 m_frame->coreFrame()->loader().loadURLIntoChildFrame(url, referrer, coreSubframe);
1564
1565 // The frame's onload handler may have removed it from the document.
1566 if (!subframe->coreFrame())
1567 return nullptr;
1568 ASSERT(subframe->coreFrame() == coreSubframe);
1569 if (!coreSubframe->tree().parent())
1570 return nullptr;
1571
1572 return coreSubframe;
1573}
1574
1575RefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugInElement& pluginElement, const URL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1576{
1577 ASSERT(paramNames.size() == paramValues.size());
1578 ASSERT(m_frame->page());
1579
1580 Plugin::Parameters parameters;
1581 parameters.url = url;
1582 parameters.names = paramNames;
1583 parameters.values = paramValues;
1584 parameters.mimeType = mimeType;
1585 parameters.isFullFramePlugin = loadManually;
1586 parameters.shouldUseManualLoader = parameters.isFullFramePlugin && !m_frameCameFromPageCache;
1587#if PLATFORM(COCOA)
1588 parameters.layerHostingMode = m_frame->page()->layerHostingMode();
1589#endif
1590
1591#if ENABLE(NETSCAPE_PLUGIN_API)
1592 auto plugin = m_frame->page()->createPlugin(m_frame, &pluginElement, parameters, parameters.mimeType);
1593 if (!plugin)
1594 return nullptr;
1595
1596 return PluginView::create(pluginElement, plugin.releaseNonNull(), parameters);
1597#else
1598 UNUSED_PARAM(pluginElement);
1599 return nullptr;
1600#endif
1601}
1602
1603void WebFrameLoaderClient::redirectDataToPlugin(Widget& pluginWidget)
1604{
1605 m_pluginView = static_cast<PluginView*>(&pluginWidget);
1606}
1607
1608#if ENABLE(WEBGL)
1609
1610WebCore::WebGLLoadPolicy WebFrameLoaderClient::webGLPolicyForURL(const URL& url) const
1611{
1612 if (auto* webPage = m_frame->page())
1613 return webPage->webGLPolicyForURL(m_frame, url);
1614
1615 return WebGLAllowCreation;
1616}
1617
1618WebCore::WebGLLoadPolicy WebFrameLoaderClient::resolveWebGLPolicyForURL(const URL& url) const
1619{
1620 if (auto* webPage = m_frame->page())
1621 return webPage->resolveWebGLPolicyForURL(m_frame, url);
1622
1623 return WebGLAllowCreation;
1624}
1625
1626#endif
1627
1628RefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement& appletElement, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues)
1629{
1630#if ENABLE(NETSCAPE_PLUGIN_API)
1631 auto plugin = createPlugin(pluginSize, appletElement, URL(), paramNames, paramValues, appletElement.serviceType(), false);
1632 if (!plugin) {
1633 if (auto* webPage = m_frame->page()) {
1634 auto frameURLString = m_frame->coreFrame()->loader().documentLoader()->responseURL().string();
1635 auto pageURLString = webPage->corePage()->mainFrame().loader().documentLoader()->responseURL().string();
1636 webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(appletElement.serviceType(), frameURLString, pageURLString));
1637 }
1638 }
1639 return plugin;
1640#else
1641 UNUSED_PARAM(pluginSize);
1642 UNUSED_PARAM(appletElement);
1643 UNUSED_PARAM(paramNames);
1644 UNUSED_PARAM(paramValues);
1645 return nullptr;
1646#endif
1647}
1648
1649static bool pluginSupportsExtension(const PluginData& pluginData, const String& extension)
1650{
1651 ASSERT(extension.convertToASCIILowercase() == extension);
1652 Vector<MimeClassInfo> mimes;
1653 Vector<size_t> mimePluginIndices;
1654 pluginData.getWebVisibleMimesAndPluginIndices(mimes, mimePluginIndices);
1655 for (auto& mimeClassInfo : mimes) {
1656 if (mimeClassInfo.extensions.contains(extension))
1657 return true;
1658 }
1659 return false;
1660}
1661
1662ObjectContentType WebFrameLoaderClient::objectContentType(const URL& url, const String& mimeTypeIn)
1663{
1664 // FIXME: This should eventually be merged with WebCore::FrameLoader::defaultObjectContentType.
1665
1666 String mimeType = mimeTypeIn;
1667 if (mimeType.isEmpty()) {
1668 String path = url.path();
1669 auto dotPosition = path.reverseFind('.');
1670 if (dotPosition == notFound)
1671 return ObjectContentType::Frame;
1672 String extension = path.substring(dotPosition + 1).convertToASCIILowercase();
1673
1674 // Try to guess the MIME type from the extension.
1675 mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1676 if (mimeType.isEmpty()) {
1677 // Check if there's a plug-in around that can handle the extension.
1678 if (WebPage* webPage = m_frame->page()) {
1679 if (pluginSupportsExtension(webPage->corePage()->pluginData(), extension))
1680 return ObjectContentType::PlugIn;
1681 }
1682 return ObjectContentType::Frame;
1683 }
1684 }
1685
1686 if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1687 return ObjectContentType::Image;
1688
1689 if (WebPage* webPage = m_frame->page()) {
1690 auto allowedPluginTypes = webFrame()->coreFrame()->loader().subframeLoader().allowPlugins()
1691 ? PluginData::AllPlugins : PluginData::OnlyApplicationPlugins;
1692 if (webPage->corePage()->pluginData().supportsMimeType(mimeType, allowedPluginTypes))
1693 return ObjectContentType::PlugIn;
1694 }
1695
1696 if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1697 return ObjectContentType::Frame;
1698
1699#if PLATFORM(IOS_FAMILY)
1700 // iOS can render PDF in <object>/<embed> via PDFDocumentImage.
1701 if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType))
1702 return ObjectContentType::Image;
1703#endif
1704
1705 return ObjectContentType::None;
1706}
1707
1708String WebFrameLoaderClient::overrideMediaType() const
1709{
1710 notImplemented();
1711 return String();
1712}
1713
1714void WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
1715{
1716 WebPage* webPage = m_frame->page();
1717 if (!webPage)
1718 return;
1719
1720 webPage->injectedBundleLoaderClient().didClearWindowObjectForFrame(*webPage, *m_frame, world);
1721
1722 WebAutomationSessionProxy* automationSessionProxy = WebProcess::singleton().automationSessionProxy();
1723 if (automationSessionProxy && world.isNormal())
1724 automationSessionProxy->didClearWindowObjectForFrame(*m_frame);
1725}
1726
1727void WebFrameLoaderClient::dispatchGlobalObjectAvailable(DOMWrapperWorld& world)
1728{
1729 WebPage* webPage = m_frame->page();
1730 if (!webPage)
1731 return;
1732
1733 webPage->injectedBundleLoaderClient().globalObjectIsAvailableForFrame(*webPage, *m_frame, world);
1734}
1735
1736void WebFrameLoaderClient::willInjectUserScript(DOMWrapperWorld& world)
1737{
1738 WebPage* webPage = m_frame->page();
1739 if (!webPage)
1740 return;
1741
1742 webPage->injectedBundleLoaderClient().willInjectUserScriptForFrame(*webPage, *m_frame, world);
1743}
1744
1745void WebFrameLoaderClient::dispatchWillDisconnectDOMWindowExtensionFromGlobalObject(WebCore::DOMWindowExtension* extension)
1746{
1747 WebPage* webPage = m_frame->page();
1748 if (!webPage)
1749 return;
1750
1751 webPage->injectedBundleLoaderClient().willDisconnectDOMWindowExtensionFromGlobalObject(*webPage, extension);
1752}
1753
1754void WebFrameLoaderClient::dispatchDidReconnectDOMWindowExtensionToGlobalObject(WebCore::DOMWindowExtension* extension)
1755{
1756 WebPage* webPage = m_frame->page();
1757 if (!webPage)
1758 return;
1759
1760 webPage->injectedBundleLoaderClient().didReconnectDOMWindowExtensionToGlobalObject(*webPage, extension);
1761}
1762
1763void WebFrameLoaderClient::dispatchWillDestroyGlobalObjectForDOMWindowExtension(WebCore::DOMWindowExtension* extension)
1764{
1765 WebPage* webPage = m_frame->page();
1766 if (!webPage)
1767 return;
1768
1769 webPage->injectedBundleLoaderClient().willDestroyGlobalObjectForDOMWindowExtension(*webPage, extension);
1770}
1771
1772#if PLATFORM(COCOA)
1773
1774RemoteAXObjectRef WebFrameLoaderClient::accessibilityRemoteObject()
1775{
1776 WebPage* webPage = m_frame->page();
1777 if (!webPage)
1778 return 0;
1779
1780 return webPage->accessibilityRemoteObject();
1781}
1782
1783void WebFrameLoaderClient::willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response, CompletionHandler<void(NSCachedURLResponse *)>&& completionHandler) const
1784{
1785 WebPage* webPage = m_frame->page();
1786 if (!webPage)
1787 return completionHandler(response);
1788
1789 return completionHandler(webPage->injectedBundleResourceLoadClient().shouldCacheResponse(*webPage, *m_frame, identifier) ? response : nil);
1790}
1791
1792NSDictionary *WebFrameLoaderClient::dataDetectionContext()
1793{
1794 WebPage* webPage = m_frame->page();
1795 if (!webPage)
1796 return nil;
1797
1798 return webPage->dataDetectionContext();
1799}
1800
1801#endif // PLATFORM(COCOA)
1802
1803void WebFrameLoaderClient::didChangeScrollOffset()
1804{
1805 WebPage* webPage = m_frame->page();
1806 if (!webPage)
1807 return;
1808
1809 webPage->didChangeScrollOffsetForFrame(m_frame->coreFrame());
1810}
1811
1812bool WebFrameLoaderClient::allowScript(bool enabledPerSettings)
1813{
1814 if (!enabledPerSettings)
1815 return false;
1816
1817 auto* pluginView = WebPage::pluginViewForFrame(m_frame->coreFrame());
1818 return !pluginView || !pluginView->shouldAllowScripting();
1819}
1820
1821bool WebFrameLoaderClient::shouldForceUniversalAccessFromLocalURL(const URL& url)
1822{
1823 WebPage* webPage = m_frame->page();
1824 if (!webPage)
1825 return false;
1826
1827 return webPage->injectedBundleLoaderClient().shouldForceUniversalAccessFromLocalURL(*webPage, url);
1828}
1829
1830Ref<FrameNetworkingContext> WebFrameLoaderClient::createNetworkingContext()
1831{
1832 ASSERT(!hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
1833 return WebFrameNetworkingContext::create(m_frame);
1834}
1835
1836#if ENABLE(CONTENT_FILTERING)
1837
1838void WebFrameLoaderClient::contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler unblockHandler)
1839{
1840 if (!unblockHandler.needsUIProcess()) {
1841 m_frame->coreFrame()->loader().policyChecker().setContentFilterUnblockHandler(WTFMove(unblockHandler));
1842 return;
1843 }
1844
1845 if (WebPage* webPage { m_frame->page() })
1846 webPage->send(Messages::WebPageProxy::ContentFilterDidBlockLoadForFrame(unblockHandler, m_frame->frameID()));
1847}
1848
1849#endif
1850
1851void WebFrameLoaderClient::prefetchDNS(const String& hostname)
1852{
1853 WebProcess::singleton().prefetchDNS(hostname);
1854}
1855
1856void WebFrameLoaderClient::didRestoreScrollPosition()
1857{
1858 WebPage* webPage = m_frame->page();
1859 if (!webPage)
1860 return;
1861
1862 webPage->didRestoreScrollPosition();
1863}
1864
1865void WebFrameLoaderClient::getLoadDecisionForIcons(const Vector<std::pair<WebCore::LinkIcon&, uint64_t>>& icons)
1866{
1867 auto* webPage = m_frame->page();
1868 if (!webPage)
1869 return;
1870
1871 for (auto& icon : icons)
1872 webPage->send(Messages::WebPageProxy::GetLoadDecisionForIcon(icon.first, CallbackID::fromInteger(icon.second)));
1873}
1874
1875void WebFrameLoaderClient::finishedLoadingIcon(uint64_t callbackIdentifier, SharedBuffer* data)
1876{
1877 auto callbackID = CallbackID::fromInteger(callbackIdentifier);
1878 if (WebPage* webPage { m_frame->page() }) {
1879 if (data)
1880 webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { reinterpret_cast<const uint8_t*>(data->data()), data->size() }));
1881 else
1882 webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { nullptr, 0 }));
1883 }
1884}
1885
1886void WebFrameLoaderClient::didCreateWindow(DOMWindow& window)
1887{
1888 auto* webPage = m_frame->page();
1889 if (!webPage)
1890 return;
1891
1892 webPage->send(Messages::WebPageProxy::DidCreateWindow(m_frame->frameID(), window.identifier()));
1893}
1894
1895#if ENABLE(APPLICATION_MANIFEST)
1896void WebFrameLoaderClient::finishedLoadingApplicationManifest(uint64_t callbackIdentifier, const Optional<WebCore::ApplicationManifest>& manifest)
1897{
1898 WebPage* webPage = m_frame->page();
1899 if (!webPage)
1900 return;
1901
1902 webPage->didFinishLoadingApplicationManifest(callbackIdentifier, manifest);
1903}
1904#endif // ENABLE(APPLICATION_MANIFEST)
1905
1906} // namespace WebKit
1907