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