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