Reuse existing WebPageProxy quota handler for NetworkProcessProxy quota requests
[WebKit-https.git] / Source / WebKit / UIProcess / WebPageProxy.cpp
1 /*
2  * Copyright (C) 2010-2019 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Intel Corporation. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
25  */
26
27 #include "config.h"
28 #include "WebPageProxy.h"
29
30 #include "APIArray.h"
31 #include "APIAttachment.h"
32 #include "APIContextMenuClient.h"
33 #include "APIFindClient.h"
34 #include "APIFindMatchesClient.h"
35 #include "APIFormClient.h"
36 #include "APIFrameInfo.h"
37 #include "APIFullscreenClient.h"
38 #include "APIGeometry.h"
39 #include "APIHistoryClient.h"
40 #include "APIHitTestResult.h"
41 #include "APIIconLoadingClient.h"
42 #include "APILegacyContextHistoryClient.h"
43 #include "APILoaderClient.h"
44 #include "APINavigation.h"
45 #include "APINavigationAction.h"
46 #include "APINavigationClient.h"
47 #include "APINavigationResponse.h"
48 #include "APIOpenPanelParameters.h"
49 #include "APIPageConfiguration.h"
50 #include "APIPolicyClient.h"
51 #include "APISecurityOrigin.h"
52 #include "APIUIClient.h"
53 #include "APIURLRequest.h"
54 #include "APIWebsitePolicies.h"
55 #include "AuthenticationChallengeProxy.h"
56 #include "AuthenticationDecisionListener.h"
57 #include "DataReference.h"
58 #include "DownloadProxy.h"
59 #include "DrawingAreaMessages.h"
60 #include "DrawingAreaProxy.h"
61 #include "EventDispatcherMessages.h"
62 #include "FormDataReference.h"
63 #include "FrameInfoData.h"
64 #include "LoadParameters.h"
65 #include "Logging.h"
66 #include "NativeWebGestureEvent.h"
67 #include "NativeWebKeyboardEvent.h"
68 #include "NativeWebMouseEvent.h"
69 #include "NativeWebWheelEvent.h"
70 #include "NavigationActionData.h"
71 #include "NetworkProcessMessages.h"
72 #include "NetworkProcessProxy.h"
73 #include "NotificationPermissionRequest.h"
74 #include "NotificationPermissionRequestManager.h"
75 #include "OptionalCallbackID.h"
76 #include "PageClient.h"
77 #include "PluginInformation.h"
78 #include "PluginProcessManager.h"
79 #include "PrintInfo.h"
80 #include "ProvisionalPageProxy.h"
81 #include "SafeBrowsingWarning.h"
82 #include "ShareSheetCallbackID.h"
83 #include "SharedBufferDataReference.h"
84 #include "SyntheticEditingCommandType.h"
85 #include "TextChecker.h"
86 #include "TextCheckerState.h"
87 #include "TextInputContext.h"
88 #include "UIMessagePortChannelProvider.h"
89 #include "URLSchemeTaskParameters.h"
90 #include "UndoOrRedo.h"
91 #include "UserMediaPermissionRequestProxy.h"
92 #include "UserMediaProcessManager.h"
93 #include "WKContextPrivate.h"
94 #include "WebAutomationSession.h"
95 #include "WebBackForwardList.h"
96 #include "WebBackForwardListItem.h"
97 #include "WebCertificateInfo.h"
98 #include "WebContextMenuItem.h"
99 #include "WebContextMenuProxy.h"
100 #include "WebCoreArgumentCoders.h"
101 #include "WebEditCommandProxy.h"
102 #include "WebEvent.h"
103 #include "WebEventConversion.h"
104 #include "WebFramePolicyListenerProxy.h"
105 #include "WebFullScreenManagerProxy.h"
106 #include "WebFullScreenManagerProxyMessages.h"
107 #include "WebImage.h"
108 #include "WebInspectorProxy.h"
109 #include "WebInspectorUtilities.h"
110 #include "WebNavigationDataStore.h"
111 #include "WebNavigationState.h"
112 #include "WebNotificationManagerProxy.h"
113 #include "WebOpenPanelResultListenerProxy.h"
114 #include "WebPageCreationParameters.h"
115 #include "WebPageDebuggable.h"
116 #include "WebPageGroup.h"
117 #include "WebPageGroupData.h"
118 #include "WebPageInspectorController.h"
119 #include "WebPageMessages.h"
120 #include "WebPageProxyMessages.h"
121 #include "WebPaymentCoordinatorProxy.h"
122 #include "WebPopupItem.h"
123 #include "WebPopupMenuProxy.h"
124 #include "WebPreferences.h"
125 #include "WebPreferencesKeys.h"
126 #include "WebProcessMessages.h"
127 #include "WebProcessPool.h"
128 #include "WebProcessProxy.h"
129 #include "WebProtectionSpace.h"
130 #include "WebResourceLoadStatisticsStore.h"
131 #include "WebURLSchemeHandler.h"
132 #include "WebUserContentControllerProxy.h"
133 #include "WebViewDidMoveToWindowObserver.h"
134 #include "WebsiteDataStore.h"
135 #include <WebCore/AdClickAttribution.h>
136 #include <WebCore/BitmapImage.h>
137 #include <WebCore/DOMPasteAccess.h>
138 #include <WebCore/DeprecatedGlobalSettings.h>
139 #include <WebCore/DiagnosticLoggingClient.h>
140 #include <WebCore/DiagnosticLoggingKeys.h>
141 #include <WebCore/DragController.h>
142 #include <WebCore/DragData.h>
143 #include <WebCore/EventNames.h>
144 #include <WebCore/FloatRect.h>
145 #include <WebCore/FocusDirection.h>
146 #include <WebCore/FontAttributeChanges.h>
147 #include <WebCore/FrameLoader.h>
148 #include <WebCore/GlobalFrameIdentifier.h>
149 #include <WebCore/GlobalWindowIdentifier.h>
150 #include <WebCore/JSDOMBinding.h>
151 #include <WebCore/JSDOMExceptionHandling.h>
152 #include <WebCore/LengthBox.h>
153 #include <WebCore/MIMETypeRegistry.h>
154 #include <WebCore/MediaStreamRequest.h>
155 #include <WebCore/PerformanceLoggingClient.h>
156 #include <WebCore/PlatformEvent.h>
157 #include <WebCore/PublicSuffix.h>
158 #include <WebCore/RenderEmbeddedObject.h>
159 #include <WebCore/ResourceLoadStatistics.h>
160 #include <WebCore/SSLKeyGenerator.h>
161 #include <WebCore/SerializedCryptoKeyWrap.h>
162 #include <WebCore/ShareData.h>
163 #include <WebCore/SharedBuffer.h>
164 #include <WebCore/ShouldTreatAsContinuingLoad.h>
165 #include <WebCore/TextCheckerClient.h>
166 #include <WebCore/TextIndicator.h>
167 #include <WebCore/ValidationBubble.h>
168 #include <WebCore/WindowFeatures.h>
169 #include <WebCore/WritingDirection.h>
170 #include <stdio.h>
171 #include <wtf/NeverDestroyed.h>
172 #include <wtf/SystemTracing.h>
173 #include <wtf/URL.h>
174 #include <wtf/URLParser.h>
175 #include <wtf/text/StringView.h>
176 #include <wtf/text/TextStream.h>
177
178 #if ENABLE(APPLICATION_MANIFEST)
179 #include "APIApplicationManifest.h"
180 #endif
181
182 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
183 #include "RemoteScrollingCoordinatorProxy.h"
184 #endif
185
186 #ifndef NDEBUG
187 #include <wtf/RefCountedLeakCounter.h>
188 #endif
189
190 #if PLATFORM(COCOA)
191 #include "AttributedString.h"
192 #include "InsertTextOptions.h"
193 #include "RemoteLayerTreeDrawingAreaProxy.h"
194 #include "RemoteLayerTreeScrollingPerformanceData.h"
195 #include "TouchBarMenuData.h"
196 #include "TouchBarMenuItemData.h"
197 #include "VideoFullscreenManagerProxy.h"
198 #include "VideoFullscreenManagerProxyMessages.h"
199 #include <WebCore/RunLoopObserver.h>
200 #include <WebCore/TextIndicatorWindow.h>
201 #include <wtf/MachSendRight.h>
202 #endif
203
204 #if PLATFORM(COCOA) || PLATFORM(GTK)
205 #include "ViewSnapshotStore.h"
206 #endif
207
208 #if PLATFORM(GTK)
209 #include "WebSelectionData.h"
210 #endif
211
212 #if USE(CAIRO)
213 #include <WebCore/CairoUtilities.h>
214 #endif
215
216 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
217 #include <WebCore/MediaPlaybackTarget.h>
218 #include <WebCore/WebMediaSessionManager.h>
219 #endif
220
221 #if ENABLE(MEDIA_SESSION)
222 #include "WebMediaSessionFocusManager.h"
223 #include "WebMediaSessionMetadata.h"
224 #include <WebCore/MediaSessionMetadata.h>
225 #endif
226
227 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
228 #include "PlaybackSessionManagerProxy.h"
229 #endif
230
231 #if ENABLE(WEB_AUTHN)
232 #include "WebAuthenticatorCoordinatorProxy.h"
233 #endif
234
235 #if ENABLE(REMOTE_INSPECTOR)
236 #include <JavaScriptCore/RemoteInspector.h>
237 #endif
238
239 #if HAVE(SEC_KEY_PROXY)
240 #include "SecKeyProxyStore.h"
241 #endif
242
243 #if HAVE(PENCILKIT)
244 #include "EditableImageController.h"
245 #endif
246
247 // This controls what strategy we use for mouse wheel coalescing.
248 #define MERGE_WHEEL_EVENTS 1
249
250 #define MESSAGE_CHECK(process, assertion) MESSAGE_CHECK_BASE(assertion, process->connection())
251 #define MESSAGE_CHECK_URL(process, url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(process, url), process->connection())
252
253 #define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - WebPageProxy::" fmt, this, ##__VA_ARGS__)
254 #define RELEASE_LOG_ERROR_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_ERROR_IF(isAlwaysOnLoggingAllowed(), channel, "%p - WebPageProxy::" fmt, this, ##__VA_ARGS__)
255
256 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
257 static const unsigned wheelEventQueueSizeThreshold = 10;
258
259 static const Seconds resetRecentCrashCountDelay = 30_s;
260 static unsigned maximumWebProcessRelaunchAttempts = 1;
261
262 namespace WebKit {
263 using namespace WebCore;
264
265 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
266
267 class StorageRequests {
268     WTF_MAKE_NONCOPYABLE(StorageRequests); WTF_MAKE_FAST_ALLOCATED;
269     friend NeverDestroyed<StorageRequests>;
270 public:
271     static StorageRequests& singleton();
272
273     void processOrAppend(CompletionHandler<void()>&& completionHandler)
274     {
275         if (m_requestsAreBeingProcessed) {
276             m_requests.append(WTFMove(completionHandler));
277             return;
278         }
279         m_requestsAreBeingProcessed = true;
280         completionHandler();
281     }
282
283     void processNextIfAny()
284     {
285         if (m_requests.isEmpty()) {
286             m_requestsAreBeingProcessed = false;
287             return;
288         }
289         m_requests.takeFirst()();
290     }
291
292 private:
293     StorageRequests() { }
294     ~StorageRequests() { }
295
296     Deque<CompletionHandler<void()>> m_requests;
297     bool m_requestsAreBeingProcessed { false };
298 };
299
300 StorageRequests& StorageRequests::singleton()
301 {
302     static NeverDestroyed<StorageRequests> requests;
303     return requests;
304 }
305
306 #if !LOG_DISABLED
307 static const char* webMouseEventTypeString(WebEvent::Type type)
308 {
309     switch (type) {
310     case WebEvent::MouseDown:
311         return "MouseDown";
312     case WebEvent::MouseUp:
313         return "MouseUp";
314     case WebEvent::MouseMove:
315         return "MouseMove";
316     case WebEvent::MouseForceChanged:
317         return "MouseForceChanged";
318     case WebEvent::MouseForceDown:
319         return "MouseForceDown";
320     case WebEvent::MouseForceUp:
321         return "MouseForceUp";
322     default:
323         ASSERT_NOT_REACHED();
324         return "<unknown>";
325     }
326 }
327
328 static const char* webKeyboardEventTypeString(WebEvent::Type type)
329 {
330     switch (type) {
331     case WebEvent::KeyDown:
332         return "KeyDown";
333     case WebEvent::KeyUp:
334         return "KeyUp";
335     case WebEvent::RawKeyDown:
336         return "RawKeyDown";
337     case WebEvent::Char:
338         return "Char";
339     default:
340         ASSERT_NOT_REACHED();
341         return "<unknown>";
342     }
343 }
344 #endif // !LOG_DISABLED
345
346 class PageClientProtector {
347     WTF_MAKE_NONCOPYABLE(PageClientProtector);
348 public:
349     PageClientProtector(PageClient& pageClient)
350         : m_pageClient(makeWeakPtr(pageClient))
351     {
352         m_pageClient->refView();
353     }
354
355     ~PageClientProtector()
356     {
357         ASSERT(m_pageClient);
358         m_pageClient->derefView();
359     }
360
361 private:
362     WeakPtr<PageClient> m_pageClient;
363 };
364
365 void WebPageProxy::forMostVisibleWebPageIfAny(PAL::SessionID sessionID, const SecurityOriginData& origin, CompletionHandler<void(WebPageProxy*)>&& completionHandler)
366 {
367     // FIXME: If not finding right away a visible page, we might want to try again for a given period of time when there is a change of visibility.
368     WebPageProxy* selectedPage = nullptr;
369     WebProcessProxy::forWebPagesWithOrigin(sessionID, origin, [&](auto& page) {
370         if (!page.mainFrame())
371             return;
372         if (page.isViewVisible() && (!selectedPage || !selectedPage->isViewVisible())) {
373             selectedPage = &page;
374             return;
375         }
376         if (page.isViewFocused() && (!selectedPage || !selectedPage->isViewFocused())) {
377             selectedPage = &page;
378             return;
379         }
380     });
381     completionHandler(selectedPage);
382 }
383
384 Ref<WebPageProxy> WebPageProxy::create(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
385 {
386     return adoptRef(*new WebPageProxy(pageClient, process, pageID, WTFMove(configuration)));
387 }
388
389 WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
390     : m_pageClient(makeWeakPtr(pageClient))
391     , m_configuration(WTFMove(configuration))
392     , m_navigationClient(makeUniqueRef<API::NavigationClient>())
393     , m_historyClient(makeUniqueRef<API::HistoryClient>())
394     , m_iconLoadingClient(std::make_unique<API::IconLoadingClient>())
395     , m_formClient(std::make_unique<API::FormClient>())
396     , m_uiClient(std::make_unique<API::UIClient>())
397     , m_findClient(std::make_unique<API::FindClient>())
398     , m_findMatchesClient(std::make_unique<API::FindMatchesClient>())
399 #if ENABLE(CONTEXT_MENUS)
400     , m_contextMenuClient(std::make_unique<API::ContextMenuClient>())
401 #endif
402     , m_navigationState(std::make_unique<WebNavigationState>())
403     , m_process(process)
404     , m_pageGroup(*m_configuration->pageGroup())
405     , m_preferences(*m_configuration->preferences())
406     , m_userContentController(*m_configuration->userContentController())
407     , m_visitedLinkStore(*m_configuration->visitedLinkStore())
408     , m_websiteDataStore(m_configuration->websiteDataStore()->websiteDataStore())
409     , m_userAgent(standardUserAgent())
410     , m_overrideContentSecurityPolicy { m_configuration->overrideContentSecurityPolicy() }
411     , m_treatsSHA1CertificatesAsInsecure(m_configuration->treatsSHA1SignedCertificatesAsInsecure())
412 #if ENABLE(FULLSCREEN_API)
413     , m_fullscreenClient(std::make_unique<API::FullscreenClient>())
414 #endif
415     , m_geolocationPermissionRequestManager(*this)
416     , m_notificationPermissionRequestManager(*this)
417 #if PLATFORM(IOS_FAMILY)
418     , m_alwaysRunsAtForegroundPriority(m_configuration->alwaysRunsAtForegroundPriority())
419 #endif
420     , m_initialCapitalizationEnabled(m_configuration->initialCapitalizationEnabled())
421     , m_cpuLimit(m_configuration->cpuLimit())
422     , m_backForwardList(WebBackForwardList::create(*this))
423     , m_waitsForPaintAfterViewDidMoveToWindow(m_configuration->waitsForPaintAfterViewDidMoveToWindow())
424     , m_hasRunningProcess(process.state() != WebProcessProxy::State::Terminated)
425     , m_pageID(pageID)
426     , m_controlledByAutomation(m_configuration->isControlledByAutomation())
427 #if PLATFORM(COCOA)
428     , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
429 #endif
430     , m_pageLoadState(*this)
431     , m_configurationPreferenceValues(m_configuration->preferenceValues())
432     , m_inspectorController(std::make_unique<WebPageInspectorController>(*this))
433 #if ENABLE(REMOTE_INSPECTOR)
434     , m_inspectorDebuggable(std::make_unique<WebPageDebuggable>(*this))
435 #endif
436     , m_resetRecentCrashCountTimer(RunLoop::main(), this, &WebPageProxy::resetRecentCrashCount)
437 {
438     RELEASE_LOG_IF_ALLOWED(Loading, "constructor: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
439
440     if (!m_configuration->drawsBackground())
441         m_backgroundColor = Color(Color::transparent);
442
443     m_webProcessLifetimeTracker.addObserver(m_visitedLinkStore);
444     m_webProcessLifetimeTracker.addObserver(m_websiteDataStore);
445
446     updateActivityState();
447     updateThrottleState();
448     updateHiddenPageThrottlingAutoIncreases();
449     
450 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
451     m_layerHostingMode = m_activityState & ActivityState::IsInWindow ? WebPageProxy::pageClient().viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
452 #endif
453
454     platformInitialize();
455
456 #ifndef NDEBUG
457     webPageProxyCounter.increment();
458 #endif
459
460     WebProcessPool::statistics().wkPageCount++;
461
462     m_preferences->addPage(*this);
463     m_pageGroup->addPage(this);
464
465     m_inspector = WebInspectorProxy::create(this);
466
467     if (hasRunningProcess())
468         didAttachToRunningProcess();
469
470     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
471
472 #if PLATFORM(IOS_FAMILY)
473     DeprecatedGlobalSettings::setDisableScreenSizeOverride(preferencesStore().getBoolValueForKey(WebPreferencesKey::disableScreenSizeOverrideKey()));
474 #endif
475
476 #if PLATFORM(COCOA)
477     m_activityStateChangeDispatcher = std::make_unique<RunLoopObserver>(static_cast<CFIndex>(RunLoopObserver::WellKnownRunLoopOrders::ActivityStateChange), [this] {
478         this->dispatchActivityStateChange();
479     });
480 #endif
481
482 #if ENABLE(REMOTE_INSPECTOR)
483     m_inspectorDebuggable->setRemoteDebuggingAllowed(true);
484     m_inspectorDebuggable->init();
485 #endif
486
487     createInspectorTargets();
488 }
489
490 WebPageProxy::~WebPageProxy()
491 {
492     RELEASE_LOG_IF_ALLOWED(Loading, "destructor: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
493
494     ASSERT(m_process->webPage(m_pageID) != this);
495 #if !ASSERT_DISABLED
496     for (WebPageProxy* page : m_process->pages())
497         ASSERT(page != this);
498 #endif
499
500     if (!m_isClosed)
501         close();
502
503     WebProcessPool::statistics().wkPageCount--;
504
505     if (m_spellDocumentTag)
506         TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag.value());
507
508     m_preferences->removePage(*this);
509     m_pageGroup->removePage(this);
510
511 #ifndef NDEBUG
512     webPageProxyCounter.decrement();
513 #endif
514 }
515
516 // FIXME: Should return a const PageClient& and add a separate non-const
517 // version of this function, but several PageClient methods will need to become
518 // const for this to be possible.
519 PageClient& WebPageProxy::pageClient() const
520 {
521     ASSERT(m_pageClient);
522     return *m_pageClient;
523 }
524
525 PAL::SessionID WebPageProxy::sessionID() const
526 {
527     return m_websiteDataStore->sessionID();
528 }
529
530 DrawingAreaProxy* WebPageProxy::provisionalDrawingArea() const
531 {
532     if (m_provisionalPage && m_provisionalPage->drawingArea())
533         return m_provisionalPage->drawingArea();
534     return drawingArea();
535 }
536
537 const API::PageConfiguration& WebPageProxy::configuration() const
538 {
539     return m_configuration.get();
540 }
541
542 ProcessID WebPageProxy::processIdentifier() const
543 {
544     if (m_isClosed)
545         return 0;
546
547     return m_process->processIdentifier();
548 }
549
550 bool WebPageProxy::hasRunningProcess() const
551 {
552     // A page that has been explicitly closed is never valid.
553     if (m_isClosed)
554         return false;
555
556     return m_hasRunningProcess;
557 }
558
559 void WebPageProxy::notifyProcessPoolToPrewarm()
560 {
561     m_process->processPool().didReachGoodTimeToPrewarm();
562 }
563
564 void WebPageProxy::setPreferences(WebPreferences& preferences)
565 {
566     if (&preferences == m_preferences.ptr())
567         return;
568
569     m_preferences->removePage(*this);
570     m_preferences = preferences;
571     m_preferences->addPage(*this);
572
573     preferencesDidChange();
574 }
575     
576 void WebPageProxy::setHistoryClient(UniqueRef<API::HistoryClient>&& historyClient)
577 {
578     m_historyClient = WTFMove(historyClient);
579 }
580
581 void WebPageProxy::setNavigationClient(UniqueRef<API::NavigationClient>&& navigationClient)
582 {
583     m_navigationClient = WTFMove(navigationClient);
584 }
585
586 void WebPageProxy::setLoaderClient(std::unique_ptr<API::LoaderClient>&& loaderClient)
587 {
588     m_loaderClient = WTFMove(loaderClient);
589 }
590
591 void WebPageProxy::setPolicyClient(std::unique_ptr<API::PolicyClient>&& policyClient)
592 {
593     m_policyClient = WTFMove(policyClient);
594 }
595
596 void WebPageProxy::setFormClient(std::unique_ptr<API::FormClient>&& formClient)
597 {
598     if (!formClient) {
599         m_formClient = std::make_unique<API::FormClient>();
600         return;
601     }
602
603     m_formClient = WTFMove(formClient);
604 }
605
606 void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient>&& uiClient)
607 {
608     if (!uiClient) {
609         m_uiClient = std::make_unique<API::UIClient>();
610         return;
611     }
612
613     m_uiClient = WTFMove(uiClient);
614
615     if (hasRunningProcess())
616         m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient->canRunBeforeUnloadConfirmPanel()), m_pageID);
617
618     setCanRunModal(m_uiClient->canRunModal());
619     setNeedsFontAttributes(m_uiClient->needsFontAttributes());
620 }
621
622 void WebPageProxy::setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&& iconLoadingClient)
623 {
624     bool hasClient = iconLoadingClient.get();
625     if (!iconLoadingClient)
626         m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
627     else
628         m_iconLoadingClient = WTFMove(iconLoadingClient);
629
630     if (!hasRunningProcess())
631         return;
632
633     m_process->send(Messages::WebPage::SetUseIconLoadingClient(hasClient), m_pageID);
634 }
635
636 void WebPageProxy::setFindClient(std::unique_ptr<API::FindClient>&& findClient)
637 {
638     if (!findClient) {
639         m_findClient = std::make_unique<API::FindClient>();
640         return;
641     }
642     
643     m_findClient = WTFMove(findClient);
644 }
645
646 void WebPageProxy::setFindMatchesClient(std::unique_ptr<API::FindMatchesClient>&& findMatchesClient)
647 {
648     if (!findMatchesClient) {
649         m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
650         return;
651     }
652
653     m_findMatchesClient = WTFMove(findMatchesClient);
654 }
655
656 void WebPageProxy::setDiagnosticLoggingClient(std::unique_ptr<API::DiagnosticLoggingClient>&& diagnosticLoggingClient)
657 {
658     m_diagnosticLoggingClient = WTFMove(diagnosticLoggingClient);
659 }
660
661 #if ENABLE(CONTEXT_MENUS)
662 void WebPageProxy::setContextMenuClient(std::unique_ptr<API::ContextMenuClient>&& contextMenuClient)
663 {
664     if (!contextMenuClient) {
665         m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
666         return;
667     }
668
669     m_contextMenuClient = WTFMove(contextMenuClient);
670 }
671 #endif
672
673 void WebPageProxy::setInjectedBundleClient(const WKPageInjectedBundleClientBase* client)
674 {
675     if (!client) {
676         m_injectedBundleClient = nullptr;
677         return;
678     }
679
680     m_injectedBundleClient = std::make_unique<WebPageInjectedBundleClient>();
681     m_injectedBundleClient->initialize(client);
682 }
683
684 void WebPageProxy::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
685 {
686     ASSERT(m_process->connection() == &connection);
687
688     if (!m_injectedBundleClient)
689         return;
690
691     m_injectedBundleClient->didReceiveMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get());
692 }
693
694 void WebPageProxy::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, CompletionHandler<void(UserData&&)>&& completionHandler)
695 {
696     ASSERT(m_process->connection() == &connection);
697
698     if (!m_injectedBundleClient)
699         return completionHandler({ });
700
701     RefPtr<API::Object> returnData;
702     m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get(), returnData);
703     completionHandler(UserData(m_process->transformObjectsToHandles(returnData.get())));
704 }
705
706 void WebPageProxy::launchProcess(const RegistrableDomain& registrableDomain)
707 {
708     ASSERT(!m_isClosed);
709     ASSERT(!hasRunningProcess());
710
711     RELEASE_LOG_IF_ALLOWED(Loading, "launchProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
712
713     m_process->removeWebPage(*this, WebProcessProxy::EndsUsingDataStore::Yes);
714     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
715
716     auto& processPool = m_process->processPool();
717
718     auto* relatedPage = m_configuration->relatedPage();
719     if (relatedPage && !relatedPage->isClosed())
720         m_process = relatedPage->ensureRunningProcess();
721     else
722         m_process = processPool.processForRegistrableDomain(m_websiteDataStore.get(), this, registrableDomain);
723     m_hasRunningProcess = true;
724
725     m_process->addExistingWebPage(*this, WebProcessProxy::BeginsUsingDataStore::Yes);
726     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
727
728     finishAttachingToWebProcess(IsProcessSwap::No);
729 }
730
731 bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, Optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient processSwapRequestedByClient, ShouldDelayClosingUntilEnteringAcceleratedCompositingMode shouldDelayClosingUntilEnteringAcceleratedCompositingMode)
732 {
733     m_lastSuspendedPage = nullptr;
734
735     if (!mainFrameID)
736         return false;
737
738     if (!hasCommittedAnyProvisionalLoads()) {
739         RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because has not committed any load yet", m_process->processIdentifier());
740         return false;
741     }
742
743     if (isPageOpenedByDOMShowingInitialEmptyDocument()) {
744         RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because it is showing the initial empty document", m_process->processIdentifier());
745         return false;
746     }
747
748     auto* fromItem = navigation.fromItem();
749
750     // If the source and the destination back / forward list items are the same, then this is a client-side redirect. In this case,
751     // there is no need to suspend the previous page as there will be no way to get back to it.
752     if (fromItem && fromItem == m_backForwardList->currentItem()) {
753         RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because this is a client-side redirect", m_process->processIdentifier());
754         return false;
755     }
756
757     if (fromItem && fromItem->url() != pageLoadState().url()) {
758         RELEASE_LOG_ERROR_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because fromItem's URL does not match the page URL.", m_process->processIdentifier());
759         ASSERT_NOT_REACHED();
760         return false;
761     }
762
763     RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Suspending current page for process pid %i", m_process->processIdentifier());
764     auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *mainFrameID, shouldDelayClosingUntilEnteringAcceleratedCompositingMode);
765
766     LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " created suspended page %s for process pid %i, back/forward item %s" PRIu64, pageID(), suspendedPage->loggingString(), m_process->processIdentifier(), fromItem ? fromItem->itemID().logString() : 0);
767
768     // If the client forced a swap then it may not be web-compatible to keep the previous page because other windows may have an opener link to it. We thus close it as soon as we
769     // can do so without flashing.
770     if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes)
771         suspendedPage->closeWithoutFlashing();
772
773     if (fromItem && m_preferences->usesPageCache())
774         fromItem->setSuspendedPage(suspendedPage.get());
775
776     m_lastSuspendedPage = makeWeakPtr(*suspendedPage);
777     m_process->processPool().addSuspendedPage(WTFMove(suspendedPage));
778     return true;
779 }
780
781 void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, std::unique_ptr<DrawingAreaProxy>&& drawingArea, RefPtr<WebFrameProxy>&& mainFrame)
782 {
783     ASSERT(!m_isClosed);
784     RELEASE_LOG_IF_ALLOWED(Loading, "swapToWebProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
785
786     m_process = WTFMove(process);
787     m_websiteDataStore = m_process->websiteDataStore();
788
789     if (m_logger)
790         m_logger->setEnabled(this, isAlwaysOnLoggingAllowed());
791
792     ASSERT(!m_drawingArea);
793     setDrawingArea(WTFMove(drawingArea));
794     ASSERT(!m_mainFrame);
795     m_mainFrame = WTFMove(mainFrame);
796     m_hasRunningProcess = true;
797
798     m_process->addExistingWebPage(*this, WebProcessProxy::BeginsUsingDataStore::No);
799     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
800
801     finishAttachingToWebProcess(IsProcessSwap::Yes);
802 }
803
804 void WebPageProxy::finishAttachingToWebProcess(IsProcessSwap isProcessSwap)
805 {
806     ASSERT(m_process->state() != AuxiliaryProcessProxy::State::Terminated);
807
808     if (m_process->state() == AuxiliaryProcessProxy::State::Running) {
809         // In the process-swap case, the ProvisionalPageProxy constructor already took care of calling webPageEnteringWebProcess()
810         // when the process was provisional.
811         if (isProcessSwap != IsProcessSwap::Yes)
812             m_webProcessLifetimeTracker.webPageEnteringWebProcess(m_process);
813     }
814
815     updateActivityState();
816     updateThrottleState();
817
818     didAttachToRunningProcess();
819
820     // In the process-swap case, the ProvisionalPageProxy already took care of initializing the WebPage in the WebProcess.
821     if (isProcessSwap != IsProcessSwap::Yes)
822         initializeWebPage();
823
824     m_inspector->updateForNewPageProcess(this);
825
826 #if ENABLE(REMOTE_INSPECTOR)
827     remoteInspectorInformationDidChange();
828 #endif
829
830     clearInspectorTargets();
831     createInspectorTargets();
832
833     pageClient().didRelaunchProcess();
834     m_pageLoadState.didSwapWebProcesses();
835     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
836 }
837
838 void WebPageProxy::didAttachToRunningProcess()
839 {
840     ASSERT(hasRunningProcess());
841
842 #if ENABLE(FULLSCREEN_API)
843     ASSERT(!m_fullScreenManager);
844     m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, pageClient().fullScreenManagerProxyClient());
845 #endif
846 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
847     ASSERT(!m_playbackSessionManager);
848     m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
849     ASSERT(!m_videoFullscreenManager);
850     m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
851 #endif
852
853 #if ENABLE(APPLE_PAY)
854     ASSERT(!m_paymentCoordinator);
855     m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
856 #endif
857
858 #if USE(SYSTEM_PREVIEW)
859     ASSERT(!m_systemPreviewController);
860     m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
861 #endif
862
863 #if ENABLE(WEB_AUTHN)
864     ASSERT(!m_credentialsMessenger);
865     m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
866 #endif
867
868 #if HAVE(PENCILKIT)
869     ASSERT(!m_editableImageController);
870     m_editableImageController = std::make_unique<EditableImageController>(*this);
871 #endif
872 }
873
874 RefPtr<API::Navigation> WebPageProxy::launchProcessForReload()
875 {
876     RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessForReload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
877
878     if (m_isClosed) {
879         RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessForReload: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
880         return nullptr;
881     }
882     
883     ASSERT(!hasRunningProcess());
884     auto registrableDomain = m_backForwardList->currentItem() ? RegistrableDomain { URL(URL(), m_backForwardList->currentItem()->url()) } : RegistrableDomain { };
885     launchProcess(registrableDomain);
886
887     if (!m_backForwardList->currentItem()) {
888         RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessForReload: no current item to reload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
889         return nullptr;
890     }
891
892     auto navigation = m_navigationState->createReloadNavigation();
893
894     // We allow stale content when reloading a WebProcess that's been killed or crashed.
895     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
896     m_process->responsivenessTimer().start();
897
898     return navigation;
899 }
900
901 RefPtr<API::Navigation> WebPageProxy::launchProcessWithItem(WebBackForwardListItem& item)
902 {
903     RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessWithItem: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
904
905     if (m_isClosed) {
906         RELEASE_LOG_IF_ALLOWED(Loading, "launchProcessWithItem: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
907         return nullptr;
908     }
909
910     ASSERT(!hasRunningProcess());
911     launchProcess(RegistrableDomain { URL(URL(), item.url()) });
912
913     if (&item != m_backForwardList->currentItem())
914         m_backForwardList->goToItem(item);
915
916     auto navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), FrameLoadType::IndexedBackForward);
917
918     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item.itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
919     m_process->responsivenessTimer().start();
920
921     return navigation;
922 }
923
924 void WebPageProxy::setDrawingArea(std::unique_ptr<DrawingAreaProxy>&& drawingArea)
925 {
926     m_drawingArea = WTFMove(drawingArea);
927     if (!m_drawingArea)
928         return;
929
930 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
931     if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) {
932         m_scrollingCoordinatorProxy = std::make_unique<RemoteScrollingCoordinatorProxy>(*this);
933 #if PLATFORM(IOS_FAMILY)
934         // On iOS, main frame scrolls are sent in terms of visible rect updates.
935         m_scrollingCoordinatorProxy->setPropagatesMainFrameScrolls(false);
936 #endif
937     }
938 #endif
939 }
940
941 void WebPageProxy::initializeWebPage()
942 {
943     if (!hasRunningProcess())
944         return;
945
946     setDrawingArea(pageClient().createDrawingAreaProxy(m_process));
947     ASSERT(m_drawingArea);
948
949     process().send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters(m_process, *m_drawingArea)), 0);
950
951     m_process->addVisitedLinkStoreUser(visitedLinkStore(), m_pageID);
952 }
953
954 void WebPageProxy::close()
955 {
956     if (m_isClosed)
957         return;
958
959     RELEASE_LOG_IF_ALLOWED(Loading, "close: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
960
961     m_isClosed = true;
962
963     reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
964
965     if (m_activePopupMenu)
966         m_activePopupMenu->cancelTracking();
967
968     if (m_controlledByAutomation) {
969         if (auto* automationSession = process().processPool().automationSession())
970             automationSession->willClosePage(*this);
971     }
972
973 #if ENABLE(CONTEXT_MENUS)
974     m_activeContextMenu = nullptr;
975 #endif
976
977     m_provisionalPage = nullptr;
978
979     m_inspector->invalidate();
980
981     m_backForwardList->pageClosed();
982     m_inspectorController->pageClosed();
983 #if ENABLE(REMOTE_INSPECTOR)
984     m_inspectorDebuggable = nullptr;
985 #endif
986     pageClient().pageClosed();
987
988     m_process->disconnectFramesFromPage(this);
989
990     resetState(ResetStateReason::PageInvalidated);
991
992     m_loaderClient = nullptr;
993     m_navigationClient = makeUniqueRef<API::NavigationClient>();
994     m_policyClient = nullptr;
995     m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
996     m_formClient = std::make_unique<API::FormClient>();
997     m_uiClient = std::make_unique<API::UIClient>();
998     m_findClient = std::make_unique<API::FindClient>();
999     m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
1000     m_diagnosticLoggingClient = nullptr;
1001 #if ENABLE(CONTEXT_MENUS)
1002     m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
1003 #endif
1004 #if ENABLE(FULLSCREEN_API)
1005     m_fullscreenClient = std::make_unique<API::FullscreenClient>();
1006 #endif
1007
1008     m_webProcessLifetimeTracker.pageWasInvalidated();
1009
1010     m_process->processPool().removeAllSuspendedPagesForPage(*this);
1011
1012     m_process->send(Messages::WebPage::Close(), m_pageID);
1013     m_process->removeWebPage(*this, WebProcessProxy::EndsUsingDataStore::Yes);
1014     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
1015     m_process->processPool().supplement<WebNotificationManagerProxy>()->clearNotifications(this);
1016
1017     // Null out related WebPageProxy to avoid leaks.
1018     m_configuration->setRelatedPage(nullptr);
1019
1020 #if PLATFORM(IOS_FAMILY)
1021     // Make sure we don't hold a process assertion after getting closed.
1022     m_activityToken = nullptr;
1023 #endif
1024
1025     stopAllURLSchemeTasks();
1026     updatePlayingMediaDidChange(MediaProducer::IsNotPlaying);
1027 }
1028
1029 bool WebPageProxy::tryClose()
1030 {
1031     if (!hasRunningProcess())
1032         return true;
1033
1034     RELEASE_LOG_IF_ALLOWED(Loading, "tryClose: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1035
1036     // Close without delay if the process allows it. Our goal is to terminate
1037     // the process, so we check a per-process status bit.
1038     if (m_process->isSuddenTerminationEnabled())
1039         return true;
1040
1041     m_process->send(Messages::WebPage::TryClose(), m_pageID);
1042     m_process->responsivenessTimer().start();
1043     return false;
1044 }
1045
1046 bool WebPageProxy::maybeInitializeSandboxExtensionHandle(WebProcessProxy& process, const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
1047 {
1048     if (!url.isLocalFile())
1049         return false;
1050
1051     if (process.hasAssumedReadAccessToURL(url))
1052         return false;
1053
1054     // Inspector resources are in a directory with assumed access.
1055     ASSERT_WITH_SECURITY_IMPLICATION(!WebKit::isInspectorPage(*this));
1056
1057     SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, sandboxExtensionHandle);
1058     return true;
1059 }
1060
1061 #if !PLATFORM(COCOA)
1062 void WebPageProxy::addPlatformLoadParameters(LoadParameters&)
1063 {
1064 }
1065 #endif
1066
1067 WebProcessProxy& WebPageProxy::ensureRunningProcess()
1068 {
1069     if (!hasRunningProcess())
1070         launchProcess({ });
1071
1072     return m_process;
1073 }
1074
1075 RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
1076 {
1077     if (m_isClosed)
1078         return nullptr;
1079
1080     RELEASE_LOG_IF_ALLOWED(Loading, "loadRequest: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1081
1082     if (!hasRunningProcess())
1083         launchProcess(RegistrableDomain { request.url() });
1084
1085     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
1086     loadRequestWithNavigationShared(m_process.copyRef(), navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, ShouldTreatAsContinuingLoad::No);
1087     return navigation;
1088 }
1089
1090 void WebPageProxy::loadRequestWithNavigationShared(Ref<WebProcessProxy>&& process, API::Navigation& navigation, ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
1091 {
1092     ASSERT(!m_isClosed);
1093
1094     RELEASE_LOG_IF_ALLOWED(Loading, "loadRequestWithNavigation: webPID = %i, pageID = %" PRIu64, process->processIdentifier(), m_pageID);
1095
1096     auto transaction = m_pageLoadState.transaction();
1097
1098     auto url = request.url();
1099     if (shouldTreatAsContinuingLoad != ShouldTreatAsContinuingLoad::Yes)
1100         m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1101
1102     LoadParameters loadParameters;
1103     loadParameters.navigationID = navigation.navigationID();
1104     loadParameters.request = WTFMove(request);
1105     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
1106     loadParameters.userData = UserData(process->transformObjectsToHandles(userData).get());
1107     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1108     loadParameters.websitePolicies = WTFMove(websitePolicies);
1109     loadParameters.lockHistory = navigation.lockHistory();
1110     loadParameters.lockBackForwardList = navigation.lockBackForwardList();
1111     loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
1112     bool createdExtension = maybeInitializeSandboxExtensionHandle(process, url, loadParameters.sandboxExtensionHandle);
1113     if (createdExtension)
1114         willAcquireUniversalFileReadSandboxExtension(process);
1115     addPlatformLoadParameters(loadParameters);
1116
1117     process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1118     process->responsivenessTimer().start();
1119 }
1120
1121 RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
1122 {
1123     RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1124
1125     if (m_isClosed) {
1126         RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1127         return nullptr;
1128     }
1129
1130     if (!hasRunningProcess())
1131         launchProcess({ });
1132
1133     URL fileURL = URL(URL(), fileURLString);
1134     if (!fileURL.isLocalFile()) {
1135         RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: file is not local: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1136         return nullptr;
1137     }
1138
1139     URL resourceDirectoryURL;
1140     if (resourceDirectoryURLString.isNull())
1141         resourceDirectoryURL = URL({ }, "file:///"_s);
1142     else {
1143         resourceDirectoryURL = URL(URL(), resourceDirectoryURLString);
1144         if (!resourceDirectoryURL.isLocalFile()) {
1145             RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: resource URL is not local: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1146             return nullptr;
1147         }
1148     }
1149
1150     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL), m_backForwardList->currentItem());
1151
1152     auto transaction = m_pageLoadState.transaction();
1153
1154     m_pageLoadState.setPendingAPIRequestURL(transaction, fileURLString);
1155
1156     String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
1157
1158     LoadParameters loadParameters;
1159     loadParameters.navigationID = navigation->navigationID();
1160     loadParameters.request = fileURL;
1161     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1162     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1163     SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::Type::ReadOnly, loadParameters.sandboxExtensionHandle);
1164     addPlatformLoadParameters(loadParameters);
1165
1166     m_process->assumeReadAccessToBaseURL(*this, resourceDirectoryURL);
1167     m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1168     m_process->responsivenessTimer().start();
1169
1170     return navigation;
1171 }
1172
1173 RefPtr<API::Navigation> WebPageProxy::loadData(const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData)
1174 {
1175     RELEASE_LOG_IF_ALLOWED(Loading, "loadData: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1176
1177     if (m_isClosed) {
1178         RELEASE_LOG_IF_ALLOWED(Loading, "loadData: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1179         return nullptr;
1180     }
1181
1182     if (!hasRunningProcess())
1183         launchProcess({ });
1184
1185     auto navigation = m_navigationState->createLoadDataNavigation(std::make_unique<API::SubstituteData>(data.vector(), MIMEType, encoding, baseURL, userData));
1186     loadDataWithNavigationShared(m_process.copyRef(), navigation, data, MIMEType, encoding, baseURL, userData, ShouldTreatAsContinuingLoad::No);
1187     return navigation;
1188 }
1189
1190 void WebPageProxy::loadDataWithNavigationShared(Ref<WebProcessProxy>&& process, API::Navigation& navigation, const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
1191 {
1192     RELEASE_LOG_IF_ALLOWED(Loading, "loadDataWithNavigation: webPID = %i, pageID = %" PRIu64, process->processIdentifier(), m_pageID);
1193
1194     ASSERT(!m_isClosed);
1195
1196     auto transaction = m_pageLoadState.transaction();
1197
1198     m_pageLoadState.setPendingAPIRequestURL(transaction, !baseURL.isEmpty() ? baseURL : WTF::blankURL().string());
1199
1200     LoadParameters loadParameters;
1201     loadParameters.navigationID = navigation.navigationID();
1202     loadParameters.data = data;
1203     loadParameters.MIMEType = MIMEType;
1204     loadParameters.encodingName = encoding;
1205     loadParameters.baseURLString = baseURL;
1206     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1207     loadParameters.userData = UserData(process->transformObjectsToHandles(userData).get());
1208     loadParameters.websitePolicies = WTFMove(websitePolicies);
1209     addPlatformLoadParameters(loadParameters);
1210
1211     process->assumeReadAccessToBaseURL(*this, baseURL);
1212     process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1213     process->responsivenessTimer().start();
1214 }
1215
1216 void WebPageProxy::loadAlternateHTML(const IPC::DataReference& htmlData, const String& encoding, const URL& baseURL, const URL& unreachableURL, API::Object* userData)
1217 {
1218     RELEASE_LOG_IF_ALLOWED(Loading, "loadAlternateHTML: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1219
1220     // When the UIProcess is in the process of handling a failing provisional load, do not attempt to
1221     // start a second alternative HTML load as this will prevent the page load state from being
1222     // handled properly.
1223     if (m_isClosed || m_isLoadingAlternateHTMLStringForFailingProvisionalLoad) {
1224         RELEASE_LOG_IF_ALLOWED(Loading, "loadAlternateHTML: page is closed (or other): webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1225         return;
1226     }
1227
1228     if (!m_failingProvisionalLoadURL.isEmpty())
1229         m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = true;
1230
1231     if (!hasRunningProcess())
1232         launchProcess(RegistrableDomain { baseURL });
1233
1234     auto transaction = m_pageLoadState.transaction();
1235
1236     m_pageLoadState.setPendingAPIRequestURL(transaction, unreachableURL);
1237     m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
1238
1239     if (m_mainFrame)
1240         m_mainFrame->setUnreachableURL(unreachableURL);
1241
1242     LoadParameters loadParameters;
1243     loadParameters.navigationID = 0;
1244     loadParameters.data = htmlData;
1245     loadParameters.MIMEType = "text/html"_s;
1246     loadParameters.encodingName = encoding;
1247     loadParameters.baseURLString = baseURL;
1248     loadParameters.unreachableURLString = unreachableURL;
1249     loadParameters.provisionalLoadErrorURLString = m_failingProvisionalLoadURL;
1250     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1251     addPlatformLoadParameters(loadParameters);
1252
1253     m_process->assumeReadAccessToBaseURL(*this, baseURL);
1254     m_process->assumeReadAccessToBaseURL(*this, unreachableURL);
1255     m_process->send(Messages::WebPage::LoadAlternateHTML(loadParameters), m_pageID);
1256     m_process->responsivenessTimer().start();
1257 }
1258
1259 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
1260 {
1261     RELEASE_LOG_IF_ALLOWED(Loading, "loadWebArchiveData: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1262
1263     if (m_isClosed) {
1264         RELEASE_LOG_IF_ALLOWED(Loading, "loadWebArchiveData: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1265         return;
1266     }
1267
1268     if (!hasRunningProcess())
1269         launchProcess({ });
1270
1271     auto transaction = m_pageLoadState.transaction();
1272     m_pageLoadState.setPendingAPIRequestURL(transaction, WTF::blankURL().string());
1273
1274     LoadParameters loadParameters;
1275     loadParameters.navigationID = 0;
1276     loadParameters.data = webArchiveData->dataReference();
1277     loadParameters.MIMEType = "application/x-webarchive"_s;
1278     loadParameters.encodingName = "utf-16"_s;
1279     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1280     addPlatformLoadParameters(loadParameters);
1281
1282     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1283     m_process->responsivenessTimer().start();
1284 }
1285
1286 void WebPageProxy::navigateToPDFLinkWithSimulatedClick(const String& urlString, IntPoint documentPoint, IntPoint screenPoint)
1287 {
1288     RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1289
1290     if (m_isClosed) {
1291         RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1292         return;
1293     }
1294
1295     if (WTF::protocolIsJavaScript(urlString))
1296         return;
1297
1298     if (!hasRunningProcess())
1299         launchProcess(RegistrableDomain { URL(URL(), urlString) });
1300
1301     m_process->send(Messages::WebPage::NavigateToPDFLinkWithSimulatedClick(urlString, documentPoint, screenPoint), m_pageID);
1302     m_process->responsivenessTimer().start();
1303 }
1304
1305 void WebPageProxy::stopLoading()
1306 {
1307     RELEASE_LOG_IF_ALLOWED(Loading, "stopLoading: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1308
1309     if (!hasRunningProcess()) {
1310         RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: page is not valid: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1311         return;
1312     }
1313
1314     m_process->send(Messages::WebPage::StopLoading(), m_pageID);
1315     if (m_provisionalPage) {
1316         m_provisionalPage->cancel();
1317         m_provisionalPage = nullptr;
1318     }
1319     m_process->responsivenessTimer().start();
1320 }
1321
1322 RefPtr<API::Navigation> WebPageProxy::reload(OptionSet<WebCore::ReloadOption> options)
1323 {
1324     RELEASE_LOG_IF_ALLOWED(Loading, "reload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1325
1326     SandboxExtension::Handle sandboxExtensionHandle;
1327
1328     String url = currentURL();
1329     if (!url.isEmpty()) {
1330         auto transaction = m_pageLoadState.transaction();
1331         m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1332
1333         // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
1334         bool createdExtension = maybeInitializeSandboxExtensionHandle(m_process, URL(URL(), url), sandboxExtensionHandle);
1335         if (createdExtension)
1336             willAcquireUniversalFileReadSandboxExtension(m_process);
1337     }
1338
1339     if (!hasRunningProcess())
1340         return launchProcessForReload();
1341     
1342     auto navigation = m_navigationState->createReloadNavigation();
1343
1344     // Store decision to reload without content blockers on the navigation so that we can later set the corresponding
1345     // WebsitePolicies flag in WebPageProxy::receivedNavigationPolicyDecision().
1346     if (options.contains(WebCore::ReloadOption::DisableContentBlockers))
1347         navigation->setUserContentExtensionsEnabled(false);
1348
1349     m_process->send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle), m_pageID);
1350     m_process->responsivenessTimer().start();
1351
1352     return navigation;
1353 }
1354
1355 void WebPageProxy::recordAutomaticNavigationSnapshot()
1356 {
1357     if (m_shouldSuppressNextAutomaticNavigationSnapshot)
1358         return;
1359
1360     if (WebBackForwardListItem* item = m_backForwardList->currentItem())
1361         recordNavigationSnapshot(*item);
1362 }
1363
1364 void WebPageProxy::recordNavigationSnapshot(WebBackForwardListItem& item)
1365 {
1366     if (!m_shouldRecordNavigationSnapshots)
1367         return;
1368
1369 #if PLATFORM(COCOA) || PLATFORM(GTK)
1370     ViewSnapshotStore::singleton().recordSnapshot(*this, item);
1371 #else
1372     UNUSED_PARAM(item);
1373 #endif
1374 }
1375
1376 RefPtr<API::Navigation> WebPageProxy::goForward()
1377 {
1378     WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
1379     if (!forwardItem)
1380         return nullptr;
1381
1382     return goToBackForwardItem(*forwardItem, FrameLoadType::Forward);
1383 }
1384
1385 RefPtr<API::Navigation> WebPageProxy::goBack()
1386 {
1387     WebBackForwardListItem* backItem = m_backForwardList->backItem();
1388     if (!backItem)
1389         return nullptr;
1390
1391     return goToBackForwardItem(*backItem, FrameLoadType::Back);
1392 }
1393
1394 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item)
1395 {
1396     return goToBackForwardItem(item, FrameLoadType::IndexedBackForward);
1397 }
1398
1399 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item, FrameLoadType frameLoadType)
1400 {
1401     RELEASE_LOG_IF_ALLOWED(Loading, "goToBackForwardItem: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1402     LOG(Loading, "WebPageProxy %p goToBackForwardItem to item URL %s", this, item.url().utf8().data());
1403
1404     if (!hasRunningProcess())
1405         return launchProcessWithItem(item);
1406
1407     auto transaction = m_pageLoadState.transaction();
1408
1409     m_pageLoadState.setPendingAPIRequestURL(transaction, item.url());
1410
1411     RefPtr<API::Navigation> navigation;
1412     if (!m_backForwardList->currentItem()->itemIsInSameDocument(item))
1413         navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), frameLoadType);
1414
1415     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
1416     m_process->responsivenessTimer().start();
1417
1418     return navigation;
1419 }
1420
1421 void WebPageProxy::tryRestoreScrollPosition()
1422 {
1423     RELEASE_LOG_IF_ALLOWED(Loading, "tryRestoreScrollPosition: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1424
1425     if (!hasRunningProcess()) {
1426         RELEASE_LOG_IF_ALLOWED(Loading, "tryRestoreScrollPosition: page is not valid: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1427         return;
1428     }
1429
1430     m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
1431 }
1432
1433 void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<Ref<WebBackForwardListItem>>&& removed)
1434 {
1435     PageClientProtector protector(pageClient());
1436
1437     if (!m_navigationClient->didChangeBackForwardList(*this, added, removed) && m_loaderClient)
1438         m_loaderClient->didChangeBackForwardList(*this, added, WTFMove(removed));
1439
1440     auto transaction = m_pageLoadState.transaction();
1441
1442     m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
1443     m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
1444 }
1445
1446 void WebPageProxy::willGoToBackForwardListItem(const BackForwardItemIdentifier& itemID, bool inPageCache)
1447 {
1448     PageClientProtector protector(pageClient());
1449
1450     if (auto* item = m_backForwardList->itemForID(itemID))
1451         m_navigationClient->willGoToBackForwardListItem(*this, *item, inPageCache);
1452 }
1453
1454 bool WebPageProxy::shouldKeepCurrentBackForwardListItemInList(WebBackForwardListItem& item)
1455 {
1456     PageClientProtector protector(pageClient());
1457
1458     return !m_loaderClient || m_loaderClient->shouldKeepCurrentBackForwardListItemInList(*this, item);
1459 }
1460
1461 bool WebPageProxy::canShowMIMEType(const String& mimeType)
1462 {
1463     if (MIMETypeRegistry::canShowMIMEType(mimeType))
1464         return true;
1465
1466 #if ENABLE(NETSCAPE_PLUGIN_API)
1467     String newMimeType = mimeType;
1468     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL());
1469     if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
1470         return true;
1471 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1472
1473 #if PLATFORM(COCOA)
1474     // On Mac, we can show PDFs.
1475     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebProcessPool::omitPDFSupport())
1476         return true;
1477 #endif // PLATFORM(COCOA)
1478
1479     return false;
1480 }
1481
1482 void WebPageProxy::setControlledByAutomation(bool controlled)
1483 {
1484     if (m_controlledByAutomation == controlled)
1485         return;
1486
1487     m_controlledByAutomation = controlled;
1488
1489     if (!hasRunningProcess())
1490         return;
1491
1492     m_process->send(Messages::WebPage::SetControlledByAutomation(controlled), m_pageID);
1493     m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation));
1494 }
1495
1496 void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
1497 {
1498     m_inspectorController->createInspectorTarget(targetId, type);
1499 }
1500
1501 void WebPageProxy::destroyInspectorTarget(const String& targetId)
1502 {
1503     m_inspectorController->destroyInspectorTarget(targetId);
1504 }
1505
1506 void WebPageProxy::sendMessageToInspectorFrontend(const String& targetId, const String& message)
1507 {
1508     m_inspectorController->sendMessageToInspectorFrontend(targetId, message);
1509 }
1510
1511 #if ENABLE(REMOTE_INSPECTOR)
1512 void WebPageProxy::setIndicating(bool indicating)
1513 {
1514     if (!hasRunningProcess())
1515         return;
1516
1517     m_process->send(Messages::WebPage::SetIndicating(indicating), m_pageID);
1518 }
1519
1520 bool WebPageProxy::allowsRemoteInspection() const
1521 {
1522     return m_inspectorDebuggable->remoteDebuggingAllowed();
1523 }
1524
1525 void WebPageProxy::setAllowsRemoteInspection(bool allow)
1526 {
1527     m_inspectorDebuggable->setRemoteDebuggingAllowed(allow);
1528 }
1529
1530 String WebPageProxy::remoteInspectionNameOverride() const
1531 {
1532     return m_inspectorDebuggable->nameOverride();
1533 }
1534
1535 void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
1536 {
1537     m_inspectorDebuggable->setNameOverride(name);
1538 }
1539
1540 void WebPageProxy::remoteInspectorInformationDidChange()
1541 {
1542     m_inspectorDebuggable->update();
1543 }
1544 #endif
1545
1546 void WebPageProxy::clearInspectorTargets()
1547 {
1548     m_inspectorController->clearTargets();
1549 }
1550
1551 void WebPageProxy::createInspectorTargets()
1552 {
1553     String pageTargetId = makeString("page-", m_pageID);
1554     m_inspectorController->createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
1555 }
1556
1557 void WebPageProxy::setBackgroundColor(const Optional<Color>& color)
1558 {
1559     if (m_backgroundColor == color)
1560         return;
1561
1562     m_backgroundColor = color;
1563     if (hasRunningProcess())
1564         m_process->send(Messages::WebPage::SetBackgroundColor(color), m_pageID);
1565 }
1566
1567 void WebPageProxy::setTopContentInset(float contentInset)
1568 {
1569     if (m_topContentInset == contentInset)
1570         return;
1571
1572     m_topContentInset = contentInset;
1573
1574     if (!hasRunningProcess())
1575         return;
1576 #if PLATFORM(COCOA)
1577     MachSendRight fence = m_drawingArea->createFence();
1578
1579     auto fenceAttachment = IPC::Attachment(fence.leakSendRight(), MACH_MSG_TYPE_MOVE_SEND);
1580     m_process->send(Messages::WebPage::SetTopContentInsetFenced(contentInset, fenceAttachment), m_pageID);
1581 #else
1582     m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
1583 #endif
1584 }
1585
1586 void WebPageProxy::setUnderlayColor(const Color& color)
1587 {
1588     if (m_underlayColor == color)
1589         return;
1590
1591     m_underlayColor = color;
1592
1593     if (hasRunningProcess())
1594         m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1595 }
1596
1597 void WebPageProxy::viewWillStartLiveResize()
1598 {
1599     if (!hasRunningProcess())
1600         return;
1601
1602     closeOverlayedViews();
1603     m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1604 }
1605
1606 void WebPageProxy::viewWillEndLiveResize()
1607 {
1608     if (!hasRunningProcess())
1609         return;
1610     m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1611 }
1612
1613 void WebPageProxy::setViewNeedsDisplay(const Region& region)
1614 {
1615     pageClient().setViewNeedsDisplay(region);
1616 }
1617
1618 void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin)
1619 {
1620     pageClient().requestScroll(scrollPosition, scrollOrigin);
1621 }
1622
1623 WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
1624 {
1625     return pageClient().viewScrollPosition();
1626 }
1627
1628 void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
1629 {
1630     if (m_suppressVisibilityUpdates == flag)
1631         return;
1632     m_suppressVisibilityUpdates = flag;
1633
1634     if (!m_suppressVisibilityUpdates) {
1635 #if PLATFORM(COCOA)
1636         m_activityStateChangeDispatcher->schedule();
1637 #else
1638         dispatchActivityStateChange();
1639 #endif
1640     }
1641 }
1642
1643 void WebPageProxy::updateActivityState(OptionSet<ActivityState::Flag> flagsToUpdate)
1644 {
1645     m_activityState.remove(flagsToUpdate);
1646     if (flagsToUpdate & ActivityState::IsFocused && pageClient().isViewFocused())
1647         m_activityState.add(ActivityState::IsFocused);
1648     if (flagsToUpdate & ActivityState::WindowIsActive && pageClient().isViewWindowActive())
1649         m_activityState.add(ActivityState::WindowIsActive);
1650     if (flagsToUpdate & ActivityState::IsVisible && pageClient().isViewVisible())
1651         m_activityState.add(ActivityState::IsVisible);
1652     if (flagsToUpdate & ActivityState::IsVisibleOrOccluded && pageClient().isViewVisibleOrOccluded())
1653         m_activityState.add(ActivityState::IsVisibleOrOccluded);
1654     if (flagsToUpdate & ActivityState::IsInWindow && pageClient().isViewInWindow())
1655         m_activityState.add(ActivityState::IsInWindow);
1656     if (flagsToUpdate & ActivityState::IsVisuallyIdle && pageClient().isVisuallyIdle())
1657         m_activityState.add(ActivityState::IsVisuallyIdle);
1658     if (flagsToUpdate & ActivityState::IsAudible && m_mediaState & MediaProducer::IsPlayingAudio && !(m_mutedState & MediaProducer::AudioIsMuted))
1659         m_activityState.add(ActivityState::IsAudible);
1660     if (flagsToUpdate & ActivityState::IsLoading && m_pageLoadState.isLoading())
1661         m_activityState.add(ActivityState::IsLoading);
1662     if (flagsToUpdate & ActivityState::IsCapturingMedia && m_mediaState & (MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice))
1663         m_activityState.add(ActivityState::IsCapturingMedia);
1664 }
1665
1666 void WebPageProxy::activityStateDidChange(OptionSet<ActivityState::Flag> mayHaveChanged, bool wantsSynchronousReply, ActivityStateChangeDispatchMode dispatchMode)
1667 {
1668     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " activityStateDidChange - mayHaveChanged " << mayHaveChanged);
1669
1670     m_potentiallyChangedActivityStateFlags.add(mayHaveChanged);
1671     m_activityStateChangeWantsSynchronousReply = m_activityStateChangeWantsSynchronousReply || wantsSynchronousReply;
1672
1673     if (m_suppressVisibilityUpdates && dispatchMode != ActivityStateChangeDispatchMode::Immediate)
1674         return;
1675
1676 #if PLATFORM(COCOA)
1677     bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ActivityState::IsInWindow) && pageClient().isViewInWindow();
1678     if (dispatchMode == ActivityStateChangeDispatchMode::Immediate || isNewlyInWindow) {
1679         dispatchActivityStateChange();
1680         return;
1681     }
1682     m_activityStateChangeDispatcher->schedule();
1683 #else
1684     UNUSED_PARAM(dispatchMode);
1685     dispatchActivityStateChange();
1686 #endif
1687 }
1688
1689 void WebPageProxy::viewDidLeaveWindow()
1690 {
1691     closeOverlayedViews();
1692 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
1693     // When leaving the current page, close the video fullscreen.
1694     if (m_videoFullscreenManager)
1695         m_videoFullscreenManager->requestHideAndExitFullscreen();
1696 #endif
1697 }
1698
1699 void WebPageProxy::viewDidEnterWindow()
1700 {
1701     LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1702     if (m_layerHostingMode != layerHostingMode) {
1703         m_layerHostingMode = layerHostingMode;
1704         m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1705     }
1706 }
1707
1708 void WebPageProxy::dispatchActivityStateChange()
1709 {
1710 #if PLATFORM(COCOA)
1711     m_activityStateChangeDispatcher->invalidate();
1712 #endif
1713
1714     if (!hasRunningProcess())
1715         return;
1716
1717     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange - potentiallyChangedActivityStateFlags " << m_potentiallyChangedActivityStateFlags);
1718
1719     // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1720     if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible)
1721         m_potentiallyChangedActivityStateFlags.add({ ActivityState::IsVisibleOrOccluded, ActivityState::IsVisuallyIdle });
1722
1723     // Record the prior view state, update the flags that may have changed,
1724     // and check which flags have actually changed.
1725     auto previousActivityState = m_activityState;
1726     updateActivityState(m_potentiallyChangedActivityStateFlags);
1727     auto changed = m_activityState ^ previousActivityState;
1728
1729     if (changed)
1730         LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange: state changed from " << previousActivityState << " to " << m_activityState);
1731
1732     if ((changed & ActivityState::WindowIsActive) && isViewWindowActive())
1733         updateCurrentModifierState();
1734
1735     if ((m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible) && isViewVisible())
1736         viewIsBecomingVisible();
1737
1738     bool isNowInWindow = (changed & ActivityState::IsInWindow) && isInWindow();
1739     // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
1740     if (m_viewWasEverInWindow && isNowInWindow) {
1741         if (m_drawingArea->hasVisibleContent() && m_waitsForPaintAfterViewDidMoveToWindow && !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
1742             m_activityStateChangeWantsSynchronousReply = true;
1743         m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
1744     }
1745
1746     // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
1747     if (!(m_activityState & ActivityState::IsVisible))
1748         m_activityStateChangeWantsSynchronousReply = false;
1749
1750     auto activityStateChangeID = m_activityStateChangeWantsSynchronousReply ? takeNextActivityStateChangeID() : static_cast<ActivityStateChangeID>(ActivityStateChangeAsynchronous);
1751
1752     if (changed || activityStateChangeID != ActivityStateChangeAsynchronous || !m_nextActivityStateChangeCallbacks.isEmpty())
1753         m_process->send(Messages::WebPage::SetActivityState(m_activityState, activityStateChangeID, m_nextActivityStateChangeCallbacks), m_pageID);
1754
1755     m_nextActivityStateChangeCallbacks.clear();
1756
1757     // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
1758     updateThrottleState();
1759
1760 #if ENABLE(POINTER_LOCK)
1761     if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !pageClient().isViewWindowActive())
1762         || ((changed & ActivityState::IsFocused) && !(m_activityState & ActivityState::IsFocused)))
1763         requestPointerUnlock();
1764 #endif
1765
1766     if (changed & ActivityState::IsVisible) {
1767         if (isViewVisible())
1768             m_visiblePageToken = m_process->visiblePageToken();
1769         else {
1770             m_visiblePageToken = nullptr;
1771
1772             // If we've started the responsiveness timer as part of telling the web process to update the backing store
1773             // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1774             // stop the unresponsiveness timer here.
1775             m_process->responsivenessTimer().stop();
1776         }
1777     }
1778
1779     if (changed & ActivityState::IsInWindow) {
1780         if (isInWindow())
1781             viewDidEnterWindow();
1782         else
1783             viewDidLeaveWindow();
1784     }
1785
1786     updateBackingStoreDiscardableState();
1787
1788     if (activityStateChangeID != ActivityStateChangeAsynchronous)
1789         waitForDidUpdateActivityState(activityStateChangeID);
1790
1791     m_potentiallyChangedActivityStateFlags = { };
1792     m_activityStateChangeWantsSynchronousReply = false;
1793     m_viewWasEverInWindow |= isNowInWindow;
1794 }
1795
1796 bool WebPageProxy::isAlwaysOnLoggingAllowed() const
1797 {
1798     return sessionID().isAlwaysOnLoggingAllowed();
1799 }
1800
1801 void WebPageProxy::updateThrottleState()
1802 {
1803     bool processSuppressionEnabled = m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
1804
1805     // If process suppression is not enabled take a token on the process pool to disable suppression of support processes.
1806     if (!processSuppressionEnabled)
1807         m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
1808     else if (!m_preventProcessSuppressionCount)
1809         m_preventProcessSuppressionCount = nullptr;
1810
1811     if (m_activityState & ActivityState::IsVisuallyIdle)
1812         m_pageIsUserObservableCount = nullptr;
1813     else if (!m_pageIsUserObservableCount)
1814         m_pageIsUserObservableCount = m_process->processPool().userObservablePageCount();
1815
1816 #if PLATFORM(IOS_FAMILY)
1817     bool isCapturingMedia = m_activityState.contains(ActivityState::IsCapturingMedia);
1818     bool isAudible = m_activityState.contains(ActivityState::IsAudible);
1819     if (!isViewVisible() && !m_alwaysRunsAtForegroundPriority && !isCapturingMedia && !isAudible) {
1820         if (m_activityToken) {
1821             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is releasing a foreground assertion because the view is no longer visible");
1822             m_activityToken = nullptr;
1823         }
1824     } else if (!m_activityToken) {
1825         if (isViewVisible())
1826             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion because the view is visible");
1827         else if (isAudible)
1828             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion because we are playing audio");
1829         else if (isCapturingMedia)
1830             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion because media capture is active");
1831         else
1832             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion even though the view is not visible because m_alwaysRunsAtForegroundPriority is true");
1833         m_activityToken = m_process->throttler().foregroundActivityToken();
1834     }
1835 #endif
1836 }
1837
1838 void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
1839 {
1840     if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
1841         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
1842     else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
1843         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
1844 }
1845
1846 void WebPageProxy::layerHostingModeDidChange()
1847 {
1848     if (!hasRunningProcess())
1849         return;
1850
1851     LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1852     if (m_layerHostingMode == layerHostingMode)
1853         return;
1854
1855     m_layerHostingMode = layerHostingMode;
1856     m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1857 }
1858
1859 void WebPageProxy::waitForDidUpdateActivityState(ActivityStateChangeID activityStateChangeID)
1860 {
1861     if (!hasRunningProcess())
1862         return;
1863
1864     if (m_process->state() != WebProcessProxy::State::Running)
1865         return;
1866
1867     // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1868     if (m_waitingForDidUpdateActivityState)
1869         return;
1870
1871 #if PLATFORM(IOS_FAMILY)
1872     // Hail Mary check. Should not be possible (dispatchActivityStateChange should force async if not visible,
1873     // and if visible we should be holding an assertion) - but we should never block on a suspended process.
1874     if (!m_activityToken) {
1875         ASSERT_NOT_REACHED();
1876         return;
1877     }
1878 #endif
1879
1880     m_waitingForDidUpdateActivityState = true;
1881
1882     m_drawingArea->waitForDidUpdateActivityState(activityStateChangeID);
1883 }
1884
1885 IntSize WebPageProxy::viewSize() const
1886 {
1887     return pageClient().viewSize();
1888 }
1889
1890 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
1891 {
1892     if (!hasRunningProcess()) {
1893         callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
1894         return;
1895     }
1896
1897     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1898     m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent, callbackID), m_pageID);
1899 }
1900
1901 void WebPageProxy::clearSelection()
1902 {
1903     if (!hasRunningProcess())
1904         return;
1905     m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1906 }
1907
1908 void WebPageProxy::restoreSelectionInFocusedEditableElement()
1909 {
1910     if (!hasRunningProcess())
1911         return;
1912     m_process->send(Messages::WebPage::RestoreSelectionInFocusedEditableElement(), m_pageID);
1913 }
1914
1915 void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&& callbackFunction)
1916 {
1917     if (!hasRunningProcess()) {
1918         callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1919         return;
1920     }
1921
1922     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1923     m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1924 }
1925
1926 void WebPageProxy::increaseListLevel()
1927 {
1928     if (!hasRunningProcess())
1929         return;
1930
1931     m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
1932 }
1933
1934 void WebPageProxy::decreaseListLevel()
1935 {
1936     if (!hasRunningProcess())
1937         return;
1938
1939     m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
1940 }
1941
1942 void WebPageProxy::changeListType()
1943 {
1944     if (!hasRunningProcess())
1945         return;
1946
1947     m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
1948 }
1949
1950 void WebPageProxy::setBaseWritingDirection(WritingDirection direction)
1951 {
1952     if (!hasRunningProcess())
1953         return;
1954
1955     m_process->send(Messages::WebPage::SetBaseWritingDirection(direction), m_pageID);
1956 }
1957
1958 void WebPageProxy::updateFontAttributesAfterEditorStateChange()
1959 {
1960     m_cachedFontAttributesAtSelectionStart.reset();
1961
1962     if (m_editorState.isMissingPostLayoutData)
1963         return;
1964
1965     if (auto fontAttributes = m_editorState.postLayoutData().fontAttributes) {
1966         m_uiClient->didChangeFontAttributes(*fontAttributes);
1967         m_cachedFontAttributesAtSelectionStart = WTFMove(fontAttributes);
1968     }
1969 }
1970
1971 void WebPageProxy::setNeedsFontAttributes(bool needsFontAttributes)
1972 {
1973     if (m_needsFontAttributes == needsFontAttributes)
1974         return;
1975
1976     m_needsFontAttributes = needsFontAttributes;
1977
1978     if (hasRunningProcess())
1979         m_process->send(Messages::WebPage::SetNeedsFontAttributes(needsFontAttributes), m_pageID);
1980 }
1981
1982 bool WebPageProxy::maintainsInactiveSelection() const
1983 {
1984     // Regardless of what the client wants to do, keep selections if a local Inspector is open.
1985     // Otherwise, there is no way to use the console to inspect the state of a selection.
1986     if (inspector() && inspector()->isVisible())
1987         return true;
1988
1989     return m_maintainsInactiveSelection;
1990 }
1991
1992 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1993 {
1994     m_maintainsInactiveSelection = newValue;
1995 }
1996
1997 void WebPageProxy::scheduleFullEditorStateUpdate()
1998 {
1999     if (!hasRunningProcess())
2000         return;
2001
2002     m_process->send(Messages::WebPage::ScheduleFullEditorStateUpdate(), m_pageID);
2003 }
2004
2005 void WebPageProxy::selectAll()
2006 {
2007     if (!hasRunningProcess())
2008         return;
2009
2010     m_process->send(Messages::WebPage::SelectAll(), m_pageID);
2011 }
2012
2013 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
2014 {
2015     if (!hasRunningProcess()) {
2016         callbackFunction(CallbackBase::Error::Unknown);
2017         return;
2018     }
2019
2020     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
2021     m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, argument, callbackID), m_pageID);
2022 }
2023     
2024 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
2025 {
2026     static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
2027
2028     if (!hasRunningProcess())
2029         return;
2030
2031     if (commandName == ignoreSpellingCommandName)
2032         ++m_pendingLearnOrIgnoreWordMessageCount;
2033
2034     m_process->send(Messages::WebPage::ExecuteEditCommand(commandName, argument), m_pageID);
2035 }
2036
2037 void WebPageProxy::requestFontAttributesAtSelectionStart(Function<void(const WebCore::FontAttributes&, CallbackBase::Error)>&& callback)
2038 {
2039     if (!hasRunningProcess()) {
2040         callback({ }, CallbackBase::Error::Unknown);
2041         return;
2042     }
2043
2044     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
2045     m_process->send(Messages::WebPage::RequestFontAttributesAtSelectionStart(callbackID), m_pageID);
2046 }
2047
2048 void WebPageProxy::fontAttributesCallback(const WebCore::FontAttributes& attributes, CallbackID callbackID)
2049 {
2050     m_cachedFontAttributesAtSelectionStart = attributes;
2051
2052     if (auto callback = m_callbacks.take<FontAttributesCallback>(callbackID))
2053         callback->performCallbackWithReturnValue(attributes);
2054 }
2055
2056 void WebPageProxy::setEditable(bool editable)
2057 {
2058     if (editable == m_isEditable)
2059         return;
2060
2061     m_isEditable = editable;
2062
2063     if (!hasRunningProcess())
2064         return;
2065
2066     m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
2067 }
2068     
2069 void WebPageProxy::setMediaStreamCaptureMuted(bool muted)
2070 {
2071     if (muted)
2072         setMuted(m_mutedState | WebCore::MediaProducer::MediaStreamCaptureIsMuted);
2073     else
2074         setMuted(m_mutedState & ~WebCore::MediaProducer::MediaStreamCaptureIsMuted);
2075 }
2076
2077 void WebPageProxy::activateMediaStreamCaptureInPage()
2078 {
2079 #if ENABLE(MEDIA_STREAM)
2080     UserMediaProcessManager::singleton().muteCaptureMediaStreamsExceptIn(*this);
2081 #endif
2082     setMuted(m_mutedState & ~WebCore::MediaProducer::MediaStreamCaptureIsMuted);
2083 }
2084
2085 #if !PLATFORM(IOS_FAMILY)
2086 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
2087 {
2088 }
2089
2090 void WebPageProxy::layerTreeCommitComplete()
2091 {
2092 }
2093 #endif
2094
2095 #if ENABLE(DRAG_SUPPORT)
2096 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
2097 {
2098     performDragControllerAction(DragControllerAction::Entered, dragData, dragStorageName, { }, { });
2099 }
2100
2101 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
2102 {
2103     performDragControllerAction(DragControllerAction::Updated, dragData, dragStorageName, { }, { });
2104 }
2105
2106 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
2107 {
2108     performDragControllerAction(DragControllerAction::Exited, dragData, dragStorageName, { }, { });
2109 }
2110
2111 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2112 {
2113     performDragControllerAction(DragControllerAction::PerformDragOperation, dragData, dragStorageName, WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload));
2114 }
2115
2116 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2117 {
2118     if (!hasRunningProcess())
2119         return;
2120 #if PLATFORM(GTK)
2121     UNUSED_PARAM(dragStorageName);
2122     UNUSED_PARAM(sandboxExtensionHandle);
2123     UNUSED_PARAM(sandboxExtensionsForUpload);
2124
2125     String url = dragData.asURL();
2126     if (!url.isEmpty())
2127         m_process->assumeReadAccessToBaseURL(*this, url);
2128
2129     ASSERT(dragData.platformData());
2130     WebSelectionData selection(*dragData.platformData());
2131     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), selection, dragData.flags()), m_pageID);
2132 #else
2133     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
2134 #endif
2135 }
2136
2137 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect, const IntRect& editableElementRect)
2138 {
2139     MESSAGE_CHECK(m_process, dragOperation <= DragOperationDelete);
2140
2141     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
2142     m_currentDragHandlingMethod = dragHandlingMethod;
2143     m_currentDragIsOverFileInput = mouseIsOverFileInput;
2144     m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
2145     m_currentDragCaretEditableElementRect = editableElementRect;
2146     setDragCaretRect(insertionRect);
2147 }
2148
2149 #if PLATFORM(GTK)
2150 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
2151 {
2152     RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
2153     pageClient().startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
2154
2155     didStartDrag();
2156 }
2157 #endif
2158
2159 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
2160 {
2161     if (!hasRunningProcess())
2162         return;
2163     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
2164     setDragCaretRect({ });
2165 }
2166
2167 void WebPageProxy::didPerformDragOperation(bool handled)
2168 {
2169     pageClient().didPerformDragOperation(handled);
2170 }
2171
2172 void WebPageProxy::didStartDrag()
2173 {
2174     if (hasRunningProcess())
2175         m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
2176 }
2177     
2178 void WebPageProxy::dragCancelled()
2179 {
2180     if (hasRunningProcess())
2181         m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
2182 }
2183
2184 void WebPageProxy::didEndDragging()
2185 {
2186     resetCurrentDragInformation();
2187 }
2188
2189 void WebPageProxy::resetCurrentDragInformation()
2190 {
2191     m_currentDragOperation = WebCore::DragOperationNone;
2192     m_currentDragHandlingMethod = DragHandlingMethod::None;
2193     m_currentDragIsOverFileInput = false;
2194     m_currentDragNumberOfFilesToBeAccepted = 0;
2195     setDragCaretRect({ });
2196 }
2197
2198 #if !ENABLE(DATA_INTERACTION)
2199
2200 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
2201 {
2202     m_currentDragCaretRect = dragCaretRect;
2203 }
2204
2205 #endif
2206
2207 #endif // ENABLE(DRAG_SUPPORT)
2208
2209 static bool removeOldRedundantEvent(Deque<NativeWebMouseEvent>& queue, WebEvent::Type incomingEventType)
2210 {
2211     if (incomingEventType != WebEvent::MouseMove && incomingEventType != WebEvent::MouseForceChanged)
2212         return false;
2213
2214     auto it = queue.rbegin();
2215     auto end = queue.rend();
2216
2217     // Must not remove the first event in the deque, since it is already being dispatched.
2218     if (it != end)
2219         --end;
2220
2221     for (; it != end; ++it) {
2222         auto type = it->type();
2223         if (type == incomingEventType) {
2224             queue.remove(--it.base());
2225             return true;
2226         }
2227         if (type != WebEvent::MouseMove && type != WebEvent::MouseForceChanged)
2228             break;
2229     }
2230     return false;
2231 }
2232
2233 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
2234 {
2235     if (!hasRunningProcess())
2236         return;
2237
2238 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2239     if (m_scrollingCoordinatorProxy)
2240         m_scrollingCoordinatorProxy->handleMouseEvent(platform(event));
2241 #endif
2242
2243     // If we receive multiple mousemove or mouseforcechanged events and the most recent mousemove or mouseforcechanged event
2244     // (respectively) has not yet been sent to WebProcess for processing, remove the pending mouse event and insert the new
2245     // event in the queue.
2246     bool didRemoveEvent = removeOldRedundantEvent(m_mouseEventQueue, event.type());
2247     m_mouseEventQueue.append(event);
2248
2249 #if LOG_DISABLED
2250     UNUSED_PARAM(didRemoveEvent);
2251 #else
2252     LOG(MouseHandling, "UIProcess: %s mouse event %s (queue size %zu)", didRemoveEvent ? "replaced" : "enqueued", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2253 #endif
2254
2255     if (m_mouseEventQueue.size() == 1) // Otherwise, called from DidReceiveEvent message handler.
2256         processNextQueuedMouseEvent();
2257 }
2258     
2259 void WebPageProxy::processNextQueuedMouseEvent()
2260 {
2261     if (!hasRunningProcess())
2262         return;
2263
2264     ASSERT(!m_mouseEventQueue.isEmpty());
2265
2266     const NativeWebMouseEvent& event = m_mouseEventQueue.first();
2267
2268     if (pageClient().windowIsFrontWindowUnderMouse(event))
2269         setToolTip(String());
2270
2271     WebEvent::Type eventType = event.type();
2272     if (eventType == WebEvent::MouseDown || eventType == WebEvent::MouseForceChanged || eventType == WebEvent::MouseForceDown)
2273         m_process->responsivenessTimer().startWithLazyStop();
2274     else if (eventType != WebEvent::MouseMove) {
2275         // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
2276         m_process->responsivenessTimer().start();
2277     }
2278
2279     LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(eventType), m_mouseEventQueue.size());
2280     m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
2281 }
2282
2283 #if MERGE_WHEEL_EVENTS
2284 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2285 {
2286     if (a.position() != b.position())
2287         return false;
2288     if (a.globalPosition() != b.globalPosition())
2289         return false;
2290     if (a.modifiers() != b.modifiers())
2291         return false;
2292     if (a.granularity() != b.granularity())
2293         return false;
2294 #if PLATFORM(COCOA)
2295     if (a.phase() != b.phase())
2296         return false;
2297     if (a.momentumPhase() != b.momentumPhase())
2298         return false;
2299     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
2300         return false;
2301 #endif
2302
2303     return true;
2304 }
2305
2306 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2307 {
2308     ASSERT(canCoalesce(a, b));
2309
2310     FloatSize mergedDelta = a.delta() + b.delta();
2311     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
2312
2313 #if PLATFORM(COCOA)
2314     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
2315
2316     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());
2317 #else
2318     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
2319 #endif
2320 }
2321 #endif // MERGE_WHEEL_EVENTS
2322
2323 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
2324 {
2325     ASSERT(!queue.isEmpty());
2326     ASSERT(coalescedEvents.isEmpty());
2327
2328 #if MERGE_WHEEL_EVENTS
2329     NativeWebWheelEvent firstEvent = queue.takeFirst();
2330     coalescedEvents.append(firstEvent);
2331
2332     WebWheelEvent event = firstEvent;
2333     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
2334         NativeWebWheelEvent firstEvent = queue.takeFirst();
2335         coalescedEvents.append(firstEvent);
2336         event = coalesce(event, firstEvent);
2337     }
2338
2339     return event;
2340 #else
2341     while (!queue.isEmpty())
2342         coalescedEvents.append(queue.takeFirst());
2343     return coalescedEvents.last();
2344 #endif
2345 }
2346
2347 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
2348 {
2349 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2350     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
2351         return;
2352 #endif
2353
2354     if (!hasRunningProcess())
2355         return;
2356
2357     closeOverlayedViews();
2358
2359     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
2360         m_wheelEventQueue.append(event);
2361         if (!shouldProcessWheelEventNow(event))
2362             return;
2363         // The queue has too many wheel events, so push a new event.
2364     }
2365
2366     if (!m_wheelEventQueue.isEmpty()) {
2367         processNextQueuedWheelEvent();
2368         return;
2369     }
2370
2371     auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2372     coalescedWheelEvent->append(event);
2373     m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
2374     sendWheelEvent(event);
2375 }
2376
2377 void WebPageProxy::processNextQueuedWheelEvent()
2378 {
2379     auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2380     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
2381     m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
2382     sendWheelEvent(nextWheelEvent);
2383 }
2384
2385 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
2386 {
2387     m_process->send(
2388         Messages::EventDispatcher::WheelEvent(
2389             m_pageID,
2390             event,
2391             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
2392             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
2393             rubberBandsAtTop(),
2394             rubberBandsAtBottom()
2395         ), 0);
2396
2397     // Manually ping the web process to check for responsiveness since our wheel
2398     // event will dispatch to a non-main thread, which always responds.
2399     m_process->isResponsiveWithLazyStop();
2400 }
2401
2402 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
2403 {
2404 #if PLATFORM(GTK)
2405     // Don't queue events representing a non-trivial scrolling phase to
2406     // avoid having them trapped in the queue, potentially preventing a
2407     // scrolling session to beginning or end correctly.
2408     // This is only needed by platforms whose WebWheelEvent has this phase
2409     // information (Cocoa and GTK+) but Cocoa was fine without it.
2410     if (event.phase() == WebWheelEvent::Phase::PhaseNone
2411         || event.phase() == WebWheelEvent::Phase::PhaseChanged
2412         || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
2413         || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
2414         return true;
2415 #else
2416     UNUSED_PARAM(event);
2417 #endif
2418     if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
2419         return true;
2420     return false;
2421 }
2422
2423 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
2424 {
2425     if (!hasRunningProcess())
2426         return;
2427     
2428     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
2429
2430     m_keyEventQueue.append(event);
2431
2432     ResponsivenessTimer& responsivenessTimer = m_process->responsivenessTimer();
2433     if (event.type() == WebEvent::KeyDown)
2434         responsivenessTimer.startWithLazyStop();
2435     else
2436         responsivenessTimer.start();
2437
2438     if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
2439         LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
2440         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2441     }
2442 }
2443
2444 WebPreferencesStore WebPageProxy::preferencesStore() const
2445 {
2446     if (m_configurationPreferenceValues.isEmpty())
2447         return m_preferences->store();
2448
2449     WebPreferencesStore store = m_preferences->store();
2450     for (const auto& preference : m_configurationPreferenceValues)
2451         store.m_values.set(preference.key, preference.value);
2452
2453     return store;
2454 }
2455
2456 #if ENABLE(NETSCAPE_PLUGIN_API)
2457 void WebPageProxy::findPlugin(const String& mimeType, uint32_t processType, const String& urlString, const String& frameURLString, const String& pageURLString, bool allowOnlyApplicationPlugins, Messages::WebPageProxy::FindPlugin::DelayedReply&& reply)
2458 {
2459     PageClientProtector protector(pageClient());
2460
2461     MESSAGE_CHECK_URL(m_process, urlString);
2462
2463     URL pluginURL = URL { URL(), urlString };
2464     String newMimeType = mimeType.convertToASCIILowercase();
2465
2466     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2467
2468     URL pageURL = URL { URL(), pageURLString };
2469     if (!m_process->processPool().pluginInfoStore().isSupportedPlugin(mimeType, pluginURL, frameURLString, pageURL)) {
2470         reply(0, newMimeType, PluginModuleLoadNormally, { }, true);
2471         return;
2472     }
2473
2474     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, pluginURL, allowedPluginTypes);
2475     if (!plugin.path) {
2476         reply(0, newMimeType, PluginModuleLoadNormally, { }, false);
2477         return;
2478     }
2479
2480     uint32_t pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2481
2482 #if PLATFORM(COCOA)
2483     auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2484 #endif
2485
2486     auto findPluginCompletion = [processType, reply = WTFMove(reply), newMimeType = WTFMove(newMimeType), plugin = WTFMove(plugin)] (uint32_t pluginLoadPolicy, const String& unavailabilityDescription) mutable {
2487         PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2488         switch (pluginLoadPolicy) {
2489         case PluginModuleLoadNormally:
2490             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2491             break;
2492         case PluginModuleLoadUnsandboxed:
2493             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2494             break;
2495
2496         case PluginModuleBlockedForSecurity:
2497         case PluginModuleBlockedForCompatibility:
2498             reply(0, newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2499             return;
2500         }
2501
2502         reply(PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy), newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2503     };
2504
2505 #if PLATFORM(COCOA)
2506     m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), WTFMove(findPluginCompletion));
2507 #else
2508     findPluginCompletion(pluginLoadPolicy, { });
2509 #endif
2510 }
2511
2512 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2513
2514 #if ENABLE(TOUCH_EVENTS)
2515
2516 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2517 {
2518     if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2519         return b;
2520     return a;
2521 }
2522
2523 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2524 {
2525 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2526     const EventNames& names = eventNames();
2527     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2528         IntPoint location = touchPoint.location();
2529         auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
2530             if (trackingType == TrackingType::Synchronous)
2531                 return;
2532
2533             TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2534
2535             trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2536         };
2537         updateTrackingType(m_touchAndPointerEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2538         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.touchstartEvent);
2539         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.touchmoveEvent);
2540         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.touchendEvent);
2541         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointerdownEvent);
2542         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.pointermoveEvent);
2543         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointerupEvent);
2544         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.mousedownEvent);
2545         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.mousemoveEvent);
2546         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.mouseupEvent);
2547     }
2548 #else
2549     UNUSED_PARAM(touchStartEvent);
2550     m_touchAndPointerEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2551     m_touchAndPointerEventTracking.touchStartTracking = TrackingType::Synchronous;
2552     m_touchAndPointerEventTracking.touchMoveTracking = TrackingType::Synchronous;
2553     m_touchAndPointerEventTracking.touchEndTracking = TrackingType::Synchronous;
2554 #endif // ENABLE(ASYNC_SCROLLING)
2555 }
2556
2557 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2558 {
2559     // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2560     //
2561     // Touch events define a sequence with strong dependencies. For example, we can expect
2562     // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2563     // the two.
2564     //
2565     // WebCore should not have to set up its state correctly after some events were dismissed.
2566     // For example, we don't want to send a TouchMoved without a TouchPressed.
2567     // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2568     TrackingType globalTrackingType = m_touchAndPointerEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2569
2570     globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchForceChangedTracking);
2571     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2572         switch (touchPoint.state()) {
2573         case WebPlatformTouchPoint::TouchReleased:
2574             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchEndTracking);
2575             break;
2576         case WebPlatformTouchPoint::TouchPressed:
2577             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchStartTracking);
2578             break;
2579         case WebPlatformTouchPoint::TouchMoved:
2580         case WebPlatformTouchPoint::TouchStationary:
2581             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchMoveTracking);
2582             break;
2583         case WebPlatformTouchPoint::TouchCancelled:
2584             globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2585             break;
2586         }
2587     }
2588
2589     return globalTrackingType;
2590 }
2591
2592 #endif
2593
2594 #if ENABLE(MAC_GESTURE_EVENTS)
2595 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2596 {
2597     if (!hasRunningProcess())
2598         return;
2599
2600     m_gestureEventQueue.append(event);
2601     // FIXME: Consider doing some coalescing here.
2602
2603     ResponsivenessTimer& responsivenessTimer = m_process->responsivenessTimer();
2604     if (event.type() == WebEvent::GestureStart || event.type() == WebEvent::GestureChange)
2605         responsivenessTimer.startWithLazyStop();
2606     else
2607         responsivenessTimer.start();
2608
2609     m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2610 }
2611 #endif
2612
2613 #if ENABLE(IOS_TOUCH_EVENTS)
2614 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2615 {
2616     if (!hasRunningProcess())
2617         return;
2618
2619     TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2620
2621     updateTouchEventTracking(event);
2622
2623     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2624     if (touchEventsTrackingType == TrackingType::NotTracking)
2625         return;
2626
2627     if (touchEventsTrackingType == TrackingType::Asynchronous) {
2628         // We can end up here if a native gesture has not started but the event handlers are passive.
2629         //
2630         // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2631         // can prevent a native gesture.
2632         // But, here we know that all events handlers that can handle this events are passive.
2633         // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2634         event.setCanPreventNativeGestures(false);
2635         handleTouchEventAsynchronously(event);
2636         didReceiveEvent(event.type(), false);
2637         return;
2638     }
2639
2640     m_process->responsivenessTimer().start();
2641     bool handled = false;
2642     bool replyReceived = m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID, 1_s);
2643     // If the sync request has timed out, we should consider the event handled. The Web Process is too busy to answer any questions, so the default action is also likely to have issues.
2644     if (!replyReceived)
2645         handled = true;
2646     didReceiveEvent(event.type(), handled);
2647     pageClient().doneWithTouchEvent(event, handled);
2648     m_process->responsivenessTimer().stop();
2649
2650     if (event.allTouchPointsAreReleased())
2651         m_touchAndPointerEventTracking.reset();
2652 }
2653
2654 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2655 {
2656     if (!hasRunningProcess())
2657         return;
2658
2659     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2660     if (touchEventsTrackingType == TrackingType::NotTracking)
2661         return;
2662
2663     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2664
2665     if (event.allTouchPointsAreReleased())
2666         m_touchAndPointerEventTracking.reset();
2667 }
2668
2669 #elif ENABLE(TOUCH_EVENTS)
2670 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2671 {
2672     if (!hasRunningProcess())
2673         return;
2674
2675     updateTouchEventTracking(event);
2676
2677     if (touchEventTrackingType(event) == TrackingType::NotTracking)
2678         return;
2679
2680     // If the page is suspended, which should be the case during panning, pinching
2681     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2682     // we do not send any of the events to the page even if is has listeners.
2683     if (!m_isPageSuspended) {
2684         m_touchEventQueue.append(event);
2685         m_process->responsivenessTimer().start();
2686         m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2687     } else {
2688         if (m_touchEventQueue.isEmpty()) {
2689             bool isEventHandled = false;
2690             pageClient().doneWithTouchEvent(event, isEventHandled);
2691         } else {
2692             // We attach the incoming events to the newest queued event so that all
2693             // the events are delivered in the correct order when the event is dequed.
2694             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2695             lastEvent.deferredTouchEvents.append(event);
2696         }
2697     }
2698
2699     if (event.allTouchPointsAreReleased())
2700         m_touchAndPointerEventTracking.reset();
2701 }
2702 #endif // ENABLE(TOUCH_EVENTS)
2703
2704 #if ENABLE(POINTER_EVENTS)
2705 void WebPageProxy::cancelPointer(WebCore::PointerID pointerId, const WebCore::IntPoint& documentPoint)
2706 {
2707     m_process->send(Messages::WebPage::CancelPointer(pointerId, documentPoint), m_pageID);
2708 }
2709 #endif
2710
2711 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2712 {
2713     if (!hasRunningProcess())
2714         return;
2715
2716     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2717 }
2718
2719 void WebPageProxy::centerSelectionInVisibleArea()
2720 {
2721     if (!hasRunningProcess())
2722         return;
2723
2724     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2725 }
2726
2727 class WebPageProxy::PolicyDecisionSender : public RefCounted<PolicyDecisionSender> {
2728 public:
2729     using SendFunction = CompletionHandler<void(PolicyCheckIdentifier, PolicyAction, uint64_t newNavigationID, DownloadID, Optional<WebsitePoliciesData>)>;
2730
2731     static Ref<PolicyDecisionSender> create(PolicyCheckIdentifier identifier, SendFunction&& sendFunction)
2732     {
2733         return adoptRef(*new PolicyDecisionSender(identifier, WTFMove(sendFunction)));
2734     }
2735
2736     template<typename... Args> void send(Args... args)
2737     {
2738         if (m_sendFunction)
2739             m_sendFunction(m_identifier, std::forward<Args>(args)...);
2740     }
2741 private:
2742     PolicyDecisionSender(PolicyCheckIdentifier identifier, SendFunction sendFunction)
2743         : m_sendFunction(WTFMove(sendFunction))
2744         , m_identifier(identifier)
2745         { }
2746
2747     SendFunction m_sendFunction;
2748     PolicyCheckIdentifier m_identifier;
2749 };
2750
2751 void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, API::Navigation* navigation, ProcessSwapRequestedByClient processSwapRequestedByClient, WebFrameProxy& frame, API::WebsitePolicies* policies, Ref<PolicyDecisionSender>&& sender)
2752 {
2753     Ref<WebsiteDataStore> websiteDataStore = m_websiteDataStore.copyRef();
2754     Optional<WebsitePoliciesData> data;
2755     if (policies) {
2756         data = policies->data();
2757         if (policies->websiteDataStore() && &policies->websiteDataStore()->websiteDataStore() != websiteDataStore.ptr()) {
2758             websiteDataStore = policies->websiteDataStore()->websiteDataStore();
2759             processSwapRequestedByClient = ProcessSwapRequestedByClient::Yes;
2760         }
2761     }
2762
2763     if (navigation && !navigation->userContentExtensionsEnabled()) {
2764         if (!data)
2765             data = WebsitePoliciesData { };
2766         data->contentBlockersEnabled = false;
2767     }
2768
2769 #if ENABLE(DEVICE_ORIENTATION)
2770     if (navigation && (!data || data->deviceOrientationAndMotionAccessState == WebCore::DeviceOrientationOrMotionPermissionState::Prompt)) {
2771         auto deviceOrientationPermission = websiteDataStore->deviceOrientationAndMotionAccessController().cachedDeviceOrientationPermission(SecurityOriginData::fromURL(navigation->currentRequest().url()));
2772         if (deviceOrientationPermission != WebCore::DeviceOrientationOrMotionPermissionState::Prompt) {
2773             if (!data)
2774                 data = WebsitePoliciesData { };
2775             data->deviceOrientationAndMotionAccessState = deviceOrientationPermission;
2776         }
2777     }
2778 #endif
2779
2780 #if PLATFORM(COCOA)
2781     static const bool forceDownloadFromDownloadAttribute = false;
2782 #else
2783     static const bool forceDownloadFromDownloadAttribute = true;
2784 #endif
2785     if (policyAction == PolicyAction::Use && navigation && (navigation->isSystemPreview() || (forceDownloadFromDownloadAttribute && navigation->shouldPerformDownload())))
2786         policyAction = PolicyAction::Download;
2787
2788     if (policyAction != PolicyAction::Use || !frame.isMainFrame() || !navigation) {
2789         receivedPolicyDecision(policyAction, navigation, WTFMove(data), WTFMove(sender));
2790         return;
2791     }
2792
2793     Ref<WebProcessProxy> sourceProcess = process();
2794     URL sourceURL = URL { URL(), pageLoadState().url() };
2795     if (auto* provisionalPage = provisionalPageProxy()) {
2796         if (provisionalPage->navigationID() == navigation->navigationID()) {
2797             sourceProcess = provisionalPage->process();
2798             sourceURL = provisionalPage->provisionalURL();
2799         }
2800     }
2801
2802     process().processPool().processForNavigation(*this, *navigation, sourceProcess.copyRef(), sourceURL, processSwapRequestedByClient, WTFMove(websiteDataStore), [this, protectedThis = makeRef(*this), policyAction, navigation = makeRef(*navigation), sourceProcess = sourceProcess.copyRef(),
2803         data = WTFMove(data), sender = WTFMove(sender), processSwapRequestedByClient] (Ref<WebProcessProxy>&& processForNavigation, SuspendedPageProxy* destinationSuspendedPage, const String& reason) mutable {
2804         // If the navigation has been destroyed, then no need to proceed.
2805         if (isClosed() || !navigationState().hasNavigation(navigation->navigationID())) {
2806             receivedPolicyDecision(policyAction, navigation.ptr(), WTFMove(data), WTFMove(sender));
2807             return;
2808         }
2809
2810         bool shouldProcessSwap = processForNavigation.ptr() != sourceProcess.ptr();
2811         if (shouldProcessSwap) {
2812             policyAction = PolicyAction::StopAllLoads;
2813             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction, swapping process %i with process %i for navigation, reason: %{public}s", processIdentifier(), processForNavigation->processIdentifier(), reason.utf8().data());
2814             LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), processForNavigation->processIdentifier(), navigation->navigationID(), navigation->loggingString());
2815         } else
2816             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction: keep using process %i for navigation, reason: %{public}s", processIdentifier(), reason.utf8().data());
2817
2818         if (shouldProcessSwap) {
2819             // FIXME: Architecturally we do not currently support multiple WebPage's with the same ID in a given WebProcess.
2820             // In the case where the destination WebProcess has a SuspendedPageProxy for this WebPage, we should have thrown
2821             // it away to support WebProcess re-use.
2822             ASSERT(destinationSuspendedPage || !process().processPool().hasSuspendedPageFor(processForNavigation, *this));
2823
2824             auto suspendedPage = destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr;
2825             if (suspendedPage && suspendedPage->failedToSuspend())
2826                 suspendedPage = nullptr;
2827
2828             continueNavigationInNewProcess(navigation, WTFMove(suspendedPage), WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
2829         }
2830
2831         receivedPolicyDecision(policyAction, navigation.ptr(), shouldProcessSwap ? WTF::nullopt : WTFMove(data), WTFMove(sender), shouldProcessSwap ? WillContinueLoadInNewProcess::Yes : WillContinueLoadInNewProcess::No);
2832     });
2833 }
2834
2835 void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, Optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender, WillContinueLoadInNewProcess willContinueLoadInNewProcess)
2836 {
2837     if (!hasRunningProcess()) {
2838         sender->send(PolicyAction::Ignore, 0, DownloadID(), WTF::nullopt);
2839         return;
2840     }
2841
2842     auto transaction = m_pageLoadState.transaction();
2843
2844     if (action == PolicyAction::Ignore && willContinueLoadInNewProcess == WillContinueLoadInNewProcess::No)
2845         m_pageLoadState.clearPendingAPIRequestURL(transaction);
2846
2847     DownloadID downloadID = { };
2848     if (action == PolicyAction::Download) {
2849         // Create a download proxy.
2850         auto& download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
2851         if (navigation) {
2852             download.setWasUserInitiated(navigation->wasUserInitiated());
2853             download.setRedirectChain(navigation->takeRedirectChain());
2854         }
2855
2856         downloadID = download.downloadID();
2857         handleDownloadRequest(download);
2858         m_decidePolicyForResponseRequest = { };
2859     }
2860
2861     sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
2862 }
2863
2864 void WebPageProxy::commitProvisionalPage(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData& userData)
2865 {
2866     ASSERT(m_provisionalPage);
2867     RELEASE_LOG_IF_ALLOWED(Loading, "commitProvisionalPage: previousPID = %i, newPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_provisionalPage->process().processIdentifier(), m_pageID);
2868
2869     Optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? makeOptional(m_mainFrame->frameID()) : WTF::nullopt;
2870
2871     ASSERT(m_process.ptr() != &m_provisionalPage->process());
2872
2873     auto shouldDelayClosingUntilEnteringAcceleratedCompositingMode = ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::No;
2874 #if PLATFORM(MAC)
2875     // On macOS, when not using UI-side compositing, we need to make sure we do not close the page in the previous process until we've
2876     // entered accelerated compositing for the new page or we will flash on navigation.
2877     if (drawingArea()->type() == DrawingAreaTypeTiledCoreAnimation)
2878         shouldDelayClosingUntilEnteringAcceleratedCompositingMode = ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::Yes;
2879 #endif
2880
2881     processDidTerminate(ProcessTerminationReason::NavigationSwap);
2882
2883     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
2884     auto* navigation = navigationState().navigation(m_provisionalPage->navigationID());
2885     bool didSuspendPreviousPage = navigation ? suspendCurrentPageIfPossible(*navigation, mainFrameIDInPreviousProcess, m_provisionalPage->processSwapRequestedByClient(), shouldDelayClosingUntilEnteringAcceleratedCompositingMode) : false;
2886     m_process->removeWebPage(*this, m_websiteDataStore.ptr() == &m_provisionalPage->process().websiteDataStore() ? WebProcessProxy::EndsUsingDataStore::No : WebProcessProxy::EndsUsingDataStore::Yes);
2887
2888     // There is no way we'll be able to return to the page in the previous page so close it.
2889     if (!didSuspendPreviousPage)
2890         m_process->send(Messages::WebPage::Close(), pageID());
2891
2892     swapToWebProcess(m_provisionalPage->process(), m_provisionalPage->takeDrawingArea(), m_provisionalPage->mainFrame());
2893
2894 #if PLATFORM(COCOA)
2895     auto accessibilityToken = m_provisionalPage->takeAccessibilityToken();
2896     if (!accessibilityToken.isEmpty())
2897         registerWebProcessAccessibilityToken({ accessibilityToken.data(), accessibilityToken.size() });
2898 #endif
2899
2900     didCommitLoadForFrame(frameID, navigationID, mimeType, frameHasCustomContentProvider, frameLoadType, certificateInfo, containsPluginDocument, forcedHasInsecureContent, userData);
2901
2902     m_provisionalPage = nullptr;
2903 }
2904
2905 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& newProcess, ProcessSwapRequestedByClient processSwapRequestedByClient, Optional<WebsitePoliciesData>&& websitePolicies)
2906 {
2907     RELEASE_LOG_IF_ALLOWED(Loading, "continueNavigationInNewProcess: webPID = %i, pageID = %" PRIu64 ", newProcessPID = %i, hasSuspendedPage = %i", m_process->processIdentifier(), m_pageID, newProcess->processIdentifier(), !!suspendedPageProxy);
2908     LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
2909
2910     if (m_provisionalPage) {
2911         RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "continueNavigationInNewProcess: There is already a pending provisional load, cancelling it (provisonalNavigationID: %llu, navigationID: %llu)", m_provisionalPage->navigationID(), navigation.navigationID());
2912         if (m_provisionalPage->navigationID() != navigation.navigationID())
2913             m_provisionalPage->cancel();
2914         m_provisionalPage = nullptr;
2915     }
2916
2917     m_provisionalPage = std::make_unique<ProvisionalPageProxy>(*this, newProcess.copyRef(), WTFMove(suspendedPageProxy), navigation.navigationID(), navigation.currentRequestIsRedirect(), navigation.currentRequest(), processSwapRequestedByClient);
2918
2919     if (auto* item = navigation.targetItem()) {
2920         LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
2921
2922         auto transaction = m_pageLoadState.transaction();
2923         m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
2924
2925         m_provisionalPage->goToBackForwardItem(navigation, *item, WTFMove(websitePolicies));
2926         return;
2927     }
2928
2929     if (m_backForwardList->currentItem() && (navigation.lockBackForwardList() == LockBackForwardList::Yes || navigation.lockHistory() == LockHistory::Yes)) {
2930         // If WebCore is supposed to lock the history for this load, then the new process needs to know about the current history item so it can update
2931         // it instead of creating a new one.
2932         newProcess->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
2933     }
2934
2935     // FIXME: Work out timing of responding with the last policy delegate, etc
2936     ASSERT(!navigation.currentRequest().isEmpty());
2937     if (auto& substituteData = navigation.substituteData())
2938         m_provisionalPage->loadData(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get(), WTFMove(websitePolicies));
2939     else
2940         m_provisionalPage->loadRequest(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, WTFMove(websitePolicies));
2941 }
2942
2943 bool WebPageProxy::isPageOpenedByDOMShowingInitialEmptyDocument() const
2944 {
2945     return openedByDOM() && !hasCommittedAnyProvisionalLoads();
2946 }
2947
2948 // MSVC gives a redeclaration error if noreturn is used on the definition and not the declaration, while
2949 // Cocoa tests segfault if it is moved to the declaration site (even if we move the definition with it!).
2950 #if !COMPILER(MSVC)
2951 NO_RETURN_DUE_TO_ASSERT
2952 #endif
2953 void WebPageProxy::didFailToSuspendAfterProcessSwap()
2954 {
2955     // Only the SuspendedPageProxy should be getting this call.
2956     ASSERT_NOT_REACHED();
2957 }
2958
2959 #if !COMPILER(MSVC)
2960 NO_RETURN_DUE_TO_ASSERT
2961 #endif
2962 void WebPageProxy::didSuspendAfterProcessSwap()
2963 {
2964     // Only the SuspendedPageProxy should be getting this call.
2965     ASSERT_NOT_REACHED();
2966 }
2967
2968 void WebPageProxy::setUserAgent(String&& userAgent)
2969 {
2970     if (m_userAgent == userAgent)
2971         return;
2972     m_userAgent = WTFMove(userAgent);
2973
2974 #if ENABLE(SERVICE_WORKER)
2975     // We update the service worker there at the moment to be sure we use values used by actual web pages.
2976     // FIXME: Refactor this when we have a better User-Agent story.
2977     process().processPool().updateServiceWorkerUserAgent(m_userAgent);
2978 #endif
2979
2980     if (!hasRunningProcess())
2981         return;
2982     m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
2983 }
2984
2985 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
2986 {
2987     if (m_applicationNameForUserAgent == applicationName)
2988         return;
2989
2990     m_applicationNameForUserAgent = applicationName;
2991     if (!m_customUserAgent.isEmpty())
2992         return;
2993
2994     setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2995 }
2996
2997 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
2998 {
2999     if (m_customUserAgent == customUserAgent)
3000         return;
3001
3002     m_customUserAgent = customUserAgent;
3003
3004     if (m_customUserAgent.isEmpty()) {
3005         setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
3006         return;
3007     }
3008
3009     setUserAgent(String { m_customUserAgent });
3010 }
3011
3012 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
3013 {
3014     if (!hasRunningProcess() || !m_isPageSuspended)
3015         return;
3016
3017     m_isPageSuspended = false;
3018
3019     m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
3020 }
3021
3022 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
3023 {
3024     if (!hasRunningProcess() || m_isPageSuspended)
3025         return;
3026
3027     m_isPageSuspended = true;
3028
3029     m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
3030 }
3031
3032 bool WebPageProxy::supportsTextEncoding() const
3033 {
3034     // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
3035     return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
3036 }
3037
3038 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
3039 {
3040     if (m_customTextEncodingName == encodingName)
3041         return;
3042     m_customTextEncodingName = encodingName;
3043
3044     if (!hasRunningProcess())
3045         return;
3046     m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
3047 }
3048
3049 SessionState WebPageProxy::sessionState(WTF::Function<bool (WebBackForwardListItem&)>&& filter) const
3050 {
3051     SessionState sessionState;
3052
3053     sessionState.backForwardListState = m_backForwardList->backForwardListState(WTFMove(filter));
3054
3055     String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
3056     if (provisionalURLString.isEmpty())
3057         provisionalURLString = m_pageLoadState.provisionalURL();
3058
3059     if (!provisionalURLString.isEmpty())
3060         sessionState.provisionalURL = URL(URL(), provisionalURLString);
3061
3062     sessionState.renderTreeSize = renderTreeSize();
3063     return sessionState;
3064 }
3065
3066 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
3067 {
3068     RELEASE_LOG_IF_ALLOWED(Loading, "restoreFromSessionState: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
3069
3070     m_sessionRestorationRenderTreeSize = 0;
3071     m_hitRenderTreeSizeThreshold = false;
3072
3073     bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
3074
3075     if (hasBackForwardList) {
3076         m_backForwardList->restoreFromState(WTFMove(sessionState.backForwardListState));
3077         process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
3078
3079         auto transaction = m_pageLoadState.transaction();
3080         m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
3081         m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
3082
3083         // The back / forward list was restored from a sessionState so we don't want to snapshot the current
3084         // page when navigating away. Suppress navigation snapshotting until the next load has committed
3085         suppressNextAutomaticNavigationSnapshot();
3086     }
3087
3088     // FIXME: Navigating should be separate from state restoration.
3089     if (navigate) {
3090         m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
3091         if (!m_sessionRestorationRenderTreeSize)
3092             m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
3093
3094         if (!sessionState.provisionalURL.isNull())
3095             return loadRequest(sessionState.provisionalURL);
3096
3097         if (hasBackForwardList) {
3098             if (WebBackForwardListItem* item = m_backForwardList->currentItem())
3099                 return goToBackForwardItem(*item);
3100         }
3101     }
3102
3103     return nullptr;
3104 }
3105
3106 bool WebPageProxy::supportsTextZoom() const
3107 {
3108     // FIXME (118840): This should also return false for standalone media and plug-in documents.
3109     if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
3110         return false;
3111
3112     return true;
3113 }
3114  
3115 void WebPageProxy::setTextZoomFactor(double zoomFactor)
3116 {
3117     if (m_textZoomFactor == zoomFactor)
3118         return;
3119
3120     m_textZoomFactor = zoomFactor;
3121
3122     if (!hasRunningProcess())
3123         return;
3124
3125     m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID); 
3126 }
3127
3128 void WebPageProxy::setPageZoomFactor(double zoomFactor)
3129 {
3130     if (m_pageZoomFactor == zoomFactor)
3131         return;
3132
3133     closeOverlayedViews();
3134
3135     m_pageZoomFactor = zoomFactor;
3136
3137     if (!hasRunningProcess())
3138         return;
3139
3140     m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID); 
3141 }
3142
3143 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
3144 {
3145     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
3146         return;
3147
3148     closeOverlayedViews();
3149
3150     m_pageZoomFactor = pageZoomFactor;
3151     m_textZoomFactor = textZoomFactor;
3152
3153     if (!hasRunningProcess())
3154         return;
3155
3156     m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID); 
3157 }
3158
3159 double WebPageProxy::pageZoomFactor() const
3160 {
3161     // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
3162     // zoom which ensures that we don't use the PDF zoom for a normal page.
3163     if (m_mainFramePluginHandlesPageScaleGesture)
3164         return m_pluginZoomFactor;
3165     return m_pageZoomFactor;
3166 }
3167
3168 double WebPageProxy::pageScaleFactor() const
3169 {
3170     // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
3171     // separately but decide which to return based on the main frame.
3172     if (m_mainFramePluginHandlesPageScaleGesture)
3173         return m_pluginScaleFactor;
3174     return m_pageScaleFactor;
3175 }
3176
3177 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
3178 {
3179     ASSERT(scale > 0);
3180
3181     m_pageScaleFactor = scale;
3182
3183     if (!hasRunningProcess())
3184         return;
3185
3186     m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
3187 }
3188
3189 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
3190 {
3191     ASSERT(scale > 0);
3192
3193     m_pageScaleFactor = scale;
3194
3195     if (!hasRunningProcess())
3196         return;
3197
3198     m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
3199 }
3200
3201 void WebPageProxy::scaleView(double scale)
3202 {
3203     ASSERT(scale > 0);
3204
3205     m_viewScaleFactor = scale;
3206
3207     if (!hasRunningProcess())
3208         return;
3209
3210     m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
3211 }
3212
3213 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
3214 {
3215     if (m_intrinsicDeviceScaleFactor == scaleFactor)
3216         return;
3217
3218     m_intrinsicDeviceScaleFactor = scaleFactor;
3219
3220     if (m_drawingArea)
3221         m_drawingArea->deviceScaleFactorDidChange();
3222 }
3223
3224 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
3225 {
3226     if (!hasRunningProcess())
3227         return;
3228
3229     m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
3230 }
3231
3232 float WebPageProxy::deviceScaleFactor() const
3233 {
3234     return m_customDeviceScaleFactor.valueOr(m_intrinsicDeviceScaleFactor);
3235 }
3236
3237 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
3238 {
3239     // FIXME: Remove this once we bump cairo requirements to support HiDPI.
3240     // https://bugs.webkit.org/show_bug.cgi?id=133378
3241 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
3242     return;
3243 #endif
3244
3245     if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
3246         return;
3247
3248     float oldScaleFactor = deviceScaleFactor();
3249
3250     // A value of 0 clears the customScaleFactor.
3251     if (customScaleFactor)
3252         m_customDeviceScaleFactor = customScaleFactor;
3253     else
3254         m_customDeviceScaleFactor = WTF::nullopt;
3255
3256     if (!hasRunningProcess())
3257         return;
3258
3259     if (deviceScaleFactor() != oldScaleFactor)
3260         m_drawingArea->deviceScaleFactorDidChange();
3261 }
3262
3263 void WebPageProxy::accessibilitySettingsDidChange()
3264 {
3265     if (!hasRunningProcess())
3266         return;
3267
3268     m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
3269 }
3270
3271 void WebPageProxy::setUseFixedLayout(bool fixed)
3272 {
3273     // This check is fine as the value is initialized in the web
3274     // process as part of the creation parameters.
3275     if (fixed == m_useFixedLayout)
3276         return;
3277
3278     m_useFixedLayout = fixed;
3279     if (!fixed)
3280         m_fixedLayoutSize = IntSize();
3281
3282     if (!hasRunningProcess())
3283         return;
3284
3285     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
3286 }
3287
3288 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
3289 {
3290     if (size == m_fixedLayoutSize)
3291         return;
3292
3293     m_fixedLayoutSize = size;
3294
3295     if (!hasRunningProcess())
3296         return;
3297
3298     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
3299 }
3300
3301 void WebPageProxy::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)
3302 {
3303     if (alwaysShowsHorizontalScroller == m_alwaysShowsHorizontalScroller)
3304         return;
3305
3306     m_alwaysShowsHorizontalScroller = alwaysShowsHorizontalScroller;
3307
3308     if (!hasRunningProcess())
3309         return;
3310
3311     m_process->send(Messages::WebPage::SetAlwaysShowsHorizontalScroller(alwaysShowsHorizontalScroller), m_pageID);
3312 }
3313
3314 void WebPageProxy::setAlwaysShowsVerticalScroller(bool alwaysShowsVerticalScroller)
3315 {
3316     if (alwaysShowsVerticalScroller == m_alwaysShowsVerticalScroller)
3317         return;
3318
3319     m_alwaysShowsVerticalScroller = alwaysShowsVerticalScroller;
3320
3321     if (!hasRunningProcess())
3322         return;
3323
3324     m_process->send(Messages::WebPage::SetAlwaysShowsVerticalScroller(alwaysShowsVerticalScroller), m_pageID);
3325 }
3326
3327 void WebPageProxy::listenForLayoutMilestones(OptionSet<WebCore::LayoutMilestone> milestones)
3328 {    
3329     if (milestones == m_observedLayoutMilestones)
3330         return;
3331
3332     m_observedLayoutMilestones = milestones;
3333
3334     if (!hasRunningProcess())
3335         return;
3336
3337     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
3338 }
3339
3340 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
3341 {
3342     if (suppressAnimations == m_suppressScrollbarAnimations)
3343         return;
3344
3345     m_suppressScrollbarAnimations = suppressAnimations;
3346
3347     if (!hasRunningProcess())
3348         return;
3349
3350     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
3351 }
3352
3353 bool WebPageProxy::rubberBandsAtLeft() const
3354 {
3355     return m_rubberBandsAtLeft;
3356 }
3357
3358 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
3359 {
3360     m_rubberBandsAtLeft = rubberBandsAtLeft;
3361 }
3362
3363 bool WebPageProxy::rubberBandsAtRight() const
3364 {
3365     return m_rubberBandsAtRight;
3366 }
3367
3368 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
3369 {
3370     m_rubberBandsAtRight = rubberBandsAtRight;
3371 }
3372
3373 bool WebPageProxy::rubberBandsAtTop() const
3374 {
3375     return m_rubberBandsAtTop;
3376 }
3377
3378 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
3379 {
3380     m_rubberBandsAtTop = rubberBandsAtTop;
3381 }
3382
3383 bool WebPageProxy::rubberBandsAtBottom() const
3384 {
3385     return m_rubberBandsAtBottom;
3386 }
3387
3388 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
3389 {
3390     m_rubberBandsAtBottom = rubberBandsAtBottom;
3391 }
3392     
3393 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
3394 {
3395     if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
3396         return;
3397
3398     m_enableVerticalRubberBanding = enableVerticalRubberBanding;
3399
3400     if (!hasRunningProcess())
3401         return;
3402     m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
3403 }
3404     
3405 bool WebPageProxy::verticalRubberBandingIsEnabled() const
3406 {
3407     return m_enableVerticalRubberBanding;
3408 }
3409     
3410 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
3411 {
3412     if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
3413         return;
3414
3415     m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
3416
3417     if (!hasRunningProcess())
3418         return;
3419     m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
3420 }
3421     
3422 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
3423 {
3424     return m_enableHorizontalRubberBanding;
3425 }
3426
3427 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
3428 {
3429     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
3430         return;
3431
3432     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
3433
3434     if (!hasRunningProcess())
3435         return;
3436     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
3437 }
3438
3439 bool WebPageProxy::backgroundExtendsBeyondPage() const
3440 {
3441     return m_backgroundExtendsBeyondPage;
3442 }
3443
3444 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
3445 {
3446     if (mode == m_paginationMode)
3447         return;
3448
3449     m_paginationMode = mode;
3450
3451     if (!hasRunningProcess())
3452         return;
3453     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
3454 }
3455
3456 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
3457 {
3458     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
3459         return;
3460
3461     m_paginationBehavesLikeColumns = behavesLikeColumns;
3462
3463     if (!hasRunningProcess())
3464         return;
3465     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
3466 }
3467
3468 void WebPageProxy::setPageLength(double pageLength)
3469 {
3470     if (pageLength == m_pageLength)
3471         return;
3472
3473     m_pageLength = pageLength;
3474
3475     if (!hasRunningProcess())
3476         return;
3477     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
3478 }
3479
3480 void WebPageProxy::setGapBetweenPages(double gap)
3481 {
3482     if (gap == m_gapBetweenPages)
3483         return;
3484
3485     m_gapBetweenPages = gap;
3486
3487     if (!hasRunningProcess())
3488         return;
3489     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
3490 }
3491
3492 void WebPageProxy::setPaginationLineGridEnabled(bool lineGridEnabled)
3493 {
3494     if (lineGridEnabled == m_paginationLineGridEnabled)
3495         return;
3496     
3497     m_paginationLineGridEnabled = lineGridEnabled;
3498     
3499     if (!hasRunningProcess())
3500         return;
3501     m_process->send(Messages::WebPage::SetPaginationLineGridEnabled(lineGridEnabled), m_pageID);
3502 }
3503
3504 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
3505 {
3506     m_pageScaleFactor = scaleFactor;
3507 }
3508
3509 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
3510 {
3511     m_pluginScaleFactor = pluginScaleFactor;
3512 }
3513
3514 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
3515 {
3516     m_pluginZoomFactor = pluginZoomFactor;
3517 }
3518
3519 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3520 {
3521     if (string.isEmpty()) {
3522         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
3523         return;
3524     }
3525
3526     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
3527 }
3528
3529 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
3530 {
3531     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
3532 }
3533
3534 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
3535 {
3536     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
3537 }
3538
3539 void WebPageProxy::selectFindMatch(int32_t matchIndex)
3540 {
3541     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
3542 }
3543
3544 void WebPageProxy::hideFindUI()
3545 {
3546     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
3547 }
3548
3549 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3550 {
3551     if (!hasRunningProcess())
3552         return;
3553
3554     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
3555 }
3556
3557 void WebPageProxy::replaceMatches(Vector<uint32_t>&& matchIndices, const String& replacementText, bool selectionOnly, Function<void(uint64_t, CallbackBase::Error)>&& callback)
3558 {
3559     if (!hasRunningProcess()) {
3560         callback(0, CallbackBase::Error::Unknown);
3561 &n