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