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