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