2 * Copyright (C) 2010-2018 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 "FrameInfoData.h"
63 #include "LoadParameters.h"
65 #include "NativeWebGestureEvent.h"
66 #include "NativeWebKeyboardEvent.h"
67 #include "NativeWebMouseEvent.h"
68 #include "NativeWebWheelEvent.h"
69 #include "NavigationActionData.h"
70 #include "NetworkProcessMessages.h"
71 #include "NetworkProcessProxy.h"
72 #include "NotificationPermissionRequest.h"
73 #include "NotificationPermissionRequestManager.h"
74 #include "OptionalCallbackID.h"
75 #include "PageClient.h"
76 #include "PluginInformation.h"
77 #include "PluginProcessManager.h"
78 #include "PrintInfo.h"
79 #include "SafeBrowsingResult.h"
80 #include "ShareSheetCallbackID.h"
81 #include "SharedBufferDataReference.h"
82 #include "TextChecker.h"
83 #include "TextCheckerState.h"
84 #include "UIMessagePortChannelProvider.h"
85 #include "URLSchemeTaskParameters.h"
86 #include "UndoOrRedo.h"
87 #include "UserMediaPermissionRequestProxy.h"
88 #include "UserMediaProcessManager.h"
89 #include "WKContextPrivate.h"
90 #include "WebAutomationSession.h"
91 #include "WebBackForwardList.h"
92 #include "WebBackForwardListItem.h"
93 #include "WebCertificateInfo.h"
94 #include "WebContextMenuItem.h"
95 #include "WebContextMenuProxy.h"
96 #include "WebCoreArgumentCoders.h"
97 #include "WebEditCommandProxy.h"
99 #include "WebEventConversion.h"
100 #include "WebFramePolicyListenerProxy.h"
101 #include "WebFullScreenManagerProxy.h"
102 #include "WebFullScreenManagerProxyMessages.h"
103 #include "WebImage.h"
104 #include "WebInspectorProxy.h"
105 #include "WebInspectorUtilities.h"
106 #include "WebNavigationDataStore.h"
107 #include "WebNavigationState.h"
108 #include "WebNotificationManagerProxy.h"
109 #include "WebOpenPanelResultListenerProxy.h"
110 #include "WebPageCreationParameters.h"
111 #include "WebPageGroup.h"
112 #include "WebPageGroupData.h"
113 #include "WebPageMessages.h"
114 #include "WebPageProxyMessages.h"
115 #include "WebPaymentCoordinatorProxy.h"
116 #include "WebPopupItem.h"
117 #include "WebPopupMenuProxy.h"
118 #include "WebPreferences.h"
119 #include "WebPreferencesKeys.h"
120 #include "WebProcessMessages.h"
121 #include "WebProcessPool.h"
122 #include "WebProcessProxy.h"
123 #include "WebProtectionSpace.h"
124 #include "WebResourceLoadStatisticsStore.h"
125 #include "WebURLSchemeHandler.h"
126 #include "WebUserContentControllerProxy.h"
127 #include "WebsiteDataStore.h"
128 #include <WebCore/BitmapImage.h>
129 #include <WebCore/DeprecatedGlobalSettings.h>
130 #include <WebCore/DiagnosticLoggingClient.h>
131 #include <WebCore/DiagnosticLoggingKeys.h>
132 #include <WebCore/DragController.h>
133 #include <WebCore/DragData.h>
134 #include <WebCore/EventNames.h>
135 #include <WebCore/FloatRect.h>
136 #include <WebCore/FocusDirection.h>
137 #include <WebCore/FontAttributeChanges.h>
138 #include <WebCore/FrameLoader.h>
139 #include <WebCore/GlobalFrameIdentifier.h>
140 #include <WebCore/GlobalWindowIdentifier.h>
141 #include <WebCore/JSDOMBinding.h>
142 #include <WebCore/JSDOMExceptionHandling.h>
143 #include <WebCore/LengthBox.h>
144 #include <WebCore/MIMETypeRegistry.h>
145 #include <WebCore/MediaStreamRequest.h>
146 #include <WebCore/PerformanceLoggingClient.h>
147 #include <WebCore/PublicSuffix.h>
148 #include <WebCore/RenderEmbeddedObject.h>
149 #include <WebCore/ResourceLoadStatistics.h>
150 #include <WebCore/SSLKeyGenerator.h>
151 #include <WebCore/SerializedCryptoKeyWrap.h>
152 #include <WebCore/ShareData.h>
153 #include <WebCore/SharedBuffer.h>
154 #include <WebCore/ShouldSkipSafeBrowsingCheck.h>
155 #include <WebCore/ShouldTreatAsContinuingLoad.h>
156 #include <WebCore/TextCheckerClient.h>
157 #include <WebCore/TextIndicator.h>
158 #include <WebCore/URL.h>
159 #include <WebCore/URLParser.h>
160 #include <WebCore/ValidationBubble.h>
161 #include <WebCore/WindowFeatures.h>
163 #include <wtf/NeverDestroyed.h>
164 #include <wtf/SystemTracing.h>
165 #include <wtf/text/StringView.h>
166 #include <wtf/text/TextStream.h>
168 #if ENABLE(APPLICATION_MANIFEST)
169 #include "APIApplicationManifest.h"
172 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
173 #include "RemoteScrollingCoordinatorProxy.h"
177 #include <wtf/RefCountedLeakCounter.h>
181 #include "RemoteLayerTreeDrawingAreaProxy.h"
182 #include "RemoteLayerTreeScrollingPerformanceData.h"
183 #include "TouchBarMenuData.h"
184 #include "TouchBarMenuItemData.h"
185 #include "VideoFullscreenManagerProxy.h"
186 #include "VideoFullscreenManagerProxyMessages.h"
187 #include "ViewSnapshotStore.h"
188 #include <WebCore/RunLoopObserver.h>
189 #include <WebCore/TextIndicatorWindow.h>
190 #include <wtf/MachSendRight.h>
194 #include "WebSelectionData.h"
198 #include <WebCore/CairoUtilities.h>
201 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
202 #include <WebCore/MediaPlaybackTarget.h>
203 #include <WebCore/WebMediaSessionManager.h>
206 #if ENABLE(MEDIA_SESSION)
207 #include "WebMediaSessionFocusManager.h"
208 #include "WebMediaSessionMetadata.h"
209 #include <WebCore/MediaSessionMetadata.h>
212 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
213 #include "PlaybackSessionManagerProxy.h"
216 #if ENABLE(WEB_AUTHN)
217 #include "WebAuthenticatorCoordinatorProxy.h"
220 #if ENABLE(RESOURCE_LOAD_STATISTICS)
221 #include "WebResourceLoadStatisticsStore.h"
224 #if HAVE(SEC_KEY_PROXY)
225 #include "SecKeyProxyStore.h"
228 // This controls what strategy we use for mouse wheel coalescing.
229 #define MERGE_WHEEL_EVENTS 1
231 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_process->connection())
232 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(m_process->checkURLReceivedFromWebProcess(url), m_process->connection())
234 #define RELEASE_LOG_IF_ALLOWED(channel, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, __VA_ARGS__)
236 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
237 static const unsigned wheelEventQueueSizeThreshold = 10;
239 static const Seconds resetRecentCrashCountDelay = 30_s;
240 static unsigned maximumWebProcessRelaunchAttempts = 1;
243 using namespace WebCore;
245 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
247 class ExceededDatabaseQuotaRecords {
248 WTF_MAKE_NONCOPYABLE(ExceededDatabaseQuotaRecords); WTF_MAKE_FAST_ALLOCATED;
249 friend NeverDestroyed<ExceededDatabaseQuotaRecords>;
253 String originIdentifier;
256 uint64_t currentQuota;
257 uint64_t currentOriginUsage;
258 uint64_t currentDatabaseUsage;
259 uint64_t expectedUsage;
260 Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply reply;
263 static ExceededDatabaseQuotaRecords& singleton();
265 std::unique_ptr<Record> createRecord(uint64_t frameID, String originIdentifier,
266 String databaseName, String displayName, uint64_t currentQuota,
267 uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage,
268 Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply&&);
270 void add(std::unique_ptr<Record>);
271 bool areBeingProcessed() const { return !!m_currentRecord; }
275 ExceededDatabaseQuotaRecords() { }
276 ~ExceededDatabaseQuotaRecords() { }
278 Deque<std::unique_ptr<Record>> m_records;
279 std::unique_ptr<Record> m_currentRecord;
282 ExceededDatabaseQuotaRecords& ExceededDatabaseQuotaRecords::singleton()
284 static NeverDestroyed<ExceededDatabaseQuotaRecords> records;
288 std::unique_ptr<ExceededDatabaseQuotaRecords::Record> ExceededDatabaseQuotaRecords::createRecord(
289 uint64_t frameID, String originIdentifier, String databaseName, String displayName,
290 uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage,
291 uint64_t expectedUsage, Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply&& reply)
293 auto record = std::make_unique<Record>();
294 record->frameID = frameID;
295 record->originIdentifier = originIdentifier;
296 record->databaseName = databaseName;
297 record->displayName = displayName;
298 record->currentQuota = currentQuota;
299 record->currentOriginUsage = currentOriginUsage;
300 record->currentDatabaseUsage = currentDatabaseUsage;
301 record->expectedUsage = expectedUsage;
302 record->reply = WTFMove(reply);
306 void ExceededDatabaseQuotaRecords::add(std::unique_ptr<ExceededDatabaseQuotaRecords::Record> record)
308 m_records.append(WTFMove(record));
311 ExceededDatabaseQuotaRecords::Record* ExceededDatabaseQuotaRecords::next()
313 m_currentRecord = nullptr;
314 if (!m_records.isEmpty())
315 m_currentRecord = m_records.takeFirst();
316 return m_currentRecord.get();
320 static const char* webMouseEventTypeString(WebEvent::Type type)
323 case WebEvent::MouseDown:
325 case WebEvent::MouseUp:
327 case WebEvent::MouseMove:
329 case WebEvent::MouseForceChanged:
330 return "MouseForceChanged";
331 case WebEvent::MouseForceDown:
332 return "MouseForceDown";
333 case WebEvent::MouseForceUp:
334 return "MouseForceUp";
336 ASSERT_NOT_REACHED();
341 static const char* webKeyboardEventTypeString(WebEvent::Type type)
344 case WebEvent::KeyDown:
346 case WebEvent::KeyUp:
348 case WebEvent::RawKeyDown:
353 ASSERT_NOT_REACHED();
357 #endif // !LOG_DISABLED
359 class PageClientProtector {
360 WTF_MAKE_NONCOPYABLE(PageClientProtector);
362 PageClientProtector(PageClient& pageClient)
363 : m_pageClient(makeWeakPtr(pageClient))
365 m_pageClient->refView();
368 ~PageClientProtector()
370 ASSERT(m_pageClient);
371 m_pageClient->derefView();
375 WeakPtr<PageClient> m_pageClient;
378 Ref<WebPageProxy> WebPageProxy::create(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
380 return adoptRef(*new WebPageProxy(pageClient, process, pageID, WTFMove(configuration)));
383 WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
384 : m_pageClient(makeWeakPtr(pageClient))
385 , m_configuration(WTFMove(configuration))
386 , m_navigationClient(makeUniqueRef<API::NavigationClient>())
387 , m_historyClient(makeUniqueRef<API::HistoryClient>())
388 , m_iconLoadingClient(std::make_unique<API::IconLoadingClient>())
389 , m_formClient(std::make_unique<API::FormClient>())
390 , m_uiClient(std::make_unique<API::UIClient>())
391 , m_findClient(std::make_unique<API::FindClient>())
392 , m_findMatchesClient(std::make_unique<API::FindMatchesClient>())
393 #if ENABLE(CONTEXT_MENUS)
394 , m_contextMenuClient(std::make_unique<API::ContextMenuClient>())
396 , m_navigationState(std::make_unique<WebNavigationState>())
398 , m_pageGroup(*m_configuration->pageGroup())
399 , m_preferences(*m_configuration->preferences())
400 , m_userContentController(*m_configuration->userContentController())
401 , m_visitedLinkStore(*m_configuration->visitedLinkStore())
402 , m_websiteDataStore(m_configuration->websiteDataStore()->websiteDataStore())
403 , m_userAgent(standardUserAgent())
404 , m_overrideContentSecurityPolicy { m_configuration->overrideContentSecurityPolicy() }
405 , m_treatsSHA1CertificatesAsInsecure(m_configuration->treatsSHA1SignedCertificatesAsInsecure())
406 #if ENABLE(FULLSCREEN_API)
407 , m_fullscreenClient(std::make_unique<API::FullscreenClient>())
409 , m_geolocationPermissionRequestManager(*this)
410 , m_notificationPermissionRequestManager(*this)
411 #if PLATFORM(IOS_FAMILY)
412 , m_alwaysRunsAtForegroundPriority(m_configuration->alwaysRunsAtForegroundPriority())
414 , m_initialCapitalizationEnabled(m_configuration->initialCapitalizationEnabled())
415 , m_cpuLimit(m_configuration->cpuLimit())
416 , m_backForwardList(WebBackForwardList::create(*this))
417 , m_waitsForPaintAfterViewDidMoveToWindow(m_configuration->waitsForPaintAfterViewDidMoveToWindow())
418 , m_drawsBackground(m_configuration->drawsBackground())
420 , m_controlledByAutomation(m_configuration->isControlledByAutomation())
422 , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
424 , m_pageLoadState(*this)
425 , m_configurationPreferenceValues(m_configuration->preferenceValues())
426 , m_resetRecentCrashCountTimer(RunLoop::main(), this, &WebPageProxy::resetRecentCrashCount)
428 m_webProcessLifetimeTracker.addObserver(m_visitedLinkStore);
429 m_webProcessLifetimeTracker.addObserver(m_websiteDataStore);
431 updateActivityState();
432 updateThrottleState();
433 updateHiddenPageThrottlingAutoIncreases();
435 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
436 m_layerHostingMode = m_activityState & ActivityState::IsInWindow ? WebPageProxy::pageClient().viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
439 platformInitialize();
442 webPageProxyCounter.increment();
445 WebProcessPool::statistics().wkPageCount++;
447 m_preferences->addPage(*this);
448 m_pageGroup->addPage(this);
450 m_inspector = WebInspectorProxy::create(this);
451 #if ENABLE(FULLSCREEN_API)
452 m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, WebPageProxy::pageClient().fullScreenManagerProxyClient());
454 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
455 m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
456 m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
459 #if ENABLE(APPLE_PAY)
460 m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
463 #if USE(SYSTEM_PREVIEW)
464 m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
467 #if ENABLE(WEB_AUTHN)
468 m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
471 m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
473 #if PLATFORM(IOS_FAMILY)
474 DeprecatedGlobalSettings::setDisableScreenSizeOverride(preferencesStore().getBoolValueForKey(WebPreferencesKey::disableScreenSizeOverrideKey()));
478 m_activityStateChangeDispatcher = std::make_unique<RunLoopObserver>(static_cast<CFIndex>(RunLoopObserver::WellKnownRunLoopOrders::ActivityStateChange), [this] {
479 this->dispatchActivityStateChange();
484 WebPageProxy::~WebPageProxy()
486 ASSERT(m_process->webPage(m_pageID) != this);
488 for (WebPageProxy* page : m_process->pages())
489 ASSERT(page != this);
495 WebProcessPool::statistics().wkPageCount--;
497 if (m_spellDocumentTag)
498 TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag.value());
500 m_preferences->removePage(*this);
501 m_pageGroup->removePage(this);
504 webPageProxyCounter.decrement();
508 // FIXME: Should return a const PageClient& and add a separate non-const
509 // version of this function, but several PageClient methods will need to become
510 // const for this to be possible.
511 PageClient& WebPageProxy::pageClient() const
513 ASSERT(m_pageClient);
514 return *m_pageClient;
517 PAL::SessionID WebPageProxy::sessionID() const
519 return m_websiteDataStore->sessionID();
522 void WebPageProxy::changeWebsiteDataStore(WebsiteDataStore& websiteDataStore)
524 m_process->processPool().pageEndUsingWebsiteDataStore(*this);
525 m_websiteDataStore = websiteDataStore;
526 m_process->processPool().pageBeginUsingWebsiteDataStore(*this);
529 const API::PageConfiguration& WebPageProxy::configuration() const
531 return m_configuration.get();
534 ProcessID WebPageProxy::processIdentifier() const
539 return m_process->processIdentifier();
542 bool WebPageProxy::isValid() const
544 // A page that has been explicitly closed is never valid.
551 void WebPageProxy::notifyProcessPoolToPrewarm()
553 m_process->processPool().didReachGoodTimeToPrewarm();
556 void WebPageProxy::setPreferences(WebPreferences& preferences)
558 if (&preferences == m_preferences.ptr())
561 m_preferences->removePage(*this);
562 m_preferences = preferences;
563 m_preferences->addPage(*this);
565 preferencesDidChange();
568 void WebPageProxy::setHistoryClient(UniqueRef<API::HistoryClient>&& historyClient)
570 m_historyClient = WTFMove(historyClient);
573 void WebPageProxy::setNavigationClient(UniqueRef<API::NavigationClient>&& navigationClient)
575 m_navigationClient = WTFMove(navigationClient);
578 void WebPageProxy::setLoaderClient(std::unique_ptr<API::LoaderClient>&& loaderClient)
580 m_loaderClient = WTFMove(loaderClient);
583 void WebPageProxy::setPolicyClient(std::unique_ptr<API::PolicyClient>&& policyClient)
585 m_policyClient = WTFMove(policyClient);
588 void WebPageProxy::setFormClient(std::unique_ptr<API::FormClient>&& formClient)
591 m_formClient = std::make_unique<API::FormClient>();
595 m_formClient = WTFMove(formClient);
598 void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient>&& uiClient)
601 m_uiClient = std::make_unique<API::UIClient>();
605 m_uiClient = WTFMove(uiClient);
610 m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient->canRunBeforeUnloadConfirmPanel()), m_pageID);
611 setCanRunModal(m_uiClient->canRunModal());
612 setNeedsFontAttributes(m_uiClient->needsFontAttributes());
615 void WebPageProxy::setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&& iconLoadingClient)
617 bool hasClient = iconLoadingClient.get();
618 if (!iconLoadingClient)
619 m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
621 m_iconLoadingClient = WTFMove(iconLoadingClient);
626 m_process->send(Messages::WebPage::SetUseIconLoadingClient(hasClient), m_pageID);
629 void WebPageProxy::setFindClient(std::unique_ptr<API::FindClient>&& findClient)
632 m_findClient = std::make_unique<API::FindClient>();
636 m_findClient = WTFMove(findClient);
639 void WebPageProxy::setFindMatchesClient(std::unique_ptr<API::FindMatchesClient>&& findMatchesClient)
641 if (!findMatchesClient) {
642 m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
646 m_findMatchesClient = WTFMove(findMatchesClient);
649 void WebPageProxy::setDiagnosticLoggingClient(std::unique_ptr<API::DiagnosticLoggingClient>&& diagnosticLoggingClient)
651 m_diagnosticLoggingClient = WTFMove(diagnosticLoggingClient);
654 #if ENABLE(CONTEXT_MENUS)
655 void WebPageProxy::setContextMenuClient(std::unique_ptr<API::ContextMenuClient>&& contextMenuClient)
657 if (!contextMenuClient) {
658 m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
662 m_contextMenuClient = WTFMove(contextMenuClient);
666 void WebPageProxy::setInjectedBundleClient(const WKPageInjectedBundleClientBase* client)
669 m_injectedBundleClient = nullptr;
673 m_injectedBundleClient = std::make_unique<WebPageInjectedBundleClient>();
674 m_injectedBundleClient->initialize(client);
677 void WebPageProxy::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
679 ASSERT(m_process->connection() == &connection);
681 if (!m_injectedBundleClient)
684 m_injectedBundleClient->didReceiveMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get());
687 void WebPageProxy::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
689 ASSERT(m_process->connection() == &connection);
691 if (!m_injectedBundleClient)
694 RefPtr<API::Object> returnData;
695 m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get(), returnData);
696 returnUserData = UserData(m_process->transformObjectsToHandles(returnData.get()));
699 void WebPageProxy::reattachToWebProcess()
703 RELEASE_LOG_IF_ALLOWED(Process, "%p WebPageProxy::reattachToWebProcess\n", this);
705 m_process->removeWebPage(*this, m_pageID);
706 m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
708 auto& processPool = m_process->processPool();
709 m_process = processPool.createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get());
712 finishAttachingToWebProcess();
715 void WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, std::optional<uint64_t> mainFrameID)
720 auto* currentItem = navigation.fromItem();
722 LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " unable to create suspended page for process pid %i - No current back/forward item", pageID(), m_process->processIdentifier());
726 auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *currentItem, *mainFrameID);
729 m_pageSuspendedDueToCurrentNavigation = makeWeakPtr(suspendedPage.get());
732 LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " created suspended page %s for process pid %i, back/forward item %s" PRIu64, pageID(), suspendedPage->loggingString(), m_process->processIdentifier(), currentItem->itemID().logString());
734 m_process->processPool().addSuspendedPageProxy(WTFMove(suspendedPage));
737 void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, API::Navigation& navigation, std::optional<uint64_t> mainFrameIDInPreviousProcess)
740 RELEASE_LOG_IF_ALLOWED(Process, "%p WebPageProxy::swapToWebProcess\n", this);
742 std::unique_ptr<SuspendedPageProxy> destinationSuspendedPage;
743 if (auto* backForwardListItem = navigation.targetItem()) {
744 if (backForwardListItem->suspendedPage() && &backForwardListItem->suspendedPage()->process() == process.ptr()) {
745 destinationSuspendedPage = this->process().processPool().takeSuspendedPageProxy(*backForwardListItem->suspendedPage());
746 ASSERT(destinationSuspendedPage);
747 destinationSuspendedPage->unsuspend();
751 m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
752 suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess);
753 m_process->removeWebPage(*this, m_pageID);
755 m_process = WTFMove(process);
758 // If we are reattaching to a SuspendedPage, then the WebProcess' WebPage already exists and
759 // WebPageProxy::didCreateMainFrame() will not be called to initialize m_mainFrame. In such
760 // case, we need to initialize m_mainFrame to reflect the fact the the WebProcess' WebPage
761 // already exists and already has a main frame.
762 if (destinationSuspendedPage) {
763 ASSERT(!m_mainFrame);
764 ASSERT(&destinationSuspendedPage->process() == m_process.ptr());
765 m_mainFrame = WebFrameProxy::create(this, destinationSuspendedPage->mainFrameID());
766 m_process->frameCreated(destinationSuspendedPage->mainFrameID(), *m_mainFrame);
769 finishAttachingToWebProcess();
772 void WebPageProxy::finishAttachingToWebProcess()
774 ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
776 if (m_process->state() == ChildProcessProxy::State::Running) {
777 m_webProcessLifetimeTracker.webPageEnteringWebProcess();
778 processDidFinishLaunching();
781 m_process->addExistingWebPage(*this, m_pageID);
782 m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
784 updateActivityState();
785 updateThrottleState();
787 m_inspector = WebInspectorProxy::create(this);
788 #if ENABLE(FULLSCREEN_API)
789 m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, pageClient().fullScreenManagerProxyClient());
791 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
792 m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
793 m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
796 #if ENABLE(APPLE_PAY)
797 m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
800 #if USE(SYSTEM_PREVIEW)
801 m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
804 #if ENABLE(WEB_AUTHN)
805 m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
810 pageClient().didRelaunchProcess();
811 m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
814 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessForReload()
820 reattachToWebProcess();
822 if (!m_backForwardList->currentItem())
825 auto navigation = m_navigationState->createReloadNavigation();
827 // We allow stale content when reloading a WebProcess that's been killed or crashed.
828 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No), m_pageID);
829 m_process->responsivenessTimer().start();
831 return WTFMove(navigation);
834 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem& item)
840 reattachToWebProcess();
842 if (&item != m_backForwardList->currentItem())
843 m_backForwardList->goToItem(item);
845 auto navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), FrameLoadType::IndexedBackForward);
847 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item.itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No), m_pageID);
848 m_process->responsivenessTimer().start();
850 return WTFMove(navigation);
853 void WebPageProxy::initializeWebPage()
857 m_drawingArea = pageClient().createDrawingAreaProxy();
858 ASSERT(m_drawingArea);
860 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
861 if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) {
862 m_scrollingCoordinatorProxy = std::make_unique<RemoteScrollingCoordinatorProxy>(*this);
863 #if PLATFORM(IOS_FAMILY)
864 // On iOS, main frame scrolls are sent in terms of visible rect updates.
865 m_scrollingCoordinatorProxy->setPropagatesMainFrameScrolls(false);
870 auto parameters = creationParameters();
872 #if ENABLE(SERVICE_WORKER)
873 parameters.hasRegisteredServiceWorkers = process().processPool().mayHaveRegisteredServiceWorkers(m_websiteDataStore);
876 process().send(Messages::WebProcess::CreateWebPage(m_pageID, parameters), 0);
878 m_needsToFinishInitializingWebPageAfterProcessLaunch = true;
879 finishInitializingWebPageAfterProcessLaunch();
882 void WebPageProxy::finishInitializingWebPageAfterProcessLaunch()
884 if (!m_needsToFinishInitializingWebPageAfterProcessLaunch)
886 if (m_process->state() != WebProcessProxy::State::Running)
889 m_needsToFinishInitializingWebPageAfterProcessLaunch = false;
890 m_process->addVisitedLinkStore(m_visitedLinkStore);
893 void WebPageProxy::close()
900 reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
902 if (m_activePopupMenu)
903 m_activePopupMenu->cancelTracking();
905 if (m_controlledByAutomation) {
906 if (auto* automationSession = process().processPool().automationSession())
907 automationSession->willClosePage(*this);
910 #if ENABLE(CONTEXT_MENUS)
911 m_activeContextMenu = nullptr;
914 m_backForwardList->pageClosed();
915 pageClient().pageClosed();
917 m_process->disconnectFramesFromPage(this);
919 resetState(ResetStateReason::PageInvalidated);
921 m_loaderClient = nullptr;
922 m_navigationClient = makeUniqueRef<API::NavigationClient>();
923 m_policyClient = nullptr;
924 m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
925 m_formClient = std::make_unique<API::FormClient>();
926 m_uiClient = std::make_unique<API::UIClient>();
927 m_findClient = std::make_unique<API::FindClient>();
928 m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
929 m_diagnosticLoggingClient = nullptr;
930 #if ENABLE(CONTEXT_MENUS)
931 m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
933 #if ENABLE(FULLSCREEN_API)
934 m_fullscreenClient = std::make_unique<API::FullscreenClient>();
937 m_webProcessLifetimeTracker.pageWasInvalidated();
939 m_process->processPool().removeAllSuspendedPageProxiesForPage(*this);
941 m_process->send(Messages::WebPage::Close(), m_pageID);
942 m_process->removeWebPage(*this, m_pageID);
943 m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
944 m_process->processPool().supplement<WebNotificationManagerProxy>()->clearNotifications(this);
946 // Null out related WebPageProxy to avoid leaks.
947 m_configuration->setRelatedPage(nullptr);
949 #if PLATFORM(IOS_FAMILY)
950 // Make sure we don't hold a process assertion after getting closed.
951 m_activityToken = nullptr;
954 #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
955 m_displayLink = nullptr;
958 stopAllURLSchemeTasks();
961 bool WebPageProxy::tryClose()
966 // Close without delay if the process allows it. Our goal is to terminate
967 // the process, so we check a per-process status bit.
968 if (m_process->isSuddenTerminationEnabled())
971 m_process->send(Messages::WebPage::TryClose(), m_pageID);
972 m_process->responsivenessTimer().start();
976 bool WebPageProxy::maybeInitializeSandboxExtensionHandle(const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
978 if (!url.isLocalFile())
981 if (m_process->hasAssumedReadAccessToURL(url))
984 // Inspector resources are in a directory with assumed access.
985 ASSERT_WITH_SECURITY_IMPLICATION(!WebKit::isInspectorPage(*this));
987 SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, sandboxExtensionHandle);
992 void WebPageProxy::addPlatformLoadParameters(LoadParameters&)
997 RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
1002 auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
1003 loadRequestWithNavigation(navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, ShouldTreatAsContinuingLoad::No);
1004 return WTFMove(navigation);
1007 void WebPageProxy::loadRequestWithNavigation(API::Navigation& navigation, ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad)
1009 ASSERT(!m_isClosed);
1011 auto transaction = m_pageLoadState.transaction();
1013 auto url = request.url();
1014 m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1017 reattachToWebProcess();
1019 LoadParameters loadParameters;
1020 loadParameters.navigationID = navigation.navigationID();
1021 loadParameters.request = WTFMove(request);
1022 loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
1023 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1024 loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1025 loadParameters.lockHistory = navigation.lockHistory();
1026 loadParameters.lockBackForwardList = navigation.lockBackForwardList();
1027 loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
1028 bool createdExtension = maybeInitializeSandboxExtensionHandle(url, loadParameters.sandboxExtensionHandle);
1029 if (createdExtension)
1030 m_process->willAcquireUniversalFileReadSandboxExtension();
1031 addPlatformLoadParameters(loadParameters);
1033 m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1034 m_process->responsivenessTimer().start();
1037 RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
1043 reattachToWebProcess();
1045 URL fileURL = URL(URL(), fileURLString);
1046 if (!fileURL.isLocalFile())
1049 URL resourceDirectoryURL;
1050 if (resourceDirectoryURLString.isNull())
1051 resourceDirectoryURL = URL({ }, "file:///"_s);
1053 resourceDirectoryURL = URL(URL(), resourceDirectoryURLString);
1054 if (!resourceDirectoryURL.isLocalFile())
1058 auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL), m_backForwardList->currentItem());
1060 auto transaction = m_pageLoadState.transaction();
1062 m_pageLoadState.setPendingAPIRequestURL(transaction, fileURLString);
1064 String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
1066 LoadParameters loadParameters;
1067 loadParameters.navigationID = navigation->navigationID();
1068 loadParameters.request = fileURL;
1069 loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1070 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1071 SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::Type::ReadOnly, loadParameters.sandboxExtensionHandle);
1072 addPlatformLoadParameters(loadParameters);
1074 m_process->assumeReadAccessToBaseURL(resourceDirectoryURL);
1075 m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1076 m_process->responsivenessTimer().start();
1078 return WTFMove(navigation);
1081 RefPtr<API::Navigation> WebPageProxy::loadData(const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData)
1086 auto navigation = m_navigationState->createLoadDataNavigation();
1088 auto transaction = m_pageLoadState.transaction();
1090 m_pageLoadState.setPendingAPIRequestURL(transaction, !baseURL.isEmpty() ? baseURL : blankURL().string());
1093 reattachToWebProcess();
1095 LoadParameters loadParameters;
1096 loadParameters.navigationID = navigation->navigationID();
1097 loadParameters.data = data;
1098 loadParameters.MIMEType = MIMEType;
1099 loadParameters.encodingName = encoding;
1100 loadParameters.baseURLString = baseURL;
1101 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1102 addPlatformLoadParameters(loadParameters);
1104 m_process->assumeReadAccessToBaseURL(baseURL);
1105 m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1106 m_process->responsivenessTimer().start();
1108 return WTFMove(navigation);
1111 void WebPageProxy::loadAlternateHTML(const IPC::DataReference& htmlData, const String& encoding, const WebCore::URL& baseURL, const WebCore::URL& unreachableURL, API::Object* userData, bool forSafeBrowsing)
1113 // When the UIProcess is in the process of handling a failing provisional load, do not attempt to
1114 // start a second alternative HTML load as this will prevent the page load state from being
1115 // handled properly.
1116 if (m_isClosed || m_isLoadingAlternateHTMLStringForFailingProvisionalLoad)
1119 if (!m_failingProvisionalLoadURL.isEmpty())
1120 m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = true;
1123 reattachToWebProcess();
1125 auto transaction = m_pageLoadState.transaction();
1127 m_pageLoadState.setPendingAPIRequestURL(transaction, unreachableURL);
1128 m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
1131 m_mainFrame->setUnreachableURL(unreachableURL);
1133 LoadParameters loadParameters;
1134 loadParameters.navigationID = 0;
1135 loadParameters.data = htmlData;
1136 loadParameters.MIMEType = "text/html"_s;
1137 loadParameters.encodingName = encoding;
1138 loadParameters.baseURLString = baseURL;
1139 loadParameters.unreachableURLString = unreachableURL;
1140 loadParameters.provisionalLoadErrorURLString = m_failingProvisionalLoadURL;
1141 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1142 loadParameters.forSafeBrowsing = forSafeBrowsing;
1143 addPlatformLoadParameters(loadParameters);
1145 m_process->assumeReadAccessToBaseURL(baseURL);
1146 m_process->assumeReadAccessToBaseURL(unreachableURL);
1147 m_process->send(Messages::WebPage::LoadAlternateHTML(loadParameters), m_pageID);
1148 m_process->responsivenessTimer().start();
1151 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
1157 reattachToWebProcess();
1159 auto transaction = m_pageLoadState.transaction();
1160 m_pageLoadState.setPendingAPIRequestURL(transaction, blankURL().string());
1162 LoadParameters loadParameters;
1163 loadParameters.navigationID = 0;
1164 loadParameters.data = webArchiveData->dataReference();
1165 loadParameters.MIMEType = "application/x-webarchive"_s;
1166 loadParameters.encodingName = "utf-16"_s;
1167 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1168 addPlatformLoadParameters(loadParameters);
1170 m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1171 m_process->responsivenessTimer().start();
1174 void WebPageProxy::navigateToPDFLinkWithSimulatedClick(const String& url, IntPoint documentPoint, IntPoint screenPoint)
1179 if (WebCore::protocolIsJavaScript(url))
1183 reattachToWebProcess();
1185 m_process->send(Messages::WebPage::NavigateToPDFLinkWithSimulatedClick(url, documentPoint, screenPoint), m_pageID);
1186 m_process->responsivenessTimer().start();
1189 void WebPageProxy::stopLoading()
1194 m_process->send(Messages::WebPage::StopLoading(), m_pageID);
1195 m_process->responsivenessTimer().start();
1198 RefPtr<API::Navigation> WebPageProxy::reload(OptionSet<WebCore::ReloadOption> options)
1200 SandboxExtension::Handle sandboxExtensionHandle;
1202 String url = currentURL();
1203 if (!url.isEmpty()) {
1204 auto transaction = m_pageLoadState.transaction();
1205 m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1207 // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
1208 bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), url), sandboxExtensionHandle);
1209 if (createdExtension)
1210 m_process->willAcquireUniversalFileReadSandboxExtension();
1214 return reattachToWebProcessForReload();
1216 auto navigation = m_navigationState->createReloadNavigation();
1218 m_process->send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle), m_pageID);
1219 m_process->responsivenessTimer().start();
1221 return WTFMove(navigation);
1224 void WebPageProxy::recordAutomaticNavigationSnapshot()
1226 if (m_shouldSuppressNextAutomaticNavigationSnapshot)
1229 if (WebBackForwardListItem* item = m_backForwardList->currentItem())
1230 recordNavigationSnapshot(*item);
1233 void WebPageProxy::recordNavigationSnapshot(WebBackForwardListItem& item)
1235 if (!m_shouldRecordNavigationSnapshots)
1239 ViewSnapshotStore::singleton().recordSnapshot(*this, item);
1245 RefPtr<API::Navigation> WebPageProxy::goForward()
1247 WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
1251 return goToBackForwardItem(*forwardItem, FrameLoadType::Forward);
1254 RefPtr<API::Navigation> WebPageProxy::goBack()
1256 WebBackForwardListItem* backItem = m_backForwardList->backItem();
1260 return goToBackForwardItem(*backItem, FrameLoadType::Back);
1263 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item)
1265 return goToBackForwardItem(item, FrameLoadType::IndexedBackForward);
1268 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item, FrameLoadType frameLoadType)
1270 LOG(Loading, "WebPageProxy %p goToBackForwardItem to item URL %s", this, item.url().utf8().data());
1273 return reattachToWebProcessWithItem(item);
1275 auto transaction = m_pageLoadState.transaction();
1277 m_pageLoadState.setPendingAPIRequestURL(transaction, item.url());
1279 RefPtr<API::Navigation> navigation;
1280 if (!m_backForwardList->currentItem()->itemIsInSameDocument(item))
1281 navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), frameLoadType);
1283 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No), m_pageID);
1284 m_process->responsivenessTimer().start();
1289 void WebPageProxy::tryRestoreScrollPosition()
1294 m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
1297 void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<Ref<WebBackForwardListItem>>&& removed)
1299 PageClientProtector protector(pageClient());
1301 if (!m_navigationClient->didChangeBackForwardList(*this, added, removed) && m_loaderClient)
1302 m_loaderClient->didChangeBackForwardList(*this, added, WTFMove(removed));
1304 auto transaction = m_pageLoadState.transaction();
1306 m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
1307 m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
1310 void WebPageProxy::willGoToBackForwardListItem(const BackForwardItemIdentifier& itemID, bool inPageCache)
1312 PageClientProtector protector(pageClient());
1314 if (auto* item = m_backForwardList->itemForID(itemID))
1315 m_navigationClient->willGoToBackForwardListItem(*this, *item, inPageCache);
1318 bool WebPageProxy::shouldKeepCurrentBackForwardListItemInList(WebBackForwardListItem& item)
1320 PageClientProtector protector(pageClient());
1322 return !m_loaderClient || m_loaderClient->shouldKeepCurrentBackForwardListItemInList(*this, item);
1325 bool WebPageProxy::canShowMIMEType(const String& mimeType)
1327 if (MIMETypeRegistry::canShowMIMEType(mimeType))
1330 #if ENABLE(NETSCAPE_PLUGIN_API)
1331 String newMimeType = mimeType;
1332 PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL());
1333 if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
1335 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1338 // On Mac, we can show PDFs.
1339 if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebProcessPool::omitPDFSupport())
1341 #endif // PLATFORM(COCOA)
1346 void WebPageProxy::setControlledByAutomation(bool controlled)
1348 if (m_controlledByAutomation == controlled)
1351 m_controlledByAutomation = controlled;
1356 m_process->send(Messages::WebPage::SetControlledByAutomation(controlled), m_pageID);
1357 m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation));
1360 #if ENABLE(REMOTE_INSPECTOR)
1361 void WebPageProxy::setAllowsRemoteInspection(bool allow)
1363 if (m_allowsRemoteInspection == allow)
1366 m_allowsRemoteInspection = allow;
1369 m_process->send(Messages::WebPage::SetAllowsRemoteInspection(allow), m_pageID);
1372 void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
1374 if (m_remoteInspectionNameOverride == name)
1377 m_remoteInspectionNameOverride = name;
1380 m_process->send(Messages::WebPage::SetRemoteInspectionNameOverride(m_remoteInspectionNameOverride), m_pageID);
1385 void WebPageProxy::setDrawsBackground(bool drawsBackground)
1387 if (m_drawsBackground == drawsBackground)
1390 m_drawsBackground = drawsBackground;
1393 m_process->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
1396 void WebPageProxy::setTopContentInset(float contentInset)
1398 if (m_topContentInset == contentInset)
1401 m_topContentInset = contentInset;
1406 MachSendRight fence = m_drawingArea->createFence();
1408 auto fenceAttachment = IPC::Attachment(fence.leakSendRight(), MACH_MSG_TYPE_MOVE_SEND);
1409 m_process->send(Messages::WebPage::SetTopContentInsetFenced(contentInset, fenceAttachment), m_pageID);
1411 m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
1415 void WebPageProxy::setUnderlayColor(const Color& color)
1417 if (m_underlayColor == color)
1420 m_underlayColor = color;
1423 m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1426 void WebPageProxy::viewWillStartLiveResize()
1431 closeOverlayedViews();
1432 m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1435 void WebPageProxy::viewWillEndLiveResize()
1439 m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1442 void WebPageProxy::setViewNeedsDisplay(const Region& region)
1444 pageClient().setViewNeedsDisplay(region);
1447 void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin, bool isProgrammaticScroll)
1449 pageClient().requestScroll(scrollPosition, scrollOrigin, isProgrammaticScroll);
1452 WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
1454 return pageClient().viewScrollPosition();
1457 void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
1459 if (m_suppressVisibilityUpdates == flag)
1461 m_suppressVisibilityUpdates = flag;
1463 if (!m_suppressVisibilityUpdates) {
1465 m_activityStateChangeDispatcher->schedule();
1467 dispatchActivityStateChange();
1472 void WebPageProxy::updateActivityState(OptionSet<ActivityState::Flag> flagsToUpdate)
1474 m_activityState.remove(flagsToUpdate);
1475 if (flagsToUpdate & ActivityState::IsFocused && pageClient().isViewFocused())
1476 m_activityState.add(ActivityState::IsFocused);
1477 if (flagsToUpdate & ActivityState::WindowIsActive && pageClient().isViewWindowActive())
1478 m_activityState.add(ActivityState::WindowIsActive);
1479 if (flagsToUpdate & ActivityState::IsVisible && pageClient().isViewVisible())
1480 m_activityState.add(ActivityState::IsVisible);
1481 if (flagsToUpdate & ActivityState::IsVisibleOrOccluded && pageClient().isViewVisibleOrOccluded())
1482 m_activityState.add(ActivityState::IsVisibleOrOccluded);
1483 if (flagsToUpdate & ActivityState::IsInWindow && pageClient().isViewInWindow())
1484 m_activityState.add(ActivityState::IsInWindow);
1485 if (flagsToUpdate & ActivityState::IsVisuallyIdle && pageClient().isVisuallyIdle())
1486 m_activityState.add(ActivityState::IsVisuallyIdle);
1487 if (flagsToUpdate & ActivityState::IsAudible && m_mediaState & MediaProducer::IsPlayingAudio && !(m_mutedState & MediaProducer::AudioIsMuted))
1488 m_activityState.add(ActivityState::IsAudible);
1489 if (flagsToUpdate & ActivityState::IsLoading && m_pageLoadState.isLoading())
1490 m_activityState.add(ActivityState::IsLoading);
1491 if (flagsToUpdate & ActivityState::IsCapturingMedia && m_mediaState & (MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice))
1492 m_activityState.add(ActivityState::IsCapturingMedia);
1495 void WebPageProxy::activityStateDidChange(OptionSet<ActivityState::Flag> mayHaveChanged, bool wantsSynchronousReply, ActivityStateChangeDispatchMode dispatchMode)
1497 LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " activityStateDidChange - mayHaveChanged " << mayHaveChanged);
1499 m_potentiallyChangedActivityStateFlags.add(mayHaveChanged);
1500 m_activityStateChangeWantsSynchronousReply = m_activityStateChangeWantsSynchronousReply || wantsSynchronousReply;
1502 if (m_suppressVisibilityUpdates && dispatchMode != ActivityStateChangeDispatchMode::Immediate)
1506 bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ActivityState::IsInWindow) && pageClient().isViewInWindow();
1507 if (dispatchMode == ActivityStateChangeDispatchMode::Immediate || isNewlyInWindow) {
1508 dispatchActivityStateChange();
1511 m_activityStateChangeDispatcher->schedule();
1513 UNUSED_PARAM(dispatchMode);
1514 dispatchActivityStateChange();
1518 void WebPageProxy::viewDidLeaveWindow()
1520 closeOverlayedViews();
1521 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
1522 // When leaving the current page, close the video fullscreen.
1523 if (m_videoFullscreenManager)
1524 m_videoFullscreenManager->requestHideAndExitFullscreen();
1528 void WebPageProxy::viewDidEnterWindow()
1530 LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1531 if (m_layerHostingMode != layerHostingMode) {
1532 m_layerHostingMode = layerHostingMode;
1533 m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1537 void WebPageProxy::dispatchActivityStateChange()
1540 m_activityStateChangeDispatcher->invalidate();
1546 LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange - potentiallyChangedActivityStateFlags " << m_potentiallyChangedActivityStateFlags);
1548 // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1549 if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible)
1550 m_potentiallyChangedActivityStateFlags.add({ ActivityState::IsVisibleOrOccluded, ActivityState::IsVisuallyIdle });
1552 // Record the prior view state, update the flags that may have changed,
1553 // and check which flags have actually changed.
1554 auto previousActivityState = m_activityState;
1555 updateActivityState(m_potentiallyChangedActivityStateFlags);
1556 auto changed = m_activityState ^ previousActivityState;
1559 LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange: state changed from " << previousActivityState << " to " << m_activityState);
1561 if ((m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible) && isViewVisible())
1562 viewIsBecomingVisible();
1564 bool isNowInWindow = (changed & ActivityState::IsInWindow) && isInWindow();
1565 // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
1566 if (m_viewWasEverInWindow && isNowInWindow) {
1567 if (m_drawingArea->hasVisibleContent() && m_waitsForPaintAfterViewDidMoveToWindow && !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
1568 m_activityStateChangeWantsSynchronousReply = true;
1569 m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
1572 // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
1573 if (!(m_activityState & ActivityState::IsVisible))
1574 m_activityStateChangeWantsSynchronousReply = false;
1576 auto activityStateChangeID = m_activityStateChangeWantsSynchronousReply ? takeNextActivityStateChangeID() : static_cast<ActivityStateChangeID>(ActivityStateChangeAsynchronous);
1578 if (changed || activityStateChangeID != ActivityStateChangeAsynchronous || !m_nextActivityStateChangeCallbacks.isEmpty())
1579 m_process->send(Messages::WebPage::SetActivityState(m_activityState, activityStateChangeID, m_nextActivityStateChangeCallbacks), m_pageID);
1581 m_nextActivityStateChangeCallbacks.clear();
1583 // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
1584 updateThrottleState();
1586 #if ENABLE(POINTER_LOCK)
1587 if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !pageClient().isViewWindowActive())
1588 || ((changed & ActivityState::IsFocused) && !(m_activityState & ActivityState::IsFocused)))
1589 requestPointerUnlock();
1592 if (changed & ActivityState::IsVisible) {
1593 if (isViewVisible())
1594 m_visiblePageToken = m_process->visiblePageToken();
1596 m_visiblePageToken = nullptr;
1598 // If we've started the responsiveness timer as part of telling the web process to update the backing store
1599 // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1600 // stop the unresponsiveness timer here.
1601 m_process->responsivenessTimer().stop();
1605 if (changed & ActivityState::IsInWindow) {
1607 viewDidEnterWindow();
1609 viewDidLeaveWindow();
1612 updateBackingStoreDiscardableState();
1614 if (activityStateChangeID != ActivityStateChangeAsynchronous)
1615 waitForDidUpdateActivityState(activityStateChangeID);
1617 m_potentiallyChangedActivityStateFlags = { };
1618 m_activityStateChangeWantsSynchronousReply = false;
1619 m_viewWasEverInWindow |= isNowInWindow;
1622 bool WebPageProxy::isAlwaysOnLoggingAllowed() const
1624 return sessionID().isAlwaysOnLoggingAllowed();
1627 void WebPageProxy::updateThrottleState()
1629 bool processSuppressionEnabled = m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
1631 // If process suppression is not enabled take a token on the process pool to disable suppression of support processes.
1632 if (!processSuppressionEnabled)
1633 m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
1634 else if (!m_preventProcessSuppressionCount)
1635 m_preventProcessSuppressionCount = nullptr;
1637 if (m_activityState & ActivityState::IsVisuallyIdle)
1638 m_pageIsUserObservableCount = nullptr;
1639 else if (!m_pageIsUserObservableCount)
1640 m_pageIsUserObservableCount = m_process->processPool().userObservablePageCount();
1642 #if PLATFORM(IOS_FAMILY)
1643 bool isCapturingMedia = m_activityState.contains(ActivityState::IsCapturingMedia);
1644 bool isAudible = m_activityState.contains(ActivityState::IsAudible);
1645 if (!isViewVisible() && !m_alwaysRunsAtForegroundPriority && !isCapturingMedia && !isAudible) {
1646 if (m_activityToken) {
1647 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is releasing a foreground assertion because the view is no longer visible", this);
1648 m_activityToken = nullptr;
1650 } else if (!m_activityToken) {
1651 if (isViewVisible())
1652 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because the view is visible", this);
1654 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because we are playing audio", this);
1655 else if (isCapturingMedia)
1656 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because media capture is active", this);
1658 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion even though the view is not visible because m_alwaysRunsAtForegroundPriority is true", this);
1659 m_activityToken = m_process->throttler().foregroundActivityToken();
1664 void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
1666 if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
1667 m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
1668 else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
1669 m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
1672 void WebPageProxy::layerHostingModeDidChange()
1677 LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1678 if (m_layerHostingMode == layerHostingMode)
1681 m_layerHostingMode = layerHostingMode;
1682 m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1685 void WebPageProxy::waitForDidUpdateActivityState(ActivityStateChangeID activityStateChangeID)
1690 if (m_process->state() != WebProcessProxy::State::Running)
1693 // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1694 if (m_waitingForDidUpdateActivityState)
1697 #if PLATFORM(IOS_FAMILY)
1698 // Hail Mary check. Should not be possible (dispatchActivityStateChange should force async if not visible,
1699 // and if visible we should be holding an assertion) - but we should never block on a suspended process.
1700 if (!m_activityToken) {
1701 ASSERT_NOT_REACHED();
1706 m_waitingForDidUpdateActivityState = true;
1708 m_drawingArea->waitForDidUpdateActivityState(activityStateChangeID);
1711 IntSize WebPageProxy::viewSize() const
1713 return pageClient().viewSize();
1716 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
1719 callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
1723 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1724 m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent, callbackID), m_pageID);
1727 void WebPageProxy::clearSelection()
1731 m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1734 void WebPageProxy::restoreSelectionInFocusedEditableElement()
1738 m_process->send(Messages::WebPage::RestoreSelectionInFocusedEditableElement(), m_pageID);
1741 void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&& callbackFunction)
1744 callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1748 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1749 m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1752 void WebPageProxy::updateFontAttributesAfterEditorStateChange()
1754 m_cachedFontAttributesAtSelectionStart.reset();
1756 if (m_editorState.isMissingPostLayoutData)
1759 if (auto fontAttributes = m_editorState.postLayoutData().fontAttributes) {
1760 m_uiClient->didChangeFontAttributes(*fontAttributes);
1761 m_cachedFontAttributesAtSelectionStart = WTFMove(fontAttributes);
1765 void WebPageProxy::setNeedsFontAttributes(bool needsFontAttributes)
1767 if (m_needsFontAttributes == needsFontAttributes)
1770 m_needsFontAttributes = needsFontAttributes;
1773 m_process->send(Messages::WebPage::SetNeedsFontAttributes(needsFontAttributes), m_pageID);
1776 bool WebPageProxy::maintainsInactiveSelection() const
1778 // Regardless of what the client wants to do, keep selections if a local Inspector is open.
1779 // Otherwise, there is no way to use the console to inspect the state of a selection.
1780 if (inspector() && inspector()->isVisible())
1783 return m_maintainsInactiveSelection;
1786 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1788 m_maintainsInactiveSelection = newValue;
1791 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
1794 callbackFunction(CallbackBase::Error::Unknown);
1798 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1799 m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, argument, callbackID), m_pageID);
1802 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
1804 static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
1809 if (commandName == ignoreSpellingCommandName)
1810 ++m_pendingLearnOrIgnoreWordMessageCount;
1812 m_process->send(Messages::WebPage::ExecuteEditCommand(commandName, argument), m_pageID);
1815 void WebPageProxy::requestFontAttributesAtSelectionStart(Function<void(const WebCore::FontAttributes&, CallbackBase::Error)>&& callback)
1818 callback({ }, CallbackBase::Error::Unknown);
1822 auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
1823 m_process->send(Messages::WebPage::RequestFontAttributesAtSelectionStart(callbackID), m_pageID);
1826 void WebPageProxy::fontAttributesCallback(const WebCore::FontAttributes& attributes, CallbackID callbackID)
1828 m_cachedFontAttributesAtSelectionStart = attributes;
1830 if (auto callback = m_callbacks.take<FontAttributesCallback>(callbackID))
1831 callback->performCallbackWithReturnValue(attributes);
1834 void WebPageProxy::setEditable(bool editable)
1836 if (editable == m_isEditable)
1841 m_isEditable = editable;
1842 m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
1845 void WebPageProxy::setMediaStreamCaptureMuted(bool muted)
1848 setMuted(m_mutedState | WebCore::MediaProducer::CaptureDevicesAreMuted);
1850 setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1853 void WebPageProxy::activateMediaStreamCaptureInPage()
1855 #if ENABLE(MEDIA_STREAM)
1856 UserMediaProcessManager::singleton().muteCaptureMediaStreamsExceptIn(*this);
1858 setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1861 #if !PLATFORM(IOS_FAMILY)
1862 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
1866 void WebPageProxy::layerTreeCommitComplete()
1871 #if ENABLE(DRAG_SUPPORT)
1872 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
1874 performDragControllerAction(DragControllerAction::Entered, dragData, dragStorageName, { }, { });
1877 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
1879 performDragControllerAction(DragControllerAction::Updated, dragData, dragStorageName, { }, { });
1882 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
1884 performDragControllerAction(DragControllerAction::Exited, dragData, dragStorageName, { }, { });
1887 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
1889 performDragControllerAction(DragControllerAction::PerformDragOperation, dragData, dragStorageName, WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload));
1892 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
1897 UNUSED_PARAM(dragStorageName);
1898 UNUSED_PARAM(sandboxExtensionHandle);
1899 UNUSED_PARAM(sandboxExtensionsForUpload);
1901 String url = dragData.asURL();
1903 m_process->assumeReadAccessToBaseURL(url);
1905 ASSERT(dragData.platformData());
1906 WebSelectionData selection(*dragData.platformData());
1907 m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), selection, dragData.flags()), m_pageID);
1909 m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
1913 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect)
1915 MESSAGE_CHECK(dragOperation <= DragOperationDelete);
1917 m_currentDragOperation = static_cast<DragOperation>(dragOperation);
1918 m_currentDragIsOverFileInput = mouseIsOverFileInput;
1919 m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
1920 setDragCaretRect(insertionRect);
1924 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
1926 RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
1927 pageClient().startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
1933 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
1937 m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
1938 setDragCaretRect({ });
1941 void WebPageProxy::didPerformDragOperation(bool handled)
1943 pageClient().didPerformDragOperation(handled);
1946 void WebPageProxy::didStartDrag()
1949 m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
1952 void WebPageProxy::dragCancelled()
1955 m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
1958 void WebPageProxy::didEndDragging()
1960 resetCurrentDragInformation();
1963 void WebPageProxy::resetCurrentDragInformation()
1965 m_currentDragOperation = WebCore::DragOperationNone;
1966 m_currentDragIsOverFileInput = false;
1967 m_currentDragNumberOfFilesToBeAccepted = 0;
1968 setDragCaretRect({ });
1971 #if !ENABLE(DATA_INTERACTION)
1973 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
1975 m_currentDragCaretRect = dragCaretRect;
1980 #endif // ENABLE(DRAG_SUPPORT)
1982 static bool removeOldRedundantEvent(Deque<NativeWebMouseEvent>& queue, WebEvent::Type incomingEventType)
1984 if (incomingEventType != WebEvent::MouseMove && incomingEventType != WebEvent::MouseForceChanged)
1987 auto it = queue.rbegin();
1988 auto end = queue.rend();
1990 // Must not remove the first event in the deque, since it is already being dispatched.
1994 for (; it != end; ++it) {
1995 auto type = it->type();
1996 if (type == incomingEventType) {
1997 queue.remove(--it.base());
2000 if (type != WebEvent::MouseMove && type != WebEvent::MouseForceChanged)
2006 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
2011 // If we receive multiple mousemove or mouseforcechanged events and the most recent mousemove or mouseforcechanged event
2012 // (respectively) has not yet been sent to WebProcess for processing, remove the pending mouse event and insert the new
2013 // event in the queue.
2014 bool didRemoveEvent = removeOldRedundantEvent(m_mouseEventQueue, event.type());
2015 m_mouseEventQueue.append(event);
2018 UNUSED_PARAM(didRemoveEvent);
2020 LOG(MouseHandling, "UIProcess: %s mouse event %s (queue size %zu)", didRemoveEvent ? "replaced" : "enqueued", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2023 if (m_mouseEventQueue.size() == 1) // Otherwise, called from DidReceiveEvent message handler.
2024 processNextQueuedMouseEvent();
2027 void WebPageProxy::processNextQueuedMouseEvent()
2032 ASSERT(!m_mouseEventQueue.isEmpty());
2034 const NativeWebMouseEvent& event = m_mouseEventQueue.first();
2036 if (pageClient().windowIsFrontWindowUnderMouse(event))
2037 setToolTip(String());
2039 // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
2040 if (event.type() != WebEvent::MouseMove)
2041 m_process->responsivenessTimer().start();
2043 LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2044 m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
2047 #if MERGE_WHEEL_EVENTS
2048 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2050 if (a.position() != b.position())
2052 if (a.globalPosition() != b.globalPosition())
2054 if (a.modifiers() != b.modifiers())
2056 if (a.granularity() != b.granularity())
2059 if (a.phase() != b.phase())
2061 if (a.momentumPhase() != b.momentumPhase())
2063 if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
2070 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2072 ASSERT(canCoalesce(a, b));
2074 FloatSize mergedDelta = a.delta() + b.delta();
2075 FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
2078 FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
2080 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());
2082 return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
2085 #endif // MERGE_WHEEL_EVENTS
2087 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
2089 ASSERT(!queue.isEmpty());
2090 ASSERT(coalescedEvents.isEmpty());
2092 #if MERGE_WHEEL_EVENTS
2093 NativeWebWheelEvent firstEvent = queue.takeFirst();
2094 coalescedEvents.append(firstEvent);
2096 WebWheelEvent event = firstEvent;
2097 while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
2098 NativeWebWheelEvent firstEvent = queue.takeFirst();
2099 coalescedEvents.append(firstEvent);
2100 event = coalesce(event, firstEvent);
2105 while (!queue.isEmpty())
2106 coalescedEvents.append(queue.takeFirst());
2107 return coalescedEvents.last();
2111 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
2113 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2114 if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
2121 closeOverlayedViews();
2123 if (!m_currentlyProcessedWheelEvents.isEmpty()) {
2124 m_wheelEventQueue.append(event);
2125 if (!shouldProcessWheelEventNow(event))
2127 // The queue has too many wheel events, so push a new event.
2130 if (!m_wheelEventQueue.isEmpty()) {
2131 processNextQueuedWheelEvent();
2135 auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2136 coalescedWheelEvent->append(event);
2137 m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
2138 sendWheelEvent(event);
2141 void WebPageProxy::processNextQueuedWheelEvent()
2143 auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2144 WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
2145 m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
2146 sendWheelEvent(nextWheelEvent);
2149 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
2152 Messages::EventDispatcher::WheelEvent(
2155 shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
2156 shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
2158 rubberBandsAtBottom()
2161 // Manually ping the web process to check for responsiveness since our wheel
2162 // event will dispatch to a non-main thread, which always responds.
2163 m_process->isResponsive(nullptr);
2166 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
2169 // Don't queue events representing a non-trivial scrolling phase to
2170 // avoid having them trapped in the queue, potentially preventing a
2171 // scrolling session to beginning or end correctly.
2172 // This is only needed by platforms whose WebWheelEvent has this phase
2173 // information (Cocoa and GTK+) but Cocoa was fine without it.
2174 if (event.phase() == WebWheelEvent::Phase::PhaseNone
2175 || event.phase() == WebWheelEvent::Phase::PhaseChanged
2176 || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
2177 || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
2180 UNUSED_PARAM(event);
2182 if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
2187 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
2192 LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
2194 m_keyEventQueue.append(event);
2196 m_process->responsivenessTimer().start();
2197 if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
2198 LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
2199 m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2203 WebPreferencesStore WebPageProxy::preferencesStore() const
2205 if (m_configurationPreferenceValues.isEmpty())
2206 return m_preferences->store();
2208 WebPreferencesStore store = m_preferences->store();
2209 for (const auto& preference : m_configurationPreferenceValues)
2210 store.m_values.set(preference.key, preference.value);
2215 #if ENABLE(NETSCAPE_PLUGIN_API)
2216 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)
2218 PageClientProtector protector(pageClient());
2220 MESSAGE_CHECK_URL(urlString);
2222 URL pluginURL = URL { URL(), urlString };
2223 String newMimeType = mimeType.convertToASCIILowercase();
2225 PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2227 URL pageURL = URL { URL(), pageURLString };
2228 if (!m_process->processPool().pluginInfoStore().isSupportedPlugin(mimeType, pluginURL, frameURLString, pageURL)) {
2229 reply(0, newMimeType, PluginModuleLoadNormally, { }, true);
2233 PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, pluginURL, allowedPluginTypes);
2235 reply(0, newMimeType, PluginModuleLoadNormally, { }, false);
2239 uint32_t pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2242 auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2245 auto findPluginCompletion = [processType, reply = WTFMove(reply), newMimeType = WTFMove(newMimeType), plugin = WTFMove(plugin)] (uint32_t pluginLoadPolicy, const String& unavailabilityDescription) mutable {
2246 PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2247 switch (pluginLoadPolicy) {
2248 case PluginModuleLoadNormally:
2249 pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2251 case PluginModuleLoadUnsandboxed:
2252 pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2255 case PluginModuleBlockedForSecurity:
2256 case PluginModuleBlockedForCompatibility:
2257 reply(0, newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2261 reply(PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy), newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2265 m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), WTFMove(findPluginCompletion));
2267 findPluginCompletion(pluginLoadPolicy, { });
2271 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2273 #if ENABLE(TOUCH_EVENTS)
2275 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2277 if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2282 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2284 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2285 const EventNames& names = eventNames();
2286 for (auto& touchPoint : touchStartEvent.touchPoints()) {
2287 IntPoint location = touchPoint.location();
2288 auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
2289 if (trackingType == TrackingType::Synchronous)
2292 TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2294 trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2296 updateTrackingType(m_touchEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2297 updateTrackingType(m_touchEventTracking.touchStartTracking, names.touchstartEvent);
2298 updateTrackingType(m_touchEventTracking.touchMoveTracking, names.touchmoveEvent);
2299 updateTrackingType(m_touchEventTracking.touchEndTracking, names.touchendEvent);
2302 UNUSED_PARAM(touchStartEvent);
2303 m_touchEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2304 m_touchEventTracking.touchStartTracking = TrackingType::Synchronous;
2305 m_touchEventTracking.touchMoveTracking = TrackingType::Synchronous;
2306 m_touchEventTracking.touchEndTracking = TrackingType::Synchronous;
2307 #endif // ENABLE(ASYNC_SCROLLING)
2310 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2312 // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2314 // Touch events define a sequence with strong dependencies. For example, we can expect
2315 // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2318 // WebCore should not have to set up its state correctly after some events were dismissed.
2319 // For example, we don't want to send a TouchMoved without a TouchPressed.
2320 // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2321 TrackingType globalTrackingType = m_touchEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2323 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchForceChangedTracking);
2324 for (auto& touchPoint : touchStartEvent.touchPoints()) {
2325 switch (touchPoint.state()) {
2326 case WebPlatformTouchPoint::TouchReleased:
2327 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchEndTracking);
2329 case WebPlatformTouchPoint::TouchPressed:
2330 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchStartTracking);
2332 case WebPlatformTouchPoint::TouchMoved:
2333 case WebPlatformTouchPoint::TouchStationary:
2334 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchMoveTracking);
2336 case WebPlatformTouchPoint::TouchCancelled:
2337 globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2342 return globalTrackingType;
2347 #if ENABLE(MAC_GESTURE_EVENTS)
2348 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2353 m_gestureEventQueue.append(event);
2354 // FIXME: Consider doing some coalescing here.
2355 m_process->responsivenessTimer().start();
2357 m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2361 #if ENABLE(IOS_TOUCH_EVENTS)
2362 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2367 TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2369 updateTouchEventTracking(event);
2371 TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2372 if (touchEventsTrackingType == TrackingType::NotTracking)
2375 if (touchEventsTrackingType == TrackingType::Asynchronous) {
2376 // We can end up here if a native gesture has not started but the event handlers are passive.
2378 // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2379 // can prevent a native gesture.
2380 // But, here we know that all events handlers that can handle this events are passive.
2381 // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2382 event.setCanPreventNativeGestures(false);
2383 handleTouchEventAsynchronously(event);
2384 didReceiveEvent(event.type(), false);
2388 m_process->responsivenessTimer().start();
2389 bool handled = false;
2390 bool replyReceived = m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID, 1_s);
2391 // 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.
2394 didReceiveEvent(event.type(), handled);
2395 pageClient().doneWithTouchEvent(event, handled);
2396 m_process->responsivenessTimer().stop();
2398 if (event.allTouchPointsAreReleased())
2399 m_touchEventTracking.reset();
2402 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2407 TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2408 if (touchEventsTrackingType == TrackingType::NotTracking)
2411 m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2413 if (event.allTouchPointsAreReleased())
2414 m_touchEventTracking.reset();
2417 #elif ENABLE(TOUCH_EVENTS)
2418 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2423 updateTouchEventTracking(event);
2425 if (touchEventTrackingType(event) == TrackingType::NotTracking)
2428 // If the page is suspended, which should be the case during panning, pinching
2429 // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2430 // we do not send any of the events to the page even if is has listeners.
2431 if (!m_isPageSuspended) {
2432 m_touchEventQueue.append(event);
2433 m_process->responsivenessTimer().start();
2434 m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2436 if (m_touchEventQueue.isEmpty()) {
2437 bool isEventHandled = false;
2438 pageClient().doneWithTouchEvent(event, isEventHandled);
2440 // We attach the incoming events to the newest queued event so that all
2441 // the events are delivered in the correct order when the event is dequed.
2442 QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2443 lastEvent.deferredTouchEvents.append(event);
2447 if (event.allTouchPointsAreReleased())
2448 m_touchEventTracking.reset();
2450 #endif // ENABLE(TOUCH_EVENTS)
2452 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2457 m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2460 void WebPageProxy::centerSelectionInVisibleArea()
2465 m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2468 class WebPageProxy::PolicyDecisionSender : public RefCounted<PolicyDecisionSender> {
2470 using SendFunction = CompletionHandler<void(WebCore::PolicyAction, uint64_t newNavigationID, DownloadID, std::optional<WebsitePoliciesData>)>;
2471 static Ref<PolicyDecisionSender> create(SendFunction&& sendFunction)
2473 return adoptRef(*new PolicyDecisionSender(WTFMove(sendFunction)));
2476 template<typename... Args> void send(Args... args)
2479 m_sendFunction(std::forward<Args>(args)...);
2482 PolicyDecisionSender(SendFunction sendFunction)
2483 : m_sendFunction(WTFMove(sendFunction)) { }
2485 SendFunction m_sendFunction;
2488 void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, API::Navigation* navigation, ProcessSwapRequestedByClient processSwapRequestedByClient, WebFrameProxy& frame, API::WebsitePolicies* policies, Ref<PolicyDecisionSender>&& sender)
2490 std::optional<WebsitePoliciesData> data;
2492 data = policies->data();
2493 if (policies->websiteDataStore())
2494 changeWebsiteDataStore(policies->websiteDataStore()->websiteDataStore());
2497 if (policyAction == PolicyAction::Use && frame.isMainFrame()) {
2499 // We're about to navigate so we need to reset m_pageSuspendedDueToCurrentNavigation. If we decide to process swap,
2500 // continueNavigationInNewProcess() will take care of updating m_pageSuspendedDueToCurrentNavigation as needed.
2501 m_pageSuspendedDueToCurrentNavigation = nullptr;
2505 auto proposedProcess = process().processPool().processForNavigation(*this, *navigation, processSwapRequestedByClient, policyAction, reason);
2506 ASSERT(!reason.isNull());
2508 if (proposedProcess.ptr() != &process()) {
2509 RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "%p - WebPageProxy::decidePolicyForNavigationAction, swapping process %i with process %i for navigation, reason: %{public}s", this, processIdentifier(), proposedProcess->processIdentifier(), reason.utf8().data());
2510 LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), proposedProcess->processIdentifier(), navigation->navigationID(), navigation->loggingString());
2512 RunLoop::main().dispatch([this, protectedThis = makeRef(*this), navigation = makeRef(*navigation), proposedProcess = WTFMove(proposedProcess)]() mutable {
2513 continueNavigationInNewProcess(navigation, WTFMove(proposedProcess));
2516 RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "%p - WebPageProxy::decidePolicyForNavigationAction, keep using process %i for navigation, reason: %{public}s", this, processIdentifier(), reason.utf8().data());
2519 receivedPolicyDecision(policyAction, navigation, WTFMove(data), WTFMove(sender));
2523 void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, std::optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender)
2526 sender->send(PolicyAction::Ignore, 0, DownloadID(), std::nullopt);
2530 auto transaction = m_pageLoadState.transaction();
2532 if (action == PolicyAction::Ignore)
2533 m_pageLoadState.clearPendingAPIRequestURL(transaction);
2535 if (navigation && navigation->shouldForceDownload() && action == PolicyAction::Use)
2536 action = PolicyAction::Download;
2538 DownloadID downloadID = { };
2539 if (action == PolicyAction::Download) {
2540 // Create a download proxy.
2541 auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
2543 download->setWasUserInitiated(navigation->wasUserInitiated());
2544 download->setRedirectChain(navigation->takeRedirectChain());
2547 downloadID = download->downloadID();
2548 handleDownloadRequest(download);
2549 m_decidePolicyForResponseRequest = { };
2552 sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
2555 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, Ref<WebProcessProxy>&& process)
2557 LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
2559 Ref<WebProcessProxy> previousProcess = m_process.copyRef();
2560 std::optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? std::make_optional(m_mainFrame->frameID()) : std::nullopt;
2561 auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : WebCore::URL();
2563 ASSERT(m_process.ptr() != process.ptr());
2565 processDidTerminate(ProcessTerminationReason::NavigationSwap);
2567 swapToWebProcess(WTFMove(process), navigation, mainFrameIDInPreviousProcess);
2569 if (auto* item = navigation.targetItem()) {
2570 LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
2572 auto transaction = m_pageLoadState.transaction();
2573 m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
2575 auto itemStates = m_backForwardList->filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
2576 if (auto* page = item.suspendedPage()) {
2577 if (&page->process() == m_process.ptr())
2580 return &item != targetItem;
2582 m_process->send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)), m_pageID);
2583 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item->itemID(), *navigation.backForwardFrameLoadType(), ShouldTreatAsContinuingLoad::Yes), m_pageID);
2584 m_process->responsivenessTimer().start();
2589 if (navigation.lockBackForwardList() == LockBackForwardList::Yes || navigation.lockHistory() == LockHistory::Yes) {
2590 // 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
2591 // it instead of creating a new one.
2592 auto itemStates = m_backForwardList->filteredItemStates([currentItem = m_backForwardList->currentItem()](WebBackForwardListItem& item) {
2593 return &item == currentItem;
2595 RELEASE_ASSERT(itemStates.size() == 1);
2596 m_process->send(Messages::WebPage::SetCurrentHistoryItemForReattach(itemStates[0]), m_pageID);
2599 // FIXME: Work out timing of responding with the last policy delegate, etc
2600 ASSERT(!navigation.currentRequest().isEmpty());
2601 loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes);
2603 ASSERT(!m_mainFrame);
2604 m_mainFrameCreationHandler = [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), request = navigation.currentRequest(), mainFrameURL, isServerRedirect = navigation.currentRequestIsRedirect()]() mutable {
2605 ASSERT(m_mainFrame);
2606 // Restore the main frame's committed URL as some clients may rely on it until the next load is committed.
2607 m_mainFrame->frameLoadState().setURL(mainFrameURL);
2609 // Normally, notification of a server redirect comes from the WebContent process.
2610 // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
2611 // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
2612 if (isServerRedirect) {
2613 m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
2614 didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigation->navigationID(), WTFMove(request), { });
2618 bool isInitialNavigationInNewWindow = openedByDOM() && !hasCommittedAnyProvisionalLoads();
2619 if (!isInitialNavigationInNewWindow || !mainFrameIDInPreviousProcess)
2622 m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess = *mainFrameIDInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) {
2623 ASSERT(m_mainFrame);
2624 GlobalFrameIdentifier navigatedFrameIdentifierInNewProcess { pageID(), m_mainFrame->frameID() };
2625 previousProcess->send(Messages::WebPage::FrameBecameRemote(mainFrameIDInPreviousProcess, navigatedFrameIdentifierInNewProcess, windowIdentifier), pageID());
2629 void WebPageProxy::setUserAgent(String&& userAgent)
2631 if (m_userAgent == userAgent)
2633 m_userAgent = WTFMove(userAgent);
2635 #if ENABLE(SERVICE_WORKER)
2636 // We update the service worker there at the moment to be sure we use values used by actual web pages.
2637 // FIXME: Refactor this when we have a better User-Agent story.
2638 process().processPool().updateServiceWorkerUserAgent(m_userAgent);
2643 m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
2646 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
2648 if (m_applicationNameForUserAgent == applicationName)
2651 m_applicationNameForUserAgent = applicationName;
2652 if (!m_customUserAgent.isEmpty())
2655 setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2658 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
2660 if (m_customUserAgent == customUserAgent)
2663 m_customUserAgent = customUserAgent;
2665 if (m_customUserAgent.isEmpty()) {
2666 setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2670 setUserAgent(String { m_customUserAgent });
2673 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
2675 if (!isValid() || !m_isPageSuspended)
2678 m_isPageSuspended = false;
2680 m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
2683 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
2685 if (!isValid() || m_isPageSuspended)
2688 m_isPageSuspended = true;
2690 m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
2693 bool WebPageProxy::supportsTextEncoding() const
2695 // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
2696 return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
2699 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
2701 if (m_customTextEncodingName == encodingName)
2703 m_customTextEncodingName = encodingName;
2707 m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
2710 SessionState WebPageProxy::sessionState(WTF::Function<bool (WebBackForwardListItem&)>&& filter) const
2712 SessionState sessionState;
2714 sessionState.backForwardListState = m_backForwardList->backForwardListState(WTFMove(filter));
2716 String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
2717 if (provisionalURLString.isEmpty())
2718 provisionalURLString = m_pageLoadState.provisionalURL();
2720 if (!provisionalURLString.isEmpty())
2721 sessionState.provisionalURL = URL(URL(), provisionalURLString);
2723 sessionState.renderTreeSize = renderTreeSize();
2724 return sessionState;
2727 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
2729 m_sessionRestorationRenderTreeSize = 0;
2730 m_hitRenderTreeSizeThreshold = false;
2732 bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
2734 if (hasBackForwardList) {
2735 m_backForwardList->restoreFromState(WTFMove(sessionState.backForwardListState));
2736 process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
2738 auto transaction = m_pageLoadState.transaction();
2739 m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
2740 m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
2742 // The back / forward list was restored from a sessionState so we don't want to snapshot the current
2743 // page when navigating away. Suppress navigation snapshotting until the next load has committed
2744 suppressNextAutomaticNavigationSnapshot();
2747 // FIXME: Navigating should be separate from state restoration.
2749 m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
2750 if (!m_sessionRestorationRenderTreeSize)
2751 m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
2753 if (!sessionState.provisionalURL.isNull())
2754 return loadRequest(sessionState.provisionalURL);
2756 if (hasBackForwardList) {
2757 if (WebBackForwardListItem* item = m_backForwardList->currentItem())
2758 return goToBackForwardItem(*item);
2765 bool WebPageProxy::supportsTextZoom() const
2767 // FIXME (118840): This should also return false for standalone media and plug-in documents.
2768 if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
2774 void WebPageProxy::setTextZoomFactor(double zoomFactor)
2779 if (m_textZoomFactor == zoomFactor)
2782 m_textZoomFactor = zoomFactor;
2783 m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID);
2786 void WebPageProxy::setPageZoomFactor(double zoomFactor)
2791 if (m_pageZoomFactor == zoomFactor)
2794 closeOverlayedViews();
2796 m_pageZoomFactor = zoomFactor;
2797 m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID);
2800 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
2805 if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
2808 closeOverlayedViews();
2810 m_pageZoomFactor = pageZoomFactor;
2811 m_textZoomFactor = textZoomFactor;
2812 m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID);
2815 double WebPageProxy::pageZoomFactor() const
2817 // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
2818 // zoom which ensures that we don't use the PDF zoom for a normal page.
2819 if (m_mainFramePluginHandlesPageScaleGesture)
2820 return m_pluginZoomFactor;
2821 return m_pageZoomFactor;
2824 double WebPageProxy::pageScaleFactor() const
2826 // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
2827 // separately but decide which to return based on the main frame.
2828 if (m_mainFramePluginHandlesPageScaleGesture)
2829 return m_pluginScaleFactor;
2830 return m_pageScaleFactor;
2833 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
2840 m_pageScaleFactor = scale;
2841 m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
2844 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
2851 m_pageScaleFactor = scale;
2852 m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
2855 void WebPageProxy::scaleView(double scale)
2862 m_viewScaleFactor = scale;
2863 m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
2866 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
2868 if (m_intrinsicDeviceScaleFactor == scaleFactor)
2871 m_intrinsicDeviceScaleFactor = scaleFactor;
2874 m_drawingArea->deviceScaleFactorDidChange();
2877 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
2882 m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
2885 float WebPageProxy::deviceScaleFactor() const
2887 return m_customDeviceScaleFactor.value_or(m_intrinsicDeviceScaleFactor);
2890 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
2895 // FIXME: Remove this once we bump cairo requirements to support HiDPI.
2896 // https://bugs.webkit.org/show_bug.cgi?id=133378
2897 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
2901 if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
2904 float oldScaleFactor = deviceScaleFactor();
2906 // A value of 0 clears the customScaleFactor.
2907 if (customScaleFactor)
2908 m_customDeviceScaleFactor = customScaleFactor;
2910 m_customDeviceScaleFactor = std::nullopt;
2912 if (deviceScaleFactor() != oldScaleFactor)
2913 m_drawingArea->deviceScaleFactorDidChange();
2916 void WebPageProxy::accessibilitySettingsDidChange()
2921 m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
2924 #if ENABLE(ACCESSIBILITY_EVENTS)
2925 void WebPageProxy::updateAccessibilityEventsEnabled(bool enabled)
2930 m_process->send(Messages::WebPage::UpdateAccessibilityEventsEnabled(enabled), m_pageID);
2934 void WebPageProxy::setUseFixedLayout(bool fixed)
2939 // This check is fine as the value is initialized in the web
2940 // process as part of the creation parameters.
2941 if (fixed == m_useFixedLayout)
2944 m_useFixedLayout = fixed;
2946 m_fixedLayoutSize = IntSize();
2947 m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
2950 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
2955 if (size == m_fixedLayoutSize)
2958 m_fixedLayoutSize = size;
2959 m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
2962 void WebPageProxy::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)
2967 if (alwaysShowsHorizontalScroller == m_alwaysShowsHorizontalScroller)
2970 m_alwaysShowsHorizontalScroller = alwaysShowsHorizontalScroller;
2971 m_process->send(Messages::WebPage::SetAlwaysShowsHorizontalScroller(alwaysShowsHorizontalScroller), m_pageID);
2974 void WebPageProxy::setAlwaysShowsVerticalScroller(bool alwaysShowsVerticalScroller)
2979 if (alwaysShowsVerticalScroller == m_alwaysShowsVerticalScroller)
2982 m_alwaysShowsVerticalScroller = alwaysShowsVerticalScroller;
2983 m_process->send(Messages::WebPage::SetAlwaysShowsVerticalScroller(alwaysShowsVerticalScroller), m_pageID);
2986 void WebPageProxy::listenForLayoutMilestones(WebCore::LayoutMilestones milestones)
2991 if (milestones == m_observedLayoutMilestones)
2994 m_observedLayoutMilestones = milestones;
2995 m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
2998 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
3003 if (suppressAnimations == m_suppressScrollbarAnimations)
3006 m_suppressScrollbarAnimations = suppressAnimations;
3007 m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
3010 bool WebPageProxy::rubberBandsAtLeft() const
3012 return m_rubberBandsAtLeft;
3015 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
3017 m_rubberBandsAtLeft = rubberBandsAtLeft;
3020 bool WebPageProxy::rubberBandsAtRight() const
3022 return m_rubberBandsAtRight;
3025 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
3027 m_rubberBandsAtRight = rubberBandsAtRight;
3030 bool WebPageProxy::rubberBandsAtTop() const
3032 return m_rubberBandsAtTop;
3035 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
3037 m_rubberBandsAtTop = rubberBandsAtTop;
3040 bool WebPageProxy::rubberBandsAtBottom() const
3042 return m_rubberBandsAtBottom;
3045 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
3047 m_rubberBandsAtBottom = rubberBandsAtBottom;
3050 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
3052 if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
3055 m_enableVerticalRubberBanding = enableVerticalRubberBanding;
3059 m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
3062 bool WebPageProxy::verticalRubberBandingIsEnabled() const
3064 return m_enableVerticalRubberBanding;
3067 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
3069 if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
3072 m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
3076 m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
3079 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
3081 return m_enableHorizontalRubberBanding;
3084 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
3086 if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
3089 m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
3093 m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
3096 bool WebPageProxy::backgroundExtendsBeyondPage() const
3098 return m_backgroundExtendsBeyondPage;
3101 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
3103 if (mode == m_paginationMode)
3106 m_paginationMode = mode;
3110 m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
3113 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
3115 if (behavesLikeColumns == m_paginationBehavesLikeColumns)
3118 m_paginationBehavesLikeColumns = behavesLikeColumns;
3122 m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
3125 void WebPageProxy::setPageLength(double pageLength)
3127 if (pageLength == m_pageLength)
3130 m_pageLength = pageLength;
3134 m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
3137 void WebPageProxy::setGapBetweenPages(double gap)
3139 if (gap == m_gapBetweenPages)
3142 m_gapBetweenPages = gap;
3146 m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
3149 void WebPageProxy::setPaginationLineGridEnabled(bool lineGridEnabled)
3151 if (lineGridEnabled == m_paginationLineGridEnabled)
3154 m_paginationLineGridEnabled = lineGridEnabled;
3158 m_process->send(Messages::WebPage::SetPaginationLineGridEnabled(lineGridEnabled), m_pageID);
3161 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
3163 m_pageScaleFactor = scaleFactor;
3166 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
3168 m_pluginScaleFactor = pluginScaleFactor;
3171 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
3173 m_pluginZoomFactor = pluginZoomFactor;
3176 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3178 if (string.isEmpty()) {
3179 didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
3183 m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
3186 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
3188 m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
3191 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
3193 m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
3196 void WebPageProxy::selectFindMatch(int32_t matchIndex)
3198 m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
3201 void WebPageProxy::hideFindUI()
3203 m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
3206 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3211 m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
3214 void WebPageProxy::runJavaScriptInMainFrame(const String& script, bool forceUserGesture, WTF::Function<void (API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3217 callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3221 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3222 m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, forceUserGesture, callbackID), m_pageID);
3225 void WebPageProxy::runJavaScriptInMainFrameScriptWorld(const String& script, bool forceUserGesture, const String& worldName, WTF::Function<void(API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3228 callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3232 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3233 m_process->send(Messages::WebPage::RunJavaScriptInMainFrameScriptWorld(script, forceUserGesture, worldName, callbackID), m_pageID);
3236 void WebPageProxy::getRenderTreeExternalRepresentation(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3239 callbackFunction(String(), CallbackBase::Error::Unknown);
3243 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3244 m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
3247 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3250 callbackFunction(String(), CallbackBase::Error::Unknown);
3254 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3255 m_loadDependentStringCallbackIDs.add(callbackID);
3256 m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
3259 void WebPageProxy::getContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3262 callbackFunction(String(), CallbackBase::Error::Unknown);
3266 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3267 m_loadDependentStringCallbackIDs.add(callbackID);
3268 m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
3271 void WebPageProxy::getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3274 callbackFunction(String(), CallbackBase::Error::Unknown);
3278 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3279 m_loadDependentStringCallbackIDs.add(callbackID);
3280 m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
3283 void WebPageProxy::getSamplingProfilerOutput(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3286 callbackFunction(String(), CallbackBase::Error::Unknown);
3290 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3291 m_loadDependentStringCallbackIDs.add(callbackID);
3292 m_process->send(Messages::WebPage::GetSamplingProfilerOutput(callbackID), m_pageID);
3295 void WebPageProxy::isWebProcessResponsive(WTF::Function<void (bool isWebProcessResponsive)>&& callbackFunction)
3298 RunLoop::main().dispatch([callbackFunction = WTFMove(callbackFunction)] {
3299 bool isWebProcessResponsive = true;
3300 callbackFunction(isWebProcessResponsive);
3305 m_process->isResponsive(WTFMove(callbackFunction));
3309 void WebPageProxy::getContentsAsMHTMLData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3312 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3316 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3317 m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID), m_pageID);
3321 void WebPageProxy::getSelectionOrContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3324 callbackFunction(String(), CallbackBase::Error::Unknown);
3328 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3329 m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
3332 void WebPageProxy::getSelectionAsWebArchiveData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3335 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3339 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3340 m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
3343 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3345 if (!isValid() || !frame) {
3346 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3350 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3351 m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
3354 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3357 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3361 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3362 m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
3365 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3368 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3372 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3373 m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
3376 void WebPageProxy::forceRepaint(RefPtr<VoidCallback>&& callback)
3379 // FIXME: If the page is invalid we should not call the callback. It'd be better to just return false from forceRepaint.
3380 callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3384 Function<void(CallbackBase::Error)> didForceRepaintCallback = [this, callback = WTFMove(callback)](CallbackBase::Error error) mutable {
3385 if (error != CallbackBase::Error::None) {
3386 callback->invalidate(error);
3391 callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3395 callAfterNextPresentationUpdate([callback = WTFMove(callback)](CallbackBase::Error error) {
3396 if (error != CallbackBase::Error::None) {
3397 callback->invalidate(error);
3401 callback->performCallback();
3405 auto callbackID = m_callbacks.put(WTFMove(didForceRepaintCallback), m_process->throttler().backgroundActivityToken());
3406 m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
3407 m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID);
3410 static OptionSet<IPC::SendOption> printingSendOptions(bool isPerformingDOMPrintOperation)
3412 if (isPerformingDOMPrintOperation)
3413 return IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply;
3418 void WebPageProxy::preferencesDidChange()
3423 updateThrottleState();
3424 updateHiddenPageThrottlingAutoIncreases();
3426 pageClient().preferencesDidChange();
3428 // FIXME: It probably makes more sense to send individual preference changes.
3429 // However, WebKitTestRunner depends on getting a preference change notification
3430 // even if nothing changed in UI process, so that overrides get removed.
3432 // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
3433 m_process->send(Messages::WebPage::PreferencesDidChange(preferencesStore()), m_pageID, printingSendOptions(m_isPerformingDOMPrintOperation));
3436 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
3438 // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateMainFrame one.
3439 // When this happens, decidePolicyForNavigationActionSync() calls didCreateMainFrame() and we need to ignore the DidCreateMainFrame
3440 // IPC when it later gets processed.
3441 if (m_mainFrame && m_mainFrame->frameID() == frameID)
3444 PageClientProtector protector(pageClient());
3446 MESSAGE_CHECK(!m_mainFrame);
3447 MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3449 m_mainFrame = WebFrameProxy::create(this, frameID);
3451 // Add the frame to the process wide map.
3452 m_process->frameCreated(frameID, *m_mainFrame);
3454 if (m_mainFrameCreationHandler) {
3455 m_mainFrameCreationHandler();
3456 m_mainFrameCreationHandler = nullptr;
3460 void WebPageProxy::didCreateSubframe(uint64_t frameID)
3462 PageClientProtector protector(pageClient());
3464 MESSAGE_CHECK(m_mainFrame);
3466 // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateSubframe one.
3467 // When this happens, decidePolicyForNavigationActionSync() calls didCreateSubframe() and we need to ignore the DidCreateSubframe
3468 // IPC when it later gets processed.
3469 if (m_process->webFrame(frameID))
3472 MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3474 RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
3476 // Add the frame to the process wide map.
3477 m_process->frameCreated(frameID, *subFrame);
3480 void WebPageProxy::didCreateWindow(uint64_t frameID, GlobalWindowIdentifier&& windowIdentifier)
3482 if (m_mainFrame && m_mainFrame->frameID() == frameID) {
3483 if (auto mainFrameWindowCreationHandler = WTFMove(m_mainFrameWindowCreationHandler))
3484 mainFrameWindowCreationHandler(windowIdentifier);
3488 double WebPageProxy::estimatedProgress() const
3490 return m_pageLoadState.estimatedProgress();
3493 void WebPageProxy::didStartProgress()
3495 PageClientProtector protector(pageClient());
3497 auto transaction = m_pageLoadState.transaction();
3498 m_pageLoadState.didStartProgress(transaction);
3500 m_pageLoadState.commitChanges();
3503 void WebPageProxy::didChangeProgress(double value)
3505 PageClientProtector protector(pageClient());
3507 auto transaction = m_pageLoadState.transaction();
3508 m_pageLoadState.didChangeProgress(transaction, value);
3510 m_pageLoadState.commitChanges();
3513 void WebPageProxy::didFinishProgress()
3515 PageClientProtector protector(pageClient());
3517 auto transaction = m_pageLoadState.transaction();
3518 m_pageLoadState.didFinishProgress(transaction);
3520 m_pageLoadState.commitChanges();
3523 void WebPageProxy::didCompletePageTransition(bool isInitialEmptyDocument)
3526 // Attach drawing area for the initial empty document only if this is not a process swap.
3527 if (isInitialEmptyDocument && m_pageSuspendedDueToCurrentNavigation)
3533 // Drawing area for the suspended page will be torn down when the attach completes.
3534 m_drawingArea->attachInWebProcess();
3536 UNUSED_PARAM(isInitialEmptyDocument);
3540 void WebPageProxy::setNetworkRequestsInProgress(bool networkRequestsInProgress)
3542 auto transaction = m_pageLoadState.transaction();
3543 m_pageLoadState.setNetworkRequestsInProgress(transaction, networkRequestsInProgress);
3546 void WebPageProxy::hasInsecureContent(HasInsecureContent& hasInsecureContent)
3548 hasInsecureContent = m_pageLoadState.committedHasInsecureContent() ? HasInsecureContent::Yes : HasInsecureContent::No;
3551 void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
3553 PageClientProtector protector(pageClient());
3555 // FIXME: Message check the navigationID.
3556 m_navigationState->didDestroyNavigation(navigationID);
3559 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&& url, WebCore::URL&& unreachableURL, const UserData& userData)
3561 PageClientProtector protector(pageClient());
3563 WebFrameProxy* frame = m_process->webFrame(frameID);
3564 MESSAGE_CHECK(frame);
3565 MESSAGE_CHECK_URL(url);
3567 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3568 RefPtr<API::Navigation> navigation;
3569 if (frame->isMainFrame() && navigationID)
3570 navigation = navigationState().navigation(navigationID);
3572 // If this seemingly new load is actually continuing a server redirect for a previous navigation in a new process,
3573 // then we ignore this notification.
3574 if (navigation && navigation->currentRequestIsRedirect()) {
3575 auto navigationProcessIdentifier = navigation->currentRequestProcessIdentifier();
3576 if (navigationProcessIdentifier && *navigationProcessIdentifier != m_process->coreProcessIdentifier())
3580 LOG(Loading, "WebPageProxy %" PRIu64 " in process pid %i didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", m_pageID, m_process->processIdentifier(), frameID, navigationID, url.string().utf8().data());
3582 auto transaction = m_pageLoadState.transaction();
3584 m_pageLoadState.clearPendingAPIRequestURL(transaction);