2 * Copyright (C) 2010-2018 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "WebFrameLoaderClient.h"
29 #include "AuthenticationManager.h"
30 #include "DataReference.h"
31 #include "DrawingArea.h"
32 #include "FindController.h"
33 #include "FrameInfoData.h"
34 #include "InjectedBundle.h"
35 #include "InjectedBundleDOMWindowExtension.h"
36 #include "InjectedBundleNavigationAction.h"
38 #include "NavigationActionData.h"
39 #include "NetworkConnectionToWebProcessMessages.h"
40 #include "NetworkProcessConnection.h"
41 #include "PluginView.h"
43 #include "WKBundleAPICast.h"
44 #include "WebAutomationSessionProxy.h"
45 #include "WebBackForwardListProxy.h"
46 #include "WebCoreArgumentCoders.h"
47 #include "WebDocumentLoader.h"
48 #include "WebErrors.h"
51 #include "WebFrameNetworkingContext.h"
52 #include "WebFullScreenManager.h"
53 #include "WebNavigationDataStore.h"
55 #include "WebPageGroupProxy.h"
56 #include "WebPageProxyMessages.h"
57 #include "WebProcess.h"
58 #include "WebProcessPoolMessages.h"
59 #include "WebsitePoliciesData.h"
60 #include <JavaScriptCore/APICast.h>
61 #include <JavaScriptCore/JSObject.h>
62 #include <WebCore/CachedFrame.h>
63 #include <WebCore/CertificateInfo.h>
64 #include <WebCore/Chrome.h>
65 #include <WebCore/DOMWrapperWorld.h>
66 #include <WebCore/DocumentLoader.h>
67 #include <WebCore/FormState.h>
68 #include <WebCore/Frame.h>
69 #include <WebCore/FrameLoadRequest.h>
70 #include <WebCore/FrameLoader.h>
71 #include <WebCore/FrameView.h>
72 #include <WebCore/HTMLAppletElement.h>
73 #include <WebCore/HTMLFormElement.h>
74 #include <WebCore/HistoryController.h>
75 #include <WebCore/HistoryItem.h>
76 #include <WebCore/MIMETypeRegistry.h>
77 #include <WebCore/MouseEvent.h>
78 #include <WebCore/NotImplemented.h>
79 #include <WebCore/Page.h>
80 #include <WebCore/PluginData.h>
81 #include <WebCore/PluginDocument.h>
82 #include <WebCore/PolicyChecker.h>
83 #include <WebCore/ProgressTracker.h>
84 #include <WebCore/ResourceError.h>
85 #include <WebCore/ResourceRequest.h>
86 #include <WebCore/ScriptController.h>
87 #include <WebCore/SecurityOriginData.h>
88 #include <WebCore/Settings.h>
89 #include <WebCore/SubframeLoader.h>
90 #include <WebCore/UIEventWithKeyState.h>
91 #include <WebCore/Widget.h>
92 #include <WebCore/WindowFeatures.h>
93 #include <wtf/NeverDestroyed.h>
94 #include <wtf/ProcessID.h>
95 #include <wtf/ProcessPrivilege.h>
98 using namespace WebCore;
100 WebFrameLoaderClient::WebFrameLoaderClient()
102 , m_hasSentResponseToPluginView(false)
103 , m_didCompletePageTransition(false)
104 , m_frameHasCustomContentProvider(false)
105 , m_frameCameFromPageCache(false)
109 WebFrameLoaderClient::~WebFrameLoaderClient()
113 std::optional<uint64_t> WebFrameLoaderClient::pageID() const
115 if (m_frame && m_frame->page())
116 return m_frame->page()->pageID();
121 std::optional<uint64_t> WebFrameLoaderClient::frameID() const
124 return m_frame->frameID();
129 PAL::SessionID WebFrameLoaderClient::sessionID() const
131 return m_frame && m_frame->page() ? m_frame->page()->sessionID() : PAL::SessionID::defaultSessionID();
134 void WebFrameLoaderClient::frameLoaderDestroyed()
136 m_frame->invalidate();
138 // Balances explicit ref() in WebFrame::create().
142 bool WebFrameLoaderClient::hasHTMLView() const
144 return !m_frameHasCustomContentProvider;
147 bool WebFrameLoaderClient::hasWebView() const
149 return m_frame->page();
152 void WebFrameLoaderClient::makeRepresentation(DocumentLoader*)
157 void WebFrameLoaderClient::forceLayoutForNonHTML()
162 void WebFrameLoaderClient::setCopiesOnScroll()
167 void WebFrameLoaderClient::detachedFromParent2()
169 WebPage* webPage = m_frame->page();
173 #if ENABLE(RESOURCE_LOAD_STATISTICS)
174 if (m_hasFrameSpecificStorageAccess) {
175 WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RemoveStorageAccessForFrame(sessionID(), frameID().value(), pageID().value()), 0);
176 m_hasFrameSpecificStorageAccess = false;
180 RefPtr<API::Object> userData;
182 // Notify the bundle client.
183 webPage->injectedBundleLoaderClient().didRemoveFrameFromHierarchy(*webPage, *m_frame, userData);
186 void WebFrameLoaderClient::detachedFromParent3()
191 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
193 WebPage* webPage = m_frame->page();
197 bool pageIsProvisionallyLoading = false;
198 if (FrameLoader* frameLoader = loader->frameLoader())
199 pageIsProvisionallyLoading = frameLoader->provisionalDocumentLoader() == loader;
201 webPage->injectedBundleResourceLoadClient().didInitiateLoadForResource(*webPage, *m_frame, identifier, request, pageIsProvisionallyLoading);
202 webPage->addResourceRequest(identifier, request);
205 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
207 WebPage* webPage = m_frame->page();
211 // The API can return a completely new request. We should ensure that at least the requester
212 // is kept, so that if this is a main resource load it's still considered as such.
213 auto requester = request.requester();
214 webPage->injectedBundleResourceLoadClient().willSendRequestForFrame(*webPage, *m_frame, identifier, request, redirectResponse);
215 if (!request.isNull())
216 request.setRequester(requester);
219 bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier)
221 WebPage* webPage = m_frame->page();
225 return webPage->injectedBundleResourceLoadClient().shouldUseCredentialStorage(*webPage, *m_frame, identifier);
228 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&)
230 ASSERT_NOT_REACHED();
233 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
234 bool WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long, const ProtectionSpace& protectionSpace)
236 // The WebKit 2 Networking process asks the UIProcess directly, so the WebContent process should never receive this callback.
237 ASSERT_NOT_REACHED();
242 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse& response)
244 WebPage* webPage = m_frame->page();
248 webPage->injectedBundleResourceLoadClient().didReceiveResponseForResource(*webPage, *m_frame, identifier, response);
251 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int dataLength)
253 WebPage* webPage = m_frame->page();
257 webPage->injectedBundleResourceLoadClient().didReceiveContentLengthForResource(*webPage, *m_frame, identifier, dataLength);
260 #if ENABLE(DATA_DETECTION)
261 void WebFrameLoaderClient::dispatchDidFinishDataDetection(NSArray *detectionResults)
263 WebPage* webPage = m_frame->page();
266 webPage->setDataDetectionResults(detectionResults);
270 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier)
272 WebPage* webPage = m_frame->page();
276 webPage->injectedBundleResourceLoadClient().didFinishLoadForResource(*webPage, *m_frame, identifier);
277 webPage->removeResourceRequest(identifier);
280 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError& error)
282 WebPage* webPage = m_frame->page();
286 webPage->injectedBundleResourceLoadClient().didFailLoadForResource(*webPage, *m_frame, identifier, error);
287 webPage->removeResourceRequest(identifier);
290 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/)
296 void WebFrameLoaderClient::dispatchDidDispatchOnloadEvents()
298 WebPage* webPage = m_frame->page();
302 // Notify the bundle client.
303 webPage->injectedBundleLoaderClient().didHandleOnloadEventsForFrame(*webPage, *m_frame);
306 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
308 WebPage* webPage = m_frame->page();
312 WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader());
313 RefPtr<API::Object> userData;
315 LOG(Loading, "WebProcess %i - dispatchDidReceiveServerRedirectForProvisionalLoad to request url %s", getCurrentProcessID(), documentLoader.request().url().string().utf8().data());
317 // Notify the bundle client.
318 webPage->injectedBundleLoaderClient().didReceiveServerRedirectForProvisionalLoadForFrame(*webPage, *m_frame, userData);
320 // Notify the UIProcess.
321 webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.request(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
324 void WebFrameLoaderClient::dispatchDidChangeProvisionalURL()
326 WebPage* webPage = m_frame->page();
330 WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader());
331 webPage->send(Messages::WebPageProxy::DidChangeProvisionalURLForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.url()));
334 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
336 WebPage* webPage = m_frame->page();
340 // Notify the bundle client.
341 webPage->injectedBundleLoaderClient().didCancelClientRedirectForFrame(*webPage, *m_frame);
343 // Notify the UIProcess.
344 webPage->send(Messages::WebPageProxy::DidCancelClientRedirectForFrame(m_frame->frameID()));
347 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const URL& url, double interval, WallTime fireDate, LockBackForwardList lockBackForwardList)
349 WebPage* webPage = m_frame->page();
353 // Notify the bundle client.
354 webPage->injectedBundleLoaderClient().willPerformClientRedirectForFrame(*webPage, *m_frame, url, interval, fireDate);
356 // Notify the UIProcess.
357 webPage->send(Messages::WebPageProxy::WillPerformClientRedirectForFrame(m_frame->frameID(), url.string(), interval, lockBackForwardList));
360 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
362 WebPage* webPage = m_frame->page();
366 RefPtr<API::Object> userData;
368 auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
370 // Notify the bundle client.
371 webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationAnchorNavigation, userData);
373 // Notify the UIProcess.
374 webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationAnchorNavigation, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
377 void WebFrameLoaderClient::dispatchDidChangeMainDocument()
379 WebPage* webPage = m_frame->page();
383 webPage->send(Messages::WebPageProxy::DidChangeMainDocument(m_frame->frameID()));
386 void WebFrameLoaderClient::dispatchWillChangeDocument(const URL& currentUrl, const URL& newUrl)
388 #if ENABLE(RESOURCE_LOAD_STATISTICS)
389 if (m_frame->isMainFrame())
392 WebPage* webPage = m_frame->page();
396 if (m_hasFrameSpecificStorageAccess && !WebCore::registrableDomainsAreEqual(currentUrl, newUrl)) {
397 WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RemoveStorageAccessForFrame(sessionID(), frameID().value(), pageID().value()), 0);
398 m_hasFrameSpecificStorageAccess = false;
403 void WebFrameLoaderClient::dispatchDidPushStateWithinPage()
405 WebPage* webPage = m_frame->page();
409 RefPtr<API::Object> userData;
411 auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
413 // Notify the bundle client.
414 webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationSessionStatePush, userData);
416 // Notify the UIProcess.
417 webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStatePush, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
420 void WebFrameLoaderClient::dispatchDidReplaceStateWithinPage()
422 WebPage* webPage = m_frame->page();
426 RefPtr<API::Object> userData;
428 auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
430 // Notify the bundle client.
431 webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationSessionStateReplace, userData);
433 // Notify the UIProcess.
434 webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStateReplace, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
437 void WebFrameLoaderClient::dispatchDidPopStateWithinPage()
439 WebPage* webPage = m_frame->page();
443 RefPtr<API::Object> userData;
445 auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
447 // Notify the bundle client.
448 webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationSessionStatePop, userData);
450 // Notify the UIProcess.
451 webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStatePop, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
454 void WebFrameLoaderClient::dispatchWillClose()
459 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
461 WebPage* webPage = m_frame->page();
465 #if ENABLE(FULLSCREEN_API)
466 Element* documentElement = m_frame->coreFrame()->document()->documentElement();
467 if (documentElement && documentElement->containsFullScreenElement())
468 webPage->fullScreenManager()->exitFullScreenForElement(webPage->fullScreenManager()->element());
471 webPage->findController().hideFindUI();
472 webPage->sandboxExtensionTracker().didStartProvisionalLoad(m_frame);
474 WebDocumentLoader& provisionalLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader());
475 auto& url = provisionalLoader.url();
476 RefPtr<API::Object> userData;
478 // Notify the bundle client.
479 webPage->injectedBundleLoaderClient().didStartProvisionalLoadForFrame(*webPage, *m_frame, userData);
481 auto& unreachableURL = provisionalLoader.unreachableURL();
483 // Notify the UIProcess.
484 webPage->send(Messages::WebPageProxy::DidStartProvisionalLoadForFrame(m_frame->frameID(), provisionalLoader.navigationID(), url, unreachableURL, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
487 static constexpr unsigned maxTitleLength = 1000; // Closest power of 10 above the W3C recommendation for Title length.
489 void WebFrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title)
491 WebPage* webPage = m_frame->page();
495 auto truncatedTitle = truncateFromEnd(title, maxTitleLength);
497 RefPtr<API::Object> userData;
499 // Notify the bundle client.
500 // FIXME: Use direction of title.
501 webPage->injectedBundleLoaderClient().didReceiveTitleForFrame(*webPage, truncatedTitle.string, *m_frame, userData);
503 // Notify the UIProcess.
504 webPage->send(Messages::WebPageProxy::DidReceiveTitleForFrame(m_frame->frameID(), truncatedTitle.string, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
507 void WebFrameLoaderClient::dispatchDidCommitLoad(std::optional<HasInsecureContent> hasInsecureContent)
509 WebPage* webPage = m_frame->page();
513 WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
514 RefPtr<API::Object> userData;
516 // Notify the bundle client.
517 webPage->injectedBundleLoaderClient().didCommitLoadForFrame(*webPage, *m_frame, userData);
519 webPage->sandboxExtensionTracker().didCommitProvisionalLoad(m_frame);
521 // Notify the UIProcess.
522 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())));
523 webPage->didCommitLoad(m_frame);
526 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
528 WebPage* webPage = m_frame->page();
532 RefPtr<API::Object> userData;
534 // Notify the bundle client.
535 webPage->injectedBundleLoaderClient().didFailProvisionalLoadWithErrorForFrame(*webPage, *m_frame, error, userData);
537 webPage->sandboxExtensionTracker().didFailProvisionalLoad(m_frame);
539 // FIXME: This is gross. This is necessary because if the client calls WKBundlePageStopLoading() from within the didFailProvisionalLoadWithErrorForFrame
540 // injected bundle client call, that will cause the provisional DocumentLoader to be disconnected from the Frame, and didDistroyNavigation message
541 // to be sent to the UIProcess (and the destruction of the DocumentLoader). If that happens, and we had captured the navigationID before injected bundle
542 // client call, the DidFailProvisionalLoadForFrame would send a navigationID of a destroyed Navigation, and the UIProcess would not be able to find it
545 // A better solution to this problem would be find a clean way to postpone the disconnection of the DocumentLoader from the Frame until
546 // the entire FrameLoaderClient function was complete.
547 uint64_t navigationID = 0;
548 if (auto documentLoader = m_frame->coreFrame()->loader().provisionalDocumentLoader())
549 navigationID = static_cast<WebDocumentLoader*>(documentLoader)->navigationID();
551 // Notify the UIProcess.
552 WebCore::Frame* coreFrame = m_frame ? m_frame->coreFrame() : nullptr;
553 webPage->send(Messages::WebPageProxy::DidFailProvisionalLoadForFrame(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), navigationID, m_frame->coreFrame()->loader().provisionalLoadErrorBeingHandledURL(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
555 // If we have a load listener, notify it.
556 if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
557 loadListener->didFailLoad(m_frame, error.isCancellation());
560 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
562 WebPage* webPage = m_frame->page();
566 RefPtr<API::Object> userData;
568 auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
570 // Notify the bundle client.
571 webPage->injectedBundleLoaderClient().didFailLoadWithErrorForFrame(*webPage, *m_frame, error, userData);
573 // Notify the UIProcess.
574 webPage->send(Messages::WebPageProxy::DidFailLoadForFrame(m_frame->frameID(), navigationID, error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
576 // If we have a load listener, notify it.
577 if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
578 loadListener->didFailLoad(m_frame, error.isCancellation());
581 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
583 WebPage* webPage = m_frame->page();
587 RefPtr<API::Object> userData;
589 auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
591 // Notify the bundle client.
592 webPage->injectedBundleLoaderClient().didFinishDocumentLoadForFrame(*webPage, *m_frame, userData);
594 // Notify the UIProcess.
595 webPage->send(Messages::WebPageProxy::DidFinishDocumentLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
598 void WebFrameLoaderClient::dispatchDidFinishLoad()
600 WebPage* webPage = m_frame->page();
604 RefPtr<API::Object> userData;
606 auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
608 // Notify the bundle client.
609 webPage->injectedBundleLoaderClient().didFinishLoadForFrame(*webPage, *m_frame, userData);
611 // Notify the UIProcess.
612 webPage->send(Messages::WebPageProxy::DidFinishLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
614 // If we have a load listener, notify it.
615 if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
616 loadListener->didFinishLoad(m_frame);
618 webPage->didFinishLoad(m_frame);
621 void WebFrameLoaderClient::forcePageTransitionIfNeeded()
623 if (m_didCompletePageTransition)
626 WebPage* webPage = m_frame->page();
630 webPage->didCompletePageTransition();
631 m_didCompletePageTransition = true;
634 void WebFrameLoaderClient::dispatchDidReachLayoutMilestone(LayoutMilestones milestones)
636 WebPage* webPage = m_frame->page();
640 RefPtr<API::Object> userData;
642 if (milestones & DidFirstLayout) {
643 // FIXME: We should consider removing the old didFirstLayout API since this is doing double duty with the
644 // new didLayout API.
645 webPage->injectedBundleLoaderClient().didFirstLayoutForFrame(*webPage, *m_frame, userData);
646 webPage->send(Messages::WebPageProxy::DidFirstLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
649 // FIXME: Do this on DidFirstVisuallyNonEmptyLayout when Mac Safari is able to handle it (<rdar://problem/17580021>)
650 if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) {
651 webPage->didCompletePageTransition();
652 m_didCompletePageTransition = true;
656 #if USE(COORDINATED_GRAPHICS)
657 // Make sure viewport properties are dispatched on the main frame by the time the first layout happens.
658 ASSERT(!webPage->useFixedLayout() || m_frame != m_frame->page()->mainWebFrame() || m_frame->coreFrame()->document()->didDispatchViewportPropertiesChanged());
662 // Send this after DidFirstLayout-specific calls since some clients expect to get those messages first.
663 webPage->dispatchDidReachLayoutMilestone(milestones);
665 if (milestones & DidFirstVisuallyNonEmptyLayout) {
666 if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) {
667 webPage->didCompletePageTransition();
668 m_didCompletePageTransition = true;
671 // FIXME: We should consider removing the old didFirstVisuallyNonEmptyLayoutForFrame API since this is doing
672 // double duty with the new didLayout API.
673 webPage->injectedBundleLoaderClient().didFirstVisuallyNonEmptyLayoutForFrame(*webPage, *m_frame, userData);
674 webPage->send(Messages::WebPageProxy::DidFirstVisuallyNonEmptyLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
678 void WebFrameLoaderClient::dispatchDidLayout()
680 WebPage* webPage = m_frame->page();
684 // Notify the bundle client.
685 webPage->injectedBundleLoaderClient().didLayoutForFrame(*webPage, *m_frame);
687 webPage->recomputeShortCircuitHorizontalWheelEventsState();
689 #if PLATFORM(IOS_FAMILY)
690 webPage->updateSelectionAppearance();
693 // NOTE: Unlike the other layout notifications, this does not notify the
694 // the UIProcess for every call.
696 if (m_frame == m_frame->page()->mainWebFrame()) {
697 // FIXME: Remove at the soonest possible time.
698 webPage->send(Messages::WebPageProxy::SetRenderTreeSize(webPage->renderTreeSize()));
699 webPage->mainFrameDidLayout();
703 Frame* WebFrameLoaderClient::dispatchCreatePage(const NavigationAction& navigationAction)
705 WebPage* webPage = m_frame->page();
709 // Just call through to the chrome client.
710 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 };
711 Page* newPage = webPage->corePage()->chrome().createWindow(*m_frame->coreFrame(), frameLoadRequest, { }, navigationAction);
715 return &newPage->mainFrame();
718 void WebFrameLoaderClient::dispatchShow()
720 WebPage* webPage = m_frame->page();
727 void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, FramePolicyFunction&& function)
729 WebPage* webPage = m_frame ? m_frame->page() : nullptr;
731 function(PolicyAction::Ignore);
735 if (!request.url().string()) {
736 function(PolicyAction::Use);
740 RefPtr<API::Object> userData;
742 // Notify the bundle client.
743 WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForResponse(webPage, m_frame, response, request, userData);
744 if (policy == WKBundlePagePolicyActionUse) {
745 function(PolicyAction::Use);
749 bool canShowResponse = webPage->canShowResponse(response);
751 WebCore::Frame* coreFrame = m_frame->coreFrame();
752 auto* policyDocumentLoader = coreFrame ? coreFrame->loader().provisionalDocumentLoader() : nullptr;
753 auto navigationID = policyDocumentLoader ? static_cast<WebDocumentLoader&>(*policyDocumentLoader).navigationID() : 0;
755 Ref<WebFrame> protector(*m_frame);
756 uint64_t listenerID = m_frame->setUpPolicyListener(WTFMove(function), WebFrame::ForNavigationAction::No);
757 if (!webPage->send(Messages::WebPageProxy::DecidePolicyForResponse(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), navigationID, response, request, canShowResponse, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))))
758 m_frame->didReceivePolicyDecision(listenerID, PolicyAction::Ignore, 0, { }, { });
761 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(const NavigationAction& navigationAction, const ResourceRequest& request, FormState* formState, const String& frameName, FramePolicyFunction&& function)
763 WebPage* webPage = m_frame ? m_frame->page() : nullptr;
765 function(PolicyAction::Ignore);
769 RefPtr<API::Object> userData;
771 RefPtr<InjectedBundleNavigationAction> action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
773 // Notify the bundle client.
774 WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNewWindowAction(webPage, m_frame, action.get(), request, frameName, userData);
775 if (policy == WKBundlePagePolicyActionUse) {
776 function(PolicyAction::Use);
780 uint64_t listenerID = m_frame->setUpPolicyListener(WTFMove(function), WebFrame::ForNavigationAction::No);
782 NavigationActionData navigationActionData;
783 navigationActionData.navigationType = action->navigationType();
784 navigationActionData.modifiers = action->modifiers();
785 navigationActionData.mouseButton = action->mouseButton();
786 navigationActionData.syntheticClickType = action->syntheticClickType();
787 navigationActionData.clickLocationInRootViewCoordinates = action->clickLocationInRootViewCoordinates();
788 navigationActionData.userGestureTokenIdentifier = WebProcess::singleton().userGestureTokenIdentifier(navigationAction.userGestureToken());
789 navigationActionData.canHandleRequest = webPage->canHandleRequest(request);
790 navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy();
791 navigationActionData.downloadAttribute = navigationAction.downloadAttribute();
793 WebCore::Frame* coreFrame = m_frame ? m_frame->coreFrame() : nullptr;
794 webPage->send(Messages::WebPageProxy::DecidePolicyForNewWindowAction(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), navigationActionData, request, frameName, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
797 void WebFrameLoaderClient::applyToDocumentLoader(WebsitePoliciesData&& websitePolicies)
801 auto* coreFrame = m_frame->coreFrame();
804 WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader());
806 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader());
808 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
812 WebsitePoliciesData::applyToDocumentLoader(WTFMove(websitePolicies), *documentLoader);
815 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const NavigationAction& navigationAction, const ResourceRequest& request, const ResourceResponse& redirectResponse, FormState* formState, PolicyDecisionMode policyDecisionMode, ShouldSkipSafeBrowsingCheck shouldSkipSafeBrowsingCheck, FramePolicyFunction&& function)
817 WebPage* webPage = m_frame ? m_frame->page() : nullptr;
819 function(PolicyAction::Ignore);
823 LOG(Loading, "WebProcess %i - dispatchDecidePolicyForNavigationAction to request url %s", getCurrentProcessID(), request.url().string().utf8().data());
825 // Always ignore requests with empty URLs.
826 if (request.isEmpty()) {
827 function(PolicyAction::Ignore);
831 RefPtr<API::Object> userData;
833 Ref<InjectedBundleNavigationAction> action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
835 // Notify the bundle client.
836 WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNavigationAction(webPage, m_frame, action.ptr(), request, userData);
837 if (policy == WKBundlePagePolicyActionUse) {
838 function(PolicyAction::Use);
842 uint64_t listenerID = m_frame->setUpPolicyListener(WTFMove(function), WebFrame::ForNavigationAction::Yes);
844 ASSERT(navigationAction.requester());
845 auto requester = navigationAction.requester().value();
847 FrameInfoData originatingFrameInfoData;
848 originatingFrameInfoData.isMainFrame = navigationAction.initiatedByMainFrame() == InitiatedByMainFrame::Yes;
849 originatingFrameInfoData.request = ResourceRequest { requester.url() };
850 originatingFrameInfoData.securityOrigin = requester.securityOrigin().data();
851 if (requester.frameID() && WebProcess::singleton().webFrame(requester.frameID()))
852 originatingFrameInfoData.frameID = requester.frameID();
854 uint64_t originatingPageID = requester.pageID() && WebProcess::singleton().webPage(requester.pageID()) ? requester.pageID() : 0;
856 NavigationActionData navigationActionData;
857 navigationActionData.navigationType = action->navigationType();
858 navigationActionData.modifiers = action->modifiers();
859 navigationActionData.mouseButton = action->mouseButton();
860 navigationActionData.syntheticClickType = action->syntheticClickType();
861 navigationActionData.clickLocationInRootViewCoordinates = action->clickLocationInRootViewCoordinates();
862 navigationActionData.userGestureTokenIdentifier = WebProcess::singleton().userGestureTokenIdentifier(navigationAction.userGestureToken());
863 navigationActionData.canHandleRequest = webPage->canHandleRequest(request);
864 navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy();
865 navigationActionData.downloadAttribute = navigationAction.downloadAttribute();
866 navigationActionData.isRedirect = !redirectResponse.isNull();
867 navigationActionData.treatAsSameOriginNavigation = navigationAction.treatAsSameOriginNavigation();
868 navigationActionData.hasOpenedFrames = navigationAction.hasOpenedFrames();
869 navigationActionData.openedViaWindowOpenWithOpener = navigationAction.openedViaWindowOpenWithOpener();
870 navigationActionData.opener = navigationAction.opener();
871 if (auto& requester = navigationAction.requester())
872 navigationActionData.requesterOrigin = requester->securityOrigin().data();
873 navigationActionData.targetBackForwardItemIdentifier = navigationAction.targetBackForwardItemIdentifier();
874 navigationActionData.lockHistory = navigationAction.lockHistory();
875 navigationActionData.lockBackForwardList = navigationAction.lockBackForwardList();
877 WebCore::Frame* coreFrame = m_frame->coreFrame();
879 return function(PolicyAction::Ignore);
880 WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader());
881 if (!documentLoader) {
882 // FIXME: When we receive a redirect after the navigation policy has been decided for the initial request,
883 // the provisional load's DocumentLoader needs to receive navigation policy decisions. We need a better model for this state.
884 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader());
887 documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
889 navigationActionData.clientRedirectSourceForHistory = documentLoader->clientRedirectSourceForHistory();
891 // Notify the UIProcess.
892 Ref<WebFrame> protect(*m_frame);
894 if (policyDecisionMode == PolicyDecisionMode::Synchronous) {
895 uint64_t newNavigationID;
896 PolicyAction policyAction;
897 DownloadID downloadID;
898 std::optional<WebsitePoliciesData> websitePolicies;
900 if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationActionSync(m_frame->frameID(), m_frame->isMainFrame(), SecurityOriginData::fromFrame(coreFrame), documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()), shouldSkipSafeBrowsingCheck), Messages::WebPageProxy::DecidePolicyForNavigationActionSync::Reply(policyAction, newNavigationID, downloadID, websitePolicies))) {
901 m_frame->didReceivePolicyDecision(listenerID, PolicyAction::Ignore, 0, { }, { });
905 m_frame->didReceivePolicyDecision(listenerID, policyAction, 0, downloadID, { });
909 ASSERT(policyDecisionMode == PolicyDecisionMode::Asynchronous);
910 if (!webPage->send(Messages::WebPageProxy::DecidePolicyForNavigationActionAsync(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()), shouldSkipSafeBrowsingCheck, listenerID)))
911 m_frame->didReceivePolicyDecision(listenerID, PolicyAction::Ignore, 0, { }, { });
914 void WebFrameLoaderClient::cancelPolicyCheck()
916 m_frame->invalidatePolicyListener();
919 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
921 WebPage* webPage = m_frame->page();
925 RefPtr<API::Object> userData;
927 // Notify the bundle client.
928 webPage->injectedBundlePolicyClient().unableToImplementPolicy(webPage, m_frame, error, userData);
930 // Notify the UIProcess.
931 webPage->send(Messages::WebPageProxy::UnableToImplementPolicy(m_frame->frameID(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
934 void WebFrameLoaderClient::dispatchWillSendSubmitEvent(Ref<FormState>&& formState)
936 auto* webPage = m_frame->page();
940 auto& form = formState->form();
942 ASSERT(formState->sourceDocument().frame());
943 auto* sourceFrame = WebFrame::fromCoreFrame(*formState->sourceDocument().frame());
946 webPage->injectedBundleFormClient().willSendSubmitEvent(webPage, &form, m_frame, sourceFrame, formState->textFieldValues());
949 void WebFrameLoaderClient::dispatchWillSubmitForm(FormState& formState, CompletionHandler<void()>&& completionHandler)
951 WebPage* webPage = m_frame->page();
957 auto& form = formState.form();
959 auto* sourceCoreFrame = formState.sourceDocument().frame();
960 RELEASE_ASSERT(sourceCoreFrame);
961 auto* sourceFrame = WebFrame::fromCoreFrame(*sourceCoreFrame);
964 auto& values = formState.textFieldValues();
966 RefPtr<API::Object> userData;
967 webPage->injectedBundleFormClient().willSubmitForm(webPage, &form, m_frame, sourceFrame, values, userData);
969 uint64_t listenerID = m_frame->setUpWillSubmitFormListener(WTFMove(completionHandler));
971 webPage->send(Messages::WebPageProxy::WillSubmitForm(m_frame->frameID(), sourceFrame->frameID(), values, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
974 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader*)
979 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
984 m_pluginView->manualLoadDidFail(error);
985 m_pluginView = nullptr;
986 m_hasSentResponseToPluginView = false;
989 void WebFrameLoaderClient::setMainFrameDocumentReady(bool)
994 void WebFrameLoaderClient::startDownload(const ResourceRequest& request, const String& suggestedName)
996 m_frame->startDownload(request, suggestedName);
999 void WebFrameLoaderClient::willChangeTitle(DocumentLoader*)
1004 void WebFrameLoaderClient::didChangeTitle(DocumentLoader*)
1009 void WebFrameLoaderClient::willReplaceMultipartContent()
1011 WebPage* webPage = m_frame->page();
1014 webPage->willReplaceMultipartContent(*m_frame);
1017 void WebFrameLoaderClient::didReplaceMultipartContent()
1019 WebPage* webPage = m_frame->page();
1022 webPage->didReplaceMultipartContent(*m_frame);
1025 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
1028 loader->commitData(data, length);
1030 // If the document is a stand-alone media document, now is the right time to cancel the WebKit load.
1031 // FIXME: This code should be shared across all ports. <http://webkit.org/b/48762>.
1032 if (m_frame->coreFrame()->document()->isMediaDocument())
1033 loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
1035 // Calling commitData did not create the plug-in view.
1039 if (!m_hasSentResponseToPluginView) {
1040 m_pluginView->manualLoadDidReceiveResponse(loader->response());
1041 // manualLoadDidReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
1042 // setting up this stream can cause the main document load to be cancelled, setting m_pluginView
1046 m_hasSentResponseToPluginView = true;
1048 m_pluginView->manualLoadDidReceiveData(data, length);
1051 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
1053 if (!m_pluginView) {
1054 if (m_frameHasCustomContentProvider) {
1055 WebPage* webPage = m_frame->page();
1059 RefPtr<SharedBuffer> mainResourceData = loader->mainResourceData();
1060 IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(mainResourceData ? mainResourceData->data() : 0), mainResourceData ? mainResourceData->size() : 0);
1061 webPage->send(Messages::WebPageProxy::DidFinishLoadingDataForCustomContentProvider(loader->response().suggestedFilename(), dataReference));
1067 // If we just received an empty response without any data, we won't have sent a response to the plug-in view.
1068 // Make sure to do this before calling manualLoadDidFinishLoading.
1069 if (!m_hasSentResponseToPluginView) {
1070 m_pluginView->manualLoadDidReceiveResponse(loader->response());
1072 // Protect against the above call nulling out the plug-in (by trying to cancel the load for example).
1077 m_pluginView->manualLoadDidFinishLoading();
1078 m_pluginView = nullptr;
1079 m_hasSentResponseToPluginView = false;
1082 void WebFrameLoaderClient::updateGlobalHistory()
1084 WebPage* webPage = m_frame->page();
1088 DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1090 WebNavigationDataStore data;
1091 data.url = loader->url().string();
1092 // FIXME: Use direction of title.
1093 data.title = loader->title().string;
1094 data.originalRequest = loader->originalRequestCopy();
1095 data.response = loader->response();
1097 webPage->send(Messages::WebPageProxy::DidNavigateWithNavigationData(data, m_frame->frameID()));
1100 void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
1102 WebPage* webPage = m_frame->page();
1106 DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
1107 ASSERT(loader->unreachableURL().isEmpty());
1110 if (!loader->clientRedirectSourceForHistory().isNull()) {
1111 webPage->send(Messages::WebPageProxy::DidPerformClientRedirect(
1112 loader->clientRedirectSourceForHistory(), loader->clientRedirectDestinationForHistory(), m_frame->frameID()));
1116 if (!loader->serverRedirectSourceForHistory().isNull()) {
1117 webPage->send(Messages::WebPageProxy::DidPerformServerRedirect(
1118 loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_frame->frameID()));
1122 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem& item) const
1124 WebPage* webPage = m_frame->page();
1127 webPage->send(Messages::WebPageProxy::WillGoToBackForwardListItem(item.identifier(), item.isInPageCache()));
1131 void WebFrameLoaderClient::didDisplayInsecureContent()
1133 WebPage* webPage = m_frame->page();
1137 RefPtr<API::Object> userData;
1139 webPage->injectedBundleLoaderClient().didDisplayInsecureContentForFrame(*webPage, *m_frame, userData);
1141 webPage->send(Messages::WebPageProxy::DidDisplayInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1144 void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin&, const URL&)
1146 WebPage* webPage = m_frame->page();
1150 RefPtr<API::Object> userData;
1152 webPage->injectedBundleLoaderClient().didRunInsecureContentForFrame(*webPage, *m_frame, userData);
1154 webPage->send(Messages::WebPageProxy::DidRunInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1157 void WebFrameLoaderClient::didDetectXSS(const URL&, bool)
1159 WebPage* webPage = m_frame->page();
1163 RefPtr<API::Object> userData;
1165 webPage->injectedBundleLoaderClient().didDetectXSSForFrame(*webPage, *m_frame, userData);
1167 webPage->send(Messages::WebPageProxy::DidDetectXSSForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1170 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
1172 return WebKit::cancelledError(request);
1175 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
1177 return WebKit::blockedError(request);
1180 ResourceError WebFrameLoaderClient::blockedByContentBlockerError(const ResourceRequest& request)
1182 return WebKit::blockedByContentBlockerError(request);
1185 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1187 return WebKit::cannotShowURLError(request);
1190 ResourceError WebFrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request)
1192 return WebKit::interruptedForPolicyChangeError(request);
1195 #if ENABLE(CONTENT_FILTERING)
1196 ResourceError WebFrameLoaderClient::blockedByContentFilterError(const ResourceRequest& request)
1198 return WebKit::blockedByContentFilterError(request);
1202 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1204 return WebKit::cannotShowMIMETypeError(response);
1207 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1209 return WebKit::fileDoesNotExistError(response);
1212 ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1214 return WebKit::pluginWillHandleLoadError(response);
1217 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
1219 static NeverDestroyed<const ResourceError> cancelledError(this->cancelledError(ResourceRequest()));
1220 static NeverDestroyed<const ResourceError> pluginWillHandleLoadError(this->pluginWillHandleLoadError(ResourceResponse()));
1222 if (error.errorCode() == cancelledError.get().errorCode() && error.domain() == cancelledError.get().domain())
1225 if (error.errorCode() == pluginWillHandleLoadError.get().errorCode() && error.domain() == pluginWillHandleLoadError.get().domain())
1231 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest&) const
1237 bool WebFrameLoaderClient::canShowMIMEType(const String& /*MIMEType*/) const
1243 bool WebFrameLoaderClient::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const
1248 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& /*URLScheme*/) const
1254 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1260 void WebFrameLoaderClient::frameLoadCompleted()
1262 // Note: Can be called multiple times.
1263 WebPage* webPage = m_frame->page();
1267 if (m_frame->isMainFrame() && !m_didCompletePageTransition) {
1268 webPage->didCompletePageTransition();
1269 m_didCompletePageTransition = true;
1273 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem& historyItem)
1275 #if PLATFORM(IOS_FAMILY)
1276 if (m_frame->isMainFrame())
1277 m_frame->page()->savePageState(historyItem);
1279 UNUSED_PARAM(historyItem);
1283 void WebFrameLoaderClient::restoreViewState()
1285 #if PLATFORM(IOS_FAMILY)
1286 Frame& frame = *m_frame->coreFrame();
1287 HistoryItem* currentItem = frame.loader().history().currentItem();
1288 if (FrameView* view = frame.view()) {
1289 if (m_frame->isMainFrame())
1290 m_frame->page()->restorePageState(*currentItem);
1291 else if (!view->wasScrolledByUser())
1292 view->setScrollPosition(currentItem->scrollPosition());
1295 // Inform the UI process of the scale factor.
1296 double scaleFactor = m_frame->coreFrame()->loader().history().currentItem()->pageScaleFactor();
1298 // A scale factor of 0 means the history item has the default scale factor, thus we do not need to update it.
1300 m_frame->page()->send(Messages::WebPageProxy::PageScaleFactorDidChange(scaleFactor));
1302 // FIXME: This should not be necessary. WebCore should be correctly invalidating
1303 // the view on restores from the back/forward cache.
1304 if (m_frame->page() && m_frame == m_frame->page()->mainWebFrame())
1305 m_frame->page()->drawingArea()->setNeedsDisplay();
1309 void WebFrameLoaderClient::provisionalLoadStarted()
1311 WebPage* webPage = m_frame->page();
1315 if (m_frame->isMainFrame()) {
1316 webPage->didStartPageTransition();
1317 m_didCompletePageTransition = false;
1321 void WebFrameLoaderClient::didFinishLoad()
1323 // If we have a load listener, notify it.
1324 if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
1325 loadListener->didFinishLoad(m_frame);
1328 void WebFrameLoaderClient::prepareForDataSourceReplacement()
1333 Ref<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
1335 return m_frame->page()->createDocumentLoader(*m_frame->coreFrame(), request, substituteData);
1338 void WebFrameLoaderClient::updateCachedDocumentLoader(WebCore::DocumentLoader& loader)
1340 m_frame->page()->updateCachedDocumentLoader(static_cast<WebDocumentLoader&>(loader), *m_frame->coreFrame());
1343 void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const URL& url)
1345 WebPage* webPage = m_frame->page();
1349 // FIXME: Use direction of title.
1350 webPage->send(Messages::WebPageProxy::DidUpdateHistoryTitle(title.string, url.string(), m_frame->frameID()));
1353 String WebFrameLoaderClient::userAgent(const URL& url)
1355 WebPage* webPage = m_frame->page();
1359 return webPage->userAgent(m_frame, url);
1362 String WebFrameLoaderClient::overrideContentSecurityPolicy() const
1364 WebPage* webPage = m_frame->page();
1368 return webPage->overrideContentSecurityPolicy();
1371 void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1373 WebPage* webPage = m_frame->page();
1377 HasInsecureContent hasInsecureContent;
1378 if (webPage->sendSync(Messages::WebPageProxy::HasInsecureContent(), Messages::WebPageProxy::HasInsecureContent::Reply(hasInsecureContent)))
1379 cachedFrame->setHasInsecureContent(hasInsecureContent);
1382 void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
1384 const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1385 m_frameHasCustomContentProvider = m_frame->isMainFrame() && m_frame->page()->shouldUseCustomContentProviderForResponse(response);
1386 m_frameCameFromPageCache = true;
1389 void WebFrameLoaderClient::transitionToCommittedForNewPage()
1391 WebPage* webPage = m_frame->page();
1393 Color backgroundColor = webPage->drawsBackground() ? Color::white : Color::transparent;
1394 bool isMainFrame = m_frame->isMainFrame();
1395 bool isTransparent = !webPage->drawsBackground();
1396 bool shouldUseFixedLayout = isMainFrame && webPage->useFixedLayout();
1397 bool shouldDisableScrolling = isMainFrame && !webPage->mainFrameIsScrollable();
1398 bool shouldHideScrollbars = shouldDisableScrolling;
1399 IntRect fixedVisibleContentRect;
1401 #if USE(COORDINATED_GRAPHICS)
1402 if (m_frame->coreFrame()->view())
1403 fixedVisibleContentRect = m_frame->coreFrame()->view()->fixedVisibleContentRect();
1404 if (shouldUseFixedLayout)
1405 shouldHideScrollbars = true;
1408 const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1409 m_frameHasCustomContentProvider = isMainFrame && webPage->shouldUseCustomContentProviderForResponse(response);
1410 m_frameCameFromPageCache = false;
1412 ScrollbarMode defaultScrollbarMode = shouldHideScrollbars ? ScrollbarAlwaysOff : ScrollbarAuto;
1414 ScrollbarMode horizontalScrollbarMode = webPage->alwaysShowsHorizontalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1415 ScrollbarMode verticalScrollbarMode = webPage->alwaysShowsVerticalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode;
1417 bool horizontalLock = shouldHideScrollbars || webPage->alwaysShowsHorizontalScroller();
1418 bool verticalLock = shouldHideScrollbars || webPage->alwaysShowsVerticalScroller();
1420 m_frame->coreFrame()->createView(webPage->size(), backgroundColor, isTransparent,
1421 webPage->fixedLayoutSize(), fixedVisibleContentRect, shouldUseFixedLayout,
1422 horizontalScrollbarMode, horizontalLock, verticalScrollbarMode, verticalLock);
1424 if (int viewLayoutWidth = webPage->viewLayoutSize().width()) {
1425 int viewLayoutHeight = std::max(webPage->viewLayoutSize().height(), 1);
1426 int maximumSize = std::numeric_limits<int>::max();
1427 m_frame->coreFrame()->view()->enableAutoSizeMode(true, IntSize(viewLayoutWidth, viewLayoutHeight), IntSize(maximumSize, maximumSize));
1429 if (webPage->autoSizingShouldExpandToViewHeight())
1430 m_frame->coreFrame()->view()->setAutoSizeFixedMinimumHeight(webPage->size().height());
1433 if (auto viewportSizeForViewportUnits = webPage->viewportSizeForCSSViewportUnits())
1434 m_frame->coreFrame()->view()->setViewportSizeForCSSViewportUnits(*viewportSizeForViewportUnits);
1435 m_frame->coreFrame()->view()->setProhibitsScrolling(shouldDisableScrolling);
1436 m_frame->coreFrame()->view()->setVisualUpdatesAllowedByClient(!webPage->shouldExtendIncrementalRenderingSuppression());
1438 m_frame->coreFrame()->view()->setViewExposedRect(webPage->drawingArea()->viewExposedRect());
1440 #if PLATFORM(IOS_FAMILY)
1441 m_frame->coreFrame()->view()->setDelegatesScrolling(true);
1444 if (webPage->scrollPinningBehavior() != DoNotPin)
1445 m_frame->coreFrame()->view()->setScrollPinningBehavior(webPage->scrollPinningBehavior());
1447 #if USE(COORDINATED_GRAPHICS)
1448 if (shouldUseFixedLayout) {
1449 m_frame->coreFrame()->view()->setDelegatesScrolling(shouldUseFixedLayout);
1450 m_frame->coreFrame()->view()->setPaintsEntireContents(shouldUseFixedLayout);
1456 void WebFrameLoaderClient::didSaveToPageCache()
1458 WebPage* webPage = m_frame->page();
1462 if (m_frame->isMainFrame())
1463 webPage->send(Messages::WebPageProxy::DidSaveToPageCache());
1466 void WebFrameLoaderClient::didRestoreFromPageCache()
1468 m_frameCameFromPageCache = true;
1471 void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool value)
1473 WebPage* webPage = m_frame->page();
1477 webPage->send(Messages::WebPageProxy::FrameDidBecomeFrameSet(m_frame->frameID(), value));
1480 bool WebFrameLoaderClient::canCachePage() const
1482 // We cannot cache frames that have custom representations because they are
1483 // rendered in the UIProcess.
1484 return !m_frameHasCustomContentProvider;
1487 void WebFrameLoaderClient::convertMainResourceLoadToDownload(DocumentLoader *documentLoader, PAL::SessionID sessionID, const ResourceRequest& request, const ResourceResponse& response)
1489 m_frame->convertMainResourceLoadToDownload(documentLoader, sessionID, request, response);
1492 RefPtr<Frame> WebFrameLoaderClient::createFrame(const URL& url, const String& name, HTMLFrameOwnerElement& ownerElement,
1493 const String& referrer)
1495 auto* webPage = m_frame->page();
1497 auto subframe = WebFrame::createSubframe(webPage, name, &ownerElement);
1498 auto* coreSubframe = subframe->coreFrame();
1502 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1503 if (!coreSubframe->page())
1506 m_frame->coreFrame()->loader().loadURLIntoChildFrame(url, referrer, coreSubframe);
1508 // The frame's onload handler may have removed it from the document.
1509 if (!subframe->coreFrame())
1511 ASSERT(subframe->coreFrame() == coreSubframe);
1512 if (!coreSubframe->tree().parent())
1515 return coreSubframe;
1518 RefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugInElement& pluginElement, const URL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1520 ASSERT(paramNames.size() == paramValues.size());
1521 ASSERT(m_frame->page());
1523 Plugin::Parameters parameters;
1524 parameters.url = url;
1525 parameters.names = paramNames;
1526 parameters.values = paramValues;
1527 parameters.mimeType = mimeType;
1528 parameters.isFullFramePlugin = loadManually;
1529 parameters.shouldUseManualLoader = parameters.isFullFramePlugin && !m_frameCameFromPageCache;
1531 parameters.layerHostingMode = m_frame->page()->layerHostingMode();
1534 #if ENABLE(NETSCAPE_PLUGIN_API)
1535 auto plugin = m_frame->page()->createPlugin(m_frame, &pluginElement, parameters, parameters.mimeType);
1539 return PluginView::create(pluginElement, plugin.releaseNonNull(), parameters);
1541 UNUSED_PARAM(pluginElement);
1546 void WebFrameLoaderClient::recreatePlugin(Widget* widget)
1548 #if ENABLE(NETSCAPE_PLUGIN_API)
1550 ASSERT(widget->isPluginViewBase());
1551 ASSERT(m_frame->page());
1553 auto& pluginView = static_cast<PluginView&>(*widget);
1555 auto plugin = m_frame->page()->createPlugin(m_frame, pluginView.pluginElement(), pluginView.initialParameters(), newMIMEType);
1556 pluginView.recreateAndInitialize(plugin.releaseNonNull());
1558 UNUSED_PARAM(widget);
1562 void WebFrameLoaderClient::redirectDataToPlugin(Widget& pluginWidget)
1564 m_pluginView = static_cast<PluginView*>(&pluginWidget);
1569 WebCore::WebGLLoadPolicy WebFrameLoaderClient::webGLPolicyForURL(const URL& url) const
1571 if (auto* webPage = m_frame->page())
1572 return webPage->webGLPolicyForURL(m_frame, url);
1574 return WebGLAllowCreation;
1577 WebCore::WebGLLoadPolicy WebFrameLoaderClient::resolveWebGLPolicyForURL(const URL& url) const
1579 if (auto* webPage = m_frame->page())
1580 return webPage->resolveWebGLPolicyForURL(m_frame, url);
1582 return WebGLAllowCreation;
1587 RefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement& appletElement, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues)
1589 #if ENABLE(NETSCAPE_PLUGIN_API)
1590 auto plugin = createPlugin(pluginSize, appletElement, URL(), paramNames, paramValues, appletElement.serviceType(), false);
1592 if (auto* webPage = m_frame->page()) {
1593 auto frameURLString = m_frame->coreFrame()->loader().documentLoader()->responseURL().string();
1594 auto pageURLString = webPage->corePage()->mainFrame().loader().documentLoader()->responseURL().string();
1595 webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(appletElement.serviceType(), frameURLString, pageURLString));
1600 UNUSED_PARAM(pluginSize);
1601 UNUSED_PARAM(appletElement);
1602 UNUSED_PARAM(paramNames);
1603 UNUSED_PARAM(paramValues);
1608 static bool pluginSupportsExtension(const PluginData& pluginData, const String& extension)
1610 ASSERT(extension.convertToASCIILowercase() == extension);
1611 Vector<MimeClassInfo> mimes;
1612 Vector<size_t> mimePluginIndices;
1613 pluginData.getWebVisibleMimesAndPluginIndices(mimes, mimePluginIndices);
1614 for (auto& mimeClassInfo : mimes) {
1615 if (mimeClassInfo.extensions.contains(extension))
1621 ObjectContentType WebFrameLoaderClient::objectContentType(const URL& url, const String& mimeTypeIn)
1623 // FIXME: This should eventually be merged with WebCore::FrameLoader::defaultObjectContentType.
1625 String mimeType = mimeTypeIn;
1626 if (mimeType.isEmpty()) {
1627 String path = url.path();
1628 auto dotPosition = path.reverseFind('.');
1629 if (dotPosition == notFound)
1630 return ObjectContentType::Frame;
1631 String extension = path.substring(dotPosition + 1).convertToASCIILowercase();
1633 // Try to guess the MIME type from the extension.
1634 mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1635 if (mimeType.isEmpty()) {
1636 // Check if there's a plug-in around that can handle the extension.
1637 if (WebPage* webPage = m_frame->page()) {
1638 if (pluginSupportsExtension(webPage->corePage()->pluginData(), extension))
1639 return ObjectContentType::PlugIn;
1641 return ObjectContentType::Frame;
1645 if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1646 return ObjectContentType::Image;
1648 if (WebPage* webPage = m_frame->page()) {
1649 auto allowedPluginTypes = webFrame()->coreFrame()->loader().subframeLoader().allowPlugins()
1650 ? PluginData::AllPlugins : PluginData::OnlyApplicationPlugins;
1651 if (webPage->corePage()->pluginData().supportsMimeType(mimeType, allowedPluginTypes))
1652 return ObjectContentType::PlugIn;
1655 if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1656 return ObjectContentType::Frame;
1658 #if PLATFORM(IOS_FAMILY)
1659 // iOS can render PDF in <object>/<embed> via PDFDocumentImage.
1660 if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType))
1661 return ObjectContentType::Image;
1664 return ObjectContentType::None;
1667 String WebFrameLoaderClient::overrideMediaType() const
1673 void WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
1675 WebPage* webPage = m_frame->page();
1679 webPage->injectedBundleLoaderClient().didClearWindowObjectForFrame(*webPage, *m_frame, world);
1682 WebAutomationSessionProxy* automationSessionProxy = WebProcess::singleton().automationSessionProxy();
1683 if (automationSessionProxy && world.isNormal())
1684 automationSessionProxy->didClearWindowObjectForFrame(*m_frame);
1686 #if HAVE(ACCESSIBILITY) && PLATFORM(GTK)
1687 // Ensure the accessibility hierarchy is updated.
1688 webPage->updateAccessibilityTree();
1692 void WebFrameLoaderClient::dispatchGlobalObjectAvailable(DOMWrapperWorld& world)
1694 WebPage* webPage = m_frame->page();
1698 webPage->injectedBundleLoaderClient().globalObjectIsAvailableForFrame(*webPage, *m_frame, world);
1701 void WebFrameLoaderClient::willInjectUserScript(DOMWrapperWorld& world)
1703 WebPage* webPage = m_frame->page();
1707 webPage->injectedBundleLoaderClient().willInjectUserScriptForFrame(*webPage, *m_frame, world);
1710 void WebFrameLoaderClient::dispatchWillDisconnectDOMWindowExtensionFromGlobalObject(WebCore::DOMWindowExtension* extension)
1712 WebPage* webPage = m_frame->page();
1716 webPage->injectedBundleLoaderClient().willDisconnectDOMWindowExtensionFromGlobalObject(*webPage, extension);
1719 void WebFrameLoaderClient::dispatchDidReconnectDOMWindowExtensionToGlobalObject(WebCore::DOMWindowExtension* extension)
1721 WebPage* webPage = m_frame->page();
1725 webPage->injectedBundleLoaderClient().didReconnectDOMWindowExtensionToGlobalObject(*webPage, extension);
1728 void WebFrameLoaderClient::dispatchWillDestroyGlobalObjectForDOMWindowExtension(WebCore::DOMWindowExtension* extension)
1730 WebPage* webPage = m_frame->page();
1734 webPage->injectedBundleLoaderClient().willDestroyGlobalObjectForDOMWindowExtension(*webPage, extension);
1739 RemoteAXObjectRef WebFrameLoaderClient::accessibilityRemoteObject()
1741 WebPage* webPage = m_frame->page();
1745 return webPage->accessibilityRemoteObject();
1748 void WebFrameLoaderClient::willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response, CompletionHandler<void(NSCachedURLResponse *)>&& completionHandler) const
1750 WebPage* webPage = m_frame->page();
1752 return completionHandler(response);
1754 return completionHandler(webPage->injectedBundleResourceLoadClient().shouldCacheResponse(*webPage, *m_frame, identifier) ? response : nil);
1757 NSDictionary *WebFrameLoaderClient::dataDetectionContext()
1759 WebPage* webPage = m_frame->page();
1763 return webPage->dataDetectionContext();
1766 #endif // PLATFORM(COCOA)
1768 bool WebFrameLoaderClient::shouldAlwaysUsePluginDocument(const String& /*mimeType*/) const
1774 void WebFrameLoaderClient::didChangeScrollOffset()
1776 WebPage* webPage = m_frame->page();
1780 webPage->didChangeScrollOffsetForFrame(m_frame->coreFrame());
1783 bool WebFrameLoaderClient::allowScript(bool enabledPerSettings)
1785 if (!enabledPerSettings)
1788 auto* pluginView = WebPage::pluginViewForFrame(m_frame->coreFrame());
1789 return !pluginView || !pluginView->shouldAllowScripting();
1792 bool WebFrameLoaderClient::shouldForceUniversalAccessFromLocalURL(const WebCore::URL& url)
1794 WebPage* webPage = m_frame->page();
1798 return webPage->injectedBundleLoaderClient().shouldForceUniversalAccessFromLocalURL(*webPage, url);
1801 Ref<FrameNetworkingContext> WebFrameLoaderClient::createNetworkingContext()
1803 ASSERT(!hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies));
1804 return WebFrameNetworkingContext::create(m_frame);
1807 #if ENABLE(CONTENT_FILTERING)
1809 void WebFrameLoaderClient::contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler unblockHandler)
1811 if (!unblockHandler.needsUIProcess()) {
1812 m_frame->coreFrame()->loader().policyChecker().setContentFilterUnblockHandler(WTFMove(unblockHandler));
1816 if (WebPage* webPage { m_frame->page() })
1817 webPage->send(Messages::WebPageProxy::ContentFilterDidBlockLoadForFrame(unblockHandler, m_frame->frameID()));
1822 void WebFrameLoaderClient::prefetchDNS(const String& hostname)
1824 WebProcess::singleton().prefetchDNS(hostname);
1827 void WebFrameLoaderClient::didRestoreScrollPosition()
1829 WebPage* webPage = m_frame->page();
1833 webPage->didRestoreScrollPosition();
1836 void WebFrameLoaderClient::getLoadDecisionForIcons(const Vector<std::pair<WebCore::LinkIcon&, uint64_t>>& icons)
1838 auto* webPage = m_frame->page();
1842 for (auto& icon : icons)
1843 webPage->send(Messages::WebPageProxy::GetLoadDecisionForIcon(icon.first, CallbackID::fromInteger(icon.second)));
1846 void WebFrameLoaderClient::finishedLoadingIcon(uint64_t callbackIdentifier, SharedBuffer* data)
1848 auto callbackID = CallbackID::fromInteger(callbackIdentifier);
1849 if (WebPage* webPage { m_frame->page() }) {
1851 webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { reinterpret_cast<const uint8_t*>(data->data()), data->size() }));
1853 webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { nullptr, 0 }));
1857 void WebFrameLoaderClient::didCreateWindow(DOMWindow& window)
1859 auto* webPage = m_frame->page();
1863 webPage->send(Messages::WebPageProxy::DidCreateWindow(m_frame->frameID(), window.identifier()));
1866 #if ENABLE(APPLICATION_MANIFEST)
1867 void WebFrameLoaderClient::finishedLoadingApplicationManifest(uint64_t callbackIdentifier, const std::optional<WebCore::ApplicationManifest>& manifest)
1869 WebPage* webPage = m_frame->page();
1873 webPage->didFinishLoadingApplicationManifest(callbackIdentifier, manifest);
1875 #endif // ENABLE(APPLICATION_MANIFEST)
1877 } // namespace WebKit