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