2 * Copyright (C) 2010-2017 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 "AuthenticationChallengeProxy.h"
55 #include "AuthenticationDecisionListener.h"
56 #include "DataReference.h"
57 #include "DownloadProxy.h"
58 #include "DrawingAreaProxy.h"
59 #include "DrawingAreaProxyMessages.h"
60 #include "EventDispatcherMessages.h"
61 #include "FrameInfoData.h"
62 #include "LoadParameters.h"
64 #include "NativeWebGestureEvent.h"
65 #include "NativeWebKeyboardEvent.h"
66 #include "NativeWebMouseEvent.h"
67 #include "NativeWebWheelEvent.h"
68 #include "NavigationActionData.h"
69 #include "NetworkProcessMessages.h"
70 #include "NotificationPermissionRequest.h"
71 #include "NotificationPermissionRequestManager.h"
72 #include "OptionalCallbackID.h"
73 #include "PageClient.h"
74 #include "PluginInformation.h"
75 #include "PluginProcessManager.h"
76 #include "PrintInfo.h"
77 #include "TextChecker.h"
78 #include "TextCheckerState.h"
79 #include "URLSchemeTaskParameters.h"
80 #include "UserMediaPermissionRequestProxy.h"
81 #include "UserMediaProcessManager.h"
82 #include "WKContextPrivate.h"
83 #include "WebAutomationSession.h"
84 #include "WebBackForwardList.h"
85 #include "WebBackForwardListItem.h"
86 #include "WebCertificateInfo.h"
87 #include "WebContextMenuItem.h"
88 #include "WebContextMenuProxy.h"
89 #include "WebCoreArgumentCoders.h"
90 #include "WebEditCommandProxy.h"
92 #include "WebEventConversion.h"
93 #include "WebFramePolicyListenerProxy.h"
94 #include "WebFullScreenManagerProxy.h"
95 #include "WebFullScreenManagerProxyMessages.h"
97 #include "WebInspectorProxy.h"
98 #include "WebInspectorUtilities.h"
99 #include "WebNavigationState.h"
100 #include "WebNotificationManagerProxy.h"
101 #include "WebOpenPanelResultListenerProxy.h"
102 #include "WebPageCreationParameters.h"
103 #include "WebPageGroup.h"
104 #include "WebPageGroupData.h"
105 #include "WebPageMessages.h"
106 #include "WebPageProxyMessages.h"
107 #include "WebPaymentCoordinatorProxy.h"
108 #include "WebPopupItem.h"
109 #include "WebPopupMenuProxy.h"
110 #include "WebPreferences.h"
111 #include "WebProcessMessages.h"
112 #include "WebProcessPool.h"
113 #include "WebProcessProxy.h"
114 #include "WebProtectionSpace.h"
115 #include "WebURLSchemeHandler.h"
116 #include "WebUserContentControllerProxy.h"
117 #include "WebsiteDataStore.h"
118 #include <WebCore/AttachmentTypes.h>
119 #include <WebCore/BitmapImage.h>
120 #include <WebCore/DiagnosticLoggingClient.h>
121 #include <WebCore/DiagnosticLoggingKeys.h>
122 #include <WebCore/DragController.h>
123 #include <WebCore/DragData.h>
124 #include <WebCore/EventNames.h>
125 #include <WebCore/FloatRect.h>
126 #include <WebCore/FocusDirection.h>
127 #include <WebCore/JSDOMBinding.h>
128 #include <WebCore/JSDOMExceptionHandling.h>
129 #include <WebCore/LengthBox.h>
130 #include <WebCore/MIMETypeRegistry.h>
131 #include <WebCore/MediaStreamRequest.h>
132 #include <WebCore/PerformanceLoggingClient.h>
133 #include <WebCore/PublicSuffix.h>
134 #include <WebCore/RenderEmbeddedObject.h>
135 #include <WebCore/SerializedCryptoKeyWrap.h>
136 #include <WebCore/SharedBuffer.h>
137 #include <WebCore/TextCheckerClient.h>
138 #include <WebCore/TextIndicator.h>
139 #include <WebCore/URL.h>
140 #include <WebCore/URLParser.h>
141 #include <WebCore/ValidationBubble.h>
142 #include <WebCore/WindowFeatures.h>
144 #include <wtf/NeverDestroyed.h>
145 #include <wtf/SystemTracing.h>
146 #include <wtf/text/StringView.h>
148 #if ENABLE(APPLICATION_MANIFEST)
149 #include "APIApplicationManifest.h"
152 #if ENABLE(ASYNC_SCROLLING)
153 #include "RemoteScrollingCoordinatorProxy.h"
157 #include <wtf/RefCountedLeakCounter.h>
161 #include "RemoteLayerTreeDrawingAreaProxy.h"
162 #include "RemoteLayerTreeScrollingPerformanceData.h"
163 #include "TouchBarMenuData.h"
164 #include "TouchBarMenuItemData.h"
165 #include "VideoFullscreenManagerProxy.h"
166 #include "VideoFullscreenManagerProxyMessages.h"
167 #include "ViewSnapshotStore.h"
168 #include <WebCore/MachSendRight.h>
169 #include <WebCore/RunLoopObserver.h>
170 #include <WebCore/TextIndicatorWindow.h>
174 #include "WebSelectionData.h"
178 #include <WebCore/CairoUtilities.h>
181 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS)
182 #include <WebCore/MediaPlaybackTarget.h>
183 #include <WebCore/WebMediaSessionManager.h>
186 #if ENABLE(MEDIA_SESSION)
187 #include "WebMediaSessionFocusManager.h"
188 #include "WebMediaSessionMetadata.h"
189 #include <WebCore/MediaSessionMetadata.h>
192 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
193 #include "PlaybackSessionManagerProxy.h"
196 // This controls what strategy we use for mouse wheel coalescing.
197 #define MERGE_WHEEL_EVENTS 1
199 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_process->connection())
200 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(m_process->checkURLReceivedFromWebProcess(url), m_process->connection())
202 #define RELEASE_LOG_IF_ALLOWED(channel, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, __VA_ARGS__)
204 using namespace WebCore;
206 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
207 static const unsigned wheelEventQueueSizeThreshold = 10;
211 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
213 class ExceededDatabaseQuotaRecords {
214 WTF_MAKE_NONCOPYABLE(ExceededDatabaseQuotaRecords); WTF_MAKE_FAST_ALLOCATED;
215 friend class NeverDestroyed<ExceededDatabaseQuotaRecords>;
219 String originIdentifier;
222 uint64_t currentQuota;
223 uint64_t currentOriginUsage;
224 uint64_t currentDatabaseUsage;
225 uint64_t expectedUsage;
226 RefPtr<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply> reply;
229 static ExceededDatabaseQuotaRecords& singleton();
231 std::unique_ptr<Record> createRecord(uint64_t frameID, String originIdentifier,
232 String databaseName, String displayName, uint64_t currentQuota,
233 uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage,
234 Ref<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply>&&);
236 void add(std::unique_ptr<Record>);
237 bool areBeingProcessed() const { return !!m_currentRecord; }
241 ExceededDatabaseQuotaRecords() { }
242 ~ExceededDatabaseQuotaRecords() { }
244 Deque<std::unique_ptr<Record>> m_records;
245 std::unique_ptr<Record> m_currentRecord;
248 ExceededDatabaseQuotaRecords& ExceededDatabaseQuotaRecords::singleton()
250 static NeverDestroyed<ExceededDatabaseQuotaRecords> records;
254 std::unique_ptr<ExceededDatabaseQuotaRecords::Record> ExceededDatabaseQuotaRecords::createRecord(
255 uint64_t frameID, String originIdentifier, String databaseName, String displayName,
256 uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage,
257 uint64_t expectedUsage, Ref<Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply>&& reply)
259 auto record = std::make_unique<Record>();
260 record->frameID = frameID;
261 record->originIdentifier = originIdentifier;
262 record->databaseName = databaseName;
263 record->displayName = displayName;
264 record->currentQuota = currentQuota;
265 record->currentOriginUsage = currentOriginUsage;
266 record->currentDatabaseUsage = currentDatabaseUsage;
267 record->expectedUsage = expectedUsage;
268 record->reply = WTFMove(reply);
272 void ExceededDatabaseQuotaRecords::add(std::unique_ptr<ExceededDatabaseQuotaRecords::Record> record)
274 m_records.append(WTFMove(record));
277 ExceededDatabaseQuotaRecords::Record* ExceededDatabaseQuotaRecords::next()
279 m_currentRecord = nullptr;
280 if (!m_records.isEmpty())
281 m_currentRecord = m_records.takeFirst();
282 return m_currentRecord.get();
286 static const char* webKeyboardEventTypeString(WebEvent::Type type)
289 case WebEvent::KeyDown:
292 case WebEvent::KeyUp:
295 case WebEvent::RawKeyDown:
302 ASSERT_NOT_REACHED();
306 #endif // !LOG_DISABLED
308 class PageClientProtector {
309 WTF_MAKE_NONCOPYABLE(PageClientProtector);
311 PageClientProtector(PageClient& pageClient)
312 : m_pageClient(pageClient)
314 m_pageClient.refView();
317 ~PageClientProtector()
319 m_pageClient.derefView();
323 PageClient& m_pageClient;
326 Ref<WebPageProxy> WebPageProxy::create(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
328 return adoptRef(*new WebPageProxy(pageClient, process, pageID, WTFMove(configuration)));
331 WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
332 : m_pageClient(pageClient)
333 , m_configuration(WTFMove(configuration))
334 , m_loaderClient(std::make_unique<API::LoaderClient>())
335 , m_policyClient(std::make_unique<API::PolicyClient>())
336 , m_iconLoadingClient(std::make_unique<API::IconLoadingClient>())
337 , m_formClient(std::make_unique<API::FormClient>())
338 , m_uiClient(std::make_unique<API::UIClient>())
339 , m_findClient(std::make_unique<API::FindClient>())
340 , m_findMatchesClient(std::make_unique<API::FindMatchesClient>())
341 #if ENABLE(CONTEXT_MENUS)
342 , m_contextMenuClient(std::make_unique<API::ContextMenuClient>())
344 , m_navigationState(std::make_unique<WebNavigationState>())
346 , m_pageGroup(*m_configuration->pageGroup())
347 , m_preferences(*m_configuration->preferences())
348 , m_userContentController(*m_configuration->userContentController())
349 , m_visitedLinkStore(*m_configuration->visitedLinkStore())
350 , m_websiteDataStore(m_configuration->websiteDataStore()->websiteDataStore())
351 , m_userAgent(standardUserAgent())
352 , m_overrideContentSecurityPolicy { m_configuration->overrideContentSecurityPolicy() }
353 , m_treatsSHA1CertificatesAsInsecure(m_configuration->treatsSHA1SignedCertificatesAsInsecure())
354 #if ENABLE(FULLSCREEN_API)
355 , m_fullscreenClient(std::make_unique<API::FullscreenClient>())
357 , m_geolocationPermissionRequestManager(*this)
358 , m_notificationPermissionRequestManager(*this)
360 , m_alwaysRunsAtForegroundPriority(m_configuration->alwaysRunsAtForegroundPriority())
362 , m_initialCapitalizationEnabled(m_configuration->initialCapitalizationEnabled())
363 , m_cpuLimit(m_configuration->cpuLimit())
364 , m_backForwardList(WebBackForwardList::create(*this))
365 , m_waitsForPaintAfterViewDidMoveToWindow(m_configuration->waitsForPaintAfterViewDidMoveToWindow())
367 , m_controlledByAutomation(m_configuration->isControlledByAutomation())
369 , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
371 , m_pageLoadState(*this)
372 , m_configurationPreferenceValues(m_configuration->preferenceValues())
374 m_webProcessLifetimeTracker.addObserver(m_visitedLinkStore);
375 m_webProcessLifetimeTracker.addObserver(m_websiteDataStore);
377 updateActivityState();
378 updateThrottleState();
379 updateHiddenPageThrottlingAutoIncreases();
381 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
382 m_layerHostingMode = m_activityState & ActivityState::IsInWindow ? m_pageClient.viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
385 platformInitialize();
388 webPageProxyCounter.increment();
391 WebProcessPool::statistics().wkPageCount++;
393 m_preferences->addPage(*this);
394 m_pageGroup->addPage(this);
396 m_inspector = WebInspectorProxy::create(this);
397 #if ENABLE(FULLSCREEN_API)
398 m_fullScreenManager = WebFullScreenManagerProxy::create(*this, m_pageClient.fullScreenManagerProxyClient());
400 #if PLATFORM(IOS) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
401 m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
402 m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
405 #if ENABLE(APPLE_PAY)
406 m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
409 m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
412 m_activityStateChangeDispatcher = std::make_unique<RunLoopObserver>(static_cast<CFIndex>(RunLoopObserver::WellKnownRunLoopOrders::ActivityStateChange), [this] {
413 this->dispatchActivityStateChange();
418 WebPageProxy::~WebPageProxy()
420 ASSERT(m_process->webPage(m_pageID) != this);
422 for (WebPageProxy* page : m_process->pages())
423 ASSERT(page != this);
429 WebProcessPool::statistics().wkPageCount--;
431 if (m_hasSpellDocumentTag)
432 TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag);
434 m_preferences->removePage(*this);
435 m_pageGroup->removePage(this);
438 webPageProxyCounter.decrement();
442 PAL::SessionID WebPageProxy::sessionID() const
444 return m_websiteDataStore->sessionID();
447 void WebPageProxy::changeWebsiteDataStore(WebsiteDataStore& websiteDataStore)
449 m_process->processPool().pageEndUsingWebsiteDataStore(*this);
450 m_websiteDataStore = websiteDataStore;
451 m_process->processPool().pageBeginUsingWebsiteDataStore(*this);
454 const API::PageConfiguration& WebPageProxy::configuration() const
456 return m_configuration.get();
459 ProcessID WebPageProxy::processIdentifier() const
464 return m_process->processIdentifier();
467 bool WebPageProxy::isValid() const
469 // A page that has been explicitly closed is never valid.
476 void WebPageProxy::setPreferences(WebPreferences& preferences)
478 if (&preferences == m_preferences.ptr())
481 m_preferences->removePage(*this);
482 m_preferences = preferences;
483 m_preferences->addPage(*this);
485 preferencesDidChange();
488 void WebPageProxy::setHistoryClient(std::unique_ptr<API::HistoryClient>&& historyClient)
490 m_historyClient = WTFMove(historyClient);
493 void WebPageProxy::setNavigationClient(std::unique_ptr<API::NavigationClient>&& navigationClient)
495 m_navigationClient = WTFMove(navigationClient);
498 void WebPageProxy::setLoaderClient(std::unique_ptr<API::LoaderClient>&& loaderClient)
501 m_loaderClient = std::make_unique<API::LoaderClient>();
505 m_loaderClient = WTFMove(loaderClient);
508 void WebPageProxy::setPolicyClient(std::unique_ptr<API::PolicyClient>&& policyClient)
511 m_policyClient = std::make_unique<API::PolicyClient>();
515 m_policyClient = WTFMove(policyClient);
518 void WebPageProxy::setFormClient(std::unique_ptr<API::FormClient>&& formClient)
521 m_formClient = std::make_unique<API::FormClient>();
525 m_formClient = WTFMove(formClient);
528 void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient>&& uiClient)
531 m_uiClient = std::make_unique<API::UIClient>();
535 m_uiClient = WTFMove(uiClient);
540 m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient->canRunBeforeUnloadConfirmPanel()), m_pageID);
541 setCanRunModal(m_uiClient->canRunModal());
544 void WebPageProxy::setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&& iconLoadingClient)
546 bool hasClient = iconLoadingClient.get();
547 if (!iconLoadingClient)
548 m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
550 m_iconLoadingClient = WTFMove(iconLoadingClient);
555 m_process->send(Messages::WebPage::SetUseIconLoadingClient(hasClient), m_pageID);
558 void WebPageProxy::setFindClient(std::unique_ptr<API::FindClient>&& findClient)
561 m_findClient = std::make_unique<API::FindClient>();
565 m_findClient = WTFMove(findClient);
568 void WebPageProxy::setFindMatchesClient(std::unique_ptr<API::FindMatchesClient>&& findMatchesClient)
570 if (!findMatchesClient) {
571 m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
575 m_findMatchesClient = WTFMove(findMatchesClient);
578 void WebPageProxy::setDiagnosticLoggingClient(std::unique_ptr<API::DiagnosticLoggingClient>&& diagnosticLoggingClient)
580 m_diagnosticLoggingClient = WTFMove(diagnosticLoggingClient);
583 #if ENABLE(CONTEXT_MENUS)
584 void WebPageProxy::setContextMenuClient(std::unique_ptr<API::ContextMenuClient>&& contextMenuClient)
586 if (!contextMenuClient) {
587 m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
591 m_contextMenuClient = WTFMove(contextMenuClient);
595 void WebPageProxy::setInjectedBundleClient(const WKPageInjectedBundleClientBase* client)
598 m_injectedBundleClient = nullptr;
602 m_injectedBundleClient = std::make_unique<WebPageInjectedBundleClient>();
603 m_injectedBundleClient->initialize(client);
606 void WebPageProxy::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
608 ASSERT(m_process->connection() == &connection);
610 if (!m_injectedBundleClient)
613 m_injectedBundleClient->didReceiveMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get());
616 void WebPageProxy::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
618 ASSERT(m_process->connection() == &connection);
620 if (!m_injectedBundleClient)
623 RefPtr<API::Object> returnData;
624 m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get(), returnData);
625 returnUserData = UserData(m_process->transformObjectsToHandles(returnData.get()));
628 void WebPageProxy::reattachToWebProcess()
632 ASSERT(m_process->state() == WebProcessProxy::State::Terminated);
635 m_process->removeWebPage(*this, m_pageID);
636 m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
638 m_process = m_process->processPool().createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get());
640 ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
641 if (m_process->state() == ChildProcessProxy::State::Running)
642 processDidFinishLaunching();
643 m_process->addExistingWebPage(*this, m_pageID);
644 m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
646 updateActivityState();
647 updateThrottleState();
649 m_inspector = WebInspectorProxy::create(this);
650 #if ENABLE(FULLSCREEN_API)
651 m_fullScreenManager = WebFullScreenManagerProxy::create(*this, m_pageClient.fullScreenManagerProxyClient());
653 #if PLATFORM(IOS) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
654 m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
655 m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
658 #if ENABLE(APPLE_PAY)
659 m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
664 m_pageClient.didRelaunchProcess();
665 m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
668 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessForReload()
674 reattachToWebProcess();
676 if (!m_backForwardList->currentItem())
679 auto navigation = m_navigationState->createReloadNavigation();
681 // We allow stale content when reloading a WebProcess that's been killed or crashed.
682 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID()), m_pageID);
683 m_process->responsivenessTimer().start();
685 return WTFMove(navigation);
688 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem* item)
694 reattachToWebProcess();
699 if (item != m_backForwardList->currentItem())
700 m_backForwardList->goToItem(*item);
702 auto navigation = m_navigationState->createBackForwardNavigation();
704 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item->itemID()), m_pageID);
705 m_process->responsivenessTimer().start();
707 return WTFMove(navigation);
710 void WebPageProxy::initializeWebPage()
714 const BackForwardListItemVector& items = m_backForwardList->entries();
715 for (size_t i = 0; i < items.size(); ++i)
716 m_process->registerNewWebBackForwardListItem(items[i].get());
718 m_drawingArea = m_pageClient.createDrawingAreaProxy();
719 ASSERT(m_drawingArea);
721 #if ENABLE(ASYNC_SCROLLING)
722 if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) {
723 m_scrollingCoordinatorProxy = std::make_unique<RemoteScrollingCoordinatorProxy>(*this);
725 // On iOS, main frame scrolls are sent in terms of visible rect updates.
726 m_scrollingCoordinatorProxy->setPropagatesMainFrameScrolls(false);
731 process().send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters()), 0);
733 m_needsToFinishInitializingWebPageAfterProcessLaunch = true;
734 finishInitializingWebPageAfterProcessLaunch();
737 void WebPageProxy::finishInitializingWebPageAfterProcessLaunch()
739 if (!m_needsToFinishInitializingWebPageAfterProcessLaunch)
741 if (m_process->state() != WebProcessProxy::State::Running)
744 m_needsToFinishInitializingWebPageAfterProcessLaunch = false;
745 m_process->addVisitedLinkStore(m_visitedLinkStore);
748 void WebPageProxy::close()
755 if (m_activePopupMenu)
756 m_activePopupMenu->cancelTracking();
758 if (m_controlledByAutomation) {
759 if (auto* automationSession = process().processPool().automationSession())
760 automationSession->willClosePage(*this);
763 #if ENABLE(CONTEXT_MENUS)
764 m_activeContextMenu = nullptr;
767 m_backForwardList->pageClosed();
768 m_pageClient.pageClosed();
770 m_process->disconnectFramesFromPage(this);
772 resetState(ResetStateReason::PageInvalidated);
774 m_loaderClient = std::make_unique<API::LoaderClient>();
775 m_navigationClient = nullptr;
776 m_policyClient = std::make_unique<API::PolicyClient>();
777 m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
778 m_formClient = std::make_unique<API::FormClient>();
779 m_uiClient = std::make_unique<API::UIClient>();
780 m_findClient = std::make_unique<API::FindClient>();
781 m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
782 m_diagnosticLoggingClient = nullptr;
783 #if ENABLE(CONTEXT_MENUS)
784 m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
786 #if ENABLE(FULLSCREEN_API)
787 m_fullscreenClient = std::make_unique<API::FullscreenClient>();
790 m_webProcessLifetimeTracker.pageWasInvalidated();
792 m_process->send(Messages::WebPage::Close(), m_pageID);
793 m_process->removeWebPage(*this, m_pageID);
794 m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
795 m_process->processPool().supplement<WebNotificationManagerProxy>()->clearNotifications(this);
797 // Null out related WebPageProxy to avoid leaks.
798 m_configuration->setRelatedPage(nullptr);
801 // Make sure we don't hold a process assertion after getting closed.
802 m_activityToken = nullptr;
805 stopAllURLSchemeTasks();
808 bool WebPageProxy::tryClose()
813 // Close without delay if the process allows it. Our goal is to terminate
814 // the process, so we check a per-process status bit.
815 if (m_process->isSuddenTerminationEnabled())
818 m_process->send(Messages::WebPage::TryClose(), m_pageID);
819 m_process->responsivenessTimer().start();
823 bool WebPageProxy::maybeInitializeSandboxExtensionHandle(const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
825 if (!url.isLocalFile())
828 if (m_process->hasAssumedReadAccessToURL(url))
831 // Inspector resources are in a directory with assumed access.
832 ASSERT_WITH_SECURITY_IMPLICATION(!WebKit::isInspectorPage(*this));
834 SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, sandboxExtensionHandle);
839 void WebPageProxy::addPlatformLoadParameters(LoadParameters&)
844 RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
849 auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request));
851 auto transaction = m_pageLoadState.transaction();
853 auto url = request.url();
854 m_pageLoadState.setPendingAPIRequestURL(transaction, url);
857 reattachToWebProcess();
859 LoadParameters loadParameters;
860 loadParameters.navigationID = navigation->navigationID();
861 loadParameters.request = WTFMove(request);
862 loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
863 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
864 bool createdExtension = maybeInitializeSandboxExtensionHandle(url, loadParameters.sandboxExtensionHandle);
865 if (createdExtension)
866 m_process->willAcquireUniversalFileReadSandboxExtension();
867 addPlatformLoadParameters(loadParameters);
869 m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
870 m_process->responsivenessTimer().start();
872 return WTFMove(navigation);
875 RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
881 reattachToWebProcess();
883 URL fileURL = URL(URL(), fileURLString);
884 if (!fileURL.isLocalFile())
887 URL resourceDirectoryURL;
888 if (resourceDirectoryURLString.isNull())
889 resourceDirectoryURL = URL(ParsedURLString, ASCIILiteral("file:///"));
891 resourceDirectoryURL = URL(URL(), resourceDirectoryURLString);
892 if (!resourceDirectoryURL.isLocalFile())
896 auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL));
898 auto transaction = m_pageLoadState.transaction();
900 m_pageLoadState.setPendingAPIRequestURL(transaction, fileURLString);
902 String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
904 LoadParameters loadParameters;
905 loadParameters.navigationID = navigation->navigationID();
906 loadParameters.request = fileURL;
907 loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)ShouldOpenExternalURLsPolicy::ShouldNotAllow;
908 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
909 SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::Type::ReadOnly, loadParameters.sandboxExtensionHandle);
910 addPlatformLoadParameters(loadParameters);
912 m_process->assumeReadAccessToBaseURL(resourceDirectoryURL);
913 m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
914 m_process->responsivenessTimer().start();
916 return WTFMove(navigation);
919 RefPtr<API::Navigation> WebPageProxy::loadData(API::Data* data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData)
924 auto navigation = m_navigationState->createLoadDataNavigation();
926 auto transaction = m_pageLoadState.transaction();
928 m_pageLoadState.setPendingAPIRequestURL(transaction, !baseURL.isEmpty() ? baseURL : blankURL().string());
931 reattachToWebProcess();
933 LoadParameters loadParameters;
934 loadParameters.navigationID = navigation->navigationID();
935 loadParameters.data = data->dataReference();
936 loadParameters.MIMEType = MIMEType;
937 loadParameters.encodingName = encoding;
938 loadParameters.baseURLString = baseURL;
939 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
940 addPlatformLoadParameters(loadParameters);
942 m_process->assumeReadAccessToBaseURL(baseURL);
943 m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
944 m_process->responsivenessTimer().start();
946 return WTFMove(navigation);
949 // FIXME: Get rid of loadHTMLString and just use loadData instead.
950 RefPtr<API::Navigation> WebPageProxy::loadHTMLString(const String& htmlString, const String& baseURL, API::Object* userData)
955 auto navigation = m_navigationState->createLoadDataNavigation();
957 auto transaction = m_pageLoadState.transaction();
959 m_pageLoadState.setPendingAPIRequestURL(transaction, !baseURL.isEmpty() ? baseURL : blankURL().string());
962 reattachToWebProcess();
964 LoadParameters loadParameters;
965 loadParameters.navigationID = navigation->navigationID();
966 loadParameters.string = htmlString;
967 loadParameters.MIMEType = ASCIILiteral("text/html");
968 loadParameters.baseURLString = baseURL;
969 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
970 addPlatformLoadParameters(loadParameters);
972 m_process->assumeReadAccessToBaseURL(baseURL);
973 m_process->send(Messages::WebPage::LoadString(loadParameters), m_pageID);
974 m_process->responsivenessTimer().start();
976 return WTFMove(navigation);
979 void WebPageProxy::loadAlternateHTMLString(const String& htmlString, const WebCore::URL& baseURL, const WebCore::URL& unreachableURL, API::Object* userData)
981 // When the UIProcess is in the process of handling a failing provisional load, do not attempt to
982 // start a second alternative HTML load as this will prevent the page load state from being
984 if (m_isClosed || m_isLoadingAlternateHTMLStringForFailingProvisionalLoad)
987 if (!m_failingProvisionalLoadURL.isEmpty())
988 m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = true;
991 reattachToWebProcess();
993 auto transaction = m_pageLoadState.transaction();
995 m_pageLoadState.setPendingAPIRequestURL(transaction, unreachableURL);
996 m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
999 m_mainFrame->setUnreachableURL(unreachableURL);
1001 LoadParameters loadParameters;
1002 loadParameters.navigationID = 0;
1003 loadParameters.string = htmlString;
1004 loadParameters.baseURLString = baseURL;
1005 loadParameters.unreachableURLString = unreachableURL;
1006 loadParameters.provisionalLoadErrorURLString = m_failingProvisionalLoadURL;
1007 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1008 addPlatformLoadParameters(loadParameters);
1010 m_process->assumeReadAccessToBaseURL(baseURL);
1011 m_process->assumeReadAccessToBaseURL(unreachableURL);
1012 m_process->send(Messages::WebPage::LoadAlternateHTMLString(loadParameters), m_pageID);
1013 m_process->responsivenessTimer().start();
1016 void WebPageProxy::loadPlainTextString(const String& string, API::Object* userData)
1022 reattachToWebProcess();
1024 auto transaction = m_pageLoadState.transaction();
1025 m_pageLoadState.setPendingAPIRequestURL(transaction, blankURL().string());
1027 LoadParameters loadParameters;
1028 loadParameters.navigationID = 0;
1029 loadParameters.string = string;
1030 loadParameters.MIMEType = ASCIILiteral("text/plain");
1031 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1032 addPlatformLoadParameters(loadParameters);
1034 m_process->send(Messages::WebPage::LoadString(loadParameters), m_pageID);
1035 m_process->responsivenessTimer().start();
1038 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
1044 reattachToWebProcess();
1046 auto transaction = m_pageLoadState.transaction();
1047 m_pageLoadState.setPendingAPIRequestURL(transaction, blankURL().string());
1049 LoadParameters loadParameters;
1050 loadParameters.navigationID = 0;
1051 loadParameters.data = webArchiveData->dataReference();
1052 loadParameters.MIMEType = ASCIILiteral("application/x-webarchive");
1053 loadParameters.encodingName = ASCIILiteral("utf-16");
1054 loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1055 addPlatformLoadParameters(loadParameters);
1057 m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1058 m_process->responsivenessTimer().start();
1061 void WebPageProxy::navigateToPDFLinkWithSimulatedClick(const String& url, IntPoint documentPoint, IntPoint screenPoint)
1066 if (WebCore::protocolIsJavaScript(url))
1070 reattachToWebProcess();
1072 m_process->send(Messages::WebPage::NavigateToPDFLinkWithSimulatedClick(url, documentPoint, screenPoint), m_pageID);
1073 m_process->responsivenessTimer().start();
1076 void WebPageProxy::stopLoading()
1081 m_process->send(Messages::WebPage::StopLoading(), m_pageID);
1082 m_process->responsivenessTimer().start();
1085 RefPtr<API::Navigation> WebPageProxy::reload(OptionSet<WebCore::ReloadOption> options)
1087 SandboxExtension::Handle sandboxExtensionHandle;
1089 String url = currentURL();
1090 if (!url.isEmpty()) {
1091 auto transaction = m_pageLoadState.transaction();
1092 m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1094 // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
1095 bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), url), sandboxExtensionHandle);
1096 if (createdExtension)
1097 m_process->willAcquireUniversalFileReadSandboxExtension();
1101 return reattachToWebProcessForReload();
1103 auto navigation = m_navigationState->createReloadNavigation();
1105 m_process->send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle), m_pageID);
1106 m_process->responsivenessTimer().start();
1108 return WTFMove(navigation);
1111 void WebPageProxy::recordAutomaticNavigationSnapshot()
1113 if (m_suppressAutomaticNavigationSnapshotting)
1116 if (WebBackForwardListItem* item = m_backForwardList->currentItem())
1117 recordNavigationSnapshot(*item);
1120 void WebPageProxy::recordNavigationSnapshot(WebBackForwardListItem& item)
1122 if (!m_shouldRecordNavigationSnapshots)
1126 ViewSnapshotStore::singleton().recordSnapshot(*this, item);
1132 RefPtr<API::Navigation> WebPageProxy::goForward()
1134 WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
1138 auto transaction = m_pageLoadState.transaction();
1140 m_pageLoadState.setPendingAPIRequestURL(transaction, forwardItem->url());
1143 return reattachToWebProcessWithItem(forwardItem);
1145 RefPtr<API::Navigation> navigation;
1146 if (!m_backForwardList->currentItem()->itemIsInSameDocument(*forwardItem))
1147 navigation = m_navigationState->createBackForwardNavigation();
1149 m_process->send(Messages::WebPage::GoForward(navigation ? navigation->navigationID() : 0, forwardItem->itemID()), m_pageID);
1150 m_process->responsivenessTimer().start();
1155 RefPtr<API::Navigation> WebPageProxy::goBack()
1157 WebBackForwardListItem* backItem = m_backForwardList->backItem();
1161 auto transaction = m_pageLoadState.transaction();
1163 m_pageLoadState.setPendingAPIRequestURL(transaction, backItem->url());
1166 return reattachToWebProcessWithItem(backItem);
1168 RefPtr<API::Navigation> navigation;
1169 if (!m_backForwardList->currentItem()->itemIsInSameDocument(*backItem))
1170 navigation = m_navigationState->createBackForwardNavigation();
1172 m_process->send(Messages::WebPage::GoBack(navigation ? navigation->navigationID() : 0, backItem->itemID()), m_pageID);
1173 m_process->responsivenessTimer().start();
1178 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem* item)
1181 return reattachToWebProcessWithItem(item);
1183 auto transaction = m_pageLoadState.transaction();
1185 m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
1187 RefPtr<API::Navigation> navigation;
1188 if (!m_backForwardList->currentItem()->itemIsInSameDocument(*item))
1189 navigation = m_navigationState->createBackForwardNavigation();
1191 m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item->itemID()), m_pageID);
1192 m_process->responsivenessTimer().start();
1197 void WebPageProxy::tryRestoreScrollPosition()
1202 m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
1205 void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<Ref<WebBackForwardListItem>>&& removed)
1207 PageClientProtector protector(m_pageClient);
1209 if (!m_navigationClient || !m_navigationClient->didChangeBackForwardList(*this, added, removed))
1210 m_loaderClient->didChangeBackForwardList(*this, added, WTFMove(removed));
1212 auto transaction = m_pageLoadState.transaction();
1214 m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
1215 m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
1218 void WebPageProxy::willGoToBackForwardListItem(uint64_t itemID, bool inPageCache, const UserData& userData)
1220 PageClientProtector protector(m_pageClient);
1222 if (auto* item = m_process->webBackForwardItem(itemID)) {
1223 if (m_navigationClient && m_navigationClient->willGoToBackForwardListItem(*this, *item, inPageCache, m_process->transformHandlesToObjects(userData.object()).get()))
1225 m_loaderClient->willGoToBackForwardListItem(*this, *item, m_process->transformHandlesToObjects(userData.object()).get());
1229 bool WebPageProxy::shouldKeepCurrentBackForwardListItemInList(WebBackForwardListItem& item)
1231 PageClientProtector protector(m_pageClient);
1233 return m_loaderClient->shouldKeepCurrentBackForwardListItemInList(*this, item);
1236 bool WebPageProxy::canShowMIMEType(const String& mimeType)
1238 if (MIMETypeRegistry::canShowMIMEType(mimeType))
1241 #if ENABLE(NETSCAPE_PLUGIN_API)
1242 String newMimeType = mimeType;
1243 PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL());
1244 if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
1246 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1249 // On Mac, we can show PDFs.
1250 if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebProcessPool::omitPDFSupport())
1252 #endif // PLATFORM(COCOA)
1257 void WebPageProxy::setControlledByAutomation(bool controlled)
1259 if (m_controlledByAutomation == controlled)
1262 m_controlledByAutomation = controlled;
1265 m_process->send(Messages::WebPage::SetControlledByAutomation(controlled), m_pageID);
1268 #if ENABLE(REMOTE_INSPECTOR)
1269 void WebPageProxy::setAllowsRemoteInspection(bool allow)
1271 if (m_allowsRemoteInspection == allow)
1274 m_allowsRemoteInspection = allow;
1277 m_process->send(Messages::WebPage::SetAllowsRemoteInspection(allow), m_pageID);
1280 void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
1282 if (m_remoteInspectionNameOverride == name)
1285 m_remoteInspectionNameOverride = name;
1288 m_process->send(Messages::WebPage::SetRemoteInspectionNameOverride(m_remoteInspectionNameOverride), m_pageID);
1293 void WebPageProxy::setDrawsBackground(bool drawsBackground)
1295 if (m_drawsBackground == drawsBackground)
1298 m_drawsBackground = drawsBackground;
1301 m_process->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
1304 void WebPageProxy::setTopContentInset(float contentInset)
1306 if (m_topContentInset == contentInset)
1309 m_topContentInset = contentInset;
1314 MachSendRight fence = m_drawingArea->createFence();
1316 auto fenceAttachment = IPC::Attachment(fence.leakSendRight(), MACH_MSG_TYPE_MOVE_SEND);
1317 m_process->send(Messages::WebPage::SetTopContentInsetFenced(contentInset, fenceAttachment), m_pageID);
1319 m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
1323 void WebPageProxy::setUnderlayColor(const Color& color)
1325 if (m_underlayColor == color)
1328 m_underlayColor = color;
1331 m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1334 void WebPageProxy::viewWillStartLiveResize()
1338 #if ENABLE(INPUT_TYPE_COLOR_POPOVER) && ENABLE(INPUT_TYPE_COLOR)
1342 m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1345 void WebPageProxy::viewWillEndLiveResize()
1349 m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1352 void WebPageProxy::setViewNeedsDisplay(const Region& region)
1354 m_pageClient.setViewNeedsDisplay(region);
1357 void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin, bool isProgrammaticScroll)
1359 m_pageClient.requestScroll(scrollPosition, scrollOrigin, isProgrammaticScroll);
1362 WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
1364 return m_pageClient.viewScrollPosition();
1367 void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
1369 if (m_suppressVisibilityUpdates == flag)
1371 m_suppressVisibilityUpdates = flag;
1373 if (!m_suppressVisibilityUpdates) {
1375 m_activityStateChangeDispatcher->schedule();
1377 dispatchActivityStateChange();
1382 void WebPageProxy::updateActivityState(ActivityState::Flags flagsToUpdate)
1384 m_activityState &= ~flagsToUpdate;
1385 if (flagsToUpdate & ActivityState::IsFocused && m_pageClient.isViewFocused())
1386 m_activityState |= ActivityState::IsFocused;
1387 if (flagsToUpdate & ActivityState::WindowIsActive && m_pageClient.isViewWindowActive())
1388 m_activityState |= ActivityState::WindowIsActive;
1389 if (flagsToUpdate & ActivityState::IsVisible && m_pageClient.isViewVisible())
1390 m_activityState |= ActivityState::IsVisible;
1391 if (flagsToUpdate & ActivityState::IsVisibleOrOccluded && m_pageClient.isViewVisibleOrOccluded())
1392 m_activityState |= ActivityState::IsVisibleOrOccluded;
1393 if (flagsToUpdate & ActivityState::IsInWindow && m_pageClient.isViewInWindow())
1394 m_activityState |= ActivityState::IsInWindow;
1395 if (flagsToUpdate & ActivityState::IsVisuallyIdle && m_pageClient.isVisuallyIdle())
1396 m_activityState |= ActivityState::IsVisuallyIdle;
1397 if (flagsToUpdate & ActivityState::IsAudible && m_mediaState & MediaProducer::IsPlayingAudio && !(m_mutedState & MediaProducer::AudioIsMuted))
1398 m_activityState |= ActivityState::IsAudible;
1399 if (flagsToUpdate & ActivityState::IsLoading && m_pageLoadState.isLoading())
1400 m_activityState |= ActivityState::IsLoading;
1401 if (flagsToUpdate & ActivityState::IsCapturingMedia && m_mediaState & (MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice))
1402 m_activityState |= ActivityState::IsCapturingMedia;
1405 void WebPageProxy::activityStateDidChange(ActivityState::Flags mayHaveChanged, bool wantsSynchronousReply, ActivityStateChangeDispatchMode dispatchMode)
1407 m_potentiallyChangedActivityStateFlags |= mayHaveChanged;
1408 m_activityStateChangeWantsSynchronousReply = m_activityStateChangeWantsSynchronousReply || wantsSynchronousReply;
1410 if (m_suppressVisibilityUpdates && dispatchMode != ActivityStateChangeDispatchMode::Immediate)
1414 bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ActivityState::IsInWindow) && m_pageClient.isViewInWindow();
1415 if (dispatchMode == ActivityStateChangeDispatchMode::Immediate || isNewlyInWindow) {
1416 dispatchActivityStateChange();
1419 m_activityStateChangeDispatcher->schedule();
1421 UNUSED_PARAM(dispatchMode);
1422 dispatchActivityStateChange();
1426 void WebPageProxy::viewDidLeaveWindow()
1428 #if ENABLE(INPUT_TYPE_COLOR_POPOVER) && ENABLE(INPUT_TYPE_COLOR)
1429 // When leaving the current page, close the popover color well.
1433 #if PLATFORM(IOS) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
1434 // When leaving the current page, close the video fullscreen.
1435 if (m_videoFullscreenManager)
1436 m_videoFullscreenManager->requestHideAndExitFullscreen();
1440 void WebPageProxy::viewDidEnterWindow()
1442 LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
1443 if (m_layerHostingMode != layerHostingMode) {
1444 m_layerHostingMode = layerHostingMode;
1445 m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1449 void WebPageProxy::dispatchActivityStateChange()
1452 m_activityStateChangeDispatcher->invalidate();
1458 // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1459 if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible)
1460 m_potentiallyChangedActivityStateFlags |= ActivityState::IsVisibleOrOccluded | ActivityState::IsVisuallyIdle;
1462 // Record the prior view state, update the flags that may have changed,
1463 // and check which flags have actually changed.
1464 ActivityState::Flags previousActivityState = m_activityState;
1465 updateActivityState(m_potentiallyChangedActivityStateFlags);
1466 ActivityState::Flags changed = m_activityState ^ previousActivityState;
1468 if ((m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible) && isViewVisible())
1469 viewIsBecomingVisible();
1471 bool isNowInWindow = (changed & ActivityState::IsInWindow) && isInWindow();
1472 // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
1473 if (m_viewWasEverInWindow && isNowInWindow) {
1474 if (m_drawingArea->hasVisibleContent() && m_waitsForPaintAfterViewDidMoveToWindow && !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
1475 m_activityStateChangeWantsSynchronousReply = true;
1476 m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
1479 // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
1480 if (!(m_activityState & ActivityState::IsVisible))
1481 m_activityStateChangeWantsSynchronousReply = false;
1483 if (changed || m_activityStateChangeWantsSynchronousReply || !m_nextActivityStateChangeCallbacks.isEmpty())
1484 m_process->send(Messages::WebPage::SetActivityState(m_activityState, m_activityStateChangeWantsSynchronousReply, m_nextActivityStateChangeCallbacks), m_pageID);
1486 m_nextActivityStateChangeCallbacks.clear();
1488 // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
1489 updateThrottleState();
1491 #if ENABLE(POINTER_LOCK)
1492 if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !m_pageClient.isViewWindowActive())
1493 || ((changed & ActivityState::IsFocused) && !(m_activityState & ActivityState::IsFocused)))
1494 requestPointerUnlock();
1497 if (changed & ActivityState::IsVisible) {
1498 if (isViewVisible())
1499 m_visiblePageToken = m_process->visiblePageToken();
1501 m_visiblePageToken = nullptr;
1503 // If we've started the responsiveness timer as part of telling the web process to update the backing store
1504 // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1505 // stop the unresponsiveness timer here.
1506 m_process->responsivenessTimer().stop();
1510 if (changed & ActivityState::IsInWindow) {
1512 viewDidEnterWindow();
1514 viewDidLeaveWindow();
1517 updateBackingStoreDiscardableState();
1519 if (m_activityStateChangeWantsSynchronousReply)
1520 waitForDidUpdateActivityState();
1522 m_potentiallyChangedActivityStateFlags = ActivityState::NoFlags;
1523 m_activityStateChangeWantsSynchronousReply = false;
1524 m_viewWasEverInWindow |= isNowInWindow;
1527 bool WebPageProxy::isAlwaysOnLoggingAllowed() const
1529 return sessionID().isAlwaysOnLoggingAllowed();
1532 void WebPageProxy::updateThrottleState()
1534 bool processSuppressionEnabled = m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
1536 // If process suppression is not enabled take a token on the process pool to disable suppression of support processes.
1537 if (!processSuppressionEnabled)
1538 m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
1539 else if (!m_preventProcessSuppressionCount)
1540 m_preventProcessSuppressionCount = nullptr;
1542 if (m_activityState & ActivityState::IsVisuallyIdle)
1543 m_pageIsUserObservableCount = nullptr;
1544 else if (!m_pageIsUserObservableCount)
1545 m_pageIsUserObservableCount = m_process->processPool().userObservablePageCount();
1548 bool isCapturingMedia = m_activityState & ActivityState::IsCapturingMedia;
1549 bool isAudible = m_activityState & ActivityState::IsAudible;
1550 if (!isViewVisible() && !m_alwaysRunsAtForegroundPriority && !isCapturingMedia && !isAudible) {
1551 if (m_activityToken) {
1552 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is releasing a foreground assertion because the view is no longer visible", this);
1553 m_activityToken = nullptr;
1555 } else if (!m_activityToken) {
1556 if (isViewVisible())
1557 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because the view is visible", this);
1559 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because we are playing audio", this);
1560 else if (isCapturingMedia)
1561 RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "%p - UIProcess is taking a foreground assertion because media capture is active", this);
1563 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);
1564 m_activityToken = m_process->throttler().foregroundActivityToken();
1569 void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
1571 if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
1572 m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
1573 else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
1574 m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
1577 void WebPageProxy::layerHostingModeDidChange()
1582 LayerHostingMode layerHostingMode = m_pageClient.viewLayerHostingMode();
1583 if (m_layerHostingMode == layerHostingMode)
1586 m_layerHostingMode = layerHostingMode;
1587 m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1590 void WebPageProxy::waitForDidUpdateActivityState()
1595 if (m_process->state() != WebProcessProxy::State::Running)
1598 // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1599 if (m_waitingForDidUpdateActivityState)
1603 // Hail Mary check. Should not be possible (dispatchActivityStateChange should force async if not visible,
1604 // and if visible we should be holding an assertion) - but we should never block on a suspended process.
1605 if (!m_activityToken) {
1606 ASSERT_NOT_REACHED();
1611 m_waitingForDidUpdateActivityState = true;
1613 m_drawingArea->waitForDidUpdateActivityState();
1616 IntSize WebPageProxy::viewSize() const
1618 return m_pageClient.viewSize();
1621 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
1624 callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
1628 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1629 m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent, callbackID), m_pageID);
1632 void WebPageProxy::clearSelection()
1636 m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1639 void WebPageProxy::restoreSelectionInFocusedEditableElement()
1643 m_process->send(Messages::WebPage::RestoreSelectionInFocusedEditableElement(), m_pageID);
1646 void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&& callbackFunction)
1649 callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1653 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1654 m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1657 bool WebPageProxy::maintainsInactiveSelection() const
1659 // Regardless of what the client wants to do, keep selections if a local Inspector is open.
1660 // Otherwise, there is no way to use the console to inspect the state of a selection.
1661 if (inspector() && inspector()->isVisible())
1664 return m_maintainsInactiveSelection;
1667 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1669 m_maintainsInactiveSelection = newValue;
1672 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
1675 callbackFunction(CallbackBase::Error::Unknown);
1679 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1680 m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, argument, callbackID), m_pageID);
1683 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
1685 static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
1690 if (commandName == ignoreSpellingCommandName)
1691 ++m_pendingLearnOrIgnoreWordMessageCount;
1693 m_process->send(Messages::WebPage::ExecuteEditCommand(commandName, argument), m_pageID);
1696 void WebPageProxy::setEditable(bool editable)
1698 if (editable == m_isEditable)
1703 m_isEditable = editable;
1704 m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
1707 void WebPageProxy::setMediaStreamCaptureMuted(bool muted)
1710 setMuted(m_mutedState | WebCore::MediaProducer::CaptureDevicesAreMuted);
1712 setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1715 void WebPageProxy::activateMediaStreamCaptureInPage()
1717 #if ENABLE(MEDIA_STREAM)
1718 UserMediaProcessManager::singleton().muteCaptureMediaStreamsExceptIn(*this);
1720 setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
1724 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
1728 void WebPageProxy::layerTreeCommitComplete()
1733 #if ENABLE(DRAG_SUPPORT)
1734 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
1736 performDragControllerAction(DragControllerAction::Entered, dragData, dragStorageName, { }, { });
1739 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
1741 performDragControllerAction(DragControllerAction::Updated, dragData, dragStorageName, { }, { });
1744 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
1746 performDragControllerAction(DragControllerAction::Exited, dragData, dragStorageName, { }, { });
1749 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
1751 performDragControllerAction(DragControllerAction::PerformDragOperation, dragData, dragStorageName, WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload));
1754 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
1759 UNUSED_PARAM(dragStorageName);
1760 UNUSED_PARAM(sandboxExtensionHandle);
1761 UNUSED_PARAM(sandboxExtensionsForUpload);
1763 String url = dragData.asURL();
1765 m_process->assumeReadAccessToBaseURL(url);
1767 ASSERT(dragData.platformData());
1768 WebSelectionData selection(*dragData.platformData());
1769 m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), selection, dragData.flags()), m_pageID);
1771 m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
1775 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect)
1777 MESSAGE_CHECK(dragOperation <= DragOperationDelete);
1779 m_currentDragOperation = static_cast<DragOperation>(dragOperation);
1780 m_currentDragIsOverFileInput = mouseIsOverFileInput;
1781 m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
1782 setDragCaretRect(insertionRect);
1786 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
1788 RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
1789 m_pageClient.startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
1795 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
1799 m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
1800 setDragCaretRect({ });
1803 void WebPageProxy::didStartDrag()
1806 m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
1809 void WebPageProxy::dragCancelled()
1812 m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
1815 void WebPageProxy::didEndDragging()
1817 resetCurrentDragInformation();
1820 void WebPageProxy::resetCurrentDragInformation()
1822 m_currentDragOperation = WebCore::DragOperationNone;
1823 m_currentDragIsOverFileInput = false;
1824 m_currentDragNumberOfFilesToBeAccepted = 0;
1825 setDragCaretRect({ });
1828 #if !ENABLE(DATA_INTERACTION)
1830 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
1832 m_currentDragCaretRect = dragCaretRect;
1837 #endif // ENABLE(DRAG_SUPPORT)
1839 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
1844 if (m_pageClient.windowIsFrontWindowUnderMouse(event))
1845 setToolTip(String());
1847 // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
1848 if (event.type() != WebEvent::MouseMove)
1849 m_process->responsivenessTimer().start();
1851 if (m_processingMouseMoveEvent) {
1852 m_nextMouseMoveEvent = std::make_unique<NativeWebMouseEvent>(event);
1856 m_processingMouseMoveEvent = true;
1859 // <https://bugs.webkit.org/show_bug.cgi?id=57904> We need to keep track of the mouse down event in the case where we
1860 // display a popup menu for select elements. When the user changes the selected item,
1861 // we fake a mouse up event by using this stored down event. This event gets cleared
1862 // when the mouse up message is received from WebProcess.
1863 if (event.type() == WebEvent::MouseDown)
1864 m_currentlyProcessedMouseDownEvent = std::make_unique<NativeWebMouseEvent>(event);
1866 m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
1869 #if MERGE_WHEEL_EVENTS
1870 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1872 if (a.position() != b.position())
1874 if (a.globalPosition() != b.globalPosition())
1876 if (a.modifiers() != b.modifiers())
1878 if (a.granularity() != b.granularity())
1881 if (a.phase() != b.phase())
1883 if (a.momentumPhase() != b.momentumPhase())
1885 if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
1892 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1894 ASSERT(canCoalesce(a, b));
1896 FloatSize mergedDelta = a.delta() + b.delta();
1897 FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
1900 FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
1902 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());
1904 return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
1907 #endif // MERGE_WHEEL_EVENTS
1909 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
1911 ASSERT(!queue.isEmpty());
1912 ASSERT(coalescedEvents.isEmpty());
1914 #if MERGE_WHEEL_EVENTS
1915 NativeWebWheelEvent firstEvent = queue.takeFirst();
1916 coalescedEvents.append(firstEvent);
1918 WebWheelEvent event = firstEvent;
1919 while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
1920 NativeWebWheelEvent firstEvent = queue.takeFirst();
1921 coalescedEvents.append(firstEvent);
1922 event = coalesce(event, firstEvent);
1927 while (!queue.isEmpty())
1928 coalescedEvents.append(queue.takeFirst());
1929 return coalescedEvents.last();
1933 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
1935 #if ENABLE(ASYNC_SCROLLING)
1936 if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
1943 hideValidationMessage();
1945 if (!m_currentlyProcessedWheelEvents.isEmpty()) {
1946 m_wheelEventQueue.append(event);
1947 if (!shouldProcessWheelEventNow(event))
1949 // The queue has too many wheel events, so push a new event.
1952 if (!m_wheelEventQueue.isEmpty()) {
1953 processNextQueuedWheelEvent();
1957 auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
1958 coalescedWheelEvent->append(event);
1959 m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
1960 sendWheelEvent(event);
1963 void WebPageProxy::processNextQueuedWheelEvent()
1965 auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
1966 WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
1967 m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
1968 sendWheelEvent(nextWheelEvent);
1971 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
1974 Messages::EventDispatcher::WheelEvent(
1977 shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
1978 shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
1980 rubberBandsAtBottom()
1983 // Manually ping the web process to check for responsiveness since our wheel
1984 // event will dispatch to a non-main thread, which always responds.
1985 m_process->isResponsive(nullptr);
1988 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
1991 // Don't queue events representing a non-trivial scrolling phase to
1992 // avoid having them trapped in the queue, potentially preventing a
1993 // scrolling session to beginning or end correctly.
1994 // This is only needed by platforms whose WebWheelEvent has this phase
1995 // information (Cocoa and GTK+) but Cocoa was fine without it.
1996 if (event.phase() == WebWheelEvent::Phase::PhaseNone
1997 || event.phase() == WebWheelEvent::Phase::PhaseChanged
1998 || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
1999 || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
2002 UNUSED_PARAM(event);
2004 if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
2009 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
2014 LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
2016 m_keyEventQueue.append(event);
2018 m_process->responsivenessTimer().start();
2019 if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
2020 LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
2021 m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2025 WebPreferencesStore WebPageProxy::preferencesStore() const
2027 if (m_configurationPreferenceValues.isEmpty())
2028 return m_preferences->store();
2030 WebPreferencesStore store = m_preferences->store();
2031 for (const auto& preference : m_configurationPreferenceValues)
2032 store.m_values.set(preference.key, preference.value);
2037 #if ENABLE(NETSCAPE_PLUGIN_API)
2038 void WebPageProxy::findPlugin(const String& mimeType, uint32_t processType, const String& urlString, const String& frameURLString, const String& pageURLString, bool allowOnlyApplicationPlugins, uint64_t& pluginProcessToken, String& newMimeType, uint32_t& pluginLoadPolicy, String& unavailabilityDescription)
2040 PageClientProtector protector(m_pageClient);
2042 MESSAGE_CHECK_URL(urlString);
2044 newMimeType = mimeType.convertToASCIILowercase();
2045 pluginLoadPolicy = PluginModuleLoadNormally;
2047 PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2048 PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL(URL(), urlString), allowedPluginTypes);
2050 pluginProcessToken = 0;
2054 pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2057 RefPtr<API::Dictionary> pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2058 if (m_navigationClient)
2059 pluginLoadPolicy = m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), unavailabilityDescription);
2061 pluginLoadPolicy = m_loaderClient->pluginLoadPolicy(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), unavailabilityDescription);
2063 UNUSED_PARAM(frameURLString);
2064 UNUSED_PARAM(pageURLString);
2065 UNUSED_PARAM(unavailabilityDescription);
2068 PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2069 switch (pluginLoadPolicy) {
2070 case PluginModuleLoadNormally:
2071 pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2073 case PluginModuleLoadUnsandboxed:
2074 pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2077 case PluginModuleBlockedForSecurity:
2078 case PluginModuleBlockedForCompatibility:
2079 pluginProcessToken = 0;
2083 pluginProcessToken = PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy);
2086 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2088 #if ENABLE(TOUCH_EVENTS)
2090 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2092 if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2097 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2099 #if ENABLE(ASYNC_SCROLLING)
2100 const EventNames& names = eventNames();
2101 for (auto& touchPoint : touchStartEvent.touchPoints()) {
2102 IntPoint location = touchPoint.location();
2103 auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
2104 if (trackingType == TrackingType::Synchronous)
2107 TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2109 trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2111 updateTrackingType(m_touchEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2112 updateTrackingType(m_touchEventTracking.touchStartTracking, names.touchstartEvent);
2113 updateTrackingType(m_touchEventTracking.touchMoveTracking, names.touchmoveEvent);
2114 updateTrackingType(m_touchEventTracking.touchEndTracking, names.touchendEvent);
2117 UNUSED_PARAM(touchStartEvent);
2118 m_touchEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2119 m_touchEventTracking.touchStartTracking = TrackingType::Synchronous;
2120 m_touchEventTracking.touchMoveTracking = TrackingType::Synchronous;
2121 m_touchEventTracking.touchEndTracking = TrackingType::Synchronous;
2122 #endif // ENABLE(ASYNC_SCROLLING)
2125 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2127 // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2129 // Touch events define a sequence with strong dependencies. For example, we can expect
2130 // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2133 // WebCore should not have to set up its state correctly after some events were dismissed.
2134 // For example, we don't want to send a TouchMoved without a TouchPressed.
2135 // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2136 TrackingType globalTrackingType = m_touchEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2138 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchForceChangedTracking);
2139 for (auto& touchPoint : touchStartEvent.touchPoints()) {
2140 switch (touchPoint.state()) {
2141 case WebPlatformTouchPoint::TouchReleased:
2142 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchEndTracking);
2144 case WebPlatformTouchPoint::TouchPressed:
2145 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchStartTracking);
2147 case WebPlatformTouchPoint::TouchMoved:
2148 case WebPlatformTouchPoint::TouchStationary:
2149 globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchEventTracking.touchMoveTracking);
2151 case WebPlatformTouchPoint::TouchCancelled:
2152 globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2157 return globalTrackingType;
2162 #if ENABLE(MAC_GESTURE_EVENTS)
2163 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2168 m_gestureEventQueue.append(event);
2169 // FIXME: Consider doing some coalescing here.
2170 m_process->responsivenessTimer().start();
2172 m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2176 #if ENABLE(IOS_TOUCH_EVENTS)
2177 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2182 TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2184 if (event.type() == WebEvent::TouchStart)
2185 updateTouchEventTracking(event);
2187 TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2188 if (touchEventsTrackingType == TrackingType::NotTracking)
2191 if (touchEventsTrackingType == TrackingType::Asynchronous) {
2192 // We can end up here if a native gesture has not started but the event handlers are passive.
2194 // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2195 // can prevent a native gesture.
2196 // But, here we know that all events handlers that can handle this events are passive.
2197 // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2198 event.setCanPreventNativeGestures(false);
2199 handleTouchEventAsynchronously(event);
2200 didReceiveEvent(event.type(), false);
2204 m_process->responsivenessTimer().start();
2205 bool handled = false;
2206 m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID);
2207 didReceiveEvent(event.type(), handled);
2208 m_pageClient.doneWithTouchEvent(event, handled);
2209 m_process->responsivenessTimer().stop();
2211 if (event.allTouchPointsAreReleased())
2212 m_touchEventTracking.reset();
2215 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2220 TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2221 if (touchEventsTrackingType == TrackingType::NotTracking)
2224 m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2226 if (event.allTouchPointsAreReleased())
2227 m_touchEventTracking.reset();
2230 #elif ENABLE(TOUCH_EVENTS)
2231 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2236 if (event.type() == WebEvent::TouchStart)
2237 updateTouchEventTracking(event);
2239 if (touchEventTrackingType(event) == TrackingType::NotTracking)
2242 // If the page is suspended, which should be the case during panning, pinching
2243 // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2244 // we do not send any of the events to the page even if is has listeners.
2245 if (!m_isPageSuspended) {
2246 m_touchEventQueue.append(event);
2247 m_process->responsivenessTimer().start();
2248 m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2250 if (m_touchEventQueue.isEmpty()) {
2251 bool isEventHandled = false;
2252 m_pageClient.doneWithTouchEvent(event, isEventHandled);
2254 // We attach the incoming events to the newest queued event so that all
2255 // the events are delivered in the correct order when the event is dequed.
2256 QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2257 lastEvent.deferredTouchEvents.append(event);
2261 if (event.allTouchPointsAreReleased())
2262 m_touchEventTracking.reset();
2264 #endif // ENABLE(TOUCH_EVENTS)
2266 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2271 m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2274 void WebPageProxy::centerSelectionInVisibleArea()
2279 m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2282 void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy& frame, uint64_t listenerID, API::Navigation* navigation, std::optional<WebsitePoliciesData>&& websitePolicies)
2287 auto transaction = m_pageLoadState.transaction();
2289 if (action == PolicyAction::Ignore)
2290 m_pageLoadState.clearPendingAPIRequestURL(transaction);
2292 if (navigation && navigation->shouldForceDownload() && action == PolicyAction::Use)
2293 action = PolicyAction::Download;
2295 DownloadID downloadID = { };
2296 if (action == PolicyAction::Download) {
2297 // Create a download proxy.
2298 const ResourceRequest& downloadRequest = m_decidePolicyForResponseRequest ? *m_decidePolicyForResponseRequest : ResourceRequest();
2299 DownloadProxy* download = m_process->processPool().createDownloadProxy(downloadRequest, this);
2301 download->setWasUserInitiated(navigation->wasUserInitiated());
2302 download->setRedirectChain(navigation->takeRedirectChain());
2305 downloadID = download->downloadID();
2306 handleDownloadRequest(download);
2309 // If we received a policy decision while in decidePolicyForResponse the decision will
2310 // be sent back to the web process by decidePolicyForResponse.
2311 if (m_inDecidePolicyForResponseSync) {
2312 m_syncMimeTypePolicyActionIsValid = true;
2313 m_syncMimeTypePolicyAction = action;
2314 m_syncMimeTypePolicyDownloadID = downloadID;
2318 // If we received a policy decision while in decidePolicyForNavigationAction the decision will
2319 // be sent back to the web process by decidePolicyForNavigationAction.
2320 if (m_inDecidePolicyForNavigationAction) {
2321 m_syncNavigationActionPolicyActionIsValid = true;
2322 m_syncNavigationActionPolicyAction = action;
2323 m_syncNavigationActionPolicyDownloadID = downloadID;
2324 m_syncNavigationActionPolicyWebsitePolicies = WTFMove(websitePolicies);
2328 m_process->send(Messages::WebPage::DidReceivePolicyDecision(frame.frameID(), listenerID, action, navigation ? navigation->navigationID() : 0, downloadID, websitePolicies), m_pageID);
2331 void WebPageProxy::setUserAgent(String&& userAgent)
2333 if (m_userAgent == userAgent)
2335 m_userAgent = WTFMove(userAgent);
2337 #if ENABLE(SERVICE_WORKER)
2338 // We update the service worker there at the moment to be sure we use values used by actual web pages.
2339 // FIXME: Refactor this when we have a better User-Agent story.
2340 process().processPool().updateServiceWorkerUserAgent(m_userAgent);
2345 m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
2348 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
2350 if (m_applicationNameForUserAgent == applicationName)
2353 m_applicationNameForUserAgent = applicationName;
2354 if (!m_customUserAgent.isEmpty())
2357 setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2360 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
2362 if (m_customUserAgent == customUserAgent)
2365 m_customUserAgent = customUserAgent;
2367 if (m_customUserAgent.isEmpty()) {
2368 setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2372 setUserAgent(String { m_customUserAgent });
2375 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
2377 if (!isValid() || !m_isPageSuspended)
2380 m_isPageSuspended = false;
2382 m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
2385 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
2387 if (!isValid() || m_isPageSuspended)
2390 m_isPageSuspended = true;
2392 m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
2395 bool WebPageProxy::supportsTextEncoding() const
2397 // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
2398 return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
2401 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
2403 if (m_customTextEncodingName == encodingName)
2405 m_customTextEncodingName = encodingName;
2409 m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
2412 SessionState WebPageProxy::sessionState(WTF::Function<bool (WebBackForwardListItem&)>&& filter) const
2414 SessionState sessionState;
2416 sessionState.backForwardListState = m_backForwardList->backForwardListState(WTFMove(filter));
2418 String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
2419 if (provisionalURLString.isEmpty())
2420 provisionalURLString = m_pageLoadState.provisionalURL();
2422 if (!provisionalURLString.isEmpty())
2423 sessionState.provisionalURL = URL(URL(), provisionalURLString);
2425 sessionState.renderTreeSize = renderTreeSize();
2426 return sessionState;
2429 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
2431 m_sessionRestorationRenderTreeSize = 0;
2432 m_hitRenderTreeSizeThreshold = false;
2434 bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
2436 if (hasBackForwardList) {
2437 m_backForwardList->restoreFromState(WTFMove(sessionState.backForwardListState));
2439 for (const auto& entry : m_backForwardList->entries())
2440 process().registerNewWebBackForwardListItem(entry.get());
2442 process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
2444 auto transaction = m_pageLoadState.transaction();
2445 m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
2446 m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
2448 // The back / forward list was restored from a sessionState so we don't want to snapshot the current
2449 // page when navigating away. Suppress navigation snapshotting until the next load has committed
2450 m_suppressAutomaticNavigationSnapshotting = true;
2453 // FIXME: Navigating should be separate from state restoration.
2455 m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
2456 if (!m_sessionRestorationRenderTreeSize)
2457 m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
2459 if (!sessionState.provisionalURL.isNull())
2460 return loadRequest(sessionState.provisionalURL);
2462 if (hasBackForwardList) {
2463 // FIXME: Do we have to null check the back forward list item here?
2464 if (WebBackForwardListItem* item = m_backForwardList->currentItem())
2465 return goToBackForwardItem(item);
2472 bool WebPageProxy::supportsTextZoom() const
2474 // FIXME (118840): This should also return false for standalone media and plug-in documents.
2475 if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
2481 void WebPageProxy::setTextZoomFactor(double zoomFactor)
2486 if (m_textZoomFactor == zoomFactor)
2489 m_textZoomFactor = zoomFactor;
2490 m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID);
2493 void WebPageProxy::setPageZoomFactor(double zoomFactor)
2498 if (m_pageZoomFactor == zoomFactor)
2501 hideValidationMessage();
2503 m_pageZoomFactor = zoomFactor;
2504 m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID);
2507 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
2512 if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
2515 hideValidationMessage();
2517 m_pageZoomFactor = pageZoomFactor;
2518 m_textZoomFactor = textZoomFactor;
2519 m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID);
2522 double WebPageProxy::pageZoomFactor() const
2524 // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
2525 // zoom which ensures that we don't use the PDF zoom for a normal page.
2526 if (m_mainFramePluginHandlesPageScaleGesture)
2527 return m_pluginZoomFactor;
2528 return m_pageZoomFactor;
2531 double WebPageProxy::pageScaleFactor() const
2533 // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
2534 // separately but decide which to return based on the main frame.
2535 if (m_mainFramePluginHandlesPageScaleGesture)
2536 return m_pluginScaleFactor;
2537 return m_pageScaleFactor;
2540 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
2547 m_pageScaleFactor = scale;
2548 m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
2551 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
2558 m_pageScaleFactor = scale;
2559 m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
2562 void WebPageProxy::scaleView(double scale)
2569 m_viewScaleFactor = scale;
2570 m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
2573 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
2575 if (m_intrinsicDeviceScaleFactor == scaleFactor)
2578 m_intrinsicDeviceScaleFactor = scaleFactor;
2581 m_drawingArea->deviceScaleFactorDidChange();
2584 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
2589 m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
2592 float WebPageProxy::deviceScaleFactor() const
2594 return m_customDeviceScaleFactor.value_or(m_intrinsicDeviceScaleFactor);
2597 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
2602 // FIXME: Remove this once we bump cairo requirements to support HiDPI.
2603 // https://bugs.webkit.org/show_bug.cgi?id=133378
2604 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
2608 if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
2611 float oldScaleFactor = deviceScaleFactor();
2613 // A value of 0 clears the customScaleFactor.
2614 if (customScaleFactor)
2615 m_customDeviceScaleFactor = customScaleFactor;
2617 m_customDeviceScaleFactor = std::nullopt;
2619 if (deviceScaleFactor() != oldScaleFactor)
2620 m_drawingArea->deviceScaleFactorDidChange();
2623 void WebPageProxy::accessibilitySettingsDidChange()
2628 m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
2631 void WebPageProxy::setUseFixedLayout(bool fixed)
2636 // This check is fine as the value is initialized in the web
2637 // process as part of the creation parameters.
2638 if (fixed == m_useFixedLayout)
2641 m_useFixedLayout = fixed;
2643 m_fixedLayoutSize = IntSize();
2644 m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
2647 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
2652 if (size == m_fixedLayoutSize)
2655 m_fixedLayoutSize = size;
2656 m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
2659 void WebPageProxy::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)
2664 if (alwaysShowsHorizontalScroller == m_alwaysShowsHorizontalScroller)
2667 m_alwaysShowsHorizontalScroller = alwaysShowsHorizontalScroller;
2668 m_process->send(Messages::WebPage::SetAlwaysShowsHorizontalScroller(alwaysShowsHorizontalScroller), m_pageID);
2671 void WebPageProxy::setAlwaysShowsVerticalScroller(bool alwaysShowsVerticalScroller)
2676 if (alwaysShowsVerticalScroller == m_alwaysShowsVerticalScroller)
2679 m_alwaysShowsVerticalScroller = alwaysShowsVerticalScroller;
2680 m_process->send(Messages::WebPage::SetAlwaysShowsVerticalScroller(alwaysShowsVerticalScroller), m_pageID);
2683 void WebPageProxy::listenForLayoutMilestones(WebCore::LayoutMilestones milestones)
2688 if (milestones == m_observedLayoutMilestones)
2691 m_observedLayoutMilestones = milestones;
2692 m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
2695 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
2700 if (suppressAnimations == m_suppressScrollbarAnimations)
2703 m_suppressScrollbarAnimations = suppressAnimations;
2704 m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
2707 bool WebPageProxy::rubberBandsAtLeft() const
2709 return m_rubberBandsAtLeft;
2712 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
2714 m_rubberBandsAtLeft = rubberBandsAtLeft;
2717 bool WebPageProxy::rubberBandsAtRight() const
2719 return m_rubberBandsAtRight;
2722 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
2724 m_rubberBandsAtRight = rubberBandsAtRight;
2727 bool WebPageProxy::rubberBandsAtTop() const
2729 return m_rubberBandsAtTop;
2732 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
2734 m_rubberBandsAtTop = rubberBandsAtTop;
2737 bool WebPageProxy::rubberBandsAtBottom() const
2739 return m_rubberBandsAtBottom;
2742 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
2744 m_rubberBandsAtBottom = rubberBandsAtBottom;
2747 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
2749 if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
2752 m_enableVerticalRubberBanding = enableVerticalRubberBanding;
2756 m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
2759 bool WebPageProxy::verticalRubberBandingIsEnabled() const
2761 return m_enableVerticalRubberBanding;
2764 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
2766 if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
2769 m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
2773 m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
2776 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
2778 return m_enableHorizontalRubberBanding;
2781 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
2783 if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
2786 m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
2790 m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
2793 bool WebPageProxy::backgroundExtendsBeyondPage() const
2795 return m_backgroundExtendsBeyondPage;
2798 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
2800 if (mode == m_paginationMode)
2803 m_paginationMode = mode;
2807 m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
2810 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
2812 if (behavesLikeColumns == m_paginationBehavesLikeColumns)
2815 m_paginationBehavesLikeColumns = behavesLikeColumns;
2819 m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
2822 void WebPageProxy::setPageLength(double pageLength)
2824 if (pageLength == m_pageLength)
2827 m_pageLength = pageLength;
2831 m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
2834 void WebPageProxy::setGapBetweenPages(double gap)
2836 if (gap == m_gapBetweenPages)
2839 m_gapBetweenPages = gap;
2843 m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
2846 void WebPageProxy::setPaginationLineGridEnabled(bool lineGridEnabled)
2848 if (lineGridEnabled == m_paginationLineGridEnabled)
2851 m_paginationLineGridEnabled = lineGridEnabled;
2855 m_process->send(Messages::WebPage::SetPaginationLineGridEnabled(lineGridEnabled), m_pageID);
2858 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
2860 m_pageScaleFactor = scaleFactor;
2863 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
2865 m_pluginScaleFactor = pluginScaleFactor;
2868 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
2870 m_pluginZoomFactor = pluginZoomFactor;
2873 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
2875 if (string.isEmpty()) {
2876 didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
2880 m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
2883 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
2885 m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
2888 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
2890 m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
2893 void WebPageProxy::selectFindMatch(int32_t matchIndex)
2895 m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
2898 void WebPageProxy::hideFindUI()
2900 m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
2903 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
2908 m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
2911 void WebPageProxy::runJavaScriptInMainFrame(const String& script, bool forceUserGesture, WTF::Function<void (API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
2914 callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
2918 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2919 m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, forceUserGesture, callbackID), m_pageID);
2922 void WebPageProxy::getRenderTreeExternalRepresentation(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2925 callbackFunction(String(), CallbackBase::Error::Unknown);
2929 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2930 m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
2933 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2936 callbackFunction(String(), CallbackBase::Error::Unknown);
2940 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2941 m_loadDependentStringCallbackIDs.add(callbackID);
2942 m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
2945 void WebPageProxy::getContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2948 callbackFunction(String(), CallbackBase::Error::Unknown);
2952 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2953 m_loadDependentStringCallbackIDs.add(callbackID);
2954 m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
2957 void WebPageProxy::getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2960 callbackFunction(String(), CallbackBase::Error::Unknown);
2964 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2965 m_loadDependentStringCallbackIDs.add(callbackID);
2966 m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
2969 void WebPageProxy::getSamplingProfilerOutput(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
2972 callbackFunction(String(), CallbackBase::Error::Unknown);
2976 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2977 m_loadDependentStringCallbackIDs.add(callbackID);
2978 m_process->send(Messages::WebPage::GetSamplingProfilerOutput(callbackID), m_pageID);
2981 void WebPageProxy::isWebProcessResponsive(WTF::Function<void (bool isWebProcessResponsive)>&& callbackFunction)
2984 RunLoop::main().dispatch([callbackFunction = WTFMove(callbackFunction)] {
2985 bool isWebProcessResponsive = true;
2986 callbackFunction(isWebProcessResponsive);
2991 m_process->isResponsive(WTFMove(callbackFunction));
2995 void WebPageProxy::getContentsAsMHTMLData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
2998 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3002 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3003 m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID), m_pageID);
3007 void WebPageProxy::getSelectionOrContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3010 callbackFunction(String(), CallbackBase::Error::Unknown);
3014 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3015 m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
3018 void WebPageProxy::getSelectionAsWebArchiveData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3021 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3025 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3026 m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
3029 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3031 if (!isValid() || !frame) {
3032 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3036 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3037 m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
3040 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3043 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3047 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3048 m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
3051 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3054 callbackFunction(nullptr, CallbackBase::Error::Unknown);
3058 auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3059 m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
3062 void WebPageProxy::forceRepaint(RefPtr<VoidCallback>&& callback)
3065 // FIXME: If the page is invalid we should not call the callback. It'd be better to just return false from forceRepaint.
3066 callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3070 Function<void(CallbackBase::Error)> didForceRepaintCallback = [this, callback = WTFMove(callback)](CallbackBase::Error error) mutable {
3071 if (error != CallbackBase::Error::None) {
3072 callback->invalidate(error);
3077 callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3081 callAfterNextPresentationUpdate([callback = WTFMove(callback)](CallbackBase::Error error) {
3082 if (error != CallbackBase::Error::None) {
3083 callback->invalidate(error);
3087 callback->performCallback();
3091 auto callbackID = m_callbacks.put(WTFMove(didForceRepaintCallback), m_process->throttler().backgroundActivityToken());
3092 m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
3093 m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID);
3096 static OptionSet<IPC::SendOption> printingSendOptions(bool isPerformingDOMPrintOperation)
3098 if (isPerformingDOMPrintOperation)
3099 return IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply;
3104 void WebPageProxy::preferencesDidChange()
3109 updateThrottleState();
3110 updateHiddenPageThrottlingAutoIncreases();
3112 m_pageClient.preferencesDidChange();
3114 // FIXME: It probably makes more sense to send individual preference changes.
3115 // However, WebKitTestRunner depends on getting a preference change notification
3116 // even if nothing changed in UI process, so that overrides get removed.
3118 // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
3119 m_process->send(Messages::WebPage::PreferencesDidChange(preferencesStore()), m_pageID, printingSendOptions(m_isPerformingDOMPrintOperation));
3122 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
3124 PageClientProtector protector(m_pageClient);
3126 MESSAGE_CHECK(!m_mainFrame);
3127 MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3129 m_mainFrame = WebFrameProxy::create(this, frameID);
3131 // Add the frame to the process wide map.
3132 m_process->frameCreated(frameID, m_mainFrame.get());
3135 void WebPageProxy::didCreateSubframe(uint64_t frameID)
3137 PageClientProtector protector(m_pageClient);
3139 MESSAGE_CHECK(m_mainFrame);
3140 MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3142 RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
3144 // Add the frame to the process wide map.
3145 m_process->frameCreated(frameID, subFrame.get());
3148 double WebPageProxy::estimatedProgress() const
3150 return m_pageLoadState.estimatedProgress();
3153 void WebPageProxy::didStartProgress()
3155 PageClientProtector protector(m_pageClient);
3157 auto transaction = m_pageLoadState.transaction();
3158 m_pageLoadState.didStartProgress(transaction);
3160 m_pageLoadState.commitChanges();
3161 m_loaderClient->didStartProgress(*this);
3164 void WebPageProxy::didChangeProgress(double value)
3166 PageClientProtector protector(m_pageClient);
3168 auto transaction = m_pageLoadState.transaction();
3169 m_pageLoadState.didChangeProgress(transaction, value);
3171 m_pageLoadState.commitChanges();
3172 m_loaderClient->didChangeProgress(*this);
3175 void WebPageProxy::didFinishProgress()
3177 PageClientProtector protector(m_pageClient);
3179 auto transaction = m_pageLoadState.transaction();
3180 m_pageLoadState.didFinishProgress(transaction);
3182 m_pageLoadState.commitChanges();
3183 m_loaderClient->didFinishProgress(*this);
3186 void WebPageProxy::setNetworkRequestsInProgress(bool networkRequestsInProgress)
3188 auto transaction = m_pageLoadState.transaction();
3189 m_pageLoadState.setNetworkRequestsInProgress(transaction, networkRequestsInProgress);
3192 void WebPageProxy::hasInsecureContent(HasInsecureContent& hasInsecureContent)
3194 hasInsecureContent = m_pageLoadState.committedHasInsecureContent() ? HasInsecureContent::Yes : HasInsecureContent::No;
3197 void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
3199 PageClientProtector protector(m_pageClient);
3201 // FIXME: Message check the navigationID.
3202 m_navigationState->didDestroyNavigation(navigationID);
3205 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&& url, WebCore::URL&& unreachableURL, const UserData& userData)
3207 PageClientProtector protector(m_pageClient);
3209 auto transaction = m_pageLoadState.transaction();
3211 m_pageLoadState.clearPendingAPIRequestURL(transaction);
3213 WebFrameProxy* frame = m_process->webFrame(frameID);
3214 MESSAGE_CHECK(frame);
3215 MESSAGE_CHECK_URL(url);
3217 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3218 RefPtr<API::Navigation> navigation;
3219 if (frame->isMainFrame() && navigationID)
3220 navigation = &navigationState().navigation(navigationID);
3222 if (frame->isMainFrame()) {
3223 m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
3224 m_pageClient.didStartProvisionalLoadForMainFrame();
3225 hideValidationMessage();
3228 frame->setUnreachableURL(unreachableURL);
3229 frame->didStartProvisionalLoad(url);
3231 m_pageLoadState.commitChanges();
3232 if (m_navigationClient) {
3233 if (frame->isMainFrame())
3234 m_navigationClient->didStartProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3236 m_loaderClient->didStartProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3239 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&& url, const UserData& userData)
3241 PageClientProtector protector(m_pageClient);
3243 WebFrameProxy* frame = m_process->webFrame(frameID);
3244 MESSAGE_CHECK(frame);
3245 MESSAGE_CHECK_URL(url);
3247 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3248 RefPtr<API::Navigation> navigation;
3250 navigation = &navigationState().navigation(navigationID);
3251 navigation->appendRedirectionURL(url);
3254 auto transaction = m_pageLoadState.transaction();
3256 if (frame->isMainFrame())
3257 m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
3259 frame->didReceiveServerRedirectForProvisionalLoad(url);
3261 m_pageLoadState.commitChanges();
3262 if (m_navigationClient) {
3263 if (frame->isMainFrame())
3264 m_navigationClient->didReceiveServerRedirectForProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3266 m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(*this, *frame, frame->isMainFrame() ? navigation.get() : nullptr, m_process->transformHandlesToObjects(userData.object()).get());
3269 void WebPageProxy::willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay)
3271 PageClientProtector protector(m_pageClient);
3273 WebFrameProxy* frame = m_process->webFrame(frameID);
3274 MESSAGE_CHECK(frame);
3276 if (m_navigationClient) {
3277 if (frame->isMainFrame())
3278 m_navigationClient->willPerformClientRedirect(*this, url, delay);
3282 void WebPageProxy::didCancelClientRedirectForFrame(uint64_t frameID)
3284 PageClientProtector protector(m_pageClient);
3286 WebFrameProxy* frame = m_process->webFrame(frameID);
3287 MESSAGE_CHECK(frame);
3289 if (m_navigationClient) {
3290 if (frame->isMainFrame())
3291 m_navigationClient->didCancelClientRedirect(*this);
3295 void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t, WebCore::URL&& url)
3297 PageClientProtector protector(m_pageClient);
3299 WebFrameProxy* frame = m_process->webFrame(frameID);
3300 MESSAGE_CHECK(frame);
3301 MESSAGE_CHECK(frame->frameLoadState().state() == FrameLoadState::State::Provisional);
3302 MESSAGE_CHECK_URL(url);
3304 auto transaction = m_pageLoadState.transaction();
3306 // Internally, we handle this the same way we handle a server redirect. There are no client callbacks
3307 // for this, but if this is the main frame, clients may observe a change to the page's URL.
3308 if (frame->isMainFrame())
3309 m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
3311 frame->didReceiveServerRedirectForProvisionalLoad(url);
3314 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
3316 PageClientProtector protector(m_pageClient);
3318 WebFrameProxy* frame = m_process->webFrame(frameID);
3319 MESSAGE_CHECK(frame);
3321 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3322 RefPtr<API::Navigation> navigation;
3323 if (frame->isMainFrame() && navigationID)
3324 navigation = navigationState().takeNavigation(navigationID);
3326 auto transaction = m_pageLoadState.transaction();
3328 if (frame->isMainFrame()) {
3329 m_pageLoadState.didFailProvisionalLoad(transaction);
3330 m_pageClient.didFailProvisionalLoadForMainFrame();
3333 frame->didFailProvisionalLoad();
3335 m_pageLoadState.commitChanges();
3337 ASSERT(!m_failingProvisionalLoadURL);
3338 m_failingProvisionalLoadURL = provisionalURL;
3340 if (m_navigationClient) {
3341 if (frame->isMainFrame())
3342 m_navigationClient->didFailProvisionalNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3344 // FIXME: Get the main frame's current navigation.
3345 m_navigationClient->didFailProvisionalLoadInSubframeWithError(*this, *frame, frameSecurityOrigin, nullptr, error, m_process->transformHandlesToObjects(userData.object()).get());
3348 m_loaderClient->didFailProvisionalLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3350 m_failingProvisionalLoadURL = { };
3353 void WebPageProxy::clearLoadDependentCallbacks()
3355 HashSet<CallbackID> loadDependentStringCallbackIDs = WTFMove(m_loadDependentStringCallbackIDs);
3356 for (auto& callbackID : loadDependentStringCallbackIDs) {
3357 if (auto callback = m_callbacks.take<StringCallback>(callbackID))
3358 callback->invalidate();
3362 void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t opaqueFrameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, std::optional<HasInsecureContent> hasInsecureContent, const UserData& userData)
3364 PageClientProtector protector(m_pageClient);
3366 WebFrameProxy* frame = m_process->webFrame(frameID);
3367 MESSAGE_CHECK(frame);
3369 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3370 RefPtr<API::Navigation> navigation;
3371 if (frame->isMainFrame() && navigationID)
3372 navigation = &navigationState().navigation(navigationID);
3375 if (frame->isMainFrame()) {
3376 m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = false;
3377 m_firstLayerTreeTransactionIdAfterDidCommitLoad = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).nextLayerTreeTransactionID();
3381 auto transaction = m_pageLoadState.transaction();
3382 Ref<WebCertificateInfo> webCertificateInfo = WebCertificateInfo::create(certificateInfo);
3383 bool markPageInsecure = hasInsecureContent ? hasInsecureContent.value() == HasInsecureContent::Yes : m_treatsSHA1CertificatesAsInsecure && certificateInfo.containsNonRootSHA1SignedCertificate();
3385 if (frame->isMainFrame()) {
3386 m_pageLoadState.didCommitLoad(transaction, webCertificateInfo, markPageInsecure);
3387 m_suppressAutomaticNavigationSnapshotting = false;
3388 } else if (markPageInsecure)
3389 m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3392 // FIXME (bug 59111): didCommitLoadForFrame comes too late when restoring a page from b/f cache, making us disable secure event mode in password fields.
3393 // FIXME: A load going on in one frame shouldn't affect text editing in other frames on the page.
3394 m_pageClient.resetSecureInputState();
3397 clearLoadDependentCallbacks();
3399 frame->didCommitLoad(mimeType, webCertificateInfo, containsPluginDocument);
3401 if (frame->isMainFrame()) {
3402 m_mainFrameHasCustomContentProvider = frameHasCustomContentProvider;
3404 if (m_mainFrameHasCustomContentProvider) {
3405 // Always assume that the main frame is pinned here, since the custom representation view will handle
3406 // any wheel events and dispatch them to the WKView when necessary.
3407 m_mainFrameIsPinnedToLeftSide = true;
3408 m_mainFrameIsPinnedToRightSide = true;
3409 m_mainFrameIsPinnedToTopSide = true;
3410 m_mainFrameIsPinnedToBottomSide = true;
3412 m_uiClient->pinnedStateDidChange(*this);
3414 m_pageClient.didCommitLoadForMainFrame(mimeType, frameHasCustomContentProvider);
3417 // Even if WebPage has the default pageScaleFactor (and therefore doesn't reset it),
3418 // WebPageProxy's cache of the value can get out of sync (e.g. in the case where a
3419 // plugin is handling page scaling itself) so we should reset it to the default
3420 // for standard main frame loads.
3421 if (frame->isMainFrame()) {
3422 if (static_cast<FrameLoadType>(opaqueFrameLoadType) == FrameLoadType::Standard) {
3423 m_pageScaleFactor = 1;
3424 m_pluginScaleFactor = 1;
3425 m_mainFramePluginHandlesPageScaleGesture = false;
3429 #if ENABLE(POINTER_LOCK)
3430 if (frame->isMainFrame())
3431 requestPointerUnlock();
3434 m_pageLoadState.commitChanges();
3435 if (m_navigationClient) {
3436 if (frame->isMainFrame())
3437 m_navigationClient->didCommitNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3439 m_loaderClient->didCommitLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3442 void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
3444 PageClientProtector protector(m_pageClient);
3446 WebFrameProxy* frame = m_process->webFrame(frameID);
3447 MESSAGE_CHECK(frame);
3449 if (m_controlledByAutomation) {
3450 if (auto* automationSession = process().processPool().automationSession())
3451 automationSession->documentLoadedForFrame(*frame);
3454 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3455 RefPtr<API::Navigation> navigation;
3456 if (frame->isMainFrame() && navigationID)
3457 navigation = &navigationState().navigation(navigationID);
3459 if (m_navigationClient) {
3460 if (frame->isMainFrame())
3461 m_navigationClient->didFinishDocumentLoad(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3463 m_loaderClient->didFinishDocumentLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3466 void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
3468 PageClientProtector protector(m_pageClient);
3470 WebFrameProxy* frame = m_process->webFrame(frameID);
3471 MESSAGE_CHECK(frame);
3473 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3474 RefPtr<API::Navigation> navigation;
3475 if (frame->isMainFrame() && navigationID)
3476 navigation = &navigationState().navigation(navigationID);
3478 auto transaction = m_pageLoadState.transaction();
3480 bool isMainFrame = frame->isMainFrame();
3482 m_pageLoadState.didFinishLoad(transaction);
3484 if (m_controlledByAutomation) {
3485 if (auto* automationSession = process().processPool().automationSession())
3486 automationSession->navigationOccurredForFrame(*frame);
3489 frame->didFinishLoad();
3491 m_pageLoadState.commitChanges();
3492 if (m_navigationClient) {
3494 m_navigationClient->didFinishNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3496 m_loaderClient->didFinishLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3499 m_pageClient.didFinishLoadForMainFrame();
3501 m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = false;
3504 void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, const UserData& userData)
3506 PageClientProtector protector(m_pageClient);
3508 WebFrameProxy* frame = m_process->webFrame(frameID);
3509 MESSAGE_CHECK(frame);
3511 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3512 RefPtr<API::Navigation> navigation;
3513 if (frame->isMainFrame() && navigationID)
3514 navigation = &navigationState().navigation(navigationID);
3516 clearLoadDependentCallbacks();
3518 auto transaction = m_pageLoadState.transaction();
3520 bool isMainFrame = frame->isMainFrame();
3523 m_pageLoadState.didFailLoad(transaction);
3525 if (m_controlledByAutomation) {
3526 if (auto* automationSession = process().processPool().automationSession())
3527 automationSession->navigationOccurredForFrame(*frame);
3530 frame->didFailLoad();
3532 m_pageLoadState.commitChanges();
3533 if (m_navigationClient) {
3534 if (frame->isMainFrame())
3535 m_navigationClient->didFailNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3537 m_loaderClient->didFailLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3540 m_pageClient.didFailLoadForMainFrame();
3543 void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint64_t navigationID, uint32_t opaqueSameDocumentNavigationType, WebCore::URL&& url, const UserData& userData)
3545 PageClientProtector protector(m_pageClient);
3547 WebFrameProxy* frame = m_process->webFrame(frameID);
3548 MESSAGE_CHECK(frame);
3549 MESSAGE_CHECK_URL(url);
3551 // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3552 RefPtr<API::Navigation> navigation;
3553 if (frame->isMainFrame() && navigationID)
3554 navigation = &navigationState().navigation(navigationID);
3556 auto transaction = m_pageLoadState.transaction();
3558 bool isMainFrame = frame->isMainFrame();
3560 m_pageLoadState.didSameDocumentNavigation(transaction, url);
3562 if (m_controlledByAutomation) {
3563 if (auto* automationSession = process().processPool().automationSession())
3564 automationSession->navigationOccurredForFrame(*frame);
3567 m_pageLoadState.clearPendingAPIRequestURL(transaction);
3568 frame->didSameDocumentNavigation(url);
3570 m_pageLoadState.commitChanges();
3572 SameDocumentNavigationType navigationType = static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType);
3573 if (m_navigationClient) {
3575 m_navigationClient->didSameDocumentNavigation(*this, navigation.get(), navigationType, m_process->transformHandlesToObjects(userData.object()).get());
3577 m_loaderClient->didSameDocumentNavigationForFrame(*this, *frame, navigation.get(), navigationType, m_process->transformHandlesToObjects(userData.object()).get());
3580 m_pageClient.didSameDocumentNavigationForMainFrame(navigationType);
3583 void WebPageProxy::didChangeMainDocument(uint64_t frameID)
3585 #if ENABLE(MEDIA_STREAM)
3586 userMediaPermissionRequestManager().resetAccess(frameID);
3588 UNUSED_PARAM(frameID);
3592 void WebPageProxy::viewIsBecomingVisible()
3594 #if ENABLE(MEDIA_STREAM)
3595 userMediaPermissionRequestManager().processPregrantedRequests();
3599 void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, const UserData& userData)
3601 PageClientProtector protector(m_pageClient);
3603 WebFrameProxy* frame = m_process->webFrame(frameID);
3604 MESSAGE_CHECK(frame);
3606 auto transaction = m_pageLoadState.transaction();
3608 if (frame->isMainFrame())
3609 m_pageLoadState.setTitle(transaction, title);
3611 frame->didChangeTitle(title);
3613 m_pageLoadState.commitChanges();
3614 m_loaderClient->didReceiveTitleForFrame(*this, title, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3617 void WebPageProxy::didFirstLayoutForFrame(uint64_t frameID, const UserData& userData)
3619 PageClientProtector protector(m_pageClient);
3621 WebFrameProxy* frame = m_process->webFrame(frameID);
3622 MESSAGE_CHECK(frame);
3624 m_loaderClient->didFirstLayoutForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3627 void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, const UserData& userData)
3629 PageClientProtector protector(m_pageClient);
3631 WebFrameProxy* frame = m_process->webFrame(frameID);
3632 MESSAGE_CHECK(frame);
3634 m_loaderClient->didFirstVisuallyNonEmptyLayoutForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3636 if (frame->isMainFrame())
3637 m_pageClient.didFirstVisuallyNonEmptyLayoutForMainFrame();
3640 void WebPageProxy::didLayoutForCustomContentProvider()
3642 didReachLayoutMilestone(DidFirstLayout | DidFirstVisuallyNonEmptyLayout | DidHitRelevantRepaintedObjectsAreaThreshold);
3645 void WebPageProxy::didReachLayoutMilestone(uint32_t layoutMilestones)
3647 PageClientProtector protector(m_pageClient);
3649 if (m_navigationClient)
3650 m_navigationClient->renderingProgressDidChange(*this, static_cast<LayoutMilestones>(layoutMilestones));
3652 m_loaderClient->didReachLayoutMilestone(*this, static_cast<LayoutMilestones>(layoutMilestones));
3655 void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, const UserData& userData)
3657 PageClientProtector protector(m_pageClient);
3659 WebFrameProxy* frame = m_process->webFrame(frameID);
3660 MESSAGE_CHECK(frame);
3662 auto transaction = m_pageLoadState.transaction();
3663 m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3664 m_pageLoadState.commitChanges();
3666 if (m_navigationClient)
3667 m_navigationClient->didDisplayInsecureContent(*this, m_process->transformHandlesToObjects(userData.object()).get());
3669 m_loaderClient->didDisplayInsecureContentForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3672 void WebPageProxy::didRunInsecureContentForFrame(uint64_t frameID, const UserData& userData)
3674 PageClientProtector protector(m_pageClient);
3676 WebFrameProxy* frame = m_process->webFrame(frameID);
3677 MESSAGE_CHECK(frame);
3679 auto transaction = m_pageLoadState.transaction();
3680 m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
3681 m_pageLoadState.commitChanges();
3683 if (m_navigationClient)
3684 m_navigationClient->didRunInsecureContent(*this, m_process->transformHandlesToObjects(userData.object()).get());
3686 m_loaderClient->didRunInsecureContentForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3689 void WebPageProxy::didDetectXSSForFrame(uint64_t frameID, const UserData& userData)
3691 PageClientProtector protector(m_pageClient);
3693 WebFrameProxy* frame = m_process->webFrame(frameID);
3694 MESSAGE_CHECK(frame);
3696 m_loaderClient->didDetectXSSForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
3699 void WebPageProxy::mainFramePluginHandlesPageScaleGestureDidChange(bool mainFramePluginHandlesPageScaleGesture)
3701 m_mainFramePluginHandlesPageScaleGesture = mainFramePluginHandlesPageScaleGesture;
3704 void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value)
3706 PageClientProtector protector(m_pageClient);
3708 WebFrameProxy* frame = m_process->webFrame(frameID);
3709 MESSAGE_CHECK(frame);
3711 frame->setIsFrameSet(value);
3712 if (frame->isMainFrame())
3713 m_frameSetLargestFrame = value ? m_mainFrame : 0;
3716 void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, const FrameInfoData& originatingFrameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, ResourceRequest&& request, uint64_t listenerID, const UserData& userData, bool& receivedPolicyAction, uint64_t& newNavigationID, WebCore::PolicyAction& policyAction, DownloadID& downloadID, std::optional<WebsitePoliciesData>& websitePolicies)
3718 PageClientProtector protector(m_pageClient);
3720 auto transaction = m_pageLoadState.transaction();
3722 bool fromAPI = request.url() == m_pageLoadState.pendingAPIRequestURL();
3724 m_pageLoadState.clearPendingAPIRequestURL(transaction);
3726 WebFrameProxy* frame = m_process->webFrame(frameID);
3727 MESSAGE_CHECK(frame);
3728 MESSAGE_CHECK_URL(request.url());
3729 MESSAGE_CHECK_URL(originalRequest.url());
3731 Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
3732 if (!navigationID) {
3733 auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request));
3734 newNavigationID = navigation->navigationID();
3735 navigation->setWasUserInitiated(!!navigationActionData.userGestureTokenIdentifier);
3736 navigation->setShouldForceDownload(!navigationActionData.downloadAttribute.isNull());
3737 listener->setNavigation(WTFMove(navigation));
3739 auto& navigation = m_navigationState->navigation(navigationID);
3740 navigation.setWasUserInitiated(!!navigationActionData.userGestureTokenIdentifier);
3741 navigation.setShouldForceDownload(!navigationActionData.downloadAttribute.isNull());
3742 listener->setNavigation(navigation);
3745 #if ENABLE(CONTENT_FILTERING)
3746 if (frame->didHandleContentFilterUnblockNavigation(request)) {
3747 receivedPolicyAction = true;
3748 policyAction = PolicyAction::Ignore;
3753 ASSERT(!m_inDecidePolicyForNavigationAction);
3755 m_inDecidePolicyForNavigationAction = true;
3756 m_syncNavigationActionPolicyActionIsValid = false;
3758 WebFrameProxy* originatingFrame = m_process->webFrame(originatingFrameInfoData.frameID);
3760 if (m_navigationClient) {
3761 auto destinationFrameInfo = API::FrameInfo::create(*frame, frameSecurityOrigin.securityOrigin());
3762 RefPtr<API::FrameInfo> sourceFrameInfo;
3763 if (!fromAPI && originatingFrame == frame)
3764 sourceFrameInfo = destinationFrameInfo.copyRef();
3766 sourceFrameInfo = API::FrameInfo::create(originatingFrameInfoData, originatingPageID ? m_process->webPage(originatingPageID) : nullptr);
3768 auto userInitiatedActivity = m_process->userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
3769 bool shouldOpenAppLinks = !m_shouldSuppressAppLinksInNextNavigationPolicyDecision && destinationFrameInfo->isMainFrame() && !hostsAreEqual(URL(ParsedURLString, m_mainFrame->url()), request.url()) && navigationActionData.navigationType != WebCore::NavigationType::BackForward;
3771 auto navigationAction = API::NavigationAction::create(WTFMove(navigationActionData), sourceFrameInfo.get(), destinationFrameInfo.ptr(), std::nullopt, WTFMove(request), originalRequest.url(), shouldOpenAppLinks, WTFMove(userInitiatedActivity));
3773 m_navigationClient->decidePolicyForNavigationAction(*this, WTFMove(navigationAction), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3775 m_policyClient->decidePolicyForNavigationAction(*this, frame, WTFMove(navigationActionData), originatingFrame, originalRequest, WTFMove(request), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3777 m_shouldSuppressAppLinksInNextNavigationPolicyDecision = false;
3778 m_inDecidePolicyForNavigationAction = false;
3780 // Check if we received a policy decision already. If we did, we can just pass it back.
3781 receivedPolicyAction = m_syncNavigationActionPolicyActionIsValid;
3782 if (m_syncNavigationActionPolicyActionIsValid) {
3783 policyAction = m_syncNavigationActionPolicyAction;
3784 downloadID = m_syncNavigationActionPolicyDownloadID;
3785 websitePolicies = WTFMove(m_syncNavigationActionPolicyWebsitePolicies);
3789 void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, NavigationActionData&& navigationActionData, ResourceRequest&& request, const String& frameName, uint64_t listenerID, const UserData& userData)
3791 PageClientProtector protector(m_pageClient);
3793 WebFrameProxy* frame = m_process->webFrame(frameID);
3794 MESSAGE_CHECK(frame);
3795 MESSAGE_CHECK_URL(request.url());
3797 Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
3799 if (m_navigationClient) {
3800 RefPtr<API::FrameInfo> sourceFrameInfo;
3802 sourceFrameInfo = API::FrameInfo::create(*frame, frameSecurityOrigin.securityOrigin());
3804 auto userInitiatedActivity = m_process->userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
3805 bool shouldOpenAppLinks = !hostsAreEqual(URL(ParsedURLString, m_mainFrame->url()), request.url());
3806 auto navigationAction = API::NavigationAction::create(WTFMove(navigationActionData), sourceFrameInfo.get(), nullptr, frameName, WTFMove(request), { }, shouldOpenAppLinks, WTFMove(userInitiatedActivity));
3808 m_navigationClient->decidePolicyForNavigationAction(*this, navigationAction.get(), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3811 m_policyClient->decidePolicyForNewWindowAction(*this, *frame, navigationActionData, request, frameName, WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3814 void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, const UserData& userData)
3816 PageClientProtector protector(m_pageClient);
3818 WebFrameProxy* frame = m_process->webFrame(frameID);
3819 MESSAGE_CHECK(frame);
3820 MESSAGE_CHECK_URL(request.url());
3821 MESSAGE_CHECK_URL(response.url());
3823 Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
3825 listener->setNavigation(m_navigationState->navigation(navigationID));
3827 if (m_navigationClient) {
3828 auto navigationResponse = API::NavigationResponse::create(API::FrameInfo::create(*frame, frameSecurityOrigin.securityOrigin()).get(), request, response, canShowMIMEType);
3829 m_navigationClient->decidePolicyForNavigationResponse(*this, WTFMove(navigationResponse), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3831 m_policyClient->decidePolicyForResponse(*this, *frame, response, request, canShowMIMEType, WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
3834 void WebPageProxy::decidePolicyForResponseSync(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, const UserData& userData, bool& receivedPolicyAction, WebCore::PolicyAction& policyAction, DownloadID& downloadID)
3836 PageClientProtector protector(m_pageClient);
3838 ASSERT(!m_inDecidePolicyForResponseSync);
3840 m_inDecidePolicyForResponseSync = true;
3841 m_decidePolicyForResponseRequest = &request;
3842 m_syncMimeTypePolicyActionIsValid = false;
3844 decidePolicyForResponse(frameID, frameSecurityOrigin, navigationID, response, request, canShowMIMEType, listenerID, userData);
3846 m_inDecidePolicyForResponseSync = false;
3847 m_decidePolicyForResponseRequest = nullptr;
3849 // Check if we received a policy decision already. If we did, we can just pass it back.
3850 receivedPolicyAction = m_syncMimeTypePolicyActionIsValid;
3851 if (m_syncMimeTypePolicyActionIsValid) {
3852 policyAction = m_syncMimeTypePolicyAction;
3853 downloadID = m_syncMimeTypePolicyDownloadID;
3857 void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError& error, const UserData& userData)
3859 PageClientProtector protector(m_pageClient);
3861 WebFrameProxy* frame = m_process->webFrame(frameID);
3862 MESSAGE_CHECK(frame);
3864 m_policyClient->unableToImplementPolicy(*this, *frame, error, m_process->transformHandlesToObjects(userData.object()).get());
3869 void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, const UserData& userData)
3871 WebFrameProxy* frame = m_process->webFrame(frameID);
3872 MESSAGE_CHECK(frame);
3874 WebFrameProxy* sourceFrame = m_process->webFrame(sourceFrameID);
3875 MESSAGE_CHECK(sourceFrame);
3877 m_formClient->willSubmitForm(*this, *frame, *sourceFrame, textFieldValues, m_process->transformHandlesToObjects(userData.object()).get(), [this, protectedThis = makeRef(*this), frameID, listenerID]() {
3878 m_process->send(Messages::WebPage::ContinueWillSubmitForm(frameID, listenerID), m_pageID);
3882 void WebPageProxy::contentRuleListNotification(WebCore::URL&& url, Vector<String>&& identifiers, Vector<String>&& notifications)
3884 if (m_navigationClient)
3885 m_navigationClient->contentRuleListNotification(*this, WTFMove(url), WTFMove(identifiers), WTFMove(notifications));
3888 void WebPageProxy::didNavigateWithNavigationData(const WebNavigationDataStore& store, uint64_t frameID)
3890 PageClientProtector protector(m_pageClient);
3892 WebFrameProxy* frame = m_process->webFrame(frameID);
3893 MESSAGE_CHECK(frame);
3894 MESSAGE_CHECK(frame->page() == this);
3896 if (m_historyClient) {
3897 if (frame->isMainFrame())
3898 m_historyClient->didNavigateWithNavigationData(*this, store);
3900 m_loaderClient->didNavigateWithNavigationData(*this, store, *frame);
3901 process().processPool().historyClient().didNavigateWithNavigationData(process().processPool(), *this, store, *frame);
3904 void WebPageProxy::didPerformClientRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
3906 PageClientProtector protector(m_pageClient);
3908 if (sourceURLString.isEmpty() || destinationURLString.isEmpty())
3911 WebFrameProxy* frame = m_process->webFrame(frameID);
3912 MESSAGE_CHECK(frame);
3913 MESSAGE_CHECK(frame->page() == this);
3915 MESSAGE_CHECK_URL(sourceURLString);
3916 MESSAGE_CHECK_URL(destinationURLString);
3918 if (m_historyClient) {
3919 if (frame->isMainFrame())
3920 m_historyClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString);
3922 m_loaderClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString, *frame);
3923 process().processPool().historyClient().didPerformClientRedirect(process().processPool(), *this, sourceURLString, destinationURLString, *frame);
3926 void WebPageProxy::didPerformServerRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
3928 PageClientProtector protector(m_pageClient);
3930 if (sourceURLString.isEmpty() || destinationURLString.isEmpty())
3933 WebFrameProxy* frame = m_process->webFrame(frameID);
3934 MESSAGE_CHECK(frame);
3935 MESSAGE_CHECK(frame->page() == this);
3937 MESSAGE_CHECK_URL(sourceURLString);
3938 MESSAGE_CHECK_URL(destinationURLString);
3940 if (m_historyClient) {
3941 if (frame->isMainFrame())
3942 m_historyClient->didPerformServerRedirect(*this, sourceURLString, destinationURLString);
3944 m_loaderClient->didPerformServerRedirect(*this, sourceURLString, destinationURLString, *frame);
3945 process().processPool().historyClient().didPerformServerRedirect(process().processPool(), *this, sourceURLString, destinationURLString, *frame);
3948 void WebPageProxy::didUpdateHistoryTitle(const String& title, const String& url, uint64_t frameID)
3950 PageClientProtector protector(m_pageClient);
3952 WebFrameProxy* frame = m_process->webFrame(frameID);
3953 MESSAGE_CHECK(frame);
3954 MESSAGE_CHECK(frame->page() == this);
3956 MESSAGE_CHECK_URL(url);
3958 if (m_historyClient) {
3959 if (frame->isMainFrame())
3960 m_historyClient->didUpdateHistoryTitle(*this, title, url);
3962 m_loaderClient->didUpdateHistoryTitle(*this, title, url, *frame);
3963 process().processPool().historyClient().didUpdateHistoryTitle(process().processPool(), *this, title, url, *frame);
3968 void WebPageProxy::createNewPage(const FrameInfoData& originatingFrameInfoData, uint64_t originatingPageID, ResourceRequest&& request, WindowFeatures&& windowFeatures, NavigationActionData&& navigationActionData, Ref<Messages::WebPageProxy::CreateNewPage::DelayedReply>&& reply)
3970 MESSAGE_CHECK(m_process->webFrame(originatingFrameInfoData.frameID));
3971 auto originatingFrameInfo = API::FrameInfo::create(originatingFrameInfoData, m_process->webPage(originatingPageID));
3973 auto mainFrameURL = m_mainFrame->url();
3975 m_uiClient->createNewPage(*this, WTFMove(originatingFrameInfo), WTFMove(request), WTFMove(windowFeatures), WTFMove(navigationActionData), [this, protectedThis = RefPtr<WebPageProxy>(this), mainFrameURL, request, reply = WTFMove(reply)](RefPtr<WebPageProxy> newPage) {
3977 reply->send(0, { });
3981 reply->send(newPage->pageID(), newPage->creationParameters());
3983 WebsiteDataStore::cloneSessionData(*this, *newPage);
3984 newPage->m_shouldSuppressAppLinksInNextNavigationPolicyDecision = hostsAreEqual(URL(ParsedURLString, mainFrameURL), request.url());
3988 void WebPageProxy::showPage()
3990 m_uiClient->showPage(this);
3993 void WebPageProxy::fullscreenMayReturnToInline()
3995 m_uiClient->fullscreenMayReturnToInline(this);
3998 void WebPageProxy::didEnterFullscreen()
4000 m_uiClient->didEnterFullscreen(this);
4003 void WebPageProxy::didExitFullscreen()
4005 m_uiClient->didExitFullscreen(this);
4008 void WebPageProxy::closePage(bool stopResponsivenessTimer)
4010 if (stopResponsivenessTimer)
4011 m_process->responsivenessTimer().stop();
4013 m_pageClient.clearAllEditCommands();
4014 m_uiClient->close(this);
4017 void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, Ref<Messages::WebPageProxy::RunJavaScriptAlert::DelayedReply>&& reply)
4019 WebFrameProxy* frame = m_process->webFrame(frameID);
4020 MESSAGE_CHECK(frame);
4022 // Since runJavaScriptAlert() can spin a nested run loop we need to turn off the responsiveness timer.
4023 m_process->responsivenessTimer().stop();
4025 if (m_controlledByAutomation) {
4026 if (auto* automationSession = process().processPool().automationSession())
4027 automationSession->willShowJavaScriptDialog(*this);
4029 m_uiClient->runJavaScriptAlert(this, message, frame, securityOrigin, [reply = WTFMove(reply)] {
4034 void WebPageProxy::runJavaScriptConfirm(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, Ref<Messages::WebPageProxy::RunJavaScriptConfirm::DelayedReply>&& reply)
4036 WebFrameProxy* frame = m_process->webFrame(frameID);
4037 MESSAGE_CHECK(frame);
4039 // Since runJavaScriptConfirm() can spin a nested run loop we need to turn off the responsiveness timer.
4040 m_process->responsivenessTimer().stop();
4042 if (m_controlledByAutomation) {
4043 if (auto* automationSession = process().processPool().automationSession())
4044 automationSession->willShowJavaScriptDialog(*this);
4047 m_uiClient->runJavaScriptConfirm(this, message, frame, securityOrigin, [reply = WTFMove(reply)](bool result) {
4048 reply->send(result);
4052 void WebPageProxy::runJavaScriptPrompt(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, const String& defaultValue, Ref<Messages::WebPageProxy::RunJavaScriptPrompt::DelayedReply>&& reply)
4054 WebFrameProxy* frame = m_process->webFrame(frameID);
4055 MESSAGE_CHECK(frame);
4057 // Since runJavaScriptPrompt() can spin a nested run loop we need to turn off the responsiveness timer.
4058 m_process->responsivenessTimer().stop();
4060 if (m_controlledByAutomation) {
4061 if (auto* automationSession = process().processPool().automationSession())
4062 automationSession->willShowJavaScriptDialog(*this);
4065 m_uiClient->runJavaScriptPrompt(this, message, defaultValue, frame, securityOrigin, [reply = WTFMove(reply)](const String& result) {
4066 reply->send(result);
4070 void WebPageProxy::setStatusText(const String& text)
4072 m_uiClient->setStatusText(this, text);
4075 void WebPageProxy::mouseDidMoveOverElement(WebHitTestResultData&& hitTestResultData, uint32_t opaqueModifiers, UserData&& userData)
4077 m_lastMouseMoveHitTestResult = API::HitTestResult::create(hitTestResultData);
4079 WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
4081 m_uiClient->mouseDidMoveOverElement(*this, hitTestResultData, modifiers, m_process->transformHandlesToObjects(userData.object()).get());
4084 void WebPageProxy::connectionWillOpen(IPC::Connection& connection)
4086 ASSERT(&connection == m_process->connection());
4088 m_webProcessLifetimeTracker.connectionWillOpen(connection);
4091 void WebPageProxy::webProcessWillShutDown()
4093 m_webProcessLifetimeTracker.webProcessWillShutDown();
4096 void WebPageProxy::processDidFinishLaunching()
4098 ASSERT(m_process->state() == WebProcessProxy::State::Running);
4099 finishInitializingWebPageAfterProcessLaunch();
4102 #if ENABLE(NETSCAPE_PLUGIN_API)
4103 void WebPageProxy::unavailablePluginButtonClicked(uint32_t opaquePluginUnavailabilityReason, const String& mimeType, const String& pluginURLString, const String& pluginspageAttributeURLString, const String& frameURLString, const String& pageURLString)
4105 MESSAGE_CHECK_URL(pluginURLString);
4106 MESSAGE_CHECK_URL(pluginspageAttributeURLString);
4107 MESSAGE_CHECK_URL(frameURLString);
4108 MESSAGE_CHECK_URL(pageURLString);
4110 String newMimeType = mimeType;
4111 PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL(URL(), pluginURLString));
4112 auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, mimeType, pageURLString, pluginspageAttributeURLString, pluginURLString);
4114 WKPluginUnavailabilityReason pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
4115 switch (static_cast<RenderEmbeddedObject::PluginUnavailabilityReason>(opaquePluginUnavailabilityReason)) {
4116 case RenderEmbeddedObject::PluginMissing:
4117 pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
4119 case RenderEmbeddedObject::InsecurePluginVersion:
4120 pluginUnavailabilityReason = kWKPluginUnavailabilityReasonInsecurePluginVersion;
4122 case RenderEmbeddedObject::PluginCrashed:
4123 pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginCrashed;
4125 case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy:
4126 ASSERT_NOT_REACHED();
4129 m_uiClient->unavailablePluginButtonClicked(*this, pluginUnavailabilityReason, pluginInformation.get());
4131 #endif // ENABLE(NETSCAPE_PLUGIN_API)
4134 void WebPageProxy::webGLPolicyForURL(URL&& url, Ref<Messages::WebPageProxy::WebGLPolicyForURL::DelayedReply>&& reply)
4136 if (m_navigationClient) {
4137 m_navigationClient->webGLLoadPolicy(*this, url, [reply = WTFMove(reply)](WebGLLoadPolicy policy) {
4138 reply->send(static_cast<uint32_t>(policy));
4141 reply->send(static_cast<uint32_t>(m_loaderClient->webGLLoadPolicy(*this, url)));
4144 void WebPageProxy::resolveWebGLPolicyForURL(URL&& url, Ref<Messages::WebPageProxy::ResolveWebGLPolicyForURL::DelayedReply>&& reply)
4146 if (m_navigationClient) {
4147 m_navigationClient->resolveWebGLLoadPolicy(*this, url, [reply = WTFMove(reply)](WebGLLoadPolicy policy) {
4148 reply->send(static_cast<uint32_t>(policy));
4151 reply->send(static_cast<uint32_t>(m_loaderClient->resolveWebGLLoadPolicy(*this, url)));
4153 #endif // ENABLE(WEBGL)
4155 void WebPageProxy::setToolbarsAreVisible(bool toolbarsAreVisible)
4157 m_uiClient->setToolbarsAreVisible(*this, toolbarsAreVisible);
4160 void WebPageProxy::getToolbarsAreVisible(Ref<Messages::WebPageProxy::GetToolbarsAreVisible::DelayedReply>&& reply)
4162 m_uiClient->toolbarsAreVisible(*this, [reply = WTFMove(reply)](bool visible) {
4163 reply->send(visible);
4167 void WebPageProxy::setMenuBarIsVisible(bool menuBarIsVisible)
4169 m_uiClient->setMenuBarIsVisible(*this, menuBarIsVisible);
4172 void WebPageProxy::getMenuBarIsVisible(Ref<Messages::WebPageProxy::GetMenuBarIsVisible::DelayedReply>&& reply)
4174 m_uiClient->menuBarIsVisible(*this, [reply = WTFMove(reply)] (bool visible) {
4175 reply->send(visible);
4179 void WebPageProxy::setStatusBarIsVisible(bool statusBarIsVisible)
4181 m_uiClient->setStatusBarIsVisible(*this, statusBarIsVisible);
4184 void WebPageProxy::getStatusBarIsVisible(Ref<Messages::WebPageProxy::GetStatusBarIsVisible::DelayedReply>&& reply)
4186 m_uiClient->statusBarIsVisible(*this, [reply = WTFMove(reply)] (bool visible) {
4187 reply->send(visible);
4191 void WebPageProxy::setIsResizable(bool isResizable)
4193 m_uiClient->setIsResizable(*this, isResizable);
4196 void WebPageProxy::setWindowFrame(const FloatRect& newWindowFrame)
4198 m_uiClient->setWindowFrame(*this, m_pageClient.convertToDeviceSpace(newWindowFrame));
4201 void WebPageProxy::getWindowFrame(Ref<Messages::WebPageProxy::GetWindowFrame::DelayedReply>&& reply)
4203 m_uiClient->windowFrame(*this, [this, protectedThis = makeRef(*this), reply = WTFMove(reply)] (FloatRect frame) {
4204 reply->send(m_pageClient.convertToUserSpace(frame));
4208 void WebPageProxy::getWindowFrameWithCallback(Function<void(FloatRect)>&& completionHandler)
4210 m_uiClient->windowFrame(*this, WTFMove(completionHandler));
4213 void WebPageProxy::screenToRootView(const IntPoint& screenPoint, Ref<Messages::WebPageProxy::ScreenToRootView::DelayedReply>&& reply)
4215 reply->send(m_pageClient.screenToRootView(screenPoint));
4218 void WebPageProxy::rootViewToScreen(const IntRect& viewRect, Ref<Messages::WebPageProxy::RootViewToScreen::DelayedReply>&& reply)
4220 reply->send(m_pageClient.rootViewToScreen(viewRect));