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