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