2 * Copyright (C) 2010-2019 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Intel Corporation. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
28 #include "WebPageProxy.h"
31 #include "APIAttachment.h"
32 #include "APIContextMenuClient.h"
33 #include "APIFindClient.h"
34 #include "APIFindMatchesClient.h"
35 #include "APIFormClient.h"
36 #include "APIFrameInfo.h"
37 #include "APIFullscreenClient.h"
38 #include "APIGeometry.h"
39 #include "APIHistoryClient.h"
40 #include "APIHitTestResult.h"
41 #include "APIIconLoadingClient.h"
42 #include "APILegacyContextHistoryClient.h"
43 #include "APILoaderClient.h"
44 #include "APINavigation.h"
45 #include "APINavigationAction.h"
46 #include "APINavigationClient.h"
47 #include "APINavigationResponse.h"
48 #include "APIOpenPanelParameters.h"
49 #include "APIPageConfiguration.h"
50 #include "APIPolicyClient.h"
51 #include "APISecurityOrigin.h"
52 #include "APIUIClient.h"
53 #include "APIURLRequest.h"
54 #include "APIWebsitePolicies.h"
55 #include "AuthenticationChallengeProxy.h"
56 #include "AuthenticationDecisionListener.h"
57 #include "DataReference.h"
58 #include "DownloadProxy.h"
59 #include "DrawingAreaMessages.h"
60 #include "DrawingAreaProxy.h"
61 #include "EventDispatcherMessages.h"
62 #include "FormDataReference.h"
63 #include "FrameInfoData.h"
64 #include "LoadParameters.h"
66 #include "NativeWebGestureEvent.h"
67 #include "NativeWebKeyboardEvent.h"
68 #include "NativeWebMouseEvent.h"
69 #include "NativeWebWheelEvent.h"
70 #include "NavigationActionData.h"
71 #include "NetworkProcessMessages.h"
72 #include "NetworkProcessProxy.h"
73 #include "NotificationPermissionRequest.h"
74 #include "NotificationPermissionRequestManager.h"
75 #include "OptionalCallbackID.h"
76 #include "PageClient.h"
77 #include "PluginInformation.h"
78 #include "PluginProcessManager.h"
79 #include "PrintInfo.h"
80 #include "ProvisionalPageProxy.h"
81 #include "SafeBrowsingWarning.h"
82 #include "ShareSheetCallbackID.h"
83 #include "SharedBufferDataReference.h"
84 #include "SyntheticEditingCommandType.h"
85 #include "TextChecker.h"
86 #include "TextCheckerState.h"
87 #include "TextInputContext.h"
88 #include "UIMessagePortChannelProvider.h"
89 #include "URLSchemeTaskParameters.h"
90 #include "UndoOrRedo.h"
91 #include "UserMediaPermissionRequestProxy.h"
92 #include "UserMediaProcessManager.h"
93 #include "WKContextPrivate.h"
94 #include "WebAutomationSession.h"
95 #include "WebBackForwardList.h"
96 #include "WebBackForwardListItem.h"
97 #include "WebCertificateInfo.h"
98 #include "WebContextMenuItem.h"
99 #include "WebContextMenuProxy.h"
100 #include "WebCoreArgumentCoders.h"
101 #include "WebEditCommandProxy.h"
102 #include "WebEvent.h"
103 #include "WebEventConversion.h"
104 #include "WebFramePolicyListenerProxy.h"
105 #include "WebFullScreenManagerProxy.h"
106 #include "WebFullScreenManagerProxyMessages.h"
107 #include "WebImage.h"
108 #include "WebInspectorProxy.h"
109 #include "WebInspectorUtilities.h"
110 #include "WebNavigationDataStore.h"
111 #include "WebNavigationState.h"
112 #include "WebNotificationManagerProxy.h"
113 #include "WebOpenPanelResultListenerProxy.h"
114 #include "WebPageCreationParameters.h"
115 #include "WebPageDebuggable.h"
116 #include "WebPageGroup.h"
117 #include "WebPageGroupData.h"
118 #include "WebPageInspectorController.h"
119 #include "WebPageMessages.h"
120 #include "WebPageProxyMessages.h"
121 #include "WebPaymentCoordinatorProxy.h"
122 #include "WebPopupItem.h"
123 #include "WebPopupMenuProxy.h"
124 #include "WebPreferences.h"
125 #include "WebPreferencesKeys.h"
126 #include "WebProcessMessages.h"
127 #include "WebProcessPool.h"
128 #include "WebProcessProxy.h"
129 #include "WebProtectionSpace.h"
130 #include "WebResourceLoadStatisticsStore.h"
131 #include "WebURLSchemeHandler.h"
132 #include "WebUserContentControllerProxy.h"
133 #include "WebViewDidMoveToWindowObserver.h"
134 #include "WebsiteDataStore.h"
135 #include <WebCore/AdClickAttribution.h>
136 #include <WebCore/BitmapImage.h>
137 #include <WebCore/CrossSiteNavigationDataTransfer.h>
138 #include <WebCore/DOMPasteAccess.h>
139 #include <WebCore/DeprecatedGlobalSettings.h>
140 #include <WebCore/DiagnosticLoggingClient.h>
141 #include <WebCore/DiagnosticLoggingKeys.h>
142 #include <WebCore/DragController.h>
143 #include <WebCore/DragData.h>
144 #include <WebCore/EventNames.h>
145 #include <WebCore/FloatRect.h>
146 #include <WebCore/FocusDirection.h>
147 #include <WebCore/FontAttributeChanges.h>
148 #include <WebCore/FrameLoader.h>
149 #include <WebCore/GlobalFrameIdentifier.h>
150 #include <WebCore/GlobalWindowIdentifier.h>
151 #include <WebCore/JSDOMBinding.h>
152 #include <WebCore/JSDOMExceptionHandling.h>
153 #include <WebCore/LengthBox.h>
154 #include <WebCore/MIMETypeRegistry.h>
155 #include <WebCore/MediaStreamRequest.h>
156 #include <WebCore/PerformanceLoggingClient.h>
157 #include <WebCore/PlatformEvent.h>
158 #include <WebCore/PublicSuffix.h>
159 #include <WebCore/RenderEmbeddedObject.h>
160 #include <WebCore/ResourceLoadStatistics.h>
161 #include <WebCore/SSLKeyGenerator.h>
162 #include <WebCore/SerializedCryptoKeyWrap.h>
163 #include <WebCore/ShareData.h>
164 #include <WebCore/SharedBuffer.h>
165 #include <WebCore/ShouldTreatAsContinuingLoad.h>
166 #include <WebCore/TextCheckerClient.h>
167 #include <WebCore/TextIndicator.h>
168 #include <WebCore/ValidationBubble.h>
169 #include <WebCore/WindowFeatures.h>
170 #include <WebCore/WritingDirection.h>
172 #include <wtf/NeverDestroyed.h>
173 #include <wtf/SystemTracing.h>
175 #include <wtf/URLParser.h>
176 #include <wtf/text/StringView.h>
177 #include <wtf/text/TextStream.h>
179 #if ENABLE(APPLICATION_MANIFEST)
180 #include "APIApplicationManifest.h"
183 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
184 #include "RemoteScrollingCoordinatorProxy.h"
188 #include <wtf/RefCountedLeakCounter.h>
192 #include "AttributedString.h"
193 #include "InsertTextOptions.h"
194 #include "RemoteLayerTreeDrawingAreaProxy.h"
195 #include "RemoteLayerTreeScrollingPerformanceData.h"
196 #include "TouchBarMenuData.h"
197 #include "TouchBarMenuItemData.h"
198 #include "VersionChecks.h"
199 #include "VideoFullscreenManagerProxy.h"
200 #include "VideoFullscreenManagerProxyMessages.h"
201 #include <WebCore/RunLoopObserver.h>
202 #include <WebCore/TextIndicatorWindow.h>
203 #include <wtf/MachSendRight.h>
206 #if PLATFORM(COCOA) || PLATFORM(GTK)
207 #include "ViewSnapshotStore.h"
211 #include "WebSelectionData.h"
215 #include <WebCore/CairoUtilities.h>
218 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
219 #include <WebCore/MediaPlaybackTarget.h>
220 #include <WebCore/WebMediaSessionManager.h>
223 #if ENABLE(MEDIA_SESSION)
224 #include "WebMediaSessionFocusManager.h"
225 #include "WebMediaSessionMetadata.h"
226 #include <WebCore/MediaSessionMetadata.h>
229 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
230 #include "PlaybackSessionManagerProxy.h"
233 #if ENABLE(WEB_AUTHN)
234 #include "WebAuthenticatorCoordinatorProxy.h"
237 #if ENABLE(REMOTE_INSPECTOR)
238 #include <JavaScriptCore/RemoteInspector.h>
241 #if HAVE(SEC_KEY_PROXY)
242 #include "SecKeyProxyStore.h"
246 #include "EditableImageController.h"
250 #include "SOAuthorizationCoordinator.h"
253 // This controls what strategy we use for mouse wheel coalescing.
254 #define MERGE_WHEEL_EVENTS 1
256 #define MESSAGE_CHECK(process, assertion) MESSAGE_CHECK_BASE(assertion, process->connection())
257 #define MESSAGE_CHECK_URL(process, url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(process, url), process->connection())
259 #define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - WebPageProxy::" fmt, this, ##__VA_ARGS__)
260 #define RELEASE_LOG_ERROR_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_ERROR_IF(isAlwaysOnLoggingAllowed(), channel, "%p - WebPageProxy::" fmt, this, ##__VA_ARGS__)
262 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
263 static const unsigned wheelEventQueueSizeThreshold = 10;
265 static const Seconds resetRecentCrashCountDelay = 30_s;
266 static unsigned maximumWebProcessRelaunchAttempts = 1;
269 using namespace WebCore;
271 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
273 class StorageRequests {
274 WTF_MAKE_NONCOPYABLE(StorageRequests); WTF_MAKE_FAST_ALLOCATED;
275 friend NeverDestroyed<StorageRequests>;
277 static StorageRequests& singleton();
279 void processOrAppend(CompletionHandler<void()>&& completionHandler)
281 if (m_requestsAreBeingProcessed) {
282 m_requests.append(WTFMove(completionHandler));
285 m_requestsAreBeingProcessed = true;
289 void processNextIfAny()
291 if (m_requests.isEmpty()) {
292 m_requestsAreBeingProcessed = false;
295 m_requests.takeFirst()();
299 StorageRequests() { }
300 ~StorageRequests() { }
302 Deque<CompletionHandler<void()>> m_requests;
303 bool m_requestsAreBeingProcessed { false };
306 StorageRequests& StorageRequests::singleton()
308 static NeverDestroyed<StorageRequests> requests;
313 static const char* webMouseEventTypeString(WebEvent::Type type)
316 case WebEvent::MouseDown:
318 case WebEvent::MouseUp:
320 case WebEvent::MouseMove:
322 case WebEvent::MouseForceChanged:
323 return "MouseForceChanged";
324 case WebEvent::MouseForceDown:
325 return "MouseForceDown";
326 case WebEvent::MouseForceUp:
327 return "MouseForceUp";
329 ASSERT_NOT_REACHED();
334 static const char* webKeyboardEventTypeString(WebEvent::Type type)
337 case WebEvent::KeyDown:
339 case WebEvent::KeyUp:
341 case WebEvent::RawKeyDown:
346 ASSERT_NOT_REACHED();
350 #endif // !LOG_DISABLED
352 class PageClientProtector {
353 WTF_MAKE_NONCOPYABLE(PageClientProtector);
355 PageClientProtector(PageClient& pageClient)
356 : m_pageClient(makeWeakPtr(pageClient))
358 m_pageClient->refView();
361 ~PageClientProtector()
363 ASSERT(m_pageClient);
364 m_pageClient->derefView();
368 WeakPtr<PageClient> m_pageClient;
371 void WebPageProxy::forMostVisibleWebPageIfAny(PAL::SessionID sessionID, const SecurityOriginData& origin, CompletionHandler<void(WebPageProxy*)>&& completionHandler)
373 // FIXME: If not finding right away a visible page, we might want to try again for a given period of time when there is a change of visibility.
374 WebPageProxy* selectedPage = nullptr;
375 WebProcessProxy::forWebPagesWithOrigin(sessionID, origin, [&](auto& page) {
376 if (!page.mainFrame())
378 if (page.isViewVisible() && (!selectedPage || !selectedPage->isViewVisible())) {
379 selectedPage = &page;
382 if (page.isViewFocused() && (!selectedPage || !selectedPage->isViewFocused())) {
383 selectedPage = &page;
387 completionHandler(selectedPage);
390 Ref<WebPageProxy> WebPageProxy::create(PageClient& pageClient, WebProcessProxy& process, PageIdentifier pageID, Ref<API::PageConfiguration>&& configuration)
392 return adoptRef(*new WebPageProxy(pageClient, process, pageID, WTFMove(configuration)));
395 WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, PageIdentifier pageID, Ref<API::PageConfiguration>&& configuration)
396 : m_pageClient(makeWeakPtr(pageClient))
397 , m_configuration(WTFMove(configuration))
398 , m_navigationClient(makeUniqueRef<API::NavigationClient>())
399 , m_historyClient(makeUniqueRef<API::HistoryClient>())
400 , m_iconLoadingClient(std::make_unique<API::IconLoadingClient>())
401 , m_formClient(std::make_unique<API::FormClient>())
402 , m_uiClient(std::make_unique<API::UIClient>())
403 , m_findClient(std::make_unique<API::FindClient>())
404 , m_findMatchesClient(std::make_unique<API::FindMatchesClient>())
405 #if ENABLE(CONTEXT_MENUS)
406 , m_contextMenuClient(std::make_unique<API::ContextMenuClient>())
408 , m_navigationState(std::make_unique<WebNavigationState>())
410 , m_pageGroup(*m_configuration->pageGroup())
411 , m_preferences(*m_configuration->preferences())
412 , m_userContentController(*m_configuration->userContentController())
413 , m_visitedLinkStore(*m_configuration->visitedLinkStore())
414 , m_websiteDataStore(m_configuration->websiteDataStore()->websiteDataStore())
415 , m_userAgent(standardUserAgent())
416 , m_overrideContentSecurityPolicy { m_configuration->overrideContentSecurityPolicy() }
417 , m_treatsSHA1CertificatesAsInsecure(m_configuration->treatsSHA1SignedCertificatesAsInsecure())
418 #if ENABLE(FULLSCREEN_API)
419 , m_fullscreenClient(std::make_unique<API::FullscreenClient>())
421 , m_geolocationPermissionRequestManager(*this)
422 , m_notificationPermissionRequestManager(*this)
423 #if PLATFORM(IOS_FAMILY)
424 , m_alwaysRunsAtForegroundPriority(m_configuration->alwaysRunsAtForegroundPriority())
426 , m_initialCapitalizationEnabled(m_configuration->initialCapitalizationEnabled())
427 , m_cpuLimit(m_configuration->cpuLimit())
428 , m_backForwardList(WebBackForwardList::create(*this))
429 , m_waitsForPaintAfterViewDidMoveToWindow(m_configuration->waitsForPaintAfterViewDidMoveToWindow())
430 , m_hasRunningProcess(process.state() != WebProcessProxy::State::Terminated)
432 , m_controlledByAutomation(m_configuration->isControlledByAutomation())
434 , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
436 , m_pageLoadState(*this)
437 , m_configurationPreferenceValues(m_configuration->preferenceValues())
438 , m_inspectorController(std::make_unique<WebPageInspectorController>(*this))
439 #if ENABLE(REMOTE_INSPECTOR)
440 , m_inspectorDebuggable(std::make_unique<WebPageDebuggable>(*this))
442 , m_resetRecentCrashCountTimer(RunLoop::main(), this, &WebPageProxy::resetRecentCrashCount)
444 RELEASE_LOG_IF_ALLOWED(Loading, "constructor: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
446 if (!m_configuration->drawsBackground())
447 m_backgroundColor = Color(Color::transparent);
449 updateActivityState();
450 updateThrottleState();
451 updateHiddenPageThrottlingAutoIncreases();
453 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
454 m_layerHostingMode = m_activityState & ActivityState::IsInWindow ? WebPageProxy::pageClient().viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
457 platformInitialize();
460 webPageProxyCounter.increment();
463 WebProcessPool::statistics().wkPageCount++;
465 m_preferences->addPage(*this);
466 m_pageGroup->addPage(this);
468 m_inspector = WebInspectorProxy::create(this);
470 if (hasRunningProcess())
471 didAttachToRunningProcess();
473 m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
475 #if PLATFORM(IOS_FAMILY)
476 DeprecatedGlobalSettings::setDisableScreenSizeOverride(preferencesStore().getBoolValueForKey(WebPreferencesKey::disableScreenSizeOverrideKey()));
480 m_activityStateChangeDispatcher = std::make_unique<RunLoopObserver>(static_cast<CFIndex>(RunLoopObserver::WellKnownRunLoopOrders::ActivityStateChange), [this] {
481 this->dispatchActivityStateChange();
485 #if ENABLE(REMOTE_INSPECTOR)
486 m_inspectorDebuggable->setRemoteDebuggingAllowed(true);
487 m_inspectorDebuggable->init();
490 createInspectorTargets();
493 WebPageProxy::~WebPageProxy()
495 RELEASE_LOG_IF_ALLOWED(Loading, "destructor: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
497 ASSERT(m_process->webPage(m_pageID) != this);
499 for (WebPageProxy* page : m_process->pages())
500 ASSERT(page != this);
503 setPageLoadStateObserver(nullptr);
508 WebProcessPool::statistics().wkPageCount--;
510 if (m_spellDocumentTag)
511 TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag.value());
513 m_preferences->removePage(*this);
514 m_pageGroup->removePage(this);
517 webPageProxyCounter.decrement();
521 // FIXME: Should return a const PageClient& and add a separate non-const
522 // version of this function, but several PageClient methods will need to become
523 // const for this to be possible.
524 PageClient& WebPageProxy::pageClient() const
526 ASSERT(m_pageClient);
527 return *m_pageClient;
530 PAL::SessionID WebPageProxy::sessionID() const
532 return m_websiteDataStore->sessionID();
535 DrawingAreaProxy* WebPageProxy::provisionalDrawingArea() const
537 if (m_provisionalPage && m_provisionalPage->drawingArea())
538 return m_provisionalPage->drawingArea();
539 return drawingArea();
542 const API::PageConfiguration& WebPageProxy::configuration() const
544 return m_configuration.get();
547 ProcessID WebPageProxy::processIdentifier() const
552 return m_process->processIdentifier();
555 bool WebPageProxy::hasRunningProcess() const
557 // A page that has been explicitly closed is never valid.
561 return m_hasRunningProcess;
564 void WebPageProxy::notifyProcessPoolToPrewarm()
566 m_process->processPool().didReachGoodTimeToPrewarm();
569 void WebPageProxy::setPreferences(WebPreferences& preferences)
571 if (&preferences == m_preferences.ptr())
574 m_preferences->removePage(*this);
575 m_preferences = preferences;
576 m_preferences->addPage(*this);
578 preferencesDidChange();
581 void WebPageProxy::setHistoryClient(UniqueRef<API::HistoryClient>&& historyClient)
583 m_historyClient = WTFMove(historyClient);
586 void WebPageProxy::setNavigationClient(UniqueRef<API::NavigationClient>&& navigationClient)
588 m_navigationClient = WTFMove(navigationClient);
591 void WebPageProxy::setLoaderClient(std::unique_ptr<API::LoaderClient>&& loaderClient)
593 m_loaderClient = WTFMove(loaderClient);
596 void WebPageProxy::setPolicyClient(std::unique_ptr<API::PolicyClient>&& policyClient)
598 m_policyClient = WTFMove(policyClient);
601 void WebPageProxy::setFormClient(std::unique_ptr<API::FormClient>&& formClient)
604 m_formClient = std::make_unique<API::FormClient>();
608 m_formClient = WTFMove(formClient);
611 void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient>&& uiClient)
614 m_uiClient = std::make_unique<API::UIClient>();
618 m_uiClient = WTFMove(uiClient);
620 if (hasRunningProcess())
621 m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient->canRunBeforeUnloadConfirmPanel()), m_pageID);
623 setCanRunModal(m_uiClient->canRunModal());
624 setNeedsFontAttributes(m_uiClient->needsFontAttributes());
627 void WebPageProxy::setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&& iconLoadingClient)
629 bool hasClient = iconLoadingClient.get();
630 if (!iconLoadingClient)
631 m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
633 m_iconLoadingClient = WTFMove(iconLoadingClient);
635 if (!hasRunningProcess())
638 m_process->send(Messages::WebPage::SetUseIconLoadingClient(hasClient), m_pageID);
641 void WebPageProxy::setPageLoadStateObserver(std::unique_ptr<PageLoadState::Observer>&& observer)
643 if (m_pageLoadStateObserver)
644 pageLoadState().removeObserver(*m_pageLoadStateObserver);
645 m_pageLoadStateObserver = WTFMove(observer);
646 if (m_pageLoadStateObserver)
647 pageLoadState().addObserver(*m_pageLoadStateObserver);
650 void WebPageProxy::setFindClient(std::unique_ptr<API::FindClient>&& findClient)
653 m_findClient = std::make_unique<API::FindClient>();
657 m_findClient = WTFMove(findClient);
660 void WebPageProxy::setFindMatchesClient(std::unique_ptr<API::FindMatchesClient>&& findMatchesClient)
662 if (!findMatchesClient) {
663 m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
667 m_findMatchesClient = WTFMove(findMatchesClient);
670 void WebPageProxy::setDiagnosticLoggingClient(std::unique_ptr<API::DiagnosticLoggingClient>&& diagnosticLoggingClient)
672 m_diagnosticLoggingClient = WTFMove(diagnosticLoggingClient);
675 #if ENABLE(CONTEXT_MENUS)
676 void WebPageProxy::setContextMenuClient(std::unique_ptr<API::ContextMenuClient>&& contextMenuClient)
678 if (!contextMenuClient) {
679 m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
683 m_contextMenuClient = WTFMove(contextMenuClient);
687 void WebPageProxy::setInjectedBundleClient(const WKPageInjectedBundleClientBase* client)
690 m_injectedBundleClient = nullptr;
694 m_injectedBundleClient = std::make_unique<WebPageInjectedBundleClient>();
695 m_injectedBundleClient->initialize(client);
698 void WebPageProxy::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
700 ASSERT(m_process->connection() == &connection);
702 if (!m_injectedBundleClient)
705 m_injectedBundleClient->didReceiveMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get());
708 void WebPageProxy::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, CompletionHandler<void(UserData&&)>&& completionHandler)
710 ASSERT(m_process->connection() == &connection);
712 if (!m_injectedBundleClient)
713 return completionHandler({ });
715 RefPtr<API::Object> returnData;
716 m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get(), [completionHandler = WTFMove(completionHandler), process = m_process.copyRef()] (RefPtr<API::Object>&& returnData) mutable {
717 completionHandler(UserData(process->transformObjectsToHandles(returnData.get())));
721 void WebPageProxy::launchProcess(const RegistrableDomain& registrableDomain)
724 ASSERT(!hasRunningProcess());
726 RELEASE_LOG_IF_ALLOWED(Loading, "launchProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
728 m_process->removeWebPage(*this, WebProcessProxy::EndsUsingDataStore::Yes);
729 m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
731 auto& processPool = m_process->processPool();
733 auto* relatedPage = m_configuration->relatedPage();
734 if (relatedPage && !relatedPage->isClosed())
735 m_process = relatedPage->ensureRunningProcess();
737 m_process = processPool.processForRegistrableDomain(m_websiteDataStore.get(), this, registrableDomain);
738 m_hasRunningProcess = true;
740 m_process->addExistingWebPage(*this, WebProcessProxy::BeginsUsingDataStore::Yes);
741 m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
743 finishAttachingToWebProcess(IsProcessSwap::No);
746 bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, Optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient processSwapRequestedByClient, ShouldDelayClosingUntilEnteringAcceleratedCompositingMode shouldDelayClosingUntilEnteringAcceleratedCompositingMode)
748 m_lastSuspendedPage = nullptr;
753 if (!hasCommittedAnyProvisionalLoads()) {
754 RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because has not committed any load yet", m_process->processIdentifier());
758 if (isPageOpenedByDOMShowingInitialEmptyDocument()) {
759 RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because it is showing the initial empty document", m_process->processIdentifier());
763 auto* fromItem = navigation.fromItem();
765 // If the source and the destination back / forward list items are the same, then this is a client-side redirect. In this case,
766 // there is no need to suspend the previous page as there will be no way to get back to it.
767 if (fromItem && fromItem == m_backForwardList->currentItem()) {
768 RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because this is a client-side redirect", m_process->processIdentifier());
772 if (fromItem && fromItem->url() != pageLoadState().url()) {
773 RELEASE_LOG_ERROR_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because fromItem's URL does not match the page URL.", m_process->processIdentifier());
774 ASSERT_NOT_REACHED();
778 RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Suspending current page for process pid %i", m_process->processIdentifier());
779 auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *mainFrameID, shouldDelayClosingUntilEnteringAcceleratedCompositingMode);
781 LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " created suspended page %s for process pid %i, back/forward item %s" PRIu64, pageID().toUInt64(), suspendedPage->loggingString(), m_process->processIdentifier(), fromItem ? fromItem->itemID().logString() : 0);
783 // If the client forced a swap then it may not be web-compatible to keep the previous page because other windows may have an opener link to it. We thus close it as soon as we
784 // can do so without flashing.
785 if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes)
786 suspendedPage->closeWithoutFlashing();
788 if (fromItem && m_preferences->usesPageCache())
789 fromItem->setSuspendedPage(suspendedPage.get());
791 m_lastSuspendedPage = makeWeakPtr(*suspendedPage);
792 m_process->processPool().addSuspendedPage(WTFMove(suspendedPage));
796 void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, std::unique_ptr<DrawingAreaProxy>&& drawingArea, RefPtr<WebFrameProxy>&& mainFrame)
799 RELEASE_LOG_IF_ALLOWED(Loading, "swapToWebProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
801 m_process = WTFMove(process);
802 m_websiteDataStore = m_process->websiteDataStore();
805 m_logger->setEnabled(this, isAlwaysOnLoggingAllowed());
807 ASSERT(!m_drawingArea);
808 setDrawingArea(WTFMove(drawingArea));
809 ASSERT(!m_mainFrame);
810 m_mainFrame = WTFMove(mainFrame);
811 m_hasRunningProcess = true;
813 m_process->addExistingWebPage(*this, WebProcessProxy::BeginsUsingDataStore::No);
814 m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
816 finishAttachingToWebProcess(IsProcessSwap::Yes);
819 void WebPageProxy::finishAttachingToWebProcess(IsProcessSwap isProcessSwap)
821 ASSERT(m_process->state() != AuxiliaryProcessProxy::State::Terminated);
823 updateActivityState();
824 updateThrottleState();
826 didAttachToRunningProcess();
828 // In the process-swap case, the ProvisionalPageProxy already took care of initializing the WebPage in the WebProcess.
829 if (isProcessSwap != IsProcessSwap::Yes)
832 m_inspector->updateForNewPageProcess(this);
834 #if ENABLE(REMOTE_INSPECTOR)
835 remoteInspectorInformationDidChange();
838 clearInspectorTargets();
839 createInspectorTargets();
841 pageClient().didRelaunchProcess();
842 m_pageLoadState.didSwapWebProcesses();
843 m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
846 void WebPageProxy::didAttachToRunningProcess()
848 ASSERT(hasRunningProcess());
850 #if ENABLE(FULLSCREEN_API)
851 ASSERT(!m_fullScreenManager);
852 m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, pageClient().fullScreenManagerProxyClient());
854 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
855 ASSERT(!m_playbackSessionManager);
856 m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
857 ASSERT(!m_videoFullscreenManager);
858 m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
861 #if ENABLE(APPLE_PAY)
862 ASSERT(!m_paymentCoordinator);
863 m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
866 #if USE(SYSTEM_PREVIEW)
867 ASSERT(!m_systemPreviewController);
868 m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
871 #if ENABLE(WEB_AUTHN)
872 ASSERT(!m_credentialsMessenger);
873 m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
877 ASSERT(!m_editableImageController);
878 m_editableImageController = std::make_unique<EditableImageController>(*this);
882 RefPtr<API::Navigation> WebPageProxy::launchProcessForReload()
884 RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessForReload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
887 RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessForReload: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
891 ASSERT(!hasRunningProcess());
892 auto registrableDomain = m_backForwardList->currentItem() ? RegistrableDomain { URL(URL(), m_backForwardList->currentItem()->url()) } : RegistrableDomain { };
893 launchProcess(registrableDomain);
895 if (!m_backForwardList->currentItem()) {
896 RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessForReload: no current item to reload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
900 auto navigation = m_navigationState->createReloadNavigation();
902 String url = currentURL();
903 if (!url.isEmpty()) {
904 auto transaction = m_pageLoadState.transaction();
905 m_pageLoadState.setPendingAPIRequest(transaction, { navigation->navigationID(), url });
908 // We allow stale content when reloading a WebProcess that's been killed or crashed.
909 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
910 m_process->responsivenessTimer().start();
915 RefPtr<API::Navigation> WebPageProxy::launchProcessWithItem(WebBackForwardListItem& item)
917 RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessWithItem: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
920 RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessWithItem: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
924 ASSERT(!hasRunningProcess());
925 launchProcess(RegistrableDomain { URL(URL(), item.url()) });
927 if (&item != m_backForwardList->currentItem())
928 m_backForwardList->goToItem(item);
930 auto navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), FrameLoadType::IndexedBackForward);
932 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item.itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
933 m_process->responsivenessTimer().start();
938 void WebPageProxy::setDrawingArea(std::unique_ptr<DrawingAreaProxy>&& drawingArea)
940 m_drawingArea = WTFMove(drawingArea);
944 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
945 if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) {
946 m_scrollingCoordinatorProxy = std::make_unique<RemoteScrollingCoordinatorProxy>(*this);
947 #if PLATFORM(IOS_FAMILY)
948 // On iOS, main frame scrolls are sent in terms of visible rect updates.
949 m_scrollingCoordinatorProxy->setPropagatesMainFrameScrolls(false);
955 void WebPageProxy::initializeWebPage()
957 if (!hasRunningProcess())
960 setDrawingArea(pageClient().createDrawingAreaProxy(m_process));
961 ASSERT(m_drawingArea);
963 process().send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters(m_process, *m_drawingArea)), 0);
965 m_process->addVisitedLinkStoreUser(visitedLinkStore(), m_pageID);
968 void WebPageProxy::close()
973 RELEASE_LOG_IF_ALLOWED(Loading, "close: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
977 reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
979 if (m_activePopupMenu)
980 m_activePopupMenu->cancelTracking();
982 if (m_controlledByAutomation) {
983 if (auto* automationSession = process().processPool().automationSession())
984 automationSession->willClosePage(*this);
987 #if ENABLE(CONTEXT_MENUS)
988 m_activeContextMenu = nullptr;
991 m_provisionalPage = nullptr;
993 m_inspector->invalidate();
995 m_backForwardList->pageClosed();
996 m_inspectorController->pageClosed();
997 #if ENABLE(REMOTE_INSPECTOR)
998 m_inspectorDebuggable = nullptr;
1000 pageClient().pageClosed();
1002 m_process->disconnectFramesFromPage(this);
1004 resetState(ResetStateReason::PageInvalidated);
1006 m_loaderClient = nullptr;
1007 m_navigationClient = makeUniqueRef<API::NavigationClient>();
1008 m_policyClient = nullptr;
1009 m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
1010 m_formClient = std::make_unique<API::FormClient>();
1011 m_uiClient = std::make_unique<API::UIClient>();
1012 m_findClient = std::make_unique<API::FindClient>();
1013 m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
1014 m_diagnosticLoggingClient = nullptr;
1015 #if ENABLE(CONTEXT_MENUS)
1016 m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
1018 #if ENABLE(FULLSCREEN_API)
1019 m_fullscreenClient = std::make_unique<API::FullscreenClient>();
1022 m_process->processPool().removeAllSuspendedPagesForPage(*this);
1024 m_process->send(Messages::WebPage::Close(), m_pageID);
1025 m_process->removeWebPage(*this, WebProcessProxy::EndsUsingDataStore::Yes);
1026 m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
1027 m_process->processPool().supplement<WebNotificationManagerProxy>()->clearNotifications(this);
1029 // Null out related WebPageProxy to avoid leaks.
1030 m_configuration->setRelatedPage(nullptr);
1032 #if PLATFORM(IOS_FAMILY)
1033 // Make sure we don't hold a process assertion after getting closed.
1034 m_activityToken = nullptr;
1037 stopAllURLSchemeTasks();
1038 updatePlayingMediaDidChange(MediaProducer::IsNotPlaying);
1041 bool WebPageProxy::tryClose()
1043 if (!hasRunningProcess())
1046 RELEASE_LOG_IF_ALLOWED(Loading, "tryClose: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1048 // Close without delay if the process allows it. Our goal is to terminate
1049 // the process, so we check a per-process status bit.
1050 if (m_process->isSuddenTerminationEnabled())
1053 m_process->send(Messages::WebPage::TryClose(), m_pageID);
1054 m_process->responsivenessTimer().start();
1058 void WebPageProxy::maybeInitializeSandboxExtensionHandle(WebProcessProxy& process, const URL& url, const URL& resourceDirectoryURL, SandboxExtension::Handle& sandboxExtensionHandle)
1060 if (!url.isLocalFile())
1063 if (!resourceDirectoryURL.isEmpty()) {
1064 if (process.hasAssumedReadAccessToURL(resourceDirectoryURL))
1067 if (SandboxExtension::createHandle(resourceDirectoryURL.fileSystemPath(), SandboxExtension::Type::ReadOnly, sandboxExtensionHandle)) {
1068 m_process->assumeReadAccessToBaseURL(*this, resourceDirectoryURL);
1073 if (process.hasAssumedReadAccessToURL(url))
1076 // Inspector resources are in a directory with assumed access.
1077 ASSERT_WITH_SECURITY_IMPLICATION(!WebKit::isInspectorPage(*this));
1079 #if PLATFORM(MAC) && HAVE(SANDBOX_ISSUE_READ_EXTENSION_TO_PROCESS_BY_PID)
1080 if (SandboxExtension::createHandleForReadByPid("/", processIdentifier(), sandboxExtensionHandle)) {
1082 if (SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, sandboxExtensionHandle)) {
1084 willAcquireUniversalFileReadSandboxExtension(process);
1089 if (!linkedOnOrAfter(SDKVersion::FirstWithoutUnconditionalUniversalSandboxExtension))
1090 willAcquireUniversalFileReadSandboxExtension(process);
1093 // We failed to issue an universal file read access sandbox, fall back to issuing one for the base URL instead.
1094 auto baseURL = URL(URL(), url.baseAsString());
1095 auto basePath = baseURL.fileSystemPath();
1096 if (basePath.isNull())
1098 #if PLATFORM(MAC) && HAVE(SANDBOX_ISSUE_READ_EXTENSION_TO_PROCESS_BY_PID)
1099 if (SandboxExtension::createHandleForReadByPid(basePath, processIdentifier(), sandboxExtensionHandle))
1101 if (SandboxExtension::createHandle(basePath, SandboxExtension::Type::ReadOnly, sandboxExtensionHandle))
1103 m_process->assumeReadAccessToBaseURL(*this, baseURL);
1106 #if !PLATFORM(COCOA)
1107 void WebPageProxy::addPlatformLoadParameters(LoadParameters&)
1112 WebProcessProxy& WebPageProxy::ensureRunningProcess()
1114 if (!hasRunningProcess())
1120 RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
1125 RELEASE_LOG_IF_ALLOWED(Loading, "loadRequest: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1127 if (!hasRunningProcess())
1128 launchProcess(RegistrableDomain { request.url() });
1130 auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
1131 loadRequestWithNavigationShared(m_process.copyRef(), navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, ShouldTreatAsContinuingLoad::No);
1135 void WebPageProxy::loadRequestWithNavigationShared(Ref<WebProcessProxy>&& process, API::Navigation& navigation, ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
1137 ASSERT(!m_isClosed);
1139 RELEASE_LOG_IF_ALLOWED(Loading, "loadRequestWithNavigation: webPID = %i, pageID = %" PRIu64, process->processIdentifier(), m_pageID.toUInt64());
1141 auto transaction = m_pageLoadState.transaction();
1143 auto url = request.url();
1144 if (shouldTreatAsContinuingLoad != ShouldTreatAsContinuingLoad::Yes)
1145 m_pageLoadState.setPendingAPIRequest(transaction, { navigation.navigationID(), url });
1147 LoadParameters loadParameters;
1148 loadParameters.navigationID = navigation.navigationID();
1149 loadParameters.request = WTFMove(request);
1150 loadParameters.shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicy;
1151 loadParameters.userData = UserData(process->transformObjectsToHandles(userData).get());
1152 loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1153 loadParameters.websitePolicies = WTFMove(websitePolicies);
1154 loadParameters.lockHistory = navigation.lockHistory();
1155 loadParameters.lockBackForwardList = navigation.lockBackForwardList();
1156 loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
1157 maybeInitializeSandboxExtensionHandle(process, url, m_pageLoadState.resourceDirectoryURL(), loadParameters.sandboxExtensionHandle);
1159 addPlatformLoadParameters(loadParameters);
1161 process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1162 process->responsivenessTimer().start();
1165 RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
1167 RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1170 RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1174 if (!hasRunningProcess())
1177 URL fileURL = URL(URL(), fileURLString);
1178 if (!fileURL.isLocalFile()) {
1179 RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: file is not local: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1183 URL resourceDirectoryURL;
1184 if (resourceDirectoryURLString.isNull())
1185 resourceDirectoryURL = URL({ }, "file:///"_s);
1187 resourceDirectoryURL = URL(URL(), resourceDirectoryURLString);
1188 if (!resourceDirectoryURL.isLocalFile()) {
1189 RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: resource URL is not local: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1194 auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL), m_backForwardList->currentItem());
1196 auto transaction = m_pageLoadState.transaction();
1198 m_pageLoadState.setPendingAPIRequest(transaction, { navigation->navigationID(), fileURLString }, resourceDirectoryURL);
1200 String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
1202 LoadParameters loadParameters;
1203 loadParameters.navigationID = navigation->navigationID();
1204 loadParameters.request = fileURL;
1205 loadParameters.shouldOpenExternalURLsPolicy = ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1206 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1207 SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::Type::ReadOnly, loadParameters.sandboxExtensionHandle);
1208 addPlatformLoadParameters(loadParameters);
1210 m_process->assumeReadAccessToBaseURL(*this, resourceDirectoryURL);
1211 m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1212 m_process->responsivenessTimer().start();
1217 RefPtr<API::Navigation> WebPageProxy::loadData(const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy)
1219 RELEASE_LOG_IF_ALLOWED(Loading, "loadData: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1222 RELEASE_LOG_IF_ALLOWED(Loading, "loadData: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1226 if (!hasRunningProcess())
1229 auto navigation = m_navigationState->createLoadDataNavigation(std::make_unique<API::SubstituteData>(data.vector(), MIMEType, encoding, baseURL, userData));
1230 loadDataWithNavigationShared(m_process.copyRef(), navigation, data, MIMEType, encoding, baseURL, userData, ShouldTreatAsContinuingLoad::No, WTF::nullopt, shouldOpenExternalURLsPolicy);
1234 void WebPageProxy::loadDataWithNavigationShared(Ref<WebProcessProxy>&& process, API::Navigation& navigation, const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy)
1236 RELEASE_LOG_IF_ALLOWED(Loading, "loadDataWithNavigation: webPID = %i, pageID = %" PRIu64, process->processIdentifier(), m_pageID.toUInt64());
1238 ASSERT(!m_isClosed);
1240 auto transaction = m_pageLoadState.transaction();
1242 m_pageLoadState.setPendingAPIRequest(transaction, { navigation.navigationID(), !baseURL.isEmpty() ? baseURL : WTF::blankURL().string() });
1244 LoadParameters loadParameters;
1245 loadParameters.navigationID = navigation.navigationID();
1246 loadParameters.data = data;
1247 loadParameters.MIMEType = MIMEType;
1248 loadParameters.encodingName = encoding;
1249 loadParameters.baseURLString = baseURL;
1250 loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1251 loadParameters.userData = UserData(process->transformObjectsToHandles(userData).get());
1252 loadParameters.websitePolicies = WTFMove(websitePolicies);
1253 loadParameters.shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicy;
1254 addPlatformLoadParameters(loadParameters);
1256 process->assumeReadAccessToBaseURL(*this, baseURL);
1257 process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1258 process->responsivenessTimer().start();
1261 void WebPageProxy::loadAlternateHTML(const IPC::DataReference& htmlData, const String& encoding, const URL& baseURL, const URL& unreachableURL, API::Object* userData)
1263 RELEASE_LOG_IF_ALLOWED(Loading, "loadAlternateHTML: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1265 // When the UIProcess is in the process of handling a failing provisional load, do not attempt to
1266 // start a second alternative HTML load as this will prevent the page load state from being
1267 // handled properly.
1268 if (m_isClosed || m_isLoadingAlternateHTMLStringForFailingProvisionalLoad) {
1269 RELEASE_LOG_IF_ALLOWED(Loading, "loadAlternateHTML: page is closed (or other): webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1273 if (!m_failingProvisionalLoadURL.isEmpty())
1274 m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = true;
1276 if (!hasRunningProcess())
1277 launchProcess(RegistrableDomain { baseURL });
1279 auto transaction = m_pageLoadState.transaction();
1281 m_pageLoadState.setPendingAPIRequest(transaction, { 0, unreachableURL });
1282 m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
1285 m_mainFrame->setUnreachableURL(unreachableURL);
1287 LoadParameters loadParameters;
1288 loadParameters.navigationID = 0;
1289 loadParameters.data = htmlData;
1290 loadParameters.MIMEType = "text/html"_s;
1291 loadParameters.encodingName = encoding;
1292 loadParameters.baseURLString = baseURL;
1293 loadParameters.unreachableURLString = unreachableURL;
1294 loadParameters.provisionalLoadErrorURLString = m_failingProvisionalLoadURL;
1295 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1296 addPlatformLoadParameters(loadParameters);
1298 m_process->assumeReadAccessToBaseURL(*this, baseURL);
1299 m_process->assumeReadAccessToBaseURL(*this, unreachableURL);
1300 m_process->send(Messages::WebPage::LoadAlternateHTML(loadParameters), m_pageID);
1301 m_process->responsivenessTimer().start();
1304 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
1306 RELEASE_LOG_IF_ALLOWED(Loading, "loadWebArchiveData: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1309 RELEASE_LOG_IF_ALLOWED(Loading, "loadWebArchiveData: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1313 if (!hasRunningProcess())
1316 auto transaction = m_pageLoadState.transaction();
1317 m_pageLoadState.setPendingAPIRequest(transaction, { 0, WTF::blankURL().string() });
1319 LoadParameters loadParameters;
1320 loadParameters.navigationID = 0;
1321 loadParameters.data = webArchiveData->dataReference();
1322 loadParameters.MIMEType = "application/x-webarchive"_s;
1323 loadParameters.encodingName = "utf-16"_s;
1324 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1325 addPlatformLoadParameters(loadParameters);
1327 m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1328 m_process->responsivenessTimer().start();
1331 void WebPageProxy::navigateToPDFLinkWithSimulatedClick(const String& urlString, IntPoint documentPoint, IntPoint screenPoint)
1333 RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1336 RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1340 if (WTF::protocolIsJavaScript(urlString))
1343 if (!hasRunningProcess())
1344 launchProcess(RegistrableDomain { URL(URL(), urlString) });
1346 m_process->send(Messages::WebPage::NavigateToPDFLinkWithSimulatedClick(urlString, documentPoint, screenPoint), m_pageID);
1347 m_process->responsivenessTimer().start();
1350 void WebPageProxy::stopLoading()
1352 RELEASE_LOG_IF_ALLOWED(Loading, "stopLoading: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1354 if (!hasRunningProcess()) {
1355 RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: page is not valid: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1359 m_process->send(Messages::WebPage::StopLoading(), m_pageID);
1360 if (m_provisionalPage) {
1361 m_provisionalPage->cancel();
1362 m_provisionalPage = nullptr;
1364 m_process->responsivenessTimer().start();
1367 RefPtr<API::Navigation> WebPageProxy::reload(OptionSet<WebCore::ReloadOption> options)
1369 RELEASE_LOG_IF_ALLOWED(Loading, "reload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1371 SandboxExtension::Handle sandboxExtensionHandle;
1373 String url = currentURL();
1374 if (!url.isEmpty()) {
1375 // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
1376 maybeInitializeSandboxExtensionHandle(m_process, URL(URL(), url), currentResourceDirectoryURL(), sandboxExtensionHandle);
1379 if (!hasRunningProcess())
1380 return launchProcessForReload();
1382 auto navigation = m_navigationState->createReloadNavigation();
1384 if (!url.isEmpty()) {
1385 auto transaction = m_pageLoadState.transaction();
1386 m_pageLoadState.setPendingAPIRequest(transaction, { navigation->navigationID(), url });
1389 // Store decision to reload without content blockers on the navigation so that we can later set the corresponding
1390 // WebsitePolicies flag in WebPageProxy::receivedNavigationPolicyDecision().
1391 if (options.contains(WebCore::ReloadOption::DisableContentBlockers))
1392 navigation->setUserContentExtensionsEnabled(false);
1394 m_process->send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle), m_pageID);
1395 m_process->responsivenessTimer().start();
1397 #if ENABLE(SPEECH_SYNTHESIS)
1398 resetSpeechSynthesizer();
1404 void WebPageProxy::recordAutomaticNavigationSnapshot()
1406 if (m_shouldSuppressNextAutomaticNavigationSnapshot)
1409 if (WebBackForwardListItem* item = m_backForwardList->currentItem())
1410 recordNavigationSnapshot(*item);
1413 void WebPageProxy::recordNavigationSnapshot(WebBackForwardListItem& item)
1415 if (!m_shouldRecordNavigationSnapshots)
1418 #if PLATFORM(COCOA) || PLATFORM(GTK)
1419 ViewSnapshotStore::singleton().recordSnapshot(*this, item);
1425 RefPtr<API::Navigation> WebPageProxy::goForward()
1427 WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
1431 return goToBackForwardItem(*forwardItem, FrameLoadType::Forward);
1434 RefPtr<API::Navigation> WebPageProxy::goBack()
1436 WebBackForwardListItem* backItem = m_backForwardList->backItem();
1440 return goToBackForwardItem(*backItem, FrameLoadType::Back);
1443 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item)
1445 return goToBackForwardItem(item, FrameLoadType::IndexedBackForward);
1448 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item, FrameLoadType frameLoadType)
1450 RELEASE_LOG_IF_ALLOWED(Loading, "goToBackForwardItem: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1451 LOG(Loading, "WebPageProxy %p goToBackForwardItem to item URL %s", this, item.url().utf8().data());
1453 if (!hasRunningProcess())
1454 return launchProcessWithItem(item);
1456 RefPtr<API::Navigation> navigation;
1457 if (!m_backForwardList->currentItem()->itemIsInSameDocument(item))
1458 navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), frameLoadType);
1460 auto transaction = m_pageLoadState.transaction();
1461 m_pageLoadState.setPendingAPIRequest(transaction, { navigation ? navigation->navigationID() : 0, item.url() });
1463 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
1464 m_process->responsivenessTimer().start();
1469 void WebPageProxy::tryRestoreScrollPosition()
1471 RELEASE_LOG_IF_ALLOWED(Loading, "tryRestoreScrollPosition: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1473 if (!hasRunningProcess()) {
1474 RELEASE_LOG_IF_ALLOWED(Loading, "tryRestoreScrollPosition: page is not valid: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
1478 m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
1481 void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<Ref<WebBackForwardListItem>>&& removed)
1483 PageClientProtector protector(pageClient());
1485 if (!m_navigationClient->didChangeBackForwardList(*this, added, removed) && m_loaderClient)
1486 m_loaderClient->didChangeBackForwardList(*this, added, WTFMove(removed));
1488 auto transaction = m_pageLoadState.transaction();
1490 m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
1491 m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
1494 void WebPageProxy::willGoToBackForwardListItem(const BackForwardItemIdentifier& itemID, bool inPageCache)
1496 PageClientProtector protector(pageClient());
1498 if (auto* item = m_backForwardList->itemForID(itemID))
1499 m_navigationClient->willGoToBackForwardListItem(*this, *item, inPageCache);
1502 bool WebPageProxy::shouldKeepCurrentBackForwardListItemInList(WebBackForwardListItem& item)
1504 PageClientProtector protector(pageClient());
1506 return !m_loaderClient || m_loaderClient->shouldKeepCurrentBackForwardListItemInList(*this, item);
1509 bool WebPageProxy::canShowMIMEType(const String& mimeType)
1511 if (MIMETypeRegistry::canShowMIMEType(mimeType))
1514 #if ENABLE(NETSCAPE_PLUGIN_API)
1515 String newMimeType = mimeType;
1516 PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL());
1517 if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
1519 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1522 // On Mac, we can show PDFs.
1523 if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebProcessPool::omitPDFSupport())
1525 #endif // PLATFORM(COCOA)
1530 void WebPageProxy::setControlledByAutomation(bool controlled)
1532 if (m_controlledByAutomation == controlled)
1535 m_controlledByAutomation = controlled;
1537 if (!hasRunningProcess())
1540 m_process->send(Messages::WebPage::SetControlledByAutomation(controlled), m_pageID);
1541 m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation));
1544 void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
1546 m_inspectorController->createInspectorTarget(targetId, type);
1549 void WebPageProxy::destroyInspectorTarget(const String& targetId)
1551 m_inspectorController->destroyInspectorTarget(targetId);
1554 void WebPageProxy::sendMessageToInspectorFrontend(const String& targetId, const String& message)
1556 m_inspectorController->sendMessageToInspectorFrontend(targetId, message);
1559 #if ENABLE(REMOTE_INSPECTOR)
1560 void WebPageProxy::setIndicating(bool indicating)
1562 if (!hasRunningProcess())
1565 m_process->send(Messages::WebPage::SetIndicating(indicating), m_pageID);
1568 bool WebPageProxy::allowsRemoteInspection() const
1570 return m_inspectorDebuggable->remoteDebuggingAllowed();
1573 void WebPageProxy::setAllowsRemoteInspection(bool allow)
1575 m_inspectorDebuggable->setRemoteDebuggingAllowed(allow);
1578 String WebPageProxy::remoteInspectionNameOverride() const
1580 return m_inspectorDebuggable->nameOverride();
1583 void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
1585 m_inspectorDebuggable->setNameOverride(name);
1588 void WebPageProxy::remoteInspectorInformationDidChange()
1590 m_inspectorDebuggable->update();
1594 void WebPageProxy::clearInspectorTargets()
1596 m_inspectorController->clearTargets();
1599 void WebPageProxy::createInspectorTargets()
1601 String pageTargetId = makeString("page-", m_pageID.toUInt64());
1602 m_inspectorController->createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
1605 void WebPageProxy::setBackgroundColor(const Optional<Color>& color)
1607 if (m_backgroundColor == color)
1610 m_backgroundColor = color;
1611 if (hasRunningProcess())
1612 m_process->send(Messages::WebPage::SetBackgroundColor(color), m_pageID);
1615 void WebPageProxy::setTopContentInset(float contentInset)
1617 if (m_topContentInset == contentInset)
1620 m_topContentInset = contentInset;
1622 if (!hasRunningProcess())
1625 MachSendRight fence = m_drawingArea->createFence();
1627 auto fenceAttachment = IPC::Attachment(fence.leakSendRight(), MACH_MSG_TYPE_MOVE_SEND);
1628 m_process->send(Messages::WebPage::SetTopContentInsetFenced(contentInset, fenceAttachment), m_pageID);
1630 m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
1634 void WebPageProxy::setUnderlayColor(const Color& color)
1636 if (m_underlayColor == color)
1639 m_underlayColor = color;
1641 if (hasRunningProcess())
1642 m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1645 void WebPageProxy::viewWillStartLiveResize()
1647 if (!hasRunningProcess())
1650 closeOverlayedViews();
1651 m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1654 void WebPageProxy::viewWillEndLiveResize()
1656 if (!hasRunningProcess())
1658 m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1661 void WebPageProxy::setViewNeedsDisplay(const Region& region)
1663 pageClient().setViewNeedsDisplay(region);
1666 void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin)
1668 pageClient().requestScroll(scrollPosition, scrollOrigin);
1671 WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
1673 return pageClient().viewScrollPosition();
1676 void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
1678 if (m_suppressVisibilityUpdates == flag)
1680 m_suppressVisibilityUpdates = flag;
1682 if (!m_suppressVisibilityUpdates) {
1684 m_activityStateChangeDispatcher->schedule();
1686 dispatchActivityStateChange();
1691 void WebPageProxy::updateActivityState(OptionSet<ActivityState::Flag> flagsToUpdate)
1693 m_activityState.remove(flagsToUpdate);
1694 if (flagsToUpdate & ActivityState::IsFocused && pageClient().isViewFocused())
1695 m_activityState.add(ActivityState::IsFocused);
1696 if (flagsToUpdate & ActivityState::WindowIsActive && pageClient().isViewWindowActive())
1697 m_activityState.add(ActivityState::WindowIsActive);
1698 if (flagsToUpdate & ActivityState::IsVisible && pageClient().isViewVisible())
1699 m_activityState.add(ActivityState::IsVisible);
1700 if (flagsToUpdate & ActivityState::IsVisibleOrOccluded && pageClient().isViewVisibleOrOccluded())
1701 m_activityState.add(ActivityState::IsVisibleOrOccluded);
1702 if (flagsToUpdate & ActivityState::IsInWindow && pageClient().isViewInWindow())
1703 m_activityState.add(ActivityState::IsInWindow);
1704 if (flagsToUpdate & ActivityState::IsVisuallyIdle && pageClient().isVisuallyIdle())
1705 m_activityState.add(ActivityState::IsVisuallyIdle);
1706 if (flagsToUpdate & ActivityState::IsAudible && m_mediaState & MediaProducer::IsPlayingAudio && !(m_mutedState & MediaProducer::AudioIsMuted))
1707 m_activityState.add(ActivityState::IsAudible);
1708 if (flagsToUpdate & ActivityState::IsLoading && m_pageLoadState.isLoading())
1709 m_activityState.add(ActivityState::IsLoading);
1710 if (flagsToUpdate & ActivityState::IsCapturingMedia && m_mediaState & (MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice))
1711 m_activityState.add(ActivityState::IsCapturingMedia);
1714 void WebPageProxy::activityStateDidChange(OptionSet<ActivityState::Flag> mayHaveChanged, bool wantsSynchronousReply, ActivityStateChangeDispatchMode dispatchMode)
1716 LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " activityStateDidChange - mayHaveChanged " << mayHaveChanged);
1718 m_potentiallyChangedActivityStateFlags.add(mayHaveChanged);
1719 m_activityStateChangeWantsSynchronousReply = m_activityStateChangeWantsSynchronousReply || wantsSynchronousReply;
1721 if (m_suppressVisibilityUpdates && dispatchMode != ActivityStateChangeDispatchMode::Immediate)
1725 bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ActivityState::IsInWindow) && pageClient().isViewInWindow();
1726 if (dispatchMode == ActivityStateChangeDispatchMode::Immediate || isNewlyInWindow) {
1727 dispatchActivityStateChange();
1730 m_activityStateChangeDispatcher->schedule();
1732 UNUSED_PARAM(dispatchMode);
1733 dispatchActivityStateChange();
1737 void WebPageProxy::viewDidLeaveWindow()
1739 closeOverlayedViews();
1740 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
1741 // When leaving the current page, close the video fullscreen.
1742 if (m_videoFullscreenManager && m_videoFullscreenManager->hasMode(WebCore::HTMLMediaElementEnums::VideoFullscreenModeStandard))
1743 m_videoFullscreenManager->requestHideAndExitFullscreen();
1747 void WebPageProxy::viewDidEnterWindow()
1749 LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1750 if (m_layerHostingMode != layerHostingMode) {
1751 m_layerHostingMode = layerHostingMode;
1752 m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1756 void WebPageProxy::dispatchActivityStateChange()
1759 m_activityStateChangeDispatcher->invalidate();
1762 if (!hasRunningProcess())
1765 LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange - potentiallyChangedActivityStateFlags " << m_potentiallyChangedActivityStateFlags);
1767 // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1768 if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible)
1769 m_potentiallyChangedActivityStateFlags.add({ ActivityState::IsVisibleOrOccluded, ActivityState::IsVisuallyIdle });
1771 // Record the prior view state, update the flags that may have changed,
1772 // and check which flags have actually changed.
1773 auto previousActivityState = m_activityState;
1774 updateActivityState(m_potentiallyChangedActivityStateFlags);
1775 auto changed = m_activityState ^ previousActivityState;
1778 LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange: state changed from " << previousActivityState << " to " << m_activityState);
1780 if ((changed & ActivityState::WindowIsActive) && isViewWindowActive())
1781 updateCurrentModifierState();
1783 if ((m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible) && isViewVisible())
1784 viewIsBecomingVisible();
1786 bool isNowInWindow = (changed & ActivityState::IsInWindow) && isInWindow();
1787 // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
1788 if (m_viewWasEverInWindow && isNowInWindow) {
1789 if (m_drawingArea->hasVisibleContent() && m_waitsForPaintAfterViewDidMoveToWindow && !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
1790 m_activityStateChangeWantsSynchronousReply = true;
1791 m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
1794 // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
1795 if (!(m_activityState & ActivityState::IsVisible))
1796 m_activityStateChangeWantsSynchronousReply = false;
1798 auto activityStateChangeID = m_activityStateChangeWantsSynchronousReply ? takeNextActivityStateChangeID() : static_cast<ActivityStateChangeID>(ActivityStateChangeAsynchronous);
1800 if (changed || activityStateChangeID != ActivityStateChangeAsynchronous || !m_nextActivityStateChangeCallbacks.isEmpty())
1801 m_process->send(Messages::WebPage::SetActivityState(m_activityState, activityStateChangeID, m_nextActivityStateChangeCallbacks), m_pageID);
1803 m_nextActivityStateChangeCallbacks.clear();
1805 // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
1806 updateThrottleState();
1808 #if ENABLE(POINTER_LOCK)
1809 if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !pageClient().isViewWindowActive())
1810 || ((changed & ActivityState::IsFocused) && !(m_activityState & ActivityState::IsFocused)))
1811 requestPointerUnlock();
1814 if (changed & ActivityState::IsVisible) {
1815 if (isViewVisible())
1816 m_visiblePageToken = m_process->visiblePageToken();
1818 m_visiblePageToken = nullptr;
1820 // If we've started the responsiveness timer as part of telling the web process to update the backing store
1821 // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1822 // stop the unresponsiveness timer here.
1823 m_process->responsivenessTimer().stop();
1827 if (changed & ActivityState::IsInWindow) {
1829 viewDidEnterWindow();
1831 viewDidLeaveWindow();
1834 updateBackingStoreDiscardableState();
1836 if (activityStateChangeID != ActivityStateChangeAsynchronous)
1837 waitForDidUpdateActivityState(activityStateChangeID);
1839 m_potentiallyChangedActivityStateFlags = { };
1840 m_activityStateChangeWantsSynchronousReply = false;
1841 m_viewWasEverInWindow |= isNowInWindow;
1844 bool WebPageProxy::isAlwaysOnLoggingAllowed() const
1846 return sessionID().isAlwaysOnLoggingAllowed();
1849 void WebPageProxy::updateThrottleState()
1851 bool processSuppressionEnabled = m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
1853 // If process suppression is not enabled take a token on the process pool to disable suppression of support processes.
1854 if (!processSuppressionEnabled)
1855 m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
1856 else if (!m_preventProcessSuppressionCount)
1857 m_preventProcessSuppressionCount = nullptr;
1859 if (m_activityState & ActivityState::IsVisuallyIdle)
1860 m_pageIsUserObservableCount = nullptr;
1861 else if (!m_pageIsUserObservableCount)
1862 m_pageIsUserObservableCount = m_process->processPool().userObservablePageCount();
1864 #if PLATFORM(IOS_FAMILY)
1865 bool isCapturingMedia = m_activityState.contains(ActivityState::IsCapturingMedia);
1866 bool isAudible = m_activityState.contains(ActivityState::IsAudible);
1867 if (!isViewVisible() && !m_alwaysRunsAtForegroundPriority && !isCapturingMedia && !isAudible) {
1868 if (m_activityToken) {
1869 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is releasing a foreground assertion because the view is no longer visible");
1870 m_activityToken = nullptr;
1872 } else if (!m_activityToken) {
1873 if (isViewVisible())
1874 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion because the view is visible");
1876 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion because we are playing audio");
1877 else if (isCapturingMedia)
1878 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion because media capture is active");
1880 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion even though the view is not visible because m_alwaysRunsAtForegroundPriority is true");
1881 m_activityToken = m_process->throttler().foregroundActivityToken();
1886 void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
1888 if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
1889 m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
1890 else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
1891 m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
1894 void WebPageProxy::layerHostingModeDidChange()
1896 LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1897 if (m_layerHostingMode == layerHostingMode)
1900 m_layerHostingMode = layerHostingMode;
1902 if (hasRunningProcess())
1903 m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1906 void WebPageProxy::waitForDidUpdateActivityState(ActivityStateChangeID activityStateChangeID)
1908 if (!hasRunningProcess())
1911 if (m_process->state() != WebProcessProxy::State::Running)
1914 // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1915 if (m_waitingForDidUpdateActivityState)
1918 #if PLATFORM(IOS_FAMILY)
1919 // Hail Mary check. Should not be possible (dispatchActivityStateChange should force async if not visible,
1920 // and if visible we should be holding an assertion) - but we should never block on a suspended process.
1921 if (!m_activityToken) {
1922 ASSERT_NOT_REACHED();
1927 m_waitingForDidUpdateActivityState = true;
1929 m_drawingArea->waitForDidUpdateActivityState(activityStateChangeID);
1932 IntSize WebPageProxy::viewSize() const
1934 return pageClient().viewSize();
1937 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
1939 if (!hasRunningProcess()) {
1940 callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
1944 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1945 m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent, callbackID), m_pageID);
1948 void WebPageProxy::clearSelection()
1950 if (!hasRunningProcess())
1952 m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1955 void WebPageProxy::restoreSelectionInFocusedEditableElement()
1957 if (!hasRunningProcess())
1959 m_process->send(Messages::WebPage::RestoreSelectionInFocusedEditableElement(), m_pageID);
1962 void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&& callbackFunction)
1964 if (!hasRunningProcess()) {
1965 callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1969 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1970 m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1973 void WebPageProxy::increaseListLevel()
1975 if (!hasRunningProcess())
1978 m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
1981 void WebPageProxy::decreaseListLevel()
1983 if (!hasRunningProcess())
1986 m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
1989 void WebPageProxy::changeListType()
1991 if (!hasRunningProcess())
1994 m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
1997 void WebPageProxy::setBaseWritingDirection(WritingDirection direction)
1999 if (!hasRunningProcess())
2002 m_process->send(Messages::WebPage::SetBaseWritingDirection(direction), m_pageID);
2005 void WebPageProxy::updateFontAttributesAfterEditorStateChange()
2007 m_cachedFontAttributesAtSelectionStart.reset();
2009 if (m_editorState.isMissingPostLayoutData)
2012 if (auto fontAttributes = m_editorState.postLayoutData().fontAttributes) {
2013 m_uiClient->didChangeFontAttributes(*fontAttributes);
2014 m_cachedFontAttributesAtSelectionStart = WTFMove(fontAttributes);
2018 void WebPageProxy::setNeedsFontAttributes(bool needsFontAttributes)
2020 if (m_needsFontAttributes == needsFontAttributes)
2023 m_needsFontAttributes = needsFontAttributes;
2025 if (hasRunningProcess())
2026 m_process->send(Messages::WebPage::SetNeedsFontAttributes(needsFontAttributes), m_pageID);
2029 bool WebPageProxy::maintainsInactiveSelection() const
2031 // Regardless of what the client wants to do, keep selections if a local Inspector is open.
2032 // Otherwise, there is no way to use the console to inspect the state of a selection.
2033 if (inspector() && inspector()->isVisible())
2036 return m_maintainsInactiveSelection;
2039 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
2041 m_maintainsInactiveSelection = newValue;
2044 void WebPageProxy::scheduleFullEditorStateUpdate()
2046 if (!hasRunningProcess())
2049 m_process->send(Messages::WebPage::ScheduleFullEditorStateUpdate(), m_pageID);
2052 void WebPageProxy::selectAll()
2054 if (!hasRunningProcess())
2057 m_process->send(Messages::WebPage::SelectAll(), m_pageID);
2060 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
2062 if (!hasRunningProcess()) {
2063 callbackFunction(CallbackBase::Error::Unknown);
2067 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2068 m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, argument, callbackID), m_pageID);
2071 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
2073 static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
2075 if (!hasRunningProcess())
2078 if (commandName == ignoreSpellingCommandName)
2079 ++m_pendingLearnOrIgnoreWordMessageCount;
2081 m_process->send(Messages::WebPage::ExecuteEditCommand(commandName, argument), m_pageID);
2084 void WebPageProxy::requestFontAttributesAtSelectionStart(Function<void(const WebCore::FontAttributes&, CallbackBase::Error)>&& callback)
2086 if (!hasRunningProcess()) {
2087 callback({ }, CallbackBase::Error::Unknown);
2091 auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
2092 m_process->send(Messages::WebPage::RequestFontAttributesAtSelectionStart(callbackID), m_pageID);
2095 void WebPageProxy::fontAttributesCallback(const WebCore::FontAttributes& attributes, CallbackID callbackID)
2097 m_cachedFontAttributesAtSelectionStart = attributes;
2099 if (auto callback = m_callbacks.take<FontAttributesCallback>(callbackID))
2100 callback->performCallbackWithReturnValue(attributes);
2103 void WebPageProxy::setEditable(bool editable)
2105 if (editable == m_isEditable)
2108 m_isEditable = editable;
2110 if (!hasRunningProcess())
2113 m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
2116 void WebPageProxy::setMediaStreamCaptureMuted(bool muted)
2119 setMuted(m_mutedState | WebCore::MediaProducer::MediaStreamCaptureIsMuted);
2121 setMuted(m_mutedState & ~WebCore::MediaProducer::MediaStreamCaptureIsMuted);
2124 void WebPageProxy::activateMediaStreamCaptureInPage()
2126 #if ENABLE(MEDIA_STREAM)
2127 UserMediaProcessManager::singleton().muteCaptureMediaStreamsExceptIn(*this);
2129 setMuted(m_mutedState & ~WebCore::MediaProducer::MediaStreamCaptureIsMuted);
2132 #if !PLATFORM(IOS_FAMILY)
2133 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
2137 void WebPageProxy::layerTreeCommitComplete()
2142 #if ENABLE(DRAG_SUPPORT)
2143 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
2145 performDragControllerAction(DragControllerAction::Entered, dragData, dragStorageName, { }, { });
2148 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
2150 performDragControllerAction(DragControllerAction::Updated, dragData, dragStorageName, { }, { });
2153 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
2155 performDragControllerAction(DragControllerAction::Exited, dragData, dragStorageName, { }, { });
2158 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2160 performDragControllerAction(DragControllerAction::PerformDragOperation, dragData, dragStorageName, WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload));
2163 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2165 if (!hasRunningProcess())
2168 UNUSED_PARAM(dragStorageName);
2169 UNUSED_PARAM(sandboxExtensionHandle);
2170 UNUSED_PARAM(sandboxExtensionsForUpload);
2172 String url = dragData.asURL();
2174 m_process->assumeReadAccessToBaseURL(*this, url);
2176 ASSERT(dragData.platformData());
2177 WebSelectionData selection(*dragData.platformData());
2178 m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), selection, dragData.flags()), m_pageID);
2180 m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
2184 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect, const IntRect& editableElementRect)
2186 MESSAGE_CHECK(m_process, dragOperation <= DragOperationDelete);
2188 m_currentDragOperation = static_cast<DragOperation>(dragOperation);
2189 m_currentDragHandlingMethod = dragHandlingMethod;
2190 m_currentDragIsOverFileInput = mouseIsOverFileInput;
2191 m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
2192 m_currentDragCaretEditableElementRect = editableElementRect;
2193 setDragCaretRect(insertionRect);
2197 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
2199 RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
2200 pageClient().startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
2206 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
2208 if (!hasRunningProcess())
2210 m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
2211 setDragCaretRect({ });
2214 void WebPageProxy::didPerformDragOperation(bool handled)
2216 pageClient().didPerformDragOperation(handled);
2219 void WebPageProxy::didStartDrag()
2221 if (hasRunningProcess())
2222 m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
2225 void WebPageProxy::dragCancelled()
2227 if (hasRunningProcess())
2228 m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
2231 void WebPageProxy::didEndDragging()
2233 resetCurrentDragInformation();
2236 void WebPageProxy::resetCurrentDragInformation()
2238 m_currentDragOperation = WebCore::DragOperationNone;
2239 m_currentDragHandlingMethod = DragHandlingMethod::None;
2240 m_currentDragIsOverFileInput = false;
2241 m_currentDragNumberOfFilesToBeAccepted = 0;
2242 setDragCaretRect({ });
2245 #if !ENABLE(DATA_INTERACTION)
2247 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
2249 m_currentDragCaretRect = dragCaretRect;
2254 #endif // ENABLE(DRAG_SUPPORT)
2256 static bool removeOldRedundantEvent(Deque<NativeWebMouseEvent>& queue, WebEvent::Type incomingEventType)
2258 if (incomingEventType != WebEvent::MouseMove && incomingEventType != WebEvent::MouseForceChanged)
2261 auto it = queue.rbegin();
2262 auto end = queue.rend();
2264 // Must not remove the first event in the deque, since it is already being dispatched.
2268 for (; it != end; ++it) {
2269 auto type = it->type();
2270 if (type == incomingEventType) {
2271 queue.remove(--it.base());
2274 if (type != WebEvent::MouseMove && type != WebEvent::MouseForceChanged)
2280 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
2282 if (!hasRunningProcess())
2285 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2286 if (m_scrollingCoordinatorProxy)
2287 m_scrollingCoordinatorProxy->handleMouseEvent(platform(event));
2290 // If we receive multiple mousemove or mouseforcechanged events and the most recent mousemove or mouseforcechanged event
2291 // (respectively) has not yet been sent to WebProcess for processing, remove the pending mouse event and insert the new
2292 // event in the queue.
2293 bool didRemoveEvent = removeOldRedundantEvent(m_mouseEventQueue, event.type());
2294 m_mouseEventQueue.append(event);
2297 UNUSED_PARAM(didRemoveEvent);
2299 LOG(MouseHandling, "UIProcess: %s mouse event %s (queue size %zu)", didRemoveEvent ? "replaced" : "enqueued", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2302 if (m_mouseEventQueue.size() == 1) // Otherwise, called from DidReceiveEvent message handler.
2303 processNextQueuedMouseEvent();
2306 void WebPageProxy::processNextQueuedMouseEvent()
2308 if (!hasRunningProcess())
2311 ASSERT(!m_mouseEventQueue.isEmpty());
2313 const NativeWebMouseEvent& event = m_mouseEventQueue.first();
2315 if (pageClient().windowIsFrontWindowUnderMouse(event))
2316 setToolTip(String());
2318 WebEvent::Type eventType = event.type();
2319 if (eventType == WebEvent::MouseDown || eventType == WebEvent::MouseForceChanged || eventType == WebEvent::MouseForceDown)
2320 m_process->responsivenessTimer().startWithLazyStop();
2321 else if (eventType != WebEvent::MouseMove) {
2322 // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
2323 m_process->responsivenessTimer().start();
2326 LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(eventType), m_mouseEventQueue.size());
2327 m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
2330 #if MERGE_WHEEL_EVENTS
2331 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2333 if (a.position() != b.position())
2335 if (a.globalPosition() != b.globalPosition())
2337 if (a.modifiers() != b.modifiers())
2339 if (a.granularity() != b.granularity())
2342 if (a.phase() != b.phase())
2344 if (a.momentumPhase() != b.momentumPhase())
2346 if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
2353 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2355 ASSERT(canCoalesce(a, b));
2357 FloatSize mergedDelta = a.delta() + b.delta();
2358 FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
2361 FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
2363 return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.directionInvertedFromDevice(), b.phase(), b.momentumPhase(), b.hasPreciseScrollingDeltas(), b.scrollCount(), mergedUnacceleratedScrollingDelta, b.modifiers(), b.timestamp());
2365 return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
2368 #endif // MERGE_WHEEL_EVENTS
2370 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
2372 ASSERT(!queue.isEmpty());
2373 ASSERT(coalescedEvents.isEmpty());
2375 #if MERGE_WHEEL_EVENTS
2376 NativeWebWheelEvent firstEvent = queue.takeFirst();
2377 coalescedEvents.append(firstEvent);
2379 WebWheelEvent event = firstEvent;
2380 while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
2381 NativeWebWheelEvent firstEvent = queue.takeFirst();
2382 coalescedEvents.append(firstEvent);
2383 event = coalesce(event, firstEvent);
2388 while (!queue.isEmpty())
2389 coalescedEvents.append(queue.takeFirst());
2390 return coalescedEvents.last();
2394 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
2396 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2397 if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
2401 if (!hasRunningProcess())
2404 closeOverlayedViews();
2406 if (!m_currentlyProcessedWheelEvents.isEmpty()) {
2407 m_wheelEventQueue.append(event);
2408 if (!shouldProcessWheelEventNow(event))
2410 // The queue has too many wheel events, so push a new event.
2413 if (!m_wheelEventQueue.isEmpty()) {
2414 processNextQueuedWheelEvent();
2418 auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2419 coalescedWheelEvent->append(event);
2420 m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
2421 sendWheelEvent(event);
2424 void WebPageProxy::processNextQueuedWheelEvent()
2426 auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2427 WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
2428 m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
2429 sendWheelEvent(nextWheelEvent);
2432 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
2435 Messages::EventDispatcher::WheelEvent(
2438 shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
2439 shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
2441 rubberBandsAtBottom()
2444 // Manually ping the web process to check for responsiveness since our wheel
2445 // event will dispatch to a non-main thread, which always responds.
2446 m_process->isResponsiveWithLazyStop();
2449 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
2452 // Don't queue events representing a non-trivial scrolling phase to
2453 // avoid having them trapped in the queue, potentially preventing a
2454 // scrolling session to beginning or end correctly.
2455 // This is only needed by platforms whose WebWheelEvent has this phase
2456 // information (Cocoa and GTK+) but Cocoa was fine without it.
2457 if (event.phase() == WebWheelEvent::Phase::PhaseNone
2458 || event.phase() == WebWheelEvent::Phase::PhaseChanged
2459 || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
2460 || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
2463 UNUSED_PARAM(event);
2465 if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
2470 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
2472 if (!hasRunningProcess())
2475 LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
2477 m_keyEventQueue.append(event);
2479 ResponsivenessTimer& responsivenessTimer = m_process->responsivenessTimer();
2480 if (event.type() == WebEvent::KeyDown)
2481 responsivenessTimer.startWithLazyStop();
2483 responsivenessTimer.start();
2485 if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
2486 LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
2487 m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2491 WebPreferencesStore WebPageProxy::preferencesStore() const
2493 if (m_configurationPreferenceValues.isEmpty())
2494 return m_preferences->store();
2496 WebPreferencesStore store = m_preferences->store();
2497 for (const auto& preference : m_configurationPreferenceValues)
2498 store.m_values.set(preference.key, preference.value);
2503 #if ENABLE(NETSCAPE_PLUGIN_API)
2504 void WebPageProxy::findPlugin(const String& mimeType, uint32_t processType, const String& urlString, const String& frameURLString, const String& pageURLString, bool allowOnlyApplicationPlugins, Messages::WebPageProxy::FindPlugin::DelayedReply&& reply)
2506 PageClientProtector protector(pageClient());
2508 MESSAGE_CHECK_URL(m_process, urlString);
2510 URL pluginURL = URL { URL(), urlString };
2511 String newMimeType = mimeType.convertToASCIILowercase();
2513 PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2515 URL pageURL = URL { URL(), pageURLString };
2516 if (!m_process->processPool().pluginInfoStore().isSupportedPlugin(mimeType, pluginURL, frameURLString, pageURL)) {
2517 reply(0, newMimeType, PluginModuleLoadNormally, { }, true);
2521 PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, pluginURL, allowedPluginTypes);
2523 reply(0, newMimeType, PluginModuleLoadNormally, { }, false);
2527 uint32_t pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2530 auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2533 auto findPluginCompletion = [processType, reply = WTFMove(reply), newMimeType = WTFMove(newMimeType), plugin = WTFMove(plugin)] (uint32_t pluginLoadPolicy, const String& unavailabilityDescription) mutable {
2534 PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2535 switch (pluginLoadPolicy) {
2536 case PluginModuleLoadNormally:
2537 pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2539 case PluginModuleLoadUnsandboxed:
2540 pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2543 case PluginModuleBlockedForSecurity:
2544 case PluginModuleBlockedForCompatibility:
2545 reply(0, newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2549 reply(PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy), newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2553 m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), WTFMove(findPluginCompletion));
2555 findPluginCompletion(pluginLoadPolicy, { });
2559 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2561 #if ENABLE(TOUCH_EVENTS)
2563 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2565 if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2570 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2572 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2573 const EventNames& names = eventNames();
2574 for (auto& touchPoint : touchStartEvent.touchPoints()) {
2575 IntPoint location = touchPoint.location();
2576 auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomString& eventName) {
2577 if (trackingType == TrackingType::Synchronous)
2580 TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2582 trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2584 updateTrackingType(m_touchAndPointerEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2585 updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.touchstartEvent);
2586 updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.touchmoveEvent);
2587 updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.touchendEvent);
2588 updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointeroverEvent);
2589 updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointerenterEvent);
2590 updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointerdownEvent);
2591 updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.pointermoveEvent);
2592 updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointerupEvent);
2593 updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointeroutEvent);
2594 updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointerleaveEvent);
2595 updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.mousedownEvent);
2596 updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.mousemoveEvent);
2597 updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.mouseupEvent);
2600 UNUSED_PARAM(touchStartEvent);
2601 m_touchAndPointerEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2602 m_touchAndPointerEventTracking.touchStartTracking = TrackingType::Synchronous;
2603 m_touchAndPointerEventTracking.touchMoveTracking = TrackingType::Synchronous;
2604 m_touchAndPointerEventTracking.touchEndTracking = TrackingType::Synchronous;
2605 #endif // ENABLE(ASYNC_SCROLLING)
2608 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2610 // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2612 // Touch events define a sequence with strong dependencies. For example, we can expect
2613 // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2616 // WebCore should not have to set up its state correctly after some events were dismissed.
2617 // For example, we don't want to send a TouchMoved without a TouchPressed.
2618 // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2619 TrackingType globalTrackingType = m_touchAndPointerEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2621 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchForceChangedTracking);
2622 for (auto& touchPoint : touchStartEvent.touchPoints()) {
2623 switch (touchPoint.state()) {
2624 case WebPlatformTouchPoint::TouchReleased:
2625 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchEndTracking);
2627 case WebPlatformTouchPoint::TouchPressed:
2628 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchStartTracking);
2630 case WebPlatformTouchPoint::TouchMoved:
2631 case WebPlatformTouchPoint::TouchStationary:
2632 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchMoveTracking);
2634 case WebPlatformTouchPoint::TouchCancelled:
2635 globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2640 return globalTrackingType;
2645 #if ENABLE(MAC_GESTURE_EVENTS)
2646 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2648 if (!hasRunningProcess())
2651 m_gestureEventQueue.append(event);
2652 // FIXME: Consider doing some coalescing here.
2654 ResponsivenessTimer& responsivenessTimer = m_process->responsivenessTimer();
2655 if (event.type() == WebEvent::GestureStart || event.type() == WebEvent::GestureChange)
2656 responsivenessTimer.startWithLazyStop();
2658 responsivenessTimer.start();
2660 m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2664 #if ENABLE(IOS_TOUCH_EVENTS)
2665 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2667 if (!hasRunningProcess())
2670 TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2672 updateTouchEventTracking(event);
2674 TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2675 if (touchEventsTrackingType == TrackingType::NotTracking)
2678 if (touchEventsTrackingType == TrackingType::Asynchronous) {
2679 // We can end up here if a native gesture has not started but the event handlers are passive.
2681 // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2682 // can prevent a native gesture.
2683 // But, here we know that all events handlers that can handle this events are passive.
2684 // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2685 event.setCanPreventNativeGestures(false);
2686 handleTouchEventAsynchronously(event);
2687 didReceiveEvent(event.type(), false);
2691 m_process->responsivenessTimer().start();
2692 bool handled = false;
2693 bool replyReceived = m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID, 1_s, IPC::SendSyncOption::ForceDispatchWhenDestinationIsWaitingForUnboundedSyncReply);
2694 // If the sync request has timed out, we should consider the event handled. The Web Process is too busy to answer any questions, so the default action is also likely to have issues.
2697 didReceiveEvent(event.type(), handled);
2698 pageClient().doneWithTouchEvent(event, handled);
2699 m_process->responsivenessTimer().stop();
2701 if (event.allTouchPointsAreReleased()) {
2702 m_touchAndPointerEventTracking.reset();
2703 didReleaseAllTouchPoints();
2707 void WebPageProxy::resetPotentialTapSecurityOrigin()
2709 if (!hasRunningProcess())
2712 m_process->send(Messages::WebPage::ResetPotentialTapSecurityOrigin(), m_pageID);
2715 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2717 if (!hasRunningProcess())
2720 TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2721 if (touchEventsTrackingType == TrackingType::NotTracking)
2724 m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2726 if (event.allTouchPointsAreReleased()) {
2727 m_touchAndPointerEventTracking.reset();
2728 didReleaseAllTouchPoints();
2732 #elif ENABLE(TOUCH_EVENTS)
2733 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2735 if (!hasRunningProcess())
2738 updateTouchEventTracking(event);
2740 if (touchEventTrackingType(event) == TrackingType::NotTracking)
2743 // If the page is suspended, which should be the case during panning, pinching
2744 // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2745 // we do not send any of the events to the page even if is has listeners.
2746 if (!m_isPageSuspended) {
2747 m_touchEventQueue.append(event);
2748 m_process->responsivenessTimer().start();
2749 m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2751 if (m_touchEventQueue.isEmpty()) {
2752 bool isEventHandled = false;
2753 pageClient().doneWithTouchEvent(event, isEventHandled);
2755 // We attach the incoming events to the newest queued event so that all
2756 // the events are delivered in the correct order when the event is dequed.
2757 QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2758 lastEvent.deferredTouchEvents.append(event);
2762 if (event.allTouchPointsAreReleased()) {
2763 m_touchAndPointerEventTracking.reset();
2764 didReleaseAllTouchPoints();
2767 #endif // ENABLE(TOUCH_EVENTS)
2769 #if ENABLE(POINTER_EVENTS)
2770 void WebPageProxy::cancelPointer(WebCore::PointerID pointerId, const WebCore::IntPoint& documentPoint)
2772 m_process->send(Messages::WebPage::CancelPointer(pointerId, documentPoint), m_pageID);
2775 void WebPageProxy::touchWithIdentifierWasRemoved(WebCore::PointerID pointerId)
2777 m_process->send(Messages::WebPage::TouchWithIdentifierWasRemoved(pointerId), m_pageID);
2781 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2783 if (!hasRunningProcess())
2786 m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2789 void WebPageProxy::centerSelectionInVisibleArea()
2791 if (!hasRunningProcess())
2794 m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2797 class WebPageProxy::PolicyDecisionSender : public RefCounted<PolicyDecisionSender> {
2799 using SendFunction = CompletionHandler<void(PolicyCheckIdentifier, PolicyAction, uint64_t newNavigationID, DownloadID, Optional<WebsitePoliciesData>)>;
2801 static Ref<PolicyDecisionSender> create(PolicyCheckIdentifier identifier, SendFunction&& sendFunction)
2803 return adoptRef(*new PolicyDecisionSender(identifier, WTFMove(sendFunction)));
2806 template<typename... Args> void send(Args... args)
2809 m_sendFunction(m_identifier, std::forward<Args>(args)...);
2812 PolicyDecisionSender(PolicyCheckIdentifier identifier, SendFunction sendFunction)
2813 : m_sendFunction(WTFMove(sendFunction))
2814 , m_identifier(identifier)
2817 SendFunction m_sendFunction;
2818 PolicyCheckIdentifier m_identifier;
2821 void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, API::Navigation* navigation, ProcessSwapRequestedByClient processSwapRequestedByClient, WebFrameProxy& frame, API::WebsitePolicies* policies, Ref<PolicyDecisionSender>&& sender)
2823 Ref<WebsiteDataStore> websiteDataStore = m_websiteDataStore.copyRef();
2824 Optional<WebsitePoliciesData> data;
2826 data = policies->data();
2827 if (policies->websiteDataStore() && &policies->websiteDataStore()->websiteDataStore() != websiteDataStore.ptr()) {
2828 websiteDataStore = policies->websiteDataStore()->websiteDataStore();
2829 processSwapRequestedByClient = ProcessSwapRequestedByClient::Yes;
2833 if (navigation && !navigation->userContentExtensionsEnabled()) {
2835 data = WebsitePoliciesData { };
2836 data->contentBlockersEnabled = false;
2839 #if ENABLE(DEVICE_ORIENTATION)
2840 if (navigation && (!data || data->deviceOrientationAndMotionAccessState == WebCore::DeviceOrientationOrMotionPermissionState::Prompt)) {
2841 auto deviceOrientationPermission = websiteDataStore->deviceOrientationAndMotionAccessController().cachedDeviceOrientationPermission(SecurityOriginData::fromURL(navigation->currentRequest().url()));
2842 if (deviceOrientationPermission != WebCore::DeviceOrientationOrMotionPermissionState::Prompt) {
2844 data = WebsitePoliciesData { };
2845 data->deviceOrientationAndMotionAccessState = deviceOrientationPermission;
2851 static const bool forceDownloadFromDownloadAttribute = false;
2853 static const bool forceDownloadFromDownloadAttribute = true;
2855 if (policyAction == PolicyAction::Use && navigation && (navigation->isSystemPreview() || (forceDownloadFromDownloadAttribute && navigation->shouldPerformDownload())))
2856 policyAction = PolicyAction::Download;
2858 if (policyAction != PolicyAction::Use || !frame.isMainFrame() || !navigation) {
2859 receivedPolicyDecision(policyAction, navigation, WTFMove(data), WTFMove(sender));
2863 Ref<WebProcessProxy> sourceProcess = process();
2864 URL sourceURL = URL { URL(), pageLoadState().url() };
2865 if (auto* provisionalPage = provisionalPageProxy()) {
2866 if (provisionalPage->navigationID() == navigation->navigationID()) {
2867 sourceProcess = provisionalPage->process();
2868 sourceURL = provisionalPage->provisionalURL();
2872 process().processPool().processForNavigation(*this, *navigation, sourceProcess.copyRef(), sourceURL, processSwapRequestedByClient, WTFMove(websiteDataStore), [this, protectedThis = makeRef(*this), policyAction, navigation = makeRef(*navigation), sourceProcess = sourceProcess.copyRef(),
2873 data = WTFMove(data), sender = WTFMove(sender), processSwapRequestedByClient] (Ref<WebProcessProxy>&& processForNavigation, SuspendedPageProxy* destinationSuspendedPage, const String& reason) mutable {
2874 // If the navigation has been destroyed, then no need to proceed.
2875 if (isClosed() || !navigationState().hasNavigation(navigation->navigationID())) {
2876 receivedPolicyDecision(policyAction, navigation.ptr(), WTFMove(data), WTFMove(sender));
2880 bool shouldProcessSwap = processForNavigation.ptr() != sourceProcess.ptr();
2881 if (shouldProcessSwap) {
2882 policyAction = PolicyAction::StopAllLoads;
2883 RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction, swapping process %i with process %i for navigation, reason: %{public}s", processIdentifier(), processForNavigation->processIdentifier(), reason.utf8().data());
2884 LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), processForNavigation->processIdentifier(), navigation->navigationID(), navigation->loggingString());
2886 RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction: keep using process %i for navigation, reason: %{public}s", processIdentifier(), reason.utf8().data());
2888 if (shouldProcessSwap) {
2889 // FIXME: Architecturally we do not currently support multiple WebPage's with the same ID in a given WebProcess.
2890 // In the case where the destination WebProcess has a SuspendedPageProxy for this WebPage, we should have thrown
2891 // it away to support WebProcess re-use.
2892 ASSERT(destinationSuspendedPage || !process().processPool().hasSuspendedPageFor(processForNavigation, *this));
2894 auto suspendedPage = destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr;
2895 if (suspendedPage && suspendedPage->pageIsClosedOrClosing())
2896 suspendedPage = nullptr;
2898 continueNavigationInNewProcess(navigation, WTFMove(suspendedPage), WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
2901 receivedPolicyDecision(policyAction, navigation.ptr(), shouldProcessSwap ? WTF::nullopt : WTFMove(data), WTFMove(sender), shouldProcessSwap ? WillContinueLoadInNewProcess::Yes : WillContinueLoadInNewProcess::No);
2905 void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, Optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender, WillContinueLoadInNewProcess willContinueLoadInNewProcess)
2907 if (!hasRunningProcess()) {
2908 sender->send(PolicyAction::Ignore, 0, DownloadID(), WTF::nullopt);
2912 auto transaction = m_pageLoadState.transaction();
2914 if (action == PolicyAction::Ignore && willContinueLoadInNewProcess == WillContinueLoadInNewProcess::No && navigation && navigation->navigationID() == m_pageLoadState.pendingAPIRequest().navigationID)
2915 m_pageLoadState.clearPendingAPIRequest(transaction);
2917 DownloadID downloadID = { };
2918 if (action == PolicyAction::Download) {
2919 // Create a download proxy.
2920 auto& download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
2922 download.setWasUserInitiated(navigation->wasUserInitiated());
2923 download.setRedirectChain(navigation->takeRedirectChain());
2926 downloadID = download.downloadID();
2927 handleDownloadRequest(download);
2928 m_decidePolicyForResponseRequest = { };
2931 sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
2934 void WebPageProxy::commitProvisionalPage(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData& userData)
2936 ASSERT(m_provisionalPage);
2937 RELEASE_LOG_IF_ALLOWED(Loading, "commitProvisionalPage: previousPID = %i, newPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_provisionalPage->process().processIdentifier(), m_pageID.toUInt64());
2939 Optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? makeOptional(m_mainFrame->frameID()) : WTF::nullopt;
2941 ASSERT(m_process.ptr() != &m_provisionalPage->process());
2943 auto shouldDelayClosingUntilEnteringAcceleratedCompositingMode = ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::No;
2945 // On macOS, when not using UI-side compositing, we need to make sure we do not close the page in the previous process until we've
2946 // entered accelerated compositing for the new page or we will flash on navigation.
2947 if (drawingArea()->type() == DrawingAreaTypeTiledCoreAnimation)
2948 shouldDelayClosingUntilEnteringAcceleratedCompositingMode = ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::Yes;
2951 processDidTerminate(ProcessTerminationReason::NavigationSwap);
2953 m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
2954 auto* navigation = navigationState().navigation(m_provisionalPage->navigationID());
2955 bool didSuspendPreviousPage = navigation ? suspendCurrentPageIfPossible(*navigation, mainFrameIDInPreviousProcess, m_provisionalPage->processSwapRequestedByClient(), shouldDelayClosingUntilEnteringAcceleratedCompositingMode) : false;
2956 m_process->removeWebPage(*this, m_websiteDataStore.ptr() == &m_provisionalPage->process().websiteDataStore() ? WebProcessProxy::EndsUsingDataStore::No : WebProcessProxy::EndsUsingDataStore::Yes);
2958 // There is no way we'll be able to return to the page in the previous page so close it.
2959 if (!didSuspendPreviousPage)
2960 m_process->send(Messages::WebPage::Close(), pageID());
2962 swapToWebProcess(m_provisionalPage->process(), m_provisionalPage->takeDrawingArea(), m_provisionalPage->mainFrame());
2965 auto accessibilityToken = m_provisionalPage->takeAccessibilityToken();
2966 if (!accessibilityToken.isEmpty())
2967 registerWebProcessAccessibilityToken({ accessibilityToken.data(), accessibilityToken.size() });
2970 didCommitLoadForFrame(frameID, navigationID, mimeType, frameHasCustomContentProvider, frameLoadType, certificateInfo, containsPluginDocument, forcedHasInsecureContent, userData);
2972 m_provisionalPage = nullptr;
2975 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& newProcess, ProcessSwapRequestedByClient processSwapRequestedByClient, Optional<WebsitePoliciesData>&& websitePolicies)
2977 RELEASE_LOG_IF_ALLOWED(Loading, "continueNavigationInNewProcess: webPID = %i, pageID = %" PRIu64 ", newProcessPID = %i, hasSuspendedPage = %i", m_process->processIdentifier(), m_pageID.toUInt64(), newProcess->processIdentifier(), !!suspendedPageProxy);
2978 LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
2980 if (m_provisionalPage) {
2981 RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "continueNavigationInNewProcess: There is already a pending provisional load, cancelling it (provisonalNavigationID: %llu, navigationID: %llu)", m_provisionalPage->navigationID(), navigation.navigationID());
2982 if (m_provisionalPage->navigationID() != navigation.navigationID())
2983 m_provisionalPage->cancel();
2984 m_provisionalPage = nullptr;
2987 m_provisionalPage = std::make_unique<ProvisionalPageProxy>(*this, newProcess.copyRef(), WTFMove(suspendedPageProxy), navigation.navigationID(), navigation.currentRequestIsRedirect(), navigation.currentRequest(), processSwapRequestedByClient);
2989 if (auto* item = navigation.targetItem()) {
2990 LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
2992 auto transaction = m_pageLoadState.transaction();
2993 m_pageLoadState.setPendingAPIRequest(transaction, { navigation.navigationID(), item->url() });
2995 m_provisionalPage->goToBackForwardItem(navigation, *item, WTFMove(websitePolicies));
2999 if (m_backForwardList->currentItem() && (navigation.lockBackForwardList() == LockBackForwardList::Yes || navigation.lockHistory() == LockHistory::Yes)) {
3000 // If WebCore is supposed to lock the history for this load, then the new process needs to know about the current history item so it can update
3001 // it instead of creating a new one.
3002 newProcess->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
3005 // FIXME: Work out timing of responding with the last policy delegate, etc
3006 ASSERT(!navigation.currentRequest().isEmpty());
3007 if (auto& substituteData = navigation.substituteData())
3008 m_provisionalPage->loadData(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get(), WTFMove(websitePolicies));
3010 m_provisionalPage->loadRequest(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, WTFMove(websitePolicies));
3013 bool WebPageProxy::isPageOpenedByDOMShowingInitialEmptyDocument() const
3015 return openedByDOM() && !hasCommittedAnyProvisionalLoads();
3018 // MSVC gives a redeclaration error if noreturn is used on the definition and not the declaration, while
3019 // Cocoa tests segfault if it is moved to the declaration site (even if we move the definition with it!).
3021 NO_RETURN_DUE_TO_ASSERT
3023 void WebPageProxy::didFailToSuspendAfterProcessSwap()
3025 // Only the SuspendedPageProxy should be getting this call.
3026 ASSERT_NOT_REACHED();
3030 NO_RETURN_DUE_TO_ASSERT
3032 void WebPageProxy::didSuspendAfterProcessSwap()
3034 // Only the SuspendedPageProxy should be getting this call.
3035 ASSERT_NOT_REACHED();
3038 void WebPageProxy::setUserAgent(String&& userAgent)
3040 if (m_userAgent == userAgent)
3042 m_userAgent = WTFMove(userAgent);
3044 #if ENABLE(SERVICE_WORKER)
3045 // We update the service worker there at the moment to be sure we use values used by actual web pages.
3046 // FIXME: Refactor this when we have a better User-Agent story.
3047 process().processPool().updateServiceWorkerUserAgent(m_userAgent);
3050 if (!hasRunningProcess())
3052 m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
3055 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
3057 if (m_applicationNameForUserAgent == applicationName)
3060 m_applicationNameForUserAgent = applicationName;
3061 if (!m_customUserAgent.isEmpty())
3064 setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
3067 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
3069 if (m_customUserAgent == customUserAgent)
3072 m_customUserAgent = customUserAgent;
3074 if (m_customUserAgent.isEmpty()) {
3075 setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
3079 setUserAgent(String { m_customUserAgent });
3082 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
3084 if (!hasRunningProcess() || !m_isPageSuspended)
3087 m_isPageSuspended = false;
3089 m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
3092 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
3094 if (!hasRunningProcess() || m_isPageSuspended)
3097 m_isPageSuspended = true;
3099 m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
3102 bool WebPageProxy::supportsTextEncoding() const
3104 // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
3105 return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
3108 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
3110 if (m_customTextEncodingName == encodingName)
3112 m_customTextEncodingName = encodingName;
3114 if (!hasRunningProcess())
3116 m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
3119 SessionState WebPageProxy::sessionState(WTF::Function<bool (WebBackForwardListItem&)>&& filter) const
3121 SessionState sessionState;
3123 sessionState.backForwardListState = m_backForwardList->backForwardListState(WTFMove(filter));
3125 String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
3126 if (provisionalURLString.isEmpty())
3127 provisionalURLString = m_pageLoadState.provisionalURL();
3129 if (!provisionalURLString.isEmpty())
3130 sessionState.provisionalURL = URL(URL(), provisionalURLString);
3132 sessionState.renderTreeSize = renderTreeSize();
3133 return sessionState;
3136 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
3138 RELEASE_LOG_IF_ALLOWED(Loading, "restoreFromSessionState: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID.toUInt64());
3140 m_sessionRestorationRenderTreeSize = 0;
3141 m_hitRenderTreeSizeThreshold = false;
3143 bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
3145 if (hasBackForwardList) {
3146 // If there isn't a running process yet the RestoreSession message below is just ignored, and
3147 // session is restored when the web process is created via creation parameters which is not
3148 // considered an API request. So, we launch the initial process here before restoring the
3149 // session to ensure the session is restored in the web process via RestoreSession IPC message
3150 // which is considered an API request. See https://bugs.webkit.org/show_bug.cgi?id=198561.
3151 launchInitialProcessIfNecessary();
3153 m_backForwardList->restoreFromState(WTFMove(sessionState.backForwardListState));
3154 process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
3156 auto transaction = m_pageLoadState.transaction();
3157 m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
3158 m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
3160 // The back / forward list was restored from a sessionState so we don't want to snapshot the current
3161 // page when navigating away. Suppress navigation snapshotting until the next load has committed
3162 suppressNextAutomaticNavigationSnapshot();
3165 // FIXME: Navigating should be separate from state restoration.
3167 m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
3168 if (!m_sessionRestorationRenderTreeSize)
3169 m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
3171 if (!sessionState.provisionalURL.isNull())
3172 return loadRequest(sessionState.provisionalURL);
3174 if (hasBackForwardList) {
3175 if (WebBackForwardListItem* item = m_backForwardList->currentItem())
3176 return goToBackForwardItem(*item);
3183 bool WebPageProxy::supportsTextZoom() const
3185 // FIXME (118840): This should also return false for standalone media and plug-in documents.
3186 if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
3192 void WebPageProxy::setTextZoomFactor(double zoomFactor)
3194 if (m_textZoomFactor == zoomFactor)
3197 m_textZoomFactor = zoomFactor;
3199 if (!hasRunningProcess())
3202 m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID);
3205 void WebPageProxy::setPageZoomFactor(double zoomFactor)
3207 if (m_pageZoomFactor == zoomFactor)
3210 closeOverlayedViews();
3212 m_pageZoomFactor = zoomFactor;
3214 if (!hasRunningProcess())
3217 m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID);
3220 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
3222 if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
3225 closeOverlayedViews();
3227 m_pageZoomFactor = pageZoomFactor;
3228 m_textZoomFactor = textZoomFactor;
3230 if (!hasRunningProcess())
3233 m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID);
3236 double WebPageProxy::pageZoomFactor() const
3238 // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
3239 // zoom which ensures that we don't use the PDF zoom for a normal page.
3240 if (m_mainFramePluginHandlesPageScaleGesture)
3241 return m_pluginZoomFactor;
3242 return m_pageZoomFactor;
3245 double WebPageProxy::pageScaleFactor() const
3247 // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
3248 // separately but decide which to return based on the main frame.
3249 if (m_mainFramePluginHandlesPageScaleGesture)
3250 return m_pluginScaleFactor;
3251 return m_pageScaleFactor;
3254 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
3258 m_pageScaleFactor = scale;
3260 if (!hasRunningProcess())
3263 m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
3266 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
3270 m_pageScaleFactor = scale;
3272 if (!hasRunningProcess())
3275 m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
3278 void WebPageProxy::scaleView(double scale)
3282 m_viewScaleFactor = scale;
3284 if (!hasRunningProcess())
3287 m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
3290 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
3292 if (m_intrinsicDeviceScaleFactor == scaleFactor)
3295 m_intrinsicDeviceScaleFactor = scaleFactor;
3298 m_drawingArea->deviceScaleFactorDidChange();
3301 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
3303 if (!hasRunningProcess())
3306 m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
3309 float WebPageProxy::deviceScaleFactor() const
3311 return m_customDeviceScaleFactor.valueOr(m_intrinsicDeviceScaleFactor);
3314 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
3316 // FIXME: Remove this once we bump cairo requirements to support HiDPI.
3317 // https://bugs.webkit.org/show_bug.cgi?id=133378
3318 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
3322 if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
3325 float oldScaleFactor = deviceScaleFactor();
3327 // A value of 0 clears the customScaleFactor.
3328 if (customScaleFactor)
3329 m_customDeviceScaleFactor = customScaleFactor;
3331 m_customDeviceScaleFactor = WTF::nullopt;
3333 if (!hasRunningProcess())
3336 if (deviceScaleFactor() != oldScaleFactor)
3337 m_drawingArea->deviceScaleFactorDidChange();
3340 void WebPageProxy::accessibilitySettingsDidChange()
3342 if (!hasRunningProcess())
3345 m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
3348 void WebPageProxy::setUseFixedLayout(bool fixed)
3350 // This check is fine as the value is initialized in the web
3351 // process as part of the creation parameters.
3352 if (fixed == m_useFixedLayout)
3355 m_useFixedLayout = fixed;
3357 m_fixedLayoutSize = IntSize();
3359 if (!hasRunningProcess())
3362 m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
3365 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
3367 if (size == m_fixedLayoutSize)
3370 m_fixedLayoutSize = size;
3372 if (!hasRunningProcess())
3375 m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
3378 void WebPageProxy::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)
3380 if (alwaysShowsHorizontalScroller == m_alwaysShowsHorizontalScroller)
3383 m_alwaysShowsHorizontalScroller = alwaysShowsHorizontalScroller;
3385 if (!hasRunningProcess())
3388 m_process->send(Messages::WebPage::SetAlwaysShowsHorizontalScroller(alwaysShowsHorizontalScroller), m_pageID);
3391 void WebPageProxy::setAlwaysShowsVerticalScroller(bool alwaysShowsVerticalScroller)
3393 if (alwaysShowsVerticalScroller == m_alwaysShowsVerticalScroller)
3396 m_alwaysShowsVerticalScroller = alwaysShowsVerticalScroller;
3398 if (!hasRunningProcess())
3401 m_process->send(Messages::WebPage::SetAlwaysShowsVerticalScroller(alwaysShowsVerticalScroller), m_pageID);
3404 void WebPageProxy::listenForLayoutMilestones(OptionSet<WebCore::LayoutMilestone> milestones)
3406 if (milestones == m_observedLayoutMilestones)
3409 m_observedLayoutMilestones = milestones;
3411 if (!hasRunningProcess())
3414 m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
3417 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
3419 if (suppressAnimations == m_suppressScrollbarAnimations)
3422 m_suppressScrollbarAnimations = suppressAnimations;
3424 if (!hasRunningProcess())
3427 m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
3430 bool WebPageProxy::rubberBandsAtLeft() const
3432 return m_rubberBandsAtLeft;
3435 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
3437 m_rubberBandsAtLeft = rubberBandsAtLeft;
3440 bool WebPageProxy::rubberBandsAtRight() const
3442 return m_rubberBandsAtRight;
3445 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
3447 m_rubberBandsAtRight = rubberBandsAtRight;
3450 bool WebPageProxy::rubberBandsAtTop() const
3452 return m_rubberBandsAtTop;
3455 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
3457 m_rubberBandsAtTop = rubberBandsAtTop;
3460 bool WebPageProxy::rubberBandsAtBottom() const
3462 return m_rubberBandsAtBottom;
3465 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
3467 m_rubberBandsAtBottom = rubberBandsAtBottom;
3470 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
3472 if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
3475 m_enableVerticalRubberBanding = enableVerticalRubberBanding;
3477 if (!hasRunningProcess())
3479 m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
3482 bool WebPageProxy::verticalRubberBandingIsEnabled() const
3484 return m_enableVerticalRubberBanding;
3487 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
3489 if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
3492 m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
3494 if (!hasRunningProcess())
3496 m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
3499 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
3501 return m_enableHorizontalRubberBanding;
3504 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
3506 if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
3509 m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
3511 if (!hasRunningProcess())
3513 m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
3516 bool WebPageProxy::backgroundExtendsBeyondPage() const
3518 return m_backgroundExtendsBeyondPage;
3521 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
3523 if (mode == m_paginationMode)
3526 m_paginationMode = mode;
3528 if (!hasRunningProcess())
3530 m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
3533 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
3535 if (behavesLikeColumns == m_paginationBehavesLikeColumns)
3538 m_paginationBehavesLikeColumns = behavesLikeColumns;
3540 if (!hasRunningProcess())
3542 m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
3545 void WebPageProxy::setPageLength(double pageLength)
3547 if (pageLength == m_pageLength)