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<PageIdentifier> 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().toUInt64(), 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().toUInt64(), 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 Optional<PageIdentifier> originatingPageID;
905 if (requester.pageID() && WebProcess::singleton().webPage(requester.pageID()))
906 originatingPageID = requester.pageID();
907
908 NavigationActionData navigationActionData;
909 navigationActionData.navigationType = action->navigationType();
910 navigationActionData.modifiers = action->modifiers();
911 navigationActionData.mouseButton = action->mouseButton();
912 navigationActionData.syntheticClickType = action->syntheticClickType();
913 navigationActionData.clickLocationInRootViewCoordinates = action->clickLocationInRootViewCoordinates();
914 navigationActionData.userGestureTokenIdentifier = WebProcess::singleton().userGestureTokenIdentifier(navigationAction.userGestureToken());
915 navigationActionData.canHandleRequest = webPage->canHandleRequest(request);
916 navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy();
917 navigationActionData.downloadAttribute = navigationAction.downloadAttribute();
918 navigationActionData.isRedirect = !redirectResponse.isNull();
919 navigationActionData.treatAsSameOriginNavigation = navigationAction.treatAsSameOriginNavigation();
920 navigationActionData.hasOpenedFrames = navigationAction.hasOpenedFrames();
921 navigationActionData.openedByDOMWithOpener = navigationAction.openedByDOMWithOpener();
922 if (auto& requester = navigationAction.requester())
923 navigationActionData.requesterOrigin = requester->securityOrigin().data();
924 navigationActionData.targetBackForwardItemIdentifier = navigationAction.targetBackForwardItemIdentifier();
925 navigationActionData.sourceBackForwardItemIdentifier = navigationAction.sourceBackForwardItemIdentifier();
926 navigationActionData.lockHistory = navigationAction.lockHistory();
927 navigationActionData.lockBackForwardList = navigationAction.lockBackForwardList();
928 navigationActionData.adClickAttribution = navigationAction.adClickAttribution();
929
930 WebCore::Frame* coreFrame = m_frame->coreFrame();
931 if (!coreFrame)
932 return function(PolicyAction::Ignore, requestIdentifier);
933 WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader());
934 if (!documentLoader) {
935 // FIXME: When we receive a redirect after the navigation policy has been decided for the initial request,
936 // the provisional load's DocumentLoader needs to receive navigation policy decisions. We need a better model for this state.
937 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader());
938 }
939 if (!documentLoader)
940 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
941
942 navigationActionData.clientRedirectSourceForHistory = documentLoader->clientRedirectSourceForHistory();
943
944 // Notify the UIProcess.
945 Ref<WebFrame> protect(*m_frame);
946
947 if (policyDecisionMode == PolicyDecisionMode::Synchronous) {
948 uint64_t newNavigationID;
949 WebCore::PolicyCheckIdentifier responseIdentifier;
950 PolicyAction policyAction;
951 DownloadID downloadID;
952 Optional<WebsitePoliciesData> websitePolicies;
953
954 if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationActionSync(m_frame->frameID(), m_frame->isMainFrame(), SecurityOriginData::fromFrame(coreFrame),
955 requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request,
956 IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())),
957 Messages::WebPageProxy::DecidePolicyForNavigationActionSync::Reply(responseIdentifier, policyAction, newNavigationID, downloadID, websitePolicies))) {
958 m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { });
959 return;
960 }
961
962 m_frame->didReceivePolicyDecision(listenerID, responseIdentifier, policyAction, 0, downloadID, { });
963 return;
964 }
965
966 ASSERT(policyDecisionMode == PolicyDecisionMode::Asynchronous);
967 if (!webPage->send(Messages::WebPageProxy::DecidePolicyForNavigationActionAsync(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame),
968 requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request,
969 IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()), listenerID)))
970 m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { });
971}
972
973void WebFrameLoaderClient::cancelPolicyCheck()
974{
975 m_frame->invalidatePolicyListener();
976}
977
978void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
979{
980 WebPage* webPage = m_frame->page();
981 if (!webPage)
982 return;
983
984 RefPtr<API::Object> userData;
985
986 // Notify the bundle client.
987 webPage->injectedBundlePolicyClient().unableToImplementPolicy(webPage, m_frame, error, userData);
988
989 // Notify the UIProcess.
990 webPage->send(Messages::WebPageProxy::UnableToImplementPolicy(m_frame->frameID(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
991}
992
993void WebFrameLoaderClient::dispatchWillSendSubmitEvent(Ref<FormState>&& formState)
994{
995 auto* webPage = m_frame->page();
996 if (!webPage)
997 return;
998
999 auto& form = formState->form();
1000
1001 ASSERT(formState->sourceDocument().frame());
1002 auto* sourceFrame = WebFrame::fromCoreFrame(*formState->sourceDocument().frame());
1003 ASSERT(sourceFrame);
1004
1005 webPage->injectedBundleFormClient().willSendSubmitEvent(webPage, &form, m_frame, sourceFrame, formState->textFieldValues());
1006}
1007
1008void WebFrameLoaderClient::dispatchWillSubmitForm(FormState& formState, CompletionHandler<void()>&& completionHandler)
1009{
1010 WebPage* webPage = m_frame->page();
1011 if (!webPage) {
1012 completionHandler();
1013 return;
1014 }
1015
1016 auto& form = formState.form();
1017
1018 auto* sourceCoreFrame = formState.sourceDocument().frame();
1019 if (!sourceCoreFrame)
1020 return completionHandler();
1021 auto* sourceFrame = WebFrame::fromCoreFrame(*sourceCoreFrame);
1022 if (!sourceFrame)
1023 return completionHandler();
1024
1025 auto& values = formState.textFieldValues();
1026
1027 RefPtr<API::Object> userData;
1028 webPage->injectedBundleFormClient().willSubmitForm(webPage, &form, m_frame, sourceFrame, values, userData);
1029
1030 uint64_t listenerID = m_frame->setUpWillSubmitFormListener(WTFMove(completionHandler));
1031
1032 webPage->send(Messages::WebPageProxy::WillSubmitForm(m_frame->frameID(), sourceFrame->frameID(), values, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1033}
1034
1035void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader*)
1036{
1037 notImplemented();
1038}
1039
1040void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
1041{
1042 if (!m_pluginView)
1043 return;
1044
1045 m_pluginView->manualLoadDidFail(error);
1046 m_pluginView = nullptr;
1047 m_hasSentResponseToPluginView = false;
1048}
1049
1050void WebFrameLoaderClient::setMainFrameDocumentReady(bool)
1051{
1052 notImplemented();
1053}
1054
1055void WebFrameLoaderClient::startDownload(const ResourceRequest& request, const String& suggestedName)
1056{
1057 m_frame->startDownload(request, suggestedName);
1058}
1059
1060void WebFrameLoaderClient::willChangeTitle(DocumentLoader*)
1061{
1062 notImplemented();
1063}
1064
1065void WebFrameLoaderClient::didChangeTitle(DocumentLoader*)
1066{
1067 notImplemented();
1068}
1069
1070void WebFrameLoaderClient::willReplaceMultipartContent()
1071{
1072 WebPage* webPage = m_frame->page();
1073 if (!webPage)
1074 return;
1075 webPage->willReplaceMultipartContent(*m_frame);
1076}
1077
1078void WebFrameLoaderClient::didReplaceMultipartContent()
1079{
1080 WebPage* webPage = m_frame->page();
1081 if (!webPage)
1082 return;
1083 webPage->didReplaceMultipartContent(*m_frame);
1084}
1085
1086void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
1087{
1088 if (!m_pluginView)
1089 loader->commitData(data, length);
1090
1091 // If the document is a stand-alone media document, now is the right time to cancel the WebKit load.
1092 // FIXME: This code should be shared across all ports. <http://webkit.org/b/48762>.
1093 if (m_frame->coreFrame()->document()->isMediaDocument())
1094 loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
1095
1096 // Calling commitData did not create the plug-in view.
1097 if (!m_pluginView)
1098 return;
1099
1100 if (!m_hasSentResponseToPluginView) {
1101 m_pluginView->manualLoadDidReceiveResponse(loader->response());
1102 // manualLoadDidReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
1103 // setting up this stream can cause the main document load to be cancelled, setting m_pluginView
1104 // to null
1105 if (!m_pluginView)
1106 return;
1107 m_hasSentResponseToPluginView = true;
1108 }
1109 m_pluginView->manualLoadDidReceiveData(data, length);
1110}
1111
1112void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
1113{
1114 if (!m_pluginView) {
1115 if (m_frameHasCustomContentProvider) {
1116 WebPage* webPage = m_frame->page();
1117 if (!webPage)
1118 return;
1119
1120 RefPtr<SharedBuffer> mainResourceData = loader->mainResourceData();
1121 IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(mainResourceData ? mainResourceData->data() : 0), mainResourceData ? mainResourceData->size() : 0);
1122 webPage->send(Messages::WebPageProxy::DidFinishLoadingDataForCustomContentProvider(loader->response().suggestedFilename(), dataReference));
1123 }
1124
1125 return;
1126 }
1127
1128 // If we just received an empty response without any data, we won't have sent a response to the plug-in view.
1129 // Make sure to do this before calling manualLoadDidFinishLoading.
1130 if (!m_hasSentResponseToPluginView) {
1131 m_pluginView->manualLoadDidReceiveResponse(loader->response());
1132
1133 // Protect against the above call nulling out the plug-in (by trying to cancel the load for example).
1134 if (!m_pluginView)
1135 return;
1136 }
1137
1138 m_pluginView->manualLoadDidFinishLoading();
1139 m_pluginView = nullptr;
1140 m_hasSentResponseToPluginView = false;
1141}
1142
1143void WebFrameLoaderClient::updateGlobalHistory()
1144{
1145 WebPage* webPage = m_frame->page();
1146 if (!webPage)
1147 return;
1148
1149 DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1150
1151 WebNavigationDataStore data;
1152 data.url = loader->url().string();
1153 // FIXME: Use direction of title.
1154 data.title = loader->title().string;
1155 data.originalRequest = loader->originalRequestCopy();
1156 data.response = loader->response();
1157
1158 webPage->send(Messages::WebPageProxy::DidNavigateWithNavigationData(data, m_frame->frameID()));
1159}
1160
1161void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
1162{
1163 WebPage* webPage = m_frame->page();
1164 if (!webPage)
1165 return;
1166
1167 DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1168 ASSERT(loader->unreachableURL().isEmpty());
1169
1170 // Client redirect
1171 if (!loader->clientRedirectSourceForHistory().isNull()) {
1172 webPage->send(Messages::WebPageProxy::DidPerformClientRedirect(
1173 loader->clientRedirectSourceForHistory(), loader->clientRedirectDestinationForHistory(), m_frame->frameID()));
1174 }
1175
1176 // Server redirect
1177 if (!loader->serverRedirectSourceForHistory().isNull()) {
1178 webPage->send(Messages::WebPageProxy::DidPerformServerRedirect(
1179 loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_frame->frameID()));
1180 }
1181}
1182
1183bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem& item) const
1184{
1185 WebPage* webPage = m_frame->page();
1186 if (!webPage)
1187 return false;
1188 webPage->send(Messages::WebPageProxy::WillGoToBackForwardListItem(item.identifier(), item.isInPageCache()));
1189 return true;
1190}
1191
1192void WebFrameLoaderClient::didDisplayInsecureContent()
1193{
1194 WebPage* webPage = m_frame->page();
1195 if (!webPage)
1196 return;
1197
1198 RefPtr<API::Object> userData;
1199
1200 webPage->injectedBundleLoaderClient().didDisplayInsecureContentForFrame(*webPage, *m_frame, userData);
1201
1202 webPage->send(Messages::WebPageProxy::DidDisplayInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1203}
1204
1205void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin&, const URL&)
1206{
1207 WebPage* webPage = m_frame->page();
1208 if (!webPage)
1209 return;
1210
1211 RefPtr<API::Object> userData;
1212
1213 webPage->injectedBundleLoaderClient().didRunInsecureContentForFrame(*webPage, *m_frame, userData);
1214
1215 webPage->send(Messages::WebPageProxy::DidRunInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1216}
1217
1218void WebFrameLoaderClient::didDetectXSS(const URL&, bool)
1219{
1220 WebPage* webPage = m_frame->page();
1221 if (!webPage)
1222 return;
1223
1224 RefPtr<API::Object> userData;
1225
1226 webPage->injectedBundleLoaderClient().didDetectXSSForFrame(*webPage, *m_frame, userData);
1227
1228 webPage->send(Messages::WebPageProxy::DidDetectXSSForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1229}
1230
1231ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
1232{
1233 return WebKit::cancelledError(request);
1234}
1235
1236ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
1237{
1238 return WebKit::blockedError(request);
1239}
1240
1241ResourceError WebFrameLoaderClient::blockedByContentBlockerError(const ResourceRequest& request)
1242{
1243 return WebKit::blockedByContentBlockerError(request);
1244}
1245
1246ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1247{
1248 return WebKit::cannotShowURLError(request);
1249}
1250
1251ResourceError WebFrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request)
1252{
1253 return WebKit::interruptedForPolicyChangeError(request);
1254}
1255
1256#if ENABLE(CONTENT_FILTERING)
1257ResourceError WebFrameLoaderClient::blockedByContentFilterError(const ResourceRequest& request)
1258{
1259 return WebKit::blockedByContentFilterError(request);
1260}
1261#endif
1262
1263ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1264{
1265 return WebKit::cannotShowMIMETypeError(response);
1266}
1267
1268ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1269{
1270 return WebKit::fileDoesNotExistError(response);
1271}
1272
1273ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1274{
1275 return WebKit::pluginWillHandleLoadError(response);
1276}
1277
1278bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
1279{
1280 static NeverDestroyed<const ResourceError> cancelledError(this->cancelledError(ResourceRequest()));
1281 static NeverDestroyed<const ResourceError> pluginWillHandleLoadError(this->pluginWillHandleLoadError(ResourceResponse()));
1282
1283 if (error.errorCode() == cancelledError.get().errorCode() && error.domain() == cancelledError.get().domain())
1284 return false;
1285
1286 if (error.errorCode() == pluginWillHandleLoadError.get().errorCode() && error.domain() == pluginWillHandleLoadError.get().domain())
1287 return false;
1288
1289 return true;
1290}
1291
1292bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest&) const
1293{
1294 notImplemented();
1295 return true;
1296}
1297
1298bool WebFrameLoaderClient::canShowMIMEType(const String& /*MIMEType*/) const
1299{
1300 notImplemented();
1301 return true;
1302}
1303
1304bool WebFrameLoaderClient::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const
1305{
1306 return true;
1307}
1308
1309bool WebFrameLoaderClient::representationExistsForURLScheme(const String& /*URLScheme*/) const
1310{
1311 notImplemented();
1312 return false;
1313}
1314
1315String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1316{
1317 notImplemented();
1318 return String();
1319}
1320
1321void WebFrameLoaderClient::frameLoadCompleted()
1322{
1323 // Note: Can be called multiple times.
1324 WebPage* webPage = m_frame->page();
1325 if (!webPage)
1326 return;
1327
1328 if (m_frame->isMainFrame() && !m_didCompletePageTransition) {
1329 webPage->didCompletePageTransition();
1330 m_didCompletePageTransition = true;
1331 }
1332}
1333
1334void WebFrameLoaderClient::saveViewStateToItem(HistoryItem& historyItem)
1335{
1336#if PLATFORM(IOS_FAMILY)
1337 if (m_frame->isMainFrame())
1338 m_frame->page()->savePageState(historyItem);
1339#else
1340 UNUSED_PARAM(historyItem);
1341#endif
1342}
1343
1344void WebFrameLoaderClient::restoreViewState()
1345{
1346#if PLATFORM(IOS_FAMILY)
1347 Frame& frame = *m_frame->coreFrame();
1348 HistoryItem* currentItem = frame.loader().history().currentItem();
1349 if (FrameView* view = frame.view()) {
1350 if (m_frame->isMainFrame())
1351 m_frame->page()->restorePageState(*currentItem);
1352 else if (!view->wasScrolledByUser())
1353 view->setScrollPosition(currentItem->scrollPosition());
1354 }
1355#else
1356 // Inform the UI process of the scale factor.
1357 double scaleFactor = m_frame->coreFrame()->loader().history().currentItem()->pageScaleFactor();
1358
1359 // A scale factor of 0 means the history item has the default scale factor, thus we do not need to update it.
1360 if (scaleFactor)
1361 m_frame->page()->send(Messages::WebPageProxy::PageScaleFactorDidChange(scaleFactor));
1362
1363 // FIXME: This should not be necessary. WebCore should be correctly invalidating
1364 // the view on restores from the back/forward cache.
1365 if (m_frame->page() && m_frame == m_frame->page()->mainWebFrame())
1366 m_frame->page()->drawingArea()->setNeedsDisplay();
1367#endif
1368}
1369
1370void WebFrameLoaderClient::provisionalLoadStarted()
1371{
1372 WebPage* webPage = m_frame->page();
1373 if (!webPage)
1374 return;
1375
1376 if (m_frame->isMainFrame()) {
1377 webPage->didStartPageTransition();
1378 m_didCompletePageTransition = false;
1379 }
1380}
1381
1382void WebFrameLoaderClient::didFinishLoad()
1383{
1384 // If we have a load listener, notify it.
1385 if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
1386 loadListener->didFinishLoad(m_frame);
1387}
1388
1389void WebFrameLoaderClient::prepareForDataSourceReplacement()
1390{
1391 notImplemented();
1392}
1393
1394Ref<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
1395{
1396 return m_frame->page()->createDocumentLoader(*m_frame->coreFrame(), request, substituteData);
1397}
1398
1399void WebFrameLoaderClient::updateCachedDocumentLoader(WebCore::DocumentLoader& loader)
1400{
1401 m_frame->page()->updateCachedDocumentLoader(static_cast<WebDocumentLoader&>(loader), *m_frame->coreFrame());
1402}
1403
1404void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const URL& url)
1405{
1406 WebPage* webPage = m_frame->page();
1407 if (!webPage)
1408 return;
1409
1410 // FIXME: Use direction of title.
1411 webPage->send(Messages::WebPageProxy::DidUpdateHistoryTitle(title.string, url.string(), m_frame->frameID()));
1412}
1413
1414String WebFrameLoaderClient::userAgent(const URL& url)
1415{
1416 auto* webPage = m_frame->page();
1417 if (!webPage)
1418 return String();
1419
1420 return webPage->userAgent(url);
1421}
1422
1423String WebFrameLoaderClient::overrideContentSecurityPolicy() const
1424{
1425 WebPage* webPage = m_frame->page();
1426 if (!webPage)
1427 return String();
1428
1429 return webPage->overrideContentSecurityPolicy();
1430}
1431
1432void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1433{
1434 WebPage* webPage = m_frame->page();
1435 if (!webPage)
1436 return;
1437
1438 HasInsecureContent hasInsecureContent;
1439 if (webPage->sendSync(Messages::WebPageProxy::HasInsecureContent(), Messages::WebPageProxy::HasInsecureContent::Reply(hasInsecureContent)))
1440 cachedFrame->setHasInsecureContent(hasInsecureContent);
1441}
1442
1443void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
1444{
1445 const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1446 m_frameHasCustomContentProvider = m_frame->isMainFrame() && m_frame->page()->shouldUseCustomContentProviderForResponse(response);
1447 m_frameCameFromPageCache = true;
1448}
1449
1450void WebFrameLoaderClient::transitionToCommittedForNewPage()
1451{
1452 WebPage* webPage = m_frame->page();
1453
1454 bool isMainFrame = m_frame->isMainFrame();
1455 bool shouldUseFixedLayout = isMainFrame && webPage->useFixedLayout();
1456 bool shouldDisableScrolling = isMainFrame && !webPage->mainFrameIsScrollable();
1457 bool shouldHideScrollbars = shouldDisableScrolling;
1458 IntRect fixedVisibleContentRect;
1459
1460#if USE(COORDINATED_GRAPHICS)
1461 if (m_frame->coreFrame()->view())
1462 fixedVisibleContentRect = m_frame->coreFrame()->view()->fixedVisibleContentRect();
1463 if (shouldUseFixedLayout)
1464 shouldHideScrollbars = true;
1465#endif
1466
1467 const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1468 m_frameHasCustomContentProvider = isMainFrame && webPage->shouldUseCustomContentProviderForResponse(response);
1469 m_frameCameFromPageCache = false;
1470
1471 ScrollbarMode defaultScrollbarMode = shouldHideScrollbars ? ScrollbarAlwaysOff : ScrollbarAuto;
1472
1473 ScrollbarMode horizontalScrollbarMode = webPage->alwaysShowsHorizontalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1474 ScrollbarMode verticalScrollbarMode = webPage->alwaysShowsVerticalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1475
1476 bool horizontalLock = shouldHideScrollbars || webPage->alwaysShowsHorizontalScroller();
1477 bool verticalLock = shouldHideScrollbars || webPage->alwaysShowsVerticalScroller();
1478
1479 m_frame->coreFrame()->createView(webPage->size(), webPage->backgroundColor(),
1480 webPage->fixedLayoutSize(), fixedVisibleContentRect, shouldUseFixedLayout,
1481 horizontalScrollbarMode, horizontalLock, verticalScrollbarMode, verticalLock);
1482
1483 if (int viewLayoutWidth = webPage->viewLayoutSize().width()) {
1484 int viewLayoutHeight = std::max(webPage->viewLayoutSize().height(), 1);
1485 m_frame->coreFrame()->view()->enableAutoSizeMode(true, { viewLayoutWidth, viewLayoutHeight });
1486
1487 if (webPage->autoSizingShouldExpandToViewHeight())
1488 m_frame->coreFrame()->view()->setAutoSizeFixedMinimumHeight(webPage->size().height());
1489 }
1490
1491 if (auto viewportSizeForViewportUnits = webPage->viewportSizeForCSSViewportUnits())
1492 m_frame->coreFrame()->view()->setViewportSizeForCSSViewportUnits(*viewportSizeForViewportUnits);
1493 m_frame->coreFrame()->view()->setProhibitsScrolling(shouldDisableScrolling);
1494 m_frame->coreFrame()->view()->setVisualUpdatesAllowedByClient(!webPage->shouldExtendIncrementalRenderingSuppression());
1495#if PLATFORM(COCOA)
1496 m_frame->coreFrame()->view()->setViewExposedRect(webPage->drawingArea()->viewExposedRect());
1497#endif
1498#if PLATFORM(IOS_FAMILY)
1499 if (isMainFrame)
1500 m_frame->coreFrame()->view()->setDelegatesScrolling(true);
1501#endif
1502
1503 if (webPage->scrollPinningBehavior() != DoNotPin)
1504 m_frame->coreFrame()->view()->setScrollPinningBehavior(webPage->scrollPinningBehavior());
1505
1506#if USE(COORDINATED_GRAPHICS)
1507 if (shouldUseFixedLayout) {
1508 m_frame->coreFrame()->view()->setDelegatesScrolling(shouldUseFixedLayout);
1509 m_frame->coreFrame()->view()->setPaintsEntireContents(shouldUseFixedLayout);
1510 return;
1511 }
1512#endif
1513}
1514
1515void WebFrameLoaderClient::didSaveToPageCache()
1516{
1517 WebPage* webPage = m_frame->page();
1518 if (!webPage)
1519 return;
1520
1521 if (m_frame->isMainFrame())
1522 webPage->send(Messages::WebPageProxy::DidSaveToPageCache());
1523}
1524
1525void WebFrameLoaderClient::didRestoreFromPageCache()
1526{
1527 m_frameCameFromPageCache = true;
1528}
1529
1530void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool value)
1531{
1532 WebPage* webPage = m_frame->page();
1533 if (!webPage)
1534 return;
1535
1536 webPage->send(Messages::WebPageProxy::FrameDidBecomeFrameSet(m_frame->frameID(), value));
1537}
1538
1539bool WebFrameLoaderClient::canCachePage() const
1540{
1541 // We cannot cache frames that have custom representations because they are
1542 // rendered in the UIProcess.
1543 return !m_frameHasCustomContentProvider;
1544}
1545
1546void WebFrameLoaderClient::convertMainResourceLoadToDownload(DocumentLoader *documentLoader, PAL::SessionID sessionID, const ResourceRequest& request, const ResourceResponse& response)
1547{
1548 m_frame->convertMainResourceLoadToDownload(documentLoader, sessionID, request, response);
1549}
1550
1551RefPtr<Frame> WebFrameLoaderClient::createFrame(const URL& url, const String& name, HTMLFrameOwnerElement& ownerElement,
1552 const String& referrer)
1553{
1554 auto* webPage = m_frame->page();
1555
1556 auto subframe = WebFrame::createSubframe(webPage, name, &ownerElement);
1557 auto* coreSubframe = subframe->coreFrame();
1558 if (!coreSubframe)
1559 return nullptr;
1560
1561 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1562 if (!coreSubframe->page())
1563 return nullptr;
1564
1565 m_frame->coreFrame()->loader().loadURLIntoChildFrame(url, referrer, coreSubframe);
1566
1567 // The frame's onload handler may have removed it from the document.
1568 if (!subframe->coreFrame())
1569 return nullptr;
1570 ASSERT(subframe->coreFrame() == coreSubframe);
1571 if (!coreSubframe->tree().parent())
1572 return nullptr;
1573
1574 return coreSubframe;
1575}
1576
1577RefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugInElement& pluginElement, const URL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1578{
1579 ASSERT(paramNames.size() == paramValues.size());
1580 ASSERT(m_frame->page());
1581
1582 Plugin::Parameters parameters;
1583 parameters.url = url;
1584 parameters.names = paramNames;
1585 parameters.values = paramValues;
1586 parameters.mimeType = mimeType;
1587 parameters.isFullFramePlugin = loadManually;
1588 parameters.shouldUseManualLoader = parameters.isFullFramePlugin && !m_frameCameFromPageCache;
1589#if PLATFORM(COCOA)
1590 parameters.layerHostingMode = m_frame->page()->layerHostingMode();
1591#endif
1592
1593#if ENABLE(NETSCAPE_PLUGIN_API)
1594 auto plugin = m_frame->page()->createPlugin(m_frame, &pluginElement, parameters, parameters.mimeType);
1595 if (!plugin)
1596 return nullptr;
1597
1598 return PluginView::create(pluginElement, plugin.releaseNonNull(), parameters);
1599#else
1600 UNUSED_PARAM(pluginElement);
1601 return nullptr;
1602#endif
1603}
1604
1605void WebFrameLoaderClient::redirectDataToPlugin(Widget& pluginWidget)
1606{
1607 m_pluginView = static_cast<PluginView*>(&pluginWidget);
1608}
1609
1610#if ENABLE(WEBGL)
1611
1612WebCore::WebGLLoadPolicy WebFrameLoaderClient::webGLPolicyForURL(const URL& url) const
1613{
1614 if (auto* webPage = m_frame->page())
1615 return webPage->webGLPolicyForURL(m_frame, url);
1616
1617 return WebGLAllowCreation;
1618}
1619
1620WebCore::WebGLLoadPolicy WebFrameLoaderClient::resolveWebGLPolicyForURL(const URL& url) const
1621{
1622 if (auto* webPage = m_frame->page())
1623 return webPage->resolveWebGLPolicyForURL(m_frame, url);
1624
1625 return WebGLAllowCreation;
1626}
1627
1628#endif
1629
1630RefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement& appletElement, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues)
1631{
1632#if ENABLE(NETSCAPE_PLUGIN_API)
1633 auto plugin = createPlugin(pluginSize, appletElement, URL(), paramNames, paramValues, appletElement.serviceType(), false);
1634 if (!plugin) {
1635 if (auto* webPage = m_frame->page()) {
1636 auto frameURLString = m_frame->coreFrame()->loader().documentLoader()->responseURL().string();
1637 auto pageURLString = webPage->corePage()->mainFrame().loader().documentLoader()->responseURL().string();
1638 webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(appletElement.serviceType(), frameURLString, pageURLString));
1639 }
1640 }
1641 return plugin;
1642#else
1643 UNUSED_PARAM(pluginSize);
1644 UNUSED_PARAM(appletElement);
1645 UNUSED_PARAM(paramNames);
1646 UNUSED_PARAM(paramValues);
1647 return nullptr;
1648#endif
1649}
1650
1651static bool pluginSupportsExtension(const PluginData& pluginData, const String& extension)
1652{
1653 ASSERT(extension.convertToASCIILowercase() == extension);
1654 Vector<MimeClassInfo> mimes;
1655 Vector<size_t> mimePluginIndices;
1656 pluginData.getWebVisibleMimesAndPluginIndices(mimes, mimePluginIndices);
1657 for (auto& mimeClassInfo : mimes) {
1658 if (mimeClassInfo.extensions.contains(extension))
1659 return true;
1660 }
1661 return false;
1662}
1663
1664ObjectContentType WebFrameLoaderClient::objectContentType(const URL& url, const String& mimeTypeIn)
1665{
1666 // FIXME: This should eventually be merged with WebCore::FrameLoader::defaultObjectContentType.
1667
1668 String mimeType = mimeTypeIn;
1669 if (mimeType.isEmpty()) {
1670 String path = url.path();
1671 auto dotPosition = path.reverseFind('.');
1672 if (dotPosition == notFound)
1673 return ObjectContentType::Frame;
1674 String extension = path.substring(dotPosition + 1).convertToASCIILowercase();
1675
1676 // Try to guess the MIME type from the extension.
1677 mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1678 if (mimeType.isEmpty()) {
1679 // Check if there's a plug-in around that can handle the extension.
1680 if (WebPage* webPage = m_frame->page()) {
1681 if (pluginSupportsExtension(webPage->corePage()->pluginData(), extension))
1682 return ObjectContentType::PlugIn;
1683 }
1684 return ObjectContentType::Frame;
1685 }
1686 }
1687
1688 if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1689 return ObjectContentType::Image;
1690
1691 if (WebPage* webPage = m_frame->page()) {
1692 auto allowedPluginTypes = webFrame()->coreFrame()->loader().subframeLoader().allowPlugins()
1693 ? PluginData::AllPlugins : PluginData::OnlyApplicationPlugins;
1694 if (webPage->corePage()->pluginData().supportsMimeType(mimeType, allowedPluginTypes))
1695 return ObjectContentType::PlugIn;
1696 }
1697
1698 if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1699 return ObjectContentType::Frame;
1700
1701#if PLATFORM(IOS_FAMILY)
1702 // iOS can render PDF in <object>/<embed> via PDFDocumentImage.
1703 if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType))
1704 return ObjectContentType::Image;
1705#endif
1706
1707 return ObjectContentType::None;
1708}
1709
1710String WebFrameLoaderClient::overrideMediaType() const
1711{
1712 notImplemented();
1713 return String();
1714}
1715
1716void WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
1717{
1718 WebPage* webPage = m_frame->page();
1719 if (!webPage)
1720 return;
1721
1722 webPage->injectedBundleLoaderClient().didClearWindowObjectForFrame(*webPage, *m_frame, world);
1723
1724 WebAutomationSessionProxy* automationSessionProxy = WebProcess::singleton().automationSessionProxy();
1725 if (automationSessionProxy && world.isNormal())
1726 automationSessionProxy->didClearWindowObjectForFrame(*m_frame);
1727}
1728
1729void WebFrameLoaderClient::dispatchGlobalObjectAvailable(DOMWrapperWorld& world)
1730{
1731 WebPage* webPage = m_frame->page();
1732 if (!webPage)
1733 return;
1734
1735 webPage->injectedBundleLoaderClient().globalObjectIsAvailableForFrame(*webPage, *m_frame, world);
1736}
1737
1738void WebFrameLoaderClient::willInjectUserScript(DOMWrapperWorld& world)
1739{
1740 WebPage* webPage = m_frame->page();
1741 if (!webPage)
1742 return;
1743
1744 webPage->injectedBundleLoaderClient().willInjectUserScriptForFrame(*webPage, *m_frame, world);
1745}
1746
1747void WebFrameLoaderClient::dispatchWillDisconnectDOMWindowExtensionFromGlobalObject(WebCore::DOMWindowExtension* extension)
1748{
1749 WebPage* webPage = m_frame->page();
1750 if (!webPage)
1751 return;
1752
1753 webPage->injectedBundleLoaderClient().willDisconnectDOMWindowExtensionFromGlobalObject(*webPage, extension);
1754}
1755
1756void WebFrameLoaderClient::dispatchDidReconnectDOMWindowExtensionToGlobalObject(WebCore::DOMWindowExtension* extension)
1757{
1758 WebPage* webPage = m_frame->page();
1759 if (!webPage)
1760 return;
1761
1762 webPage->injectedBundleLoaderClient().didReconnectDOMWindowExtensionToGlobalObject(*webPage, extension);
1763}
1764
1765void WebFrameLoaderClient::dispatchWillDestroyGlobalObjectForDOMWindowExtension(WebCore::DOMWindowExtension* extension)
1766{
1767 WebPage* webPage = m_frame->page();
1768 if (!webPage)
1769 return;
1770
1771 webPage->injectedBundleLoaderClient().willDestroyGlobalObjectForDOMWindowExtension(*webPage, extension);
1772}
1773
1774#if PLATFORM(COCOA)
1775
1776RemoteAXObjectRef WebFrameLoaderClient::accessibilityRemoteObject()
1777{
1778 WebPage* webPage = m_frame->page();
1779 if (!webPage)
1780 return 0;
1781
1782 return webPage->accessibilityRemoteObject();
1783}
1784
1785void WebFrameLoaderClient::willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response, CompletionHandler<void(NSCachedURLResponse *)>&& completionHandler) const
1786{
1787 WebPage* webPage = m_frame->page();
1788 if (!webPage)
1789 return completionHandler(response);
1790
1791 return completionHandler(webPage->injectedBundleResourceLoadClient().shouldCacheResponse(*webPage, *m_frame, identifier) ? response : nil);
1792}
1793
1794NSDictionary *WebFrameLoaderClient::dataDetectionContext()
1795{
1796 WebPage* webPage = m_frame->page();
1797 if (!webPage)
1798 return nil;
1799
1800 return webPage->dataDetectionContext();
1801}
1802
1803#endif // PLATFORM(COCOA)
1804
1805void WebFrameLoaderClient::didChangeScrollOffset()
1806{
1807 WebPage* webPage = m_frame->page();
1808 if (!webPage)
1809 return;
1810
1811 webPage->didChangeScrollOffsetForFrame(m_frame->coreFrame());
1812}
1813
1814bool WebFrameLoaderClient::allowScript(bool enabledPerSettings)
1815{
1816 if (!enabledPerSettings)
1817 return false;
1818
1819 auto* pluginView = WebPage::pluginViewForFrame(m_frame->coreFrame());
1820 return !pluginView || !pluginView->shouldAllowScripting();
1821}
1822
1823bool WebFrameLoaderClient::shouldForceUniversalAccessFromLocalURL(const URL& url)
1824{
1825 WebPage* webPage = m_frame->page();
1826 if (!webPage)
1827 return false;
1828
1829 return webPage->injectedBundleLoaderClient().shouldForceUniversalAccessFromLocalURL(*webPage, url);
1830}
1831
1832Ref<FrameNetworkingContext> WebFrameLoaderClient::createNetworkingContext()
1833{
1834 ASSERT(!hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
1835 return WebFrameNetworkingContext::create(m_frame);
1836}
1837
1838#if ENABLE(CONTENT_FILTERING)
1839
1840void WebFrameLoaderClient::contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler unblockHandler)
1841{
1842 if (!unblockHandler.needsUIProcess()) {
1843 m_frame->coreFrame()->loader().policyChecker().setContentFilterUnblockHandler(WTFMove(unblockHandler));
1844 return;
1845 }
1846
1847 if (WebPage* webPage { m_frame->page() })
1848 webPage->send(Messages::WebPageProxy::ContentFilterDidBlockLoadForFrame(unblockHandler, m_frame->frameID()));
1849}
1850
1851#endif
1852
1853void WebFrameLoaderClient::prefetchDNS(const String& hostname)
1854{
1855 WebProcess::singleton().prefetchDNS(hostname);
1856}
1857
1858void WebFrameLoaderClient::didRestoreScrollPosition()
1859{
1860 WebPage* webPage = m_frame->page();
1861 if (!webPage)
1862 return;
1863
1864 webPage->didRestoreScrollPosition();
1865}
1866
1867void WebFrameLoaderClient::getLoadDecisionForIcons(const Vector<std::pair<WebCore::LinkIcon&, uint64_t>>& icons)
1868{
1869 auto* webPage = m_frame->page();
1870 if (!webPage)
1871 return;
1872
1873 for (auto& icon : icons)
1874 webPage->send(Messages::WebPageProxy::GetLoadDecisionForIcon(icon.first, CallbackID::fromInteger(icon.second)));
1875}
1876
1877void WebFrameLoaderClient::finishedLoadingIcon(uint64_t callbackIdentifier, SharedBuffer* data)
1878{
1879 auto callbackID = CallbackID::fromInteger(callbackIdentifier);
1880 if (WebPage* webPage { m_frame->page() }) {
1881 if (data)
1882 webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { reinterpret_cast<const uint8_t*>(data->data()), data->size() }));
1883 else
1884 webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { nullptr, 0 }));
1885 }
1886}
1887
1888void WebFrameLoaderClient::didCreateWindow(DOMWindow& window)
1889{
1890 auto* webPage = m_frame->page();
1891 if (!webPage)
1892 return;
1893
1894 webPage->send(Messages::WebPageProxy::DidCreateWindow(m_frame->frameID(), window.identifier()));
1895}
1896
1897#if ENABLE(APPLICATION_MANIFEST)
1898void WebFrameLoaderClient::finishedLoadingApplicationManifest(uint64_t callbackIdentifier, const Optional<WebCore::ApplicationManifest>& manifest)
1899{
1900 WebPage* webPage = m_frame->page();
1901 if (!webPage)
1902 return;
1903
1904 webPage->didFinishLoadingApplicationManifest(callbackIdentifier, manifest);
1905}
1906#endif // ENABLE(APPLICATION_MANIFEST)
1907
1908} // namespace WebKit
1909