5e8847910dee09606dce98a881f4b04599df488e
[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 "SafeBrowsingWarning.h"
81 #include "ShareSheetCallbackID.h"
82 #include "SharedBufferDataReference.h"
83 #include "TextChecker.h"
84 #include "TextCheckerState.h"
85 #include "UIMessagePortChannelProvider.h"
86 #include "URLSchemeTaskParameters.h"
87 #include "UndoOrRedo.h"
88 #include "UserMediaPermissionRequestProxy.h"
89 #include "UserMediaProcessManager.h"
90 #include "WKContextPrivate.h"
91 #include "WebAutomationSession.h"
92 #include "WebBackForwardList.h"
93 #include "WebBackForwardListItem.h"
94 #include "WebCertificateInfo.h"
95 #include "WebContextMenuItem.h"
96 #include "WebContextMenuProxy.h"
97 #include "WebCoreArgumentCoders.h"
98 #include "WebEditCommandProxy.h"
99 #include "WebEvent.h"
100 #include "WebEventConversion.h"
101 #include "WebFramePolicyListenerProxy.h"
102 #include "WebFullScreenManagerProxy.h"
103 #include "WebFullScreenManagerProxyMessages.h"
104 #include "WebImage.h"
105 #include "WebInspectorProxy.h"
106 #include "WebInspectorUtilities.h"
107 #include "WebNavigationDataStore.h"
108 #include "WebNavigationState.h"
109 #include "WebNotificationManagerProxy.h"
110 #include "WebOpenPanelResultListenerProxy.h"
111 #include "WebPageCreationParameters.h"
112 #include "WebPageDebuggable.h"
113 #include "WebPageGroup.h"
114 #include "WebPageGroupData.h"
115 #include "WebPageInspectorController.h"
116 #include "WebPageMessages.h"
117 #include "WebPageProxyMessages.h"
118 #include "WebPaymentCoordinatorProxy.h"
119 #include "WebPopupItem.h"
120 #include "WebPopupMenuProxy.h"
121 #include "WebPreferences.h"
122 #include "WebPreferencesKeys.h"
123 #include "WebProcessMessages.h"
124 #include "WebProcessPool.h"
125 #include "WebProcessProxy.h"
126 #include "WebProtectionSpace.h"
127 #include "WebResourceLoadStatisticsStore.h"
128 #include "WebURLSchemeHandler.h"
129 #include "WebUserContentControllerProxy.h"
130 #include "WebsiteDataStore.h"
131 #include <WebCore/BitmapImage.h>
132 #include <WebCore/DeprecatedGlobalSettings.h>
133 #include <WebCore/DiagnosticLoggingClient.h>
134 #include <WebCore/DiagnosticLoggingKeys.h>
135 #include <WebCore/DragController.h>
136 #include <WebCore/DragData.h>
137 #include <WebCore/EventNames.h>
138 #include <WebCore/FloatRect.h>
139 #include <WebCore/FocusDirection.h>
140 #include <WebCore/FontAttributeChanges.h>
141 #include <WebCore/FrameLoader.h>
142 #include <WebCore/GlobalFrameIdentifier.h>
143 #include <WebCore/GlobalWindowIdentifier.h>
144 #include <WebCore/JSDOMBinding.h>
145 #include <WebCore/JSDOMExceptionHandling.h>
146 #include <WebCore/LengthBox.h>
147 #include <WebCore/MIMETypeRegistry.h>
148 #include <WebCore/MediaStreamRequest.h>
149 #include <WebCore/PerformanceLoggingClient.h>
150 #include <WebCore/PlatformEvent.h>
151 #include <WebCore/PublicSuffix.h>
152 #include <WebCore/RenderEmbeddedObject.h>
153 #include <WebCore/ResourceLoadStatistics.h>
154 #include <WebCore/SSLKeyGenerator.h>
155 #include <WebCore/SerializedCryptoKeyWrap.h>
156 #include <WebCore/ShareData.h>
157 #include <WebCore/SharedBuffer.h>
158 #include <WebCore/ShouldTreatAsContinuingLoad.h>
159 #include <WebCore/TextCheckerClient.h>
160 #include <WebCore/TextIndicator.h>
161 #include <WebCore/ValidationBubble.h>
162 #include <WebCore/WindowFeatures.h>
163 #include <WebCore/WritingDirection.h>
164 #include <stdio.h>
165 #include <wtf/NeverDestroyed.h>
166 #include <wtf/SystemTracing.h>
167 #include <wtf/URL.h>
168 #include <wtf/URLParser.h>
169 #include <wtf/text/StringView.h>
170 #include <wtf/text/TextStream.h>
171
172 #if ENABLE(APPLICATION_MANIFEST)
173 #include "APIApplicationManifest.h"
174 #endif
175
176 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
177 #include "RemoteScrollingCoordinatorProxy.h"
178 #endif
179
180 #ifndef NDEBUG
181 #include <wtf/RefCountedLeakCounter.h>
182 #endif
183
184 #if PLATFORM(COCOA)
185 #include "RemoteLayerTreeDrawingAreaProxy.h"
186 #include "RemoteLayerTreeScrollingPerformanceData.h"
187 #include "TouchBarMenuData.h"
188 #include "TouchBarMenuItemData.h"
189 #include "VideoFullscreenManagerProxy.h"
190 #include "VideoFullscreenManagerProxyMessages.h"
191 #include "ViewSnapshotStore.h"
192 #include <WebCore/RunLoopObserver.h>
193 #include <WebCore/TextIndicatorWindow.h>
194 #include <wtf/MachSendRight.h>
195 #endif
196
197 #if PLATFORM(GTK)
198 #include "WebSelectionData.h"
199 #endif
200
201 #if USE(CAIRO)
202 #include <WebCore/CairoUtilities.h>
203 #endif
204
205 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
206 #include <WebCore/MediaPlaybackTarget.h>
207 #include <WebCore/WebMediaSessionManager.h>
208 #endif
209
210 #if ENABLE(MEDIA_SESSION)
211 #include "WebMediaSessionFocusManager.h"
212 #include "WebMediaSessionMetadata.h"
213 #include <WebCore/MediaSessionMetadata.h>
214 #endif
215
216 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
217 #include "PlaybackSessionManagerProxy.h"
218 #endif
219
220 #if ENABLE(WEB_AUTHN)
221 #include "WebAuthenticatorCoordinatorProxy.h"
222 #endif
223
224 #if ENABLE(RESOURCE_LOAD_STATISTICS)
225 #include "WebResourceLoadStatisticsStore.h"
226 #endif
227
228 #if ENABLE(REMOTE_INSPECTOR)
229 #include <JavaScriptCore/RemoteInspector.h>
230 #endif
231
232 #if HAVE(SEC_KEY_PROXY)
233 #include "SecKeyProxyStore.h"
234 #endif
235
236 #if HAVE(PENCILKIT)
237 #include "EditableImageController.h"
238 #endif
239
240 // This controls what strategy we use for mouse wheel coalescing.
241 #define MERGE_WHEEL_EVENTS 1
242
243 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_process->connection())
244 #define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(url), m_process->connection())
245
246 #define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - WebPageProxy::" fmt, this, ##__VA_ARGS__)
247
248 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
249 static const unsigned wheelEventQueueSizeThreshold = 10;
250
251 static const Seconds resetRecentCrashCountDelay = 30_s;
252 static unsigned maximumWebProcessRelaunchAttempts = 1;
253
254 namespace WebKit {
255 using namespace WebCore;
256
257 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
258
259 class ExceededDatabaseQuotaRecords {
260     WTF_MAKE_NONCOPYABLE(ExceededDatabaseQuotaRecords); WTF_MAKE_FAST_ALLOCATED;
261     friend NeverDestroyed<ExceededDatabaseQuotaRecords>;
262 public:
263     struct Record {
264         uint64_t frameID;
265         String originIdentifier;
266         String databaseName;
267         String displayName;
268         uint64_t currentQuota;
269         uint64_t currentOriginUsage;
270         uint64_t currentDatabaseUsage;
271         uint64_t expectedUsage;
272         Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply reply;
273     };
274
275     static ExceededDatabaseQuotaRecords& singleton();
276
277     std::unique_ptr<Record> createRecord(uint64_t frameID, String originIdentifier,
278         String databaseName, String displayName, uint64_t currentQuota,
279         uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage, 
280         Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply&&);
281
282     void add(std::unique_ptr<Record>);
283     bool areBeingProcessed() const { return !!m_currentRecord; }
284     Record* next();
285
286 private:
287     ExceededDatabaseQuotaRecords() { }
288     ~ExceededDatabaseQuotaRecords() { }
289
290     Deque<std::unique_ptr<Record>> m_records;
291     std::unique_ptr<Record> m_currentRecord;
292 };
293
294 ExceededDatabaseQuotaRecords& ExceededDatabaseQuotaRecords::singleton()
295 {
296     static NeverDestroyed<ExceededDatabaseQuotaRecords> records;
297     return records;
298 }
299
300 std::unique_ptr<ExceededDatabaseQuotaRecords::Record> ExceededDatabaseQuotaRecords::createRecord(
301     uint64_t frameID, String originIdentifier, String databaseName, String displayName,
302     uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage,
303     uint64_t expectedUsage, Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply&& reply)
304 {
305     auto record = std::make_unique<Record>();
306     record->frameID = frameID;
307     record->originIdentifier = originIdentifier;
308     record->databaseName = databaseName;
309     record->displayName = displayName;
310     record->currentQuota = currentQuota;
311     record->currentOriginUsage = currentOriginUsage;
312     record->currentDatabaseUsage = currentDatabaseUsage;
313     record->expectedUsage = expectedUsage;
314     record->reply = WTFMove(reply);
315     return record;
316 }
317
318 void ExceededDatabaseQuotaRecords::add(std::unique_ptr<ExceededDatabaseQuotaRecords::Record> record)
319 {
320     m_records.append(WTFMove(record));
321 }
322
323 ExceededDatabaseQuotaRecords::Record* ExceededDatabaseQuotaRecords::next()
324 {
325     m_currentRecord = nullptr;
326     if (!m_records.isEmpty())
327         m_currentRecord = m_records.takeFirst();
328     return m_currentRecord.get();
329 }
330
331 #if !LOG_DISABLED
332 static const char* webMouseEventTypeString(WebEvent::Type type)
333 {
334     switch (type) {
335     case WebEvent::MouseDown:
336         return "MouseDown";
337     case WebEvent::MouseUp:
338         return "MouseUp";
339     case WebEvent::MouseMove:
340         return "MouseMove";
341     case WebEvent::MouseForceChanged:
342         return "MouseForceChanged";
343     case WebEvent::MouseForceDown:
344         return "MouseForceDown";
345     case WebEvent::MouseForceUp:
346         return "MouseForceUp";
347     default:
348         ASSERT_NOT_REACHED();
349         return "<unknown>";
350     }
351 }
352
353 static const char* webKeyboardEventTypeString(WebEvent::Type type)
354 {
355     switch (type) {
356     case WebEvent::KeyDown:
357         return "KeyDown";
358     case WebEvent::KeyUp:
359         return "KeyUp";
360     case WebEvent::RawKeyDown:
361         return "RawKeyDown";
362     case WebEvent::Char:
363         return "Char";
364     default:
365         ASSERT_NOT_REACHED();
366         return "<unknown>";
367     }
368 }
369 #endif // !LOG_DISABLED
370
371 class PageClientProtector {
372     WTF_MAKE_NONCOPYABLE(PageClientProtector);
373 public:
374     PageClientProtector(PageClient& pageClient)
375         : m_pageClient(makeWeakPtr(pageClient))
376     {
377         m_pageClient->refView();
378     }
379
380     ~PageClientProtector()
381     {
382         ASSERT(m_pageClient);
383         m_pageClient->derefView();
384     }
385
386 private:
387     WeakPtr<PageClient> m_pageClient;
388 };
389
390 Ref<WebPageProxy> WebPageProxy::create(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
391 {
392     return adoptRef(*new WebPageProxy(pageClient, process, pageID, WTFMove(configuration)));
393 }
394
395 WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
396     : m_pageClient(makeWeakPtr(pageClient))
397     , m_configuration(WTFMove(configuration))
398     , m_navigationClient(makeUniqueRef<API::NavigationClient>())
399     , m_historyClient(makeUniqueRef<API::HistoryClient>())
400     , m_iconLoadingClient(std::make_unique<API::IconLoadingClient>())
401     , m_formClient(std::make_unique<API::FormClient>())
402     , m_uiClient(std::make_unique<API::UIClient>())
403     , m_findClient(std::make_unique<API::FindClient>())
404     , m_findMatchesClient(std::make_unique<API::FindMatchesClient>())
405 #if ENABLE(CONTEXT_MENUS)
406     , m_contextMenuClient(std::make_unique<API::ContextMenuClient>())
407 #endif
408     , m_navigationState(std::make_unique<WebNavigationState>())
409     , m_process(process)
410     , m_pageGroup(*m_configuration->pageGroup())
411     , m_preferences(*m_configuration->preferences())
412     , m_userContentController(*m_configuration->userContentController())
413     , m_visitedLinkStore(*m_configuration->visitedLinkStore())
414     , m_websiteDataStore(m_configuration->websiteDataStore()->websiteDataStore())
415     , m_userAgent(standardUserAgent())
416     , m_overrideContentSecurityPolicy { m_configuration->overrideContentSecurityPolicy() }
417     , m_treatsSHA1CertificatesAsInsecure(m_configuration->treatsSHA1SignedCertificatesAsInsecure())
418 #if ENABLE(FULLSCREEN_API)
419     , m_fullscreenClient(std::make_unique<API::FullscreenClient>())
420 #endif
421     , m_geolocationPermissionRequestManager(*this)
422     , m_notificationPermissionRequestManager(*this)
423 #if PLATFORM(IOS_FAMILY)
424     , m_alwaysRunsAtForegroundPriority(m_configuration->alwaysRunsAtForegroundPriority())
425 #endif
426     , m_initialCapitalizationEnabled(m_configuration->initialCapitalizationEnabled())
427     , m_cpuLimit(m_configuration->cpuLimit())
428     , m_backForwardList(WebBackForwardList::create(*this))
429     , m_waitsForPaintAfterViewDidMoveToWindow(m_configuration->waitsForPaintAfterViewDidMoveToWindow())
430     , m_drawsBackground(m_configuration->drawsBackground())
431     , m_pageID(pageID)
432     , m_controlledByAutomation(m_configuration->isControlledByAutomation())
433 #if PLATFORM(COCOA)
434     , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
435 #endif
436     , m_pageLoadState(*this)
437     , m_configurationPreferenceValues(m_configuration->preferenceValues())
438     , m_inspectorController(std::make_unique<WebPageInspectorController>(*this))
439 #if ENABLE(REMOTE_INSPECTOR)
440     , m_inspectorDebuggable(std::make_unique<WebPageDebuggable>(*this))
441 #endif
442     , m_resetRecentCrashCountTimer(RunLoop::main(), this, &WebPageProxy::resetRecentCrashCount)
443 #if HAVE(PENCILKIT)
444     , m_editableImageController(std::make_unique<EditableImageController>(*this))
445 #endif
446 {
447     RELEASE_LOG_IF_ALLOWED(Loading, "constructor: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
448
449     m_webProcessLifetimeTracker.addObserver(m_visitedLinkStore);
450     m_webProcessLifetimeTracker.addObserver(m_websiteDataStore);
451
452     updateActivityState();
453     updateThrottleState();
454     updateHiddenPageThrottlingAutoIncreases();
455     
456 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
457     m_layerHostingMode = m_activityState & ActivityState::IsInWindow ? WebPageProxy::pageClient().viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
458 #endif
459
460     platformInitialize();
461
462 #ifndef NDEBUG
463     webPageProxyCounter.increment();
464 #endif
465
466     WebProcessPool::statistics().wkPageCount++;
467
468     m_preferences->addPage(*this);
469     m_pageGroup->addPage(this);
470
471     m_inspector = WebInspectorProxy::create(this);
472 #if ENABLE(FULLSCREEN_API)
473     m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, WebPageProxy::pageClient().fullScreenManagerProxyClient());
474 #endif
475 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
476     m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
477     m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
478 #endif
479
480 #if ENABLE(APPLE_PAY)
481     m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
482 #endif
483
484 #if USE(SYSTEM_PREVIEW)
485     m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
486 #endif
487
488 #if ENABLE(WEB_AUTHN)
489     m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
490 #endif
491
492     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
493
494 #if PLATFORM(IOS_FAMILY)
495     DeprecatedGlobalSettings::setDisableScreenSizeOverride(preferencesStore().getBoolValueForKey(WebPreferencesKey::disableScreenSizeOverrideKey()));
496 #endif
497
498 #if PLATFORM(COCOA)
499     m_activityStateChangeDispatcher = std::make_unique<RunLoopObserver>(static_cast<CFIndex>(RunLoopObserver::WellKnownRunLoopOrders::ActivityStateChange), [this] {
500         this->dispatchActivityStateChange();
501     });
502 #endif
503
504 #if ENABLE(REMOTE_INSPECTOR)
505     m_inspectorDebuggable->setRemoteDebuggingAllowed(true);
506     m_inspectorDebuggable->init();
507 #endif
508
509     createInspectorTargets();
510 }
511
512 WebPageProxy::~WebPageProxy()
513 {
514     RELEASE_LOG_IF_ALLOWED(Loading, "destructor: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
515
516     ASSERT(m_process->webPage(m_pageID) != this);
517 #if !ASSERT_DISABLED
518     for (WebPageProxy* page : m_process->pages())
519         ASSERT(page != this);
520 #endif
521
522     if (!m_isClosed)
523         close();
524
525     WebProcessPool::statistics().wkPageCount--;
526
527     if (m_spellDocumentTag)
528         TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag.value());
529
530     m_preferences->removePage(*this);
531     m_pageGroup->removePage(this);
532
533 #ifndef NDEBUG
534     webPageProxyCounter.decrement();
535 #endif
536 }
537
538 // FIXME: Should return a const PageClient& and add a separate non-const
539 // version of this function, but several PageClient methods will need to become
540 // const for this to be possible.
541 PageClient& WebPageProxy::pageClient() const
542 {
543     ASSERT(m_pageClient);
544     return *m_pageClient;
545 }
546
547 PAL::SessionID WebPageProxy::sessionID() const
548 {
549     return m_websiteDataStore->sessionID();
550 }
551
552 void WebPageProxy::changeWebsiteDataStore(WebsiteDataStore& websiteDataStore)
553 {
554     m_process->processPool().pageEndUsingWebsiteDataStore(*this);
555     m_websiteDataStore = websiteDataStore;
556     m_process->processPool().pageBeginUsingWebsiteDataStore(*this);
557 }
558
559 const API::PageConfiguration& WebPageProxy::configuration() const
560 {
561     return m_configuration.get();
562 }
563
564 ProcessID WebPageProxy::processIdentifier() const
565 {
566     if (m_isClosed)
567         return 0;
568
569     return m_process->processIdentifier();
570 }
571
572 bool WebPageProxy::isValid() const
573 {
574     // A page that has been explicitly closed is never valid.
575     if (m_isClosed)
576         return false;
577
578     return m_isValid;
579 }
580
581 void WebPageProxy::notifyProcessPoolToPrewarm()
582 {
583     m_process->processPool().didReachGoodTimeToPrewarm();
584 }
585
586 void WebPageProxy::setPreferences(WebPreferences& preferences)
587 {
588     if (&preferences == m_preferences.ptr())
589         return;
590
591     m_preferences->removePage(*this);
592     m_preferences = preferences;
593     m_preferences->addPage(*this);
594
595     preferencesDidChange();
596 }
597     
598 void WebPageProxy::setHistoryClient(UniqueRef<API::HistoryClient>&& historyClient)
599 {
600     m_historyClient = WTFMove(historyClient);
601 }
602
603 void WebPageProxy::setNavigationClient(UniqueRef<API::NavigationClient>&& navigationClient)
604 {
605     m_navigationClient = WTFMove(navigationClient);
606 }
607
608 void WebPageProxy::setLoaderClient(std::unique_ptr<API::LoaderClient>&& loaderClient)
609 {
610     m_loaderClient = WTFMove(loaderClient);
611 }
612
613 void WebPageProxy::setPolicyClient(std::unique_ptr<API::PolicyClient>&& policyClient)
614 {
615     m_policyClient = WTFMove(policyClient);
616 }
617
618 void WebPageProxy::setFormClient(std::unique_ptr<API::FormClient>&& formClient)
619 {
620     if (!formClient) {
621         m_formClient = std::make_unique<API::FormClient>();
622         return;
623     }
624
625     m_formClient = WTFMove(formClient);
626 }
627
628 void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient>&& uiClient)
629 {
630     if (!uiClient) {
631         m_uiClient = std::make_unique<API::UIClient>();
632         return;
633     }
634
635     m_uiClient = WTFMove(uiClient);
636
637     if (!isValid())
638         return;
639
640     m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient->canRunBeforeUnloadConfirmPanel()), m_pageID);
641     setCanRunModal(m_uiClient->canRunModal());
642     setNeedsFontAttributes(m_uiClient->needsFontAttributes());
643 }
644
645 void WebPageProxy::setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&& iconLoadingClient)
646 {
647     bool hasClient = iconLoadingClient.get();
648     if (!iconLoadingClient)
649         m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
650     else
651         m_iconLoadingClient = WTFMove(iconLoadingClient);
652
653     if (!isValid())
654         return;
655
656     m_process->send(Messages::WebPage::SetUseIconLoadingClient(hasClient), m_pageID);
657 }
658
659 void WebPageProxy::setFindClient(std::unique_ptr<API::FindClient>&& findClient)
660 {
661     if (!findClient) {
662         m_findClient = std::make_unique<API::FindClient>();
663         return;
664     }
665     
666     m_findClient = WTFMove(findClient);
667 }
668
669 void WebPageProxy::setFindMatchesClient(std::unique_ptr<API::FindMatchesClient>&& findMatchesClient)
670 {
671     if (!findMatchesClient) {
672         m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
673         return;
674     }
675
676     m_findMatchesClient = WTFMove(findMatchesClient);
677 }
678
679 void WebPageProxy::setDiagnosticLoggingClient(std::unique_ptr<API::DiagnosticLoggingClient>&& diagnosticLoggingClient)
680 {
681     m_diagnosticLoggingClient = WTFMove(diagnosticLoggingClient);
682 }
683
684 #if ENABLE(CONTEXT_MENUS)
685 void WebPageProxy::setContextMenuClient(std::unique_ptr<API::ContextMenuClient>&& contextMenuClient)
686 {
687     if (!contextMenuClient) {
688         m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
689         return;
690     }
691
692     m_contextMenuClient = WTFMove(contextMenuClient);
693 }
694 #endif
695
696 void WebPageProxy::setInjectedBundleClient(const WKPageInjectedBundleClientBase* client)
697 {
698     if (!client) {
699         m_injectedBundleClient = nullptr;
700         return;
701     }
702
703     m_injectedBundleClient = std::make_unique<WebPageInjectedBundleClient>();
704     m_injectedBundleClient->initialize(client);
705 }
706
707 void WebPageProxy::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
708 {
709     ASSERT(m_process->connection() == &connection);
710
711     if (!m_injectedBundleClient)
712         return;
713
714     m_injectedBundleClient->didReceiveMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get());
715 }
716
717 void WebPageProxy::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
718 {
719     ASSERT(m_process->connection() == &connection);
720
721     if (!m_injectedBundleClient)
722         return;
723
724     RefPtr<API::Object> returnData;
725     m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get(), returnData);
726     returnUserData = UserData(m_process->transformObjectsToHandles(returnData.get()));
727 }
728
729 void WebPageProxy::reattachToWebProcess()
730 {
731     ASSERT(!m_isClosed);
732     ASSERT(!isValid());
733
734     RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
735
736     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::Yes);
737     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
738
739     auto& processPool = m_process->processPool();
740     m_process = processPool.createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get());
741     m_isValid = true;
742
743     m_process->addExistingWebPage(*this, m_pageID, WebProcessProxy::BeginsUsingDataStore::Yes);
744     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
745
746     finishAttachingToWebProcess();
747 }
748
749 bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, Optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient processSwapRequestedByClient)
750 {
751     if (!mainFrameID)
752         return false;
753
754     // 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.
755     if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes)
756         return false;
757
758     if (isPageOpenedByDOMShowingInitialEmptyDocument())
759         return false;
760
761     auto* currentItem = navigation.fromItem();
762     if (!currentItem) {
763         LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " unable to create suspended page for process pid %i - No current back/forward item", pageID(), m_process->processIdentifier());
764         return false;
765     }
766
767     auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *currentItem, *mainFrameID);
768
769     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());
770
771     m_process->processPool().addSuspendedPage(WTFMove(suspendedPage));
772     return true;
773 }
774
775 void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, std::unique_ptr<SuspendedPageProxy>&& destinationSuspendedPage, IsSwapFromSuspended isSwapFromSuspended)
776 {
777     ASSERT(!m_isClosed);
778     RELEASE_LOG_IF_ALLOWED(Loading, "swapToWebProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
779
780     m_process = WTFMove(process);
781     m_isValid = true;
782
783     // If we are reattaching to a SuspendedPage, then the WebProcess' WebPage already exists and
784     // WebPageProxy::didCreateMainFrame() will not be called to initialize m_mainFrame. In such
785     // case, we need to initialize m_mainFrame to reflect the fact the the WebProcess' WebPage
786     // already exists and already has a main frame.
787     if (destinationSuspendedPage) {
788         if (!destinationSuspendedPage->failedToSuspend()) {
789             ASSERT(!m_mainFrame);
790             ASSERT(&destinationSuspendedPage->process() == m_process.ptr());
791             destinationSuspendedPage->unsuspend();
792             m_mainFrame = WebFrameProxy::create(*this, destinationSuspendedPage->mainFrameID());
793             m_process->frameCreated(destinationSuspendedPage->mainFrameID(), *m_mainFrame);
794         } else {
795             // We failed to suspend the page so destroy it now and merely reuse its WebContent process.
796             destinationSuspendedPage = nullptr;
797         }
798     }
799
800     m_process->addExistingWebPage(*this, m_pageID, WebProcessProxy::BeginsUsingDataStore::No);
801     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
802
803     finishAttachingToWebProcess(isSwapFromSuspended);
804 }
805
806 void WebPageProxy::finishAttachingToWebProcess(IsSwapFromSuspended isSwapFromSuspended)
807 {
808     ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
809
810     if (m_process->state() == ChildProcessProxy::State::Running) {
811         m_webProcessLifetimeTracker.webPageEnteringWebProcess();
812         processDidFinishLaunching();
813     }
814
815     updateActivityState();
816     updateThrottleState();
817
818 #if ENABLE(FULLSCREEN_API)
819     m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, pageClient().fullScreenManagerProxyClient());
820 #endif
821 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
822     m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
823     m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
824 #endif
825
826 #if ENABLE(APPLE_PAY)
827     m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
828 #endif
829
830 #if USE(SYSTEM_PREVIEW)
831     m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
832 #endif
833
834 #if ENABLE(WEB_AUTHN)
835     m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
836 #endif
837
838 #if HAVE(PENCILKIT)
839     m_editableImageController = std::make_unique<EditableImageController>(*this);
840 #endif
841
842     initializeWebPage(isSwapFromSuspended);
843
844     m_inspector->updateForNewPageProcess(this);
845
846 #if ENABLE(REMOTE_INSPECTOR)
847     remoteInspectorInformationDidChange();
848 #endif
849
850     clearInspectorTargets();
851     createInspectorTargets();
852
853     pageClient().didRelaunchProcess();
854     m_pageLoadState.didSwapWebProcesses();
855     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
856 }
857
858 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessForReload()
859 {
860     RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessForReload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
861
862     if (m_isClosed) {
863         RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessForReload: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
864         return nullptr;
865     }
866     
867     ASSERT(!isValid());
868     reattachToWebProcess();
869
870     if (!m_backForwardList->currentItem()) {
871         RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessForReload: no current item to reload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
872         return nullptr;
873     }
874
875     auto navigation = m_navigationState->createReloadNavigation();
876
877     // We allow stale content when reloading a WebProcess that's been killed or crashed.
878     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
879     m_process->responsivenessTimer().start();
880
881     return WTFMove(navigation);
882 }
883
884 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem& item)
885 {
886     RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessWithItem: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
887
888     if (m_isClosed) {
889         RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessWithItem: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
890         return nullptr;
891     }
892
893     ASSERT(!isValid());
894     reattachToWebProcess();
895
896     if (&item != m_backForwardList->currentItem())
897         m_backForwardList->goToItem(item);
898
899     auto navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), FrameLoadType::IndexedBackForward);
900
901     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item.itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
902     m_process->responsivenessTimer().start();
903
904     return WTFMove(navigation);
905 }
906
907 void WebPageProxy::initializeWebPage(IsSwapFromSuspended isSwapFromSuspended)
908 {
909     ASSERT(isValid());
910
911     m_drawingArea = pageClient().createDrawingAreaProxy();
912     ASSERT(m_drawingArea);
913
914 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
915     if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) {
916         m_scrollingCoordinatorProxy = std::make_unique<RemoteScrollingCoordinatorProxy>(*this);
917 #if PLATFORM(IOS_FAMILY)
918         // On iOS, main frame scrolls are sent in terms of visible rect updates.
919         m_scrollingCoordinatorProxy->setPropagatesMainFrameScrolls(false);
920 #endif
921     }
922 #endif
923
924     auto parameters = creationParameters();
925     parameters.isSwapFromSuspended = isSwapFromSuspended == IsSwapFromSuspended::Yes;
926
927 #if ENABLE(SERVICE_WORKER)
928     parameters.hasRegisteredServiceWorkers = process().processPool().mayHaveRegisteredServiceWorkers(m_websiteDataStore);
929 #endif
930
931     process().send(Messages::WebProcess::CreateWebPage(m_pageID, parameters), 0);
932
933     m_needsToFinishInitializingWebPageAfterProcessLaunch = true;
934     finishInitializingWebPageAfterProcessLaunch();
935 }
936
937 void WebPageProxy::finishInitializingWebPageAfterProcessLaunch()
938 {
939     if (!m_needsToFinishInitializingWebPageAfterProcessLaunch)
940         return;
941     if (m_process->state() != WebProcessProxy::State::Running)
942         return;
943
944     m_needsToFinishInitializingWebPageAfterProcessLaunch = false;
945     m_process->addVisitedLinkStore(m_visitedLinkStore);
946 }
947
948 void WebPageProxy::close()
949 {
950     if (m_isClosed)
951         return;
952
953     RELEASE_LOG_IF_ALLOWED(Loading, "close: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
954
955     m_isClosed = true;
956
957 #if ENABLE(MEDIA_STREAM)
958     m_userMediaPermissionRequestManager = nullptr;
959 #endif
960
961     reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
962
963     if (m_activePopupMenu)
964         m_activePopupMenu->cancelTracking();
965
966     if (m_controlledByAutomation) {
967         if (auto* automationSession = process().processPool().automationSession())
968             automationSession->willClosePage(*this);
969     }
970
971 #if ENABLE(CONTEXT_MENUS)
972     m_activeContextMenu = nullptr;
973 #endif
974
975     m_inspector->invalidate();
976
977     m_backForwardList->pageClosed();
978     m_inspectorController->pageClosed();
979 #if ENABLE(REMOTE_INSPECTOR)
980     m_inspectorDebuggable = nullptr;
981 #endif
982     pageClient().pageClosed();
983
984     m_process->disconnectFramesFromPage(this);
985
986     resetState(ResetStateReason::PageInvalidated);
987
988     m_loaderClient = nullptr;
989     m_navigationClient = makeUniqueRef<API::NavigationClient>();
990     m_policyClient = nullptr;
991     m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
992     m_formClient = std::make_unique<API::FormClient>();
993     m_uiClient = std::make_unique<API::UIClient>();
994     m_findClient = std::make_unique<API::FindClient>();
995     m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
996     m_diagnosticLoggingClient = nullptr;
997 #if ENABLE(CONTEXT_MENUS)
998     m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
999 #endif
1000 #if ENABLE(FULLSCREEN_API)
1001     m_fullscreenClient = std::make_unique<API::FullscreenClient>();
1002 #endif
1003
1004     m_webProcessLifetimeTracker.pageWasInvalidated();
1005
1006     m_process->processPool().removeAllSuspendedPagesForPage(*this);
1007
1008     m_process->send(Messages::WebPage::Close(), m_pageID);
1009     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::Yes);
1010     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
1011     m_process->processPool().supplement<WebNotificationManagerProxy>()->clearNotifications(this);
1012
1013     // Null out related WebPageProxy to avoid leaks.
1014     m_configuration->setRelatedPage(nullptr);
1015
1016 #if PLATFORM(IOS_FAMILY)
1017     // Make sure we don't hold a process assertion after getting closed.
1018     m_activityToken = nullptr;
1019 #endif
1020
1021     stopAllURLSchemeTasks();
1022 }
1023
1024 bool WebPageProxy::tryClose()
1025 {
1026     if (!isValid())
1027         return true;
1028
1029     RELEASE_LOG_IF_ALLOWED(Loading, "tryClose: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1030
1031     // Close without delay if the process allows it. Our goal is to terminate
1032     // the process, so we check a per-process status bit.
1033     if (m_process->isSuddenTerminationEnabled())
1034         return true;
1035
1036     m_process->send(Messages::WebPage::TryClose(), m_pageID);
1037     m_process->responsivenessTimer().start();
1038     return false;
1039 }
1040
1041 bool WebPageProxy::maybeInitializeSandboxExtensionHandle(const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
1042 {
1043     if (!url.isLocalFile())
1044         return false;
1045
1046     if (m_process->hasAssumedReadAccessToURL(url))
1047         return false;
1048
1049     // Inspector resources are in a directory with assumed access.
1050     ASSERT_WITH_SECURITY_IMPLICATION(!WebKit::isInspectorPage(*this));
1051
1052     SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, sandboxExtensionHandle);
1053     return true;
1054 }
1055
1056 #if !PLATFORM(COCOA)
1057 void WebPageProxy::addPlatformLoadParameters(LoadParameters&)
1058 {
1059 }
1060 #endif
1061
1062 RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
1063 {
1064     if (m_isClosed)
1065         return nullptr;
1066
1067     RELEASE_LOG_IF_ALLOWED(Loading, "loadRequest: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1068
1069     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
1070     loadRequestWithNavigation(navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, ShouldTreatAsContinuingLoad::No);
1071     return WTFMove(navigation);
1072 }
1073
1074 void WebPageProxy::loadRequestWithNavigation(API::Navigation& navigation, ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
1075 {
1076     ASSERT(!m_isClosed);
1077
1078     RELEASE_LOG_IF_ALLOWED(Loading, "loadRequestWithNavigation: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1079
1080     auto transaction = m_pageLoadState.transaction();
1081
1082     auto url = request.url();
1083     m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1084
1085     if (!isValid())
1086         reattachToWebProcess();
1087
1088     LoadParameters loadParameters;
1089     loadParameters.navigationID = navigation.navigationID();
1090     loadParameters.request = WTFMove(request);
1091     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
1092     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1093     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1094     loadParameters.websitePolicies = WTFMove(websitePolicies);
1095     loadParameters.lockHistory = navigation.lockHistory();
1096     loadParameters.lockBackForwardList = navigation.lockBackForwardList();
1097     loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
1098     bool createdExtension = maybeInitializeSandboxExtensionHandle(url, loadParameters.sandboxExtensionHandle);
1099     if (createdExtension)
1100         willAcquireUniversalFileReadSandboxExtension();
1101     addPlatformLoadParameters(loadParameters);
1102
1103     m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1104     m_process->responsivenessTimer().start();
1105 }
1106
1107 RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
1108 {
1109     RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1110
1111     if (m_isClosed) {
1112         RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1113         return nullptr;
1114     }
1115
1116     if (!isValid())
1117         reattachToWebProcess();
1118
1119     URL fileURL = URL(URL(), fileURLString);
1120     if (!fileURL.isLocalFile()) {
1121         RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: file is not local: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1122         return nullptr;
1123     }
1124
1125     URL resourceDirectoryURL;
1126     if (resourceDirectoryURLString.isNull())
1127         resourceDirectoryURL = URL({ }, "file:///"_s);
1128     else {
1129         resourceDirectoryURL = URL(URL(), resourceDirectoryURLString);
1130         if (!resourceDirectoryURL.isLocalFile()) {
1131             RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: resource URL is not local: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1132             return nullptr;
1133         }
1134     }
1135
1136     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL), m_backForwardList->currentItem());
1137
1138     auto transaction = m_pageLoadState.transaction();
1139
1140     m_pageLoadState.setPendingAPIRequestURL(transaction, fileURLString);
1141
1142     String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
1143
1144     LoadParameters loadParameters;
1145     loadParameters.navigationID = navigation->navigationID();
1146     loadParameters.request = fileURL;
1147     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1148     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1149     SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::Type::ReadOnly, loadParameters.sandboxExtensionHandle);
1150     addPlatformLoadParameters(loadParameters);
1151
1152     m_process->assumeReadAccessToBaseURL(*this, resourceDirectoryURL);
1153     m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1154     m_process->responsivenessTimer().start();
1155
1156     return WTFMove(navigation);
1157 }
1158
1159 RefPtr<API::Navigation> WebPageProxy::loadData(const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData)
1160 {
1161     RELEASE_LOG_IF_ALLOWED(Loading, "loadData: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1162
1163     if (m_isClosed) {
1164         RELEASE_LOG_IF_ALLOWED(Loading, "loadData: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1165         return nullptr;
1166     }
1167
1168     auto navigation = m_navigationState->createLoadDataNavigation(std::make_unique<API::SubstituteData>(data.vector(), MIMEType, encoding, baseURL, userData));
1169     loadDataWithNavigation(navigation, data, MIMEType, encoding, baseURL, userData, ShouldTreatAsContinuingLoad::No);
1170     return WTFMove(navigation);
1171 }
1172
1173 void WebPageProxy::loadDataWithNavigation(API::Navigation& navigation, const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
1174 {
1175     RELEASE_LOG_IF_ALLOWED(Loading, "loadDataWithNavigation: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1176
1177     ASSERT(!m_isClosed);
1178
1179     auto transaction = m_pageLoadState.transaction();
1180
1181     m_pageLoadState.setPendingAPIRequestURL(transaction, !baseURL.isEmpty() ? baseURL : WTF::blankURL().string());
1182
1183     if (!isValid())
1184         reattachToWebProcess();
1185
1186     LoadParameters loadParameters;
1187     loadParameters.navigationID = navigation.navigationID();
1188     loadParameters.data = data;
1189     loadParameters.MIMEType = MIMEType;
1190     loadParameters.encodingName = encoding;
1191     loadParameters.baseURLString = baseURL;
1192     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1193     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1194     loadParameters.websitePolicies = WTFMove(websitePolicies);
1195     addPlatformLoadParameters(loadParameters);
1196
1197     m_process->assumeReadAccessToBaseURL(*this, baseURL);
1198     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1199     m_process->responsivenessTimer().start();
1200 }
1201
1202 void WebPageProxy::loadAlternateHTML(const IPC::DataReference& htmlData, const String& encoding, const URL& baseURL, const URL& unreachableURL, API::Object* userData)
1203 {
1204     RELEASE_LOG_IF_ALLOWED(Loading, "loadAlternateHTML: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1205
1206     // When the UIProcess is in the process of handling a failing provisional load, do not attempt to
1207     // start a second alternative HTML load as this will prevent the page load state from being
1208     // handled properly.
1209     if (m_isClosed || m_isLoadingAlternateHTMLStringForFailingProvisionalLoad) {
1210         RELEASE_LOG_IF_ALLOWED(Loading, "loadAlternateHTML: page is closed (or other): webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1211         return;
1212     }
1213
1214     if (!m_failingProvisionalLoadURL.isEmpty())
1215         m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = true;
1216
1217     if (!isValid())
1218         reattachToWebProcess();
1219
1220     auto transaction = m_pageLoadState.transaction();
1221
1222     m_pageLoadState.setPendingAPIRequestURL(transaction, unreachableURL);
1223     m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
1224
1225     if (m_mainFrame)
1226         m_mainFrame->setUnreachableURL(unreachableURL);
1227
1228     LoadParameters loadParameters;
1229     loadParameters.navigationID = 0;
1230     loadParameters.data = htmlData;
1231     loadParameters.MIMEType = "text/html"_s;
1232     loadParameters.encodingName = encoding;
1233     loadParameters.baseURLString = baseURL;
1234     loadParameters.unreachableURLString = unreachableURL;
1235     loadParameters.provisionalLoadErrorURLString = m_failingProvisionalLoadURL;
1236     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1237     addPlatformLoadParameters(loadParameters);
1238
1239     m_process->assumeReadAccessToBaseURL(*this, baseURL);
1240     m_process->assumeReadAccessToBaseURL(*this, unreachableURL);
1241     m_process->send(Messages::WebPage::LoadAlternateHTML(loadParameters), m_pageID);
1242     m_process->responsivenessTimer().start();
1243 }
1244
1245 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
1246 {
1247     RELEASE_LOG_IF_ALLOWED(Loading, "loadWebArchiveData: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1248
1249     if (m_isClosed) {
1250         RELEASE_LOG_IF_ALLOWED(Loading, "loadWebArchiveData: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1251         return;
1252     }
1253
1254     if (!isValid())
1255         reattachToWebProcess();
1256
1257     auto transaction = m_pageLoadState.transaction();
1258     m_pageLoadState.setPendingAPIRequestURL(transaction, WTF::blankURL().string());
1259
1260     LoadParameters loadParameters;
1261     loadParameters.navigationID = 0;
1262     loadParameters.data = webArchiveData->dataReference();
1263     loadParameters.MIMEType = "application/x-webarchive"_s;
1264     loadParameters.encodingName = "utf-16"_s;
1265     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1266     addPlatformLoadParameters(loadParameters);
1267
1268     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1269     m_process->responsivenessTimer().start();
1270 }
1271
1272 void WebPageProxy::navigateToPDFLinkWithSimulatedClick(const String& url, IntPoint documentPoint, IntPoint screenPoint)
1273 {
1274     RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1275
1276     if (m_isClosed) {
1277         RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1278         return;
1279     }
1280
1281     if (WTF::protocolIsJavaScript(url))
1282         return;
1283
1284     if (!isValid())
1285         reattachToWebProcess();
1286
1287     m_process->send(Messages::WebPage::NavigateToPDFLinkWithSimulatedClick(url, documentPoint, screenPoint), m_pageID);
1288     m_process->responsivenessTimer().start();
1289 }
1290
1291 void WebPageProxy::stopLoading()
1292 {
1293     RELEASE_LOG_IF_ALLOWED(Loading, "stopLoading: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1294
1295     if (!isValid()) {
1296         RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: page is not valid: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1297         return;
1298     }
1299
1300     m_process->send(Messages::WebPage::StopLoading(), m_pageID);
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(URL(URL(), url), sandboxExtensionHandle);
1317         if (createdExtension)
1318             willAcquireUniversalFileReadSandboxExtension();
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)
2098 {
2099     MESSAGE_CHECK(dragOperation <= DragOperationDelete);
2100
2101     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
2102     m_currentDragHandlingMethod = dragHandlingMethod;
2103     m_currentDragIsOverFileInput = mouseIsOverFileInput;
2104     m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
2105     setDragCaretRect(insertionRect);
2106 }
2107
2108 #if PLATFORM(GTK)
2109 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
2110 {
2111     RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
2112     pageClient().startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
2113
2114     didStartDrag();
2115 }
2116 #endif
2117
2118 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
2119 {
2120     if (!isValid())
2121         return;
2122     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
2123     setDragCaretRect({ });
2124 }
2125
2126 void WebPageProxy::didPerformDragOperation(bool handled)
2127 {
2128     pageClient().didPerformDragOperation(handled);
2129 }
2130
2131 void WebPageProxy::didStartDrag()
2132 {
2133     if (isValid())
2134         m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
2135 }
2136     
2137 void WebPageProxy::dragCancelled()
2138 {
2139     if (isValid())
2140         m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
2141 }
2142
2143 void WebPageProxy::didEndDragging()
2144 {
2145     resetCurrentDragInformation();
2146 }
2147
2148 void WebPageProxy::resetCurrentDragInformation()
2149 {
2150     m_currentDragOperation = WebCore::DragOperationNone;
2151     m_currentDragHandlingMethod = DragHandlingMethod::None;
2152     m_currentDragIsOverFileInput = false;
2153     m_currentDragNumberOfFilesToBeAccepted = 0;
2154     setDragCaretRect({ });
2155 }
2156
2157 #if !ENABLE(DATA_INTERACTION)
2158
2159 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
2160 {
2161     m_currentDragCaretRect = dragCaretRect;
2162 }
2163
2164 #endif
2165
2166 #endif // ENABLE(DRAG_SUPPORT)
2167
2168 static bool removeOldRedundantEvent(Deque<NativeWebMouseEvent>& queue, WebEvent::Type incomingEventType)
2169 {
2170     if (incomingEventType != WebEvent::MouseMove && incomingEventType != WebEvent::MouseForceChanged)
2171         return false;
2172
2173     auto it = queue.rbegin();
2174     auto end = queue.rend();
2175
2176     // Must not remove the first event in the deque, since it is already being dispatched.
2177     if (it != end)
2178         --end;
2179
2180     for (; it != end; ++it) {
2181         auto type = it->type();
2182         if (type == incomingEventType) {
2183             queue.remove(--it.base());
2184             return true;
2185         }
2186         if (type != WebEvent::MouseMove && type != WebEvent::MouseForceChanged)
2187             break;
2188     }
2189     return false;
2190 }
2191
2192 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
2193 {
2194     if (!isValid())
2195         return;
2196
2197 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2198     if (m_scrollingCoordinatorProxy)
2199         m_scrollingCoordinatorProxy->handleMouseEvent(platform(event));
2200 #endif
2201
2202     // If we receive multiple mousemove or mouseforcechanged events and the most recent mousemove or mouseforcechanged event
2203     // (respectively) has not yet been sent to WebProcess for processing, remove the pending mouse event and insert the new
2204     // event in the queue.
2205     bool didRemoveEvent = removeOldRedundantEvent(m_mouseEventQueue, event.type());
2206     m_mouseEventQueue.append(event);
2207
2208 #if LOG_DISABLED
2209     UNUSED_PARAM(didRemoveEvent);
2210 #else
2211     LOG(MouseHandling, "UIProcess: %s mouse event %s (queue size %zu)", didRemoveEvent ? "replaced" : "enqueued", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2212 #endif
2213
2214     if (m_mouseEventQueue.size() == 1) // Otherwise, called from DidReceiveEvent message handler.
2215         processNextQueuedMouseEvent();
2216 }
2217     
2218 void WebPageProxy::processNextQueuedMouseEvent()
2219 {
2220     if (!isValid())
2221         return;
2222
2223     ASSERT(!m_mouseEventQueue.isEmpty());
2224
2225     const NativeWebMouseEvent& event = m_mouseEventQueue.first();
2226     
2227     if (pageClient().windowIsFrontWindowUnderMouse(event))
2228         setToolTip(String());
2229
2230     // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
2231     if (event.type() != WebEvent::MouseMove)
2232         m_process->responsivenessTimer().start();
2233
2234     LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2235     m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
2236 }
2237
2238 #if MERGE_WHEEL_EVENTS
2239 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2240 {
2241     if (a.position() != b.position())
2242         return false;
2243     if (a.globalPosition() != b.globalPosition())
2244         return false;
2245     if (a.modifiers() != b.modifiers())
2246         return false;
2247     if (a.granularity() != b.granularity())
2248         return false;
2249 #if PLATFORM(COCOA)
2250     if (a.phase() != b.phase())
2251         return false;
2252     if (a.momentumPhase() != b.momentumPhase())
2253         return false;
2254     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
2255         return false;
2256 #endif
2257
2258     return true;
2259 }
2260
2261 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2262 {
2263     ASSERT(canCoalesce(a, b));
2264
2265     FloatSize mergedDelta = a.delta() + b.delta();
2266     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
2267
2268 #if PLATFORM(COCOA)
2269     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
2270
2271     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());
2272 #else
2273     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
2274 #endif
2275 }
2276 #endif // MERGE_WHEEL_EVENTS
2277
2278 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
2279 {
2280     ASSERT(!queue.isEmpty());
2281     ASSERT(coalescedEvents.isEmpty());
2282
2283 #if MERGE_WHEEL_EVENTS
2284     NativeWebWheelEvent firstEvent = queue.takeFirst();
2285     coalescedEvents.append(firstEvent);
2286
2287     WebWheelEvent event = firstEvent;
2288     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
2289         NativeWebWheelEvent firstEvent = queue.takeFirst();
2290         coalescedEvents.append(firstEvent);
2291         event = coalesce(event, firstEvent);
2292     }
2293
2294     return event;
2295 #else
2296     while (!queue.isEmpty())
2297         coalescedEvents.append(queue.takeFirst());
2298     return coalescedEvents.last();
2299 #endif
2300 }
2301
2302 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
2303 {
2304 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2305     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
2306         return;
2307 #endif
2308
2309     if (!isValid())
2310         return;
2311
2312     closeOverlayedViews();
2313
2314     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
2315         m_wheelEventQueue.append(event);
2316         if (!shouldProcessWheelEventNow(event))
2317             return;
2318         // The queue has too many wheel events, so push a new event.
2319     }
2320
2321     if (!m_wheelEventQueue.isEmpty()) {
2322         processNextQueuedWheelEvent();
2323         return;
2324     }
2325
2326     auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2327     coalescedWheelEvent->append(event);
2328     m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
2329     sendWheelEvent(event);
2330 }
2331
2332 void WebPageProxy::processNextQueuedWheelEvent()
2333 {
2334     auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2335     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
2336     m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
2337     sendWheelEvent(nextWheelEvent);
2338 }
2339
2340 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
2341 {
2342     m_process->send(
2343         Messages::EventDispatcher::WheelEvent(
2344             m_pageID,
2345             event,
2346             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
2347             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
2348             rubberBandsAtTop(),
2349             rubberBandsAtBottom()
2350         ), 0);
2351
2352     // Manually ping the web process to check for responsiveness since our wheel
2353     // event will dispatch to a non-main thread, which always responds.
2354     m_process->isResponsive(nullptr);
2355 }
2356
2357 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
2358 {
2359 #if PLATFORM(GTK)
2360     // Don't queue events representing a non-trivial scrolling phase to
2361     // avoid having them trapped in the queue, potentially preventing a
2362     // scrolling session to beginning or end correctly.
2363     // This is only needed by platforms whose WebWheelEvent has this phase
2364     // information (Cocoa and GTK+) but Cocoa was fine without it.
2365     if (event.phase() == WebWheelEvent::Phase::PhaseNone
2366         || event.phase() == WebWheelEvent::Phase::PhaseChanged
2367         || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
2368         || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
2369         return true;
2370 #else
2371     UNUSED_PARAM(event);
2372 #endif
2373     if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
2374         return true;
2375     return false;
2376 }
2377
2378 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
2379 {
2380     if (!isValid())
2381         return;
2382     
2383     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
2384
2385     m_keyEventQueue.append(event);
2386
2387     m_process->responsivenessTimer().start();
2388     if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
2389         LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
2390         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2391     }
2392 }
2393
2394 WebPreferencesStore WebPageProxy::preferencesStore() const
2395 {
2396     if (m_configurationPreferenceValues.isEmpty())
2397         return m_preferences->store();
2398
2399     WebPreferencesStore store = m_preferences->store();
2400     for (const auto& preference : m_configurationPreferenceValues)
2401         store.m_values.set(preference.key, preference.value);
2402
2403     return store;
2404 }
2405
2406 #if ENABLE(NETSCAPE_PLUGIN_API)
2407 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)
2408 {
2409     PageClientProtector protector(pageClient());
2410
2411     MESSAGE_CHECK_URL(urlString);
2412
2413     URL pluginURL = URL { URL(), urlString };
2414     String newMimeType = mimeType.convertToASCIILowercase();
2415
2416     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2417
2418     URL pageURL = URL { URL(), pageURLString };
2419     if (!m_process->processPool().pluginInfoStore().isSupportedPlugin(mimeType, pluginURL, frameURLString, pageURL)) {
2420         reply(0, newMimeType, PluginModuleLoadNormally, { }, true);
2421         return;
2422     }
2423
2424     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, pluginURL, allowedPluginTypes);
2425     if (!plugin.path) {
2426         reply(0, newMimeType, PluginModuleLoadNormally, { }, false);
2427         return;
2428     }
2429
2430     uint32_t pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2431
2432 #if PLATFORM(COCOA)
2433     auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2434 #endif
2435
2436     auto findPluginCompletion = [processType, reply = WTFMove(reply), newMimeType = WTFMove(newMimeType), plugin = WTFMove(plugin)] (uint32_t pluginLoadPolicy, const String& unavailabilityDescription) mutable {
2437         PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2438         switch (pluginLoadPolicy) {
2439         case PluginModuleLoadNormally:
2440             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2441             break;
2442         case PluginModuleLoadUnsandboxed:
2443             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2444             break;
2445
2446         case PluginModuleBlockedForSecurity:
2447         case PluginModuleBlockedForCompatibility:
2448             reply(0, newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2449             return;
2450         }
2451
2452         reply(PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy), newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2453     };
2454
2455 #if PLATFORM(COCOA)
2456     m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), WTFMove(findPluginCompletion));
2457 #else
2458     findPluginCompletion(pluginLoadPolicy, { });
2459 #endif
2460 }
2461
2462 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2463
2464 #if ENABLE(TOUCH_EVENTS)
2465
2466 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2467 {
2468     if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2469         return b;
2470     return a;
2471 }
2472
2473 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2474 {
2475 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2476     const EventNames& names = eventNames();
2477     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2478         IntPoint location = touchPoint.location();
2479         auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
2480             if (trackingType == TrackingType::Synchronous)
2481                 return;
2482
2483             TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2484
2485             trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2486         };
2487         updateTrackingType(m_touchAndPointerEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2488         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.touchstartEvent);
2489         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.touchmoveEvent);
2490         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.touchendEvent);
2491         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointerdownEvent);
2492         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.pointermoveEvent);
2493         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointerupEvent);
2494     }
2495 #else
2496     UNUSED_PARAM(touchStartEvent);
2497     m_touchAndPointerEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2498     m_touchAndPointerEventTracking.touchStartTracking = TrackingType::Synchronous;
2499     m_touchAndPointerEventTracking.touchMoveTracking = TrackingType::Synchronous;
2500     m_touchAndPointerEventTracking.touchEndTracking = TrackingType::Synchronous;
2501 #endif // ENABLE(ASYNC_SCROLLING)
2502 }
2503
2504 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2505 {
2506     // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2507     //
2508     // Touch events define a sequence with strong dependencies. For example, we can expect
2509     // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2510     // the two.
2511     //
2512     // WebCore should not have to set up its state correctly after some events were dismissed.
2513     // For example, we don't want to send a TouchMoved without a TouchPressed.
2514     // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2515     TrackingType globalTrackingType = m_touchAndPointerEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2516
2517     globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchForceChangedTracking);
2518     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2519         switch (touchPoint.state()) {
2520         case WebPlatformTouchPoint::TouchReleased:
2521             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchEndTracking);
2522             break;
2523         case WebPlatformTouchPoint::TouchPressed:
2524             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchStartTracking);
2525             break;
2526         case WebPlatformTouchPoint::TouchMoved:
2527         case WebPlatformTouchPoint::TouchStationary:
2528             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchMoveTracking);
2529             break;
2530         case WebPlatformTouchPoint::TouchCancelled:
2531             globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2532             break;
2533         }
2534     }
2535
2536     return globalTrackingType;
2537 }
2538
2539 #endif
2540
2541 #if ENABLE(MAC_GESTURE_EVENTS)
2542 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2543 {
2544     if (!isValid())
2545         return;
2546
2547     m_gestureEventQueue.append(event);
2548     // FIXME: Consider doing some coalescing here.
2549     m_process->responsivenessTimer().start();
2550
2551     m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2552 }
2553 #endif
2554
2555 #if ENABLE(IOS_TOUCH_EVENTS)
2556 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2557 {
2558     if (!isValid())
2559         return;
2560
2561     TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2562
2563     updateTouchEventTracking(event);
2564
2565     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2566     if (touchEventsTrackingType == TrackingType::NotTracking)
2567         return;
2568
2569     if (touchEventsTrackingType == TrackingType::Asynchronous) {
2570         // We can end up here if a native gesture has not started but the event handlers are passive.
2571         //
2572         // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2573         // can prevent a native gesture.
2574         // But, here we know that all events handlers that can handle this events are passive.
2575         // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2576         event.setCanPreventNativeGestures(false);
2577         handleTouchEventAsynchronously(event);
2578         didReceiveEvent(event.type(), false);
2579         return;
2580     }
2581
2582     m_process->responsivenessTimer().start();
2583     bool handled = false;
2584     bool replyReceived = m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID, 1_s);
2585     // 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.
2586     if (!replyReceived)
2587         handled = true;
2588     didReceiveEvent(event.type(), handled);
2589     pageClient().doneWithTouchEvent(event, handled);
2590     m_process->responsivenessTimer().stop();
2591
2592     if (event.allTouchPointsAreReleased())
2593         m_touchAndPointerEventTracking.reset();
2594 }
2595
2596 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2597 {
2598     if (!isValid())
2599         return;
2600
2601     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2602     if (touchEventsTrackingType == TrackingType::NotTracking)
2603         return;
2604
2605     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2606
2607     if (event.allTouchPointsAreReleased())
2608         m_touchAndPointerEventTracking.reset();
2609 }
2610
2611 #elif ENABLE(TOUCH_EVENTS)
2612 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2613 {
2614     if (!isValid())
2615         return;
2616
2617     updateTouchEventTracking(event);
2618
2619     if (touchEventTrackingType(event) == TrackingType::NotTracking)
2620         return;
2621
2622     // If the page is suspended, which should be the case during panning, pinching
2623     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2624     // we do not send any of the events to the page even if is has listeners.
2625     if (!m_isPageSuspended) {
2626         m_touchEventQueue.append(event);
2627         m_process->responsivenessTimer().start();
2628         m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2629     } else {
2630         if (m_touchEventQueue.isEmpty()) {
2631             bool isEventHandled = false;
2632             pageClient().doneWithTouchEvent(event, isEventHandled);
2633         } else {
2634             // We attach the incoming events to the newest queued event so that all
2635             // the events are delivered in the correct order when the event is dequed.
2636             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2637             lastEvent.deferredTouchEvents.append(event);
2638         }
2639     }
2640
2641     if (event.allTouchPointsAreReleased())
2642         m_touchAndPointerEventTracking.reset();
2643 }
2644 #endif // ENABLE(TOUCH_EVENTS)
2645
2646 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2647 {
2648     if (!isValid())
2649         return;
2650
2651     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2652 }
2653
2654 void WebPageProxy::centerSelectionInVisibleArea()
2655 {
2656     if (!isValid())
2657         return;
2658
2659     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2660 }
2661
2662 class WebPageProxy::PolicyDecisionSender : public RefCounted<PolicyDecisionSender> {
2663 public:
2664     using SendFunction = CompletionHandler<void(WebPolicyAction, uint64_t newNavigationID, DownloadID, Optional<WebsitePoliciesData>)>;
2665     static Ref<PolicyDecisionSender> create(SendFunction&& sendFunction)
2666     {
2667         return adoptRef(*new PolicyDecisionSender(WTFMove(sendFunction)));
2668     }
2669
2670     template<typename... Args> void send(Args... args)
2671     {
2672         if (m_sendFunction)
2673             m_sendFunction(std::forward<Args>(args)...);
2674     }
2675 private:
2676     PolicyDecisionSender(SendFunction sendFunction)
2677         : m_sendFunction(WTFMove(sendFunction)) { }
2678
2679     SendFunction m_sendFunction;
2680 };
2681
2682 void WebPageProxy::receivedNavigationPolicyDecision(WebPolicyAction policyAction, API::Navigation* navigation, ProcessSwapRequestedByClient processSwapRequestedByClient, WebFrameProxy& frame, API::WebsitePolicies* policies, Ref<PolicyDecisionSender>&& sender)
2683 {
2684     Optional<WebsitePoliciesData> data;
2685     if (policies) {
2686         data = policies->data();
2687         if (policies->websiteDataStore())
2688             changeWebsiteDataStore(policies->websiteDataStore()->websiteDataStore());
2689     }
2690
2691     if (policyAction != WebPolicyAction::Use || !frame.isMainFrame() || !navigation) {
2692         receivedPolicyDecision(policyAction, navigation, WTFMove(data), WTFMove(sender));
2693         return;
2694     }
2695
2696     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 {
2697         // If the navigation has been destroyed, then no need to proceed.
2698         if (isClosed() || !navigationState().hasNavigation(navigation->navigationID())) {
2699             receivedPolicyDecision(policyAction, navigation.ptr(), WTFMove(data), WTFMove(sender));
2700             return;
2701         }
2702
2703         if (processForNavigation.ptr() != &process()) {
2704             policyAction = isPageOpenedByDOMShowingInitialEmptyDocument() ? WebPolicyAction::Ignore : WebPolicyAction::Suspend;
2705             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction, swapping process %i with process %i for navigation, reason: %{public}s", processIdentifier(), processForNavigation->processIdentifier(), reason.utf8().data());
2706             LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), processForNavigation->processIdentifier(), navigation->navigationID(), navigation->loggingString());
2707         } else
2708             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction: keep using process %i for navigation, reason: %{public}s", processIdentifier(), reason.utf8().data());
2709
2710         bool shouldProcessSwap = processForNavigation.ptr() != &process();
2711         receivedPolicyDecision(policyAction, navigation.ptr(), shouldProcessSwap ? WTF::nullopt : WTFMove(data), WTFMove(sender));
2712
2713         if (shouldProcessSwap)
2714             continueNavigationInNewProcess(navigation, destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr, WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
2715     });
2716 }
2717
2718 void WebPageProxy::receivedPolicyDecision(WebPolicyAction action, API::Navigation* navigation, Optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender)
2719 {
2720     if (!isValid()) {
2721         sender->send(WebPolicyAction::Ignore, 0, DownloadID(), WTF::nullopt);
2722         return;
2723     }
2724
2725     auto transaction = m_pageLoadState.transaction();
2726
2727     if (action == WebPolicyAction::Ignore)
2728         m_pageLoadState.clearPendingAPIRequestURL(transaction);
2729
2730     if (navigation && navigation->shouldForceDownload() && action == WebPolicyAction::Use)
2731         action = WebPolicyAction::Download;
2732
2733     DownloadID downloadID = { };
2734     if (action == WebPolicyAction::Download) {
2735         // Create a download proxy.
2736         auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
2737         if (navigation) {
2738             download->setWasUserInitiated(navigation->wasUserInitiated());
2739             download->setRedirectChain(navigation->takeRedirectChain());
2740         }
2741
2742         downloadID = download->downloadID();
2743         handleDownloadRequest(download);
2744         m_decidePolicyForResponseRequest = { };
2745     }
2746
2747     sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
2748 }
2749
2750 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& process, ProcessSwapRequestedByClient processSwapRequestedByClient, Optional<WebsitePoliciesData>&& websitePolicies)
2751 {
2752     RELEASE_LOG_IF_ALLOWED(Loading, "continueNavigationInNewProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
2753     LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
2754
2755     Ref<WebProcessProxy> previousProcess = m_process.copyRef();
2756     Optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? makeOptional(m_mainFrame->frameID()) : WTF::nullopt;
2757     auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : URL();
2758
2759     ASSERT(m_process.ptr() != process.ptr());
2760
2761     processDidTerminate(ProcessTerminationReason::NavigationSwap);
2762
2763     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
2764     bool didSuspendPreviousPage = suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess, processSwapRequestedByClient);
2765     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::No);
2766
2767     swapToWebProcess(WTFMove(process), WTFMove(suspendedPageProxy), didSuspendPreviousPage ? IsSwapFromSuspended::Yes : IsSwapFromSuspended::No);
2768
2769     if (auto* item = navigation.targetItem()) {
2770         LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
2771
2772         auto transaction = m_pageLoadState.transaction();
2773         m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
2774
2775         auto itemStates = m_backForwardList->filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
2776             if (auto* page = item.suspendedPage()) {
2777                 if (&page->process() == m_process.ptr())
2778                     return false;
2779             }
2780             return &item != targetItem;
2781         });
2782         m_process->send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)), m_pageID);
2783         m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item->itemID(), *navigation.backForwardFrameLoadType(), ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies)), m_pageID);
2784         m_process->responsivenessTimer().start();
2785
2786         return;
2787     }
2788
2789     if (m_backForwardList->currentItem() && (navigation.lockBackForwardList() == LockBackForwardList::Yes || navigation.lockHistory() == LockHistory::Yes)) {
2790         // 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
2791         // it instead of creating a new one.
2792         m_process->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
2793     }
2794
2795     // FIXME: Work out timing of responding with the last policy delegate, etc
2796     ASSERT(!navigation.currentRequest().isEmpty());
2797     if (auto& substituteData = navigation.substituteData())
2798         loadDataWithNavigation(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get(), ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
2799     else
2800         loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
2801
2802     ASSERT(!m_mainFrame);
2803     m_mainFrameCreationHandler = [this, weakThis = makeWeakPtr(*this), navigationID = navigation.navigationID(), request =  navigation.currentRequest(), mainFrameURL, isServerRedirect = navigation.currentRequestIsRedirect()]() mutable {
2804         if (!weakThis)
2805             return;
2806
2807         ASSERT(m_mainFrame);
2808         // This navigation was destroyed so no need to notify of redirect.
2809         if (!navigationState().navigation(navigationID))
2810             return;
2811
2812         // Restore the main frame's committed URL as some clients may rely on it until the next load is committed.
2813         m_mainFrame->frameLoadState().setURL(mainFrameURL);
2814
2815         // Normally, notification of a server redirect comes from the WebContent process.
2816         // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
2817         // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
2818         if (isServerRedirect) {
2819             m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
2820             didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigationID, WTFMove(request), { });
2821         }
2822     };
2823
2824     if (!m_process->processPool().configuration().processSwapsOnWindowOpenWithOpener() || !isPageOpenedByDOMShowingInitialEmptyDocument() || !mainFrameIDInPreviousProcess) {
2825         // There is no way we'll be able to return to the page in the previous page so close it.
2826         if (!didSuspendPreviousPage)
2827             previousProcess->send(Messages::WebPage::Close(), m_pageID);
2828         return;
2829     }
2830
2831     m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess = *mainFrameIDInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) {
2832         ASSERT(m_mainFrame);
2833         GlobalFrameIdentifier navigatedFrameIdentifierInNewProcess { pageID(), m_mainFrame->frameID() };
2834         previousProcess->send(Messages::WebPage::FrameBecameRemote(mainFrameIDInPreviousProcess, navigatedFrameIdentifierInNewProcess, windowIdentifier), pageID());
2835     };
2836 }
2837
2838 bool WebPageProxy::isPageOpenedByDOMShowingInitialEmptyDocument() const
2839 {
2840     return openedByDOM() && !hasCommittedAnyProvisionalLoads();
2841 }
2842
2843 // MSVC gives a redeclaration error if noreturn is used on the definition and not the declaration, while
2844 // Cocoa tests segfault if it is moved to the declaration site (even if we move the definition with it!).
2845 #if !COMPILER(MSVC)
2846 NO_RETURN_DUE_TO_ASSERT
2847 #endif
2848 void WebPageProxy::didFailToSuspendAfterProcessSwap()
2849 {
2850     // Only the SuspendedPageProxy should be getting this call.
2851     ASSERT_NOT_REACHED();
2852 }
2853
2854 #if !COMPILER(MSVC)
2855 NO_RETURN_DUE_TO_ASSERT
2856 #endif
2857 void WebPageProxy::didSuspendAfterProcessSwap()
2858 {
2859     // Only the SuspendedPageProxy should be getting this call.
2860     ASSERT_NOT_REACHED();
2861 }
2862
2863 void WebPageProxy::setUserAgent(String&& userAgent)
2864 {
2865     if (m_userAgent == userAgent)
2866         return;
2867     m_userAgent = WTFMove(userAgent);
2868
2869 #if ENABLE(SERVICE_WORKER)
2870     // We update the service worker there at the moment to be sure we use values used by actual web pages.
2871     // FIXME: Refactor this when we have a better User-Agent story.
2872     process().processPool().updateServiceWorkerUserAgent(m_userAgent);
2873 #endif
2874
2875     if (!isValid())
2876         return;
2877     m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
2878 }
2879
2880 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
2881 {
2882     if (m_applicationNameForUserAgent == applicationName)
2883         return;
2884
2885     m_applicationNameForUserAgent = applicationName;
2886     if (!m_customUserAgent.isEmpty())
2887         return;
2888
2889     setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2890 }
2891
2892 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
2893 {
2894     if (m_customUserAgent == customUserAgent)
2895         return;
2896
2897     m_customUserAgent = customUserAgent;
2898
2899     if (m_customUserAgent.isEmpty()) {
2900         setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2901         return;
2902     }
2903
2904     setUserAgent(String { m_customUserAgent });
2905 }
2906
2907 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
2908 {
2909     if (!isValid() || !m_isPageSuspended)
2910         return;
2911
2912     m_isPageSuspended = false;
2913
2914     m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
2915 }
2916
2917 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
2918 {
2919     if (!isValid() || m_isPageSuspended)
2920         return;
2921
2922     m_isPageSuspended = true;
2923
2924     m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
2925 }
2926
2927 bool WebPageProxy::supportsTextEncoding() const
2928 {
2929     // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
2930     return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
2931 }
2932
2933 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
2934 {
2935     if (m_customTextEncodingName == encodingName)
2936         return;
2937     m_customTextEncodingName = encodingName;
2938
2939     if (!isValid())
2940         return;
2941     m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
2942 }
2943
2944 SessionState WebPageProxy::sessionState(WTF::Function<bool (WebBackForwardListItem&)>&& filter) const
2945 {
2946     SessionState sessionState;
2947
2948     sessionState.backForwardListState = m_backForwardList->backForwardListState(WTFMove(filter));
2949
2950     String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
2951     if (provisionalURLString.isEmpty())
2952         provisionalURLString = m_pageLoadState.provisionalURL();
2953
2954     if (!provisionalURLString.isEmpty())
2955         sessionState.provisionalURL = URL(URL(), provisionalURLString);
2956
2957     sessionState.renderTreeSize = renderTreeSize();
2958     return sessionState;
2959 }
2960
2961 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
2962 {
2963     RELEASE_LOG_IF_ALLOWED(Loading, "restoreFromSessionState: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
2964
2965     m_sessionRestorationRenderTreeSize = 0;
2966     m_hitRenderTreeSizeThreshold = false;
2967
2968     bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
2969
2970     if (hasBackForwardList) {
2971         m_backForwardList->restoreFromState(WTFMove(sessionState.backForwardListState));
2972         process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
2973
2974         auto transaction = m_pageLoadState.transaction();
2975         m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
2976         m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
2977
2978         // The back / forward list was restored from a sessionState so we don't want to snapshot the current
2979         // page when navigating away. Suppress navigation snapshotting until the next load has committed
2980         suppressNextAutomaticNavigationSnapshot();
2981     }
2982
2983     // FIXME: Navigating should be separate from state restoration.
2984     if (navigate) {
2985         m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
2986         if (!m_sessionRestorationRenderTreeSize)
2987             m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
2988
2989         if (!sessionState.provisionalURL.isNull())
2990             return loadRequest(sessionState.provisionalURL);
2991
2992         if (hasBackForwardList) {
2993             if (WebBackForwardListItem* item = m_backForwardList->currentItem())
2994                 return goToBackForwardItem(*item);
2995         }
2996     }
2997
2998     return nullptr;
2999 }
3000
3001 bool WebPageProxy::supportsTextZoom() const
3002 {
3003     // FIXME (118840): This should also return false for standalone media and plug-in documents.
3004     if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
3005         return false;
3006
3007     return true;
3008 }
3009  
3010 void WebPageProxy::setTextZoomFactor(double zoomFactor)
3011 {
3012     if (!isValid())
3013         return;
3014
3015     if (m_textZoomFactor == zoomFactor)
3016         return;
3017
3018     m_textZoomFactor = zoomFactor;
3019     m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID); 
3020 }
3021
3022 void WebPageProxy::setPageZoomFactor(double zoomFactor)
3023 {
3024     if (!isValid())
3025         return;
3026
3027     if (m_pageZoomFactor == zoomFactor)
3028         return;
3029
3030     closeOverlayedViews();
3031
3032     m_pageZoomFactor = zoomFactor;
3033     m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID); 
3034 }
3035
3036 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
3037 {
3038     if (!isValid())
3039         return;
3040
3041     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
3042         return;
3043
3044     closeOverlayedViews();
3045
3046     m_pageZoomFactor = pageZoomFactor;
3047     m_textZoomFactor = textZoomFactor;
3048     m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID); 
3049 }
3050
3051 double WebPageProxy::pageZoomFactor() const
3052 {
3053     // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
3054     // zoom which ensures that we don't use the PDF zoom for a normal page.
3055     if (m_mainFramePluginHandlesPageScaleGesture)
3056         return m_pluginZoomFactor;
3057     return m_pageZoomFactor;
3058 }
3059
3060 double WebPageProxy::pageScaleFactor() const
3061 {
3062     // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
3063     // separately but decide which to return based on the main frame.
3064     if (m_mainFramePluginHandlesPageScaleGesture)
3065         return m_pluginScaleFactor;
3066     return m_pageScaleFactor;
3067 }
3068
3069 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
3070 {
3071     ASSERT(scale > 0);
3072
3073     if (!isValid())
3074         return;
3075
3076     m_pageScaleFactor = scale;
3077     m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
3078 }
3079
3080 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
3081 {
3082     ASSERT(scale > 0);
3083
3084     if (!isValid())
3085         return;
3086
3087     m_pageScaleFactor = scale;
3088     m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
3089 }
3090
3091 void WebPageProxy::scaleView(double scale)
3092 {
3093     ASSERT(scale > 0);
3094
3095     if (!isValid())
3096         return;
3097
3098     m_viewScaleFactor = scale;
3099     m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
3100 }
3101
3102 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
3103 {
3104     if (m_intrinsicDeviceScaleFactor == scaleFactor)
3105         return;
3106
3107     m_intrinsicDeviceScaleFactor = scaleFactor;
3108
3109     if (m_drawingArea)
3110         m_drawingArea->deviceScaleFactorDidChange();
3111 }
3112
3113 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
3114 {
3115     if (!isValid())
3116         return;
3117
3118     m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
3119 }
3120
3121 float WebPageProxy::deviceScaleFactor() const
3122 {
3123     return m_customDeviceScaleFactor.valueOr(m_intrinsicDeviceScaleFactor);
3124 }
3125
3126 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
3127 {
3128     if (!isValid())
3129         return;
3130
3131     // FIXME: Remove this once we bump cairo requirements to support HiDPI.
3132     // https://bugs.webkit.org/show_bug.cgi?id=133378
3133 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
3134     return;
3135 #endif
3136
3137     if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
3138         return;
3139
3140     float oldScaleFactor = deviceScaleFactor();
3141
3142     // A value of 0 clears the customScaleFactor.
3143     if (customScaleFactor)
3144         m_customDeviceScaleFactor = customScaleFactor;
3145     else
3146         m_customDeviceScaleFactor = WTF::nullopt;
3147
3148     if (deviceScaleFactor() != oldScaleFactor)
3149         m_drawingArea->deviceScaleFactorDidChange();
3150 }
3151
3152 void WebPageProxy::accessibilitySettingsDidChange()
3153 {
3154     if (!isValid())
3155         return;
3156
3157     m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
3158 }
3159
3160 #if ENABLE(ACCESSIBILITY_EVENTS)
3161 void WebPageProxy::updateAccessibilityEventsEnabled(bool enabled)
3162 {
3163     if (!isValid())
3164         return;
3165
3166     m_process->send(Messages::WebPage::UpdateAccessibilityEventsEnabled(enabled), m_pageID);
3167 }
3168 #endif
3169
3170 void WebPageProxy::setUseFixedLayout(bool fixed)
3171 {
3172     if (!isValid())
3173         return;
3174
3175     // This check is fine as the value is initialized in the web
3176     // process as part of the creation parameters.
3177     if (fixed == m_useFixedLayout)
3178         return;
3179
3180     m_useFixedLayout = fixed;
3181     if (!fixed)
3182         m_fixedLayoutSize = IntSize();
3183     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
3184 }
3185
3186 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
3187 {
3188     if (!isValid())
3189         return;
3190
3191     if (size == m_fixedLayoutSize)
3192         return;
3193
3194     m_fixedLayoutSize = size;
3195     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
3196 }
3197
3198 void WebPageProxy::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)
3199 {
3200     if (!isValid())
3201         return;
3202
3203     if (alwaysShowsHorizontalScroller == m_alwaysShowsHorizontalScroller)
3204         return;
3205
3206     m_alwaysShowsHorizontalScroller = alwaysShowsHorizontalScroller;
3207     m_process->send(Messages::WebPage::SetAlwaysShowsHorizontalScroller(alwaysShowsHorizontalScroller), m_pageID);
3208 }
3209
3210 void WebPageProxy::setAlwaysShowsVerticalScroller(bool alwaysShowsVerticalScroller)
3211 {
3212     if (!isValid())
3213         return;
3214
3215     if (alwaysShowsVerticalScroller == m_alwaysShowsVerticalScroller)
3216         return;
3217
3218     m_alwaysShowsVerticalScroller = alwaysShowsVerticalScroller;
3219     m_process->send(Messages::WebPage::SetAlwaysShowsVerticalScroller(alwaysShowsVerticalScroller), m_pageID);
3220 }
3221
3222 void WebPageProxy::listenForLayoutMilestones(OptionSet<WebCore::LayoutMilestone> milestones)
3223 {
3224     if (!isValid())
3225         return;
3226     
3227     if (milestones == m_observedLayoutMilestones)
3228         return;
3229
3230     m_observedLayoutMilestones = milestones;
3231     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
3232 }
3233
3234 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
3235 {
3236     if (!isValid())
3237         return;
3238
3239     if (suppressAnimations == m_suppressScrollbarAnimations)
3240         return;
3241
3242     m_suppressScrollbarAnimations = suppressAnimations;
3243     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
3244 }
3245
3246 bool WebPageProxy::rubberBandsAtLeft() const
3247 {
3248     return m_rubberBandsAtLeft;
3249 }
3250
3251 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
3252 {
3253     m_rubberBandsAtLeft = rubberBandsAtLeft;
3254 }
3255
3256 bool WebPageProxy::rubberBandsAtRight() const
3257 {
3258     return m_rubberBandsAtRight;
3259 }
3260
3261 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
3262 {
3263     m_rubberBandsAtRight = rubberBandsAtRight;
3264 }
3265
3266 bool WebPageProxy::rubberBandsAtTop() const
3267 {
3268     return m_rubberBandsAtTop;
3269 }
3270
3271 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
3272 {
3273     m_rubberBandsAtTop = rubberBandsAtTop;
3274 }
3275
3276 bool WebPageProxy::rubberBandsAtBottom() const
3277 {
3278     return m_rubberBandsAtBottom;
3279 }
3280
3281 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
3282 {
3283     m_rubberBandsAtBottom = rubberBandsAtBottom;
3284 }
3285     
3286 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
3287 {
3288     if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
3289         return;
3290
3291     m_enableVerticalRubberBanding = enableVerticalRubberBanding;
3292
3293     if (!isValid())
3294         return;
3295     m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
3296 }
3297     
3298 bool WebPageProxy::verticalRubberBandingIsEnabled() const
3299 {
3300     return m_enableVerticalRubberBanding;
3301 }
3302     
3303 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
3304 {
3305     if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
3306         return;
3307
3308     m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
3309
3310     if (!isValid())
3311         return;
3312     m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
3313 }
3314     
3315 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
3316 {
3317     return m_enableHorizontalRubberBanding;
3318 }
3319
3320 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
3321 {
3322     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
3323         return;
3324
3325     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
3326
3327     if (!isValid())
3328         return;
3329     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
3330 }
3331
3332 bool WebPageProxy::backgroundExtendsBeyondPage() const
3333 {
3334     return m_backgroundExtendsBeyondPage;
3335 }
3336
3337 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
3338 {
3339     if (mode == m_paginationMode)
3340         return;
3341
3342     m_paginationMode = mode;
3343
3344     if (!isValid())
3345         return;
3346     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
3347 }
3348
3349 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
3350 {
3351     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
3352         return;
3353
3354     m_paginationBehavesLikeColumns = behavesLikeColumns;
3355
3356     if (!isValid())
3357         return;
3358     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
3359 }
3360
3361 void WebPageProxy::setPageLength(double pageLength)
3362 {
3363     if (pageLength == m_pageLength)
3364         return;
3365
3366     m_pageLength = pageLength;
3367
3368     if (!isValid())
3369         return;
3370     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
3371 }
3372
3373 void WebPageProxy::setGapBetweenPages(double gap)
3374 {
3375     if (gap == m_gapBetweenPages)
3376         return;
3377
3378     m_gapBetweenPages = gap;
3379
3380     if (!isValid())
3381         return;
3382     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
3383 }
3384
3385 void WebPageProxy::setPaginationLineGridEnabled(bool lineGridEnabled)
3386 {
3387     if (lineGridEnabled == m_paginationLineGridEnabled)
3388         return;
3389     
3390     m_paginationLineGridEnabled = lineGridEnabled;
3391     
3392     if (!isValid())
3393         return;
3394     m_process->send(Messages::WebPage::SetPaginationLineGridEnabled(lineGridEnabled), m_pageID);
3395 }
3396
3397 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
3398 {
3399     m_pageScaleFactor = scaleFactor;
3400 }
3401
3402 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
3403 {
3404     m_pluginScaleFactor = pluginScaleFactor;
3405 }
3406
3407 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
3408 {
3409     m_pluginZoomFactor = pluginZoomFactor;
3410 }
3411
3412 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3413 {
3414     if (string.isEmpty()) {
3415         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
3416         return;
3417     }
3418
3419     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
3420 }
3421
3422 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
3423 {
3424     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
3425 }
3426
3427 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
3428 {
3429     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
3430 }
3431
3432 void WebPageProxy::selectFindMatch(int32_t matchIndex)
3433 {
3434     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
3435 }
3436
3437 void WebPageProxy::hideFindUI()
3438 {
3439     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
3440 }
3441
3442 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3443 {
3444     if (!isValid())
3445         return;
3446
3447     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
3448 }
3449
3450 void WebPageProxy::replaceMatches(Vector<uint32_t>&& matchIndices, const String& replacementText, bool selectionOnly, Function<void(uint64_t, CallbackBase::Error)>&& callback)
3451 {
3452     if (!isValid()) {
3453         callback(0, CallbackBase::Error::Unknown);
3454         return;
3455     }
3456
3457     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
3458     m_process->send(Messages::WebPage::ReplaceMatches(WTFMove(matchIndices), replacementText, selectionOnly, callbackID), m_pageID);
3459 }
3460
3461 void WebPageProxy::runJavaScriptInMainFrame(const String& script, bool forceUserGesture, 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::RunJavaScriptInMainFrame(script, forceUserGesture, callbackID), m_pageID);
3470 }
3471
3472 void WebPageProxy::runJavaScriptInMainFrameScriptWorld(const String& script, bool forceUserGesture, const String& worldName, WTF::Function<void(API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3473 {
3474     if (!isValid()) {
3475         callbackFunction(nullptr, false, { }, 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::RunJavaScriptInMainFrameScriptWorld(script, forceUserGesture, worldName, callbackID), m_pageID);
3481 }
3482
3483 void WebPageProxy::getRenderTreeExternalRepresentation(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_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
3492 }
3493
3494 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3495 {
3496     if (!isValid()) {
3497         callbackFunction(String(), CallbackBase::Error::Unknown);
3498         return;
3499     }
3500     
3501     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3502     m_loadDependentStringCallbackIDs.add(callbackID);
3503     m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
3504 }
3505
3506 void WebPageProxy::getContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3507 {
3508     if (!isValid()) {
3509         callbackFunction(String(), CallbackBase::Error::Unknown);
3510         return;
3511     }
3512     
3513     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3514     m_loadDependentStringCallbackIDs.add(callbackID);
3515     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
3516 }
3517
3518 void WebPageProxy::getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3519 {
3520     if (!isValid()) {
3521         callbackFunction(String(), CallbackBase::Error::Unknown);
3522         return;
3523     }
3524     
3525     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3526     m_loadDependentStringCallbackIDs.add(callbackID);
3527     m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
3528 }
3529
3530 void WebPageProxy::getSamplingProfilerOutput(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3531 {
3532     if (!isValid()) {
3533         callbackFunction(String(), CallbackBase::Error::Unknown);
3534         return;
3535     }
3536     
3537     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3538     m_loadDependentStringCallbackIDs.add(callbackID);
3539     m_process->send(Messages::WebPage::GetSamplingProfilerOutput(callbackID), m_pageID);
3540 }
3541
3542 void WebPageProxy::isWebProcessResponsive(WTF::Function<void (bool isWebProcessResponsive)>&& callbackFunction)
3543 {
3544     if (!isValid()) {
3545         RunLoop::main().dispatch([callbackFunction = WTFMove(callbackFunction)] {
3546             bool isWebProcessResponsive = true;
3547             callbackFunction(isWebProcessResponsive);
3548         });
3549         return;
3550     }
3551
3552     m_process->isResponsive(WTFMove(callbackFunction));
3553 }
3554
3555 #if ENABLE(MHTML)
3556 void WebPageProxy::getContentsAsMHTMLData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3557 {
3558     if (!isValid()) {
3559         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3560         return;
3561     }
3562
3563     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3564     m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID), m_pageID);
3565 }
3566 #endif
3567
3568 void WebPageProxy::getSelectionOrContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3569 {
3570     if (!isValid()) {
3571         callbackFunction(String(), 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::GetSelectionOrContentsAsString(callbackID), m_pageID);
3577 }
3578
3579 void WebPageProxy::getSelectionAsWebArchiveData(Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3580 {
3581     if (!isValid()) {
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::GetSelectionAsWebArchiveData(callbackID), m_pageID);
3588 }
3589
3590 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3591 {
3592     if (!isValid() || !frame) {
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::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
3599 }
3600
3601 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, 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::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
3610 }
3611
3612 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, Function<void (API::Data*, CallbackBase::Error)>&& callbackFunction)
3613 {
3614     if (!isValid()) {
3615         callbackFunction(nullptr, CallbackBase::Error::Unknown);
3616         return;
3617     }
3618     
3619     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3620     m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
3621 }
3622
3623 void WebPageProxy::forceRepaint(RefPtr<VoidCallback>&& callback)
3624 {
3625     if (!isValid()) {
3626         // FIXME: If the page is invalid we should not call the callback. It'd be better to just return false from forceRepaint.
3627         callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3628         return;
3629     }
3630
3631     Function<void(CallbackBase::Error)> didForceRepaintCallback = [this, callback = WTFMove(callback)](CallbackBase::Error error) mutable {
3632         if (error != CallbackBase::Error::None) {
3633             callback->invalidate(error);
3634             return;
3635         }
3636
3637         if (!isValid()) {
3638             callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
3639             return;
3640         }
3641     
3642         callAfterNextPresentationUpdate([callback = WTFMove(callback)](CallbackBase::Error error) {
3643             if (error != CallbackBase::Error::None) {
3644                 callback->invalidate(error);
3645                 return;
3646             }
3647
3648             callback->performCallback();
3649         });
3650     };
3651
3652     auto callbackID = m_callbacks.put(WTFMove(didForceRepaintCallback), m_process->throttler().backgroundActivityToken());
3653     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
3654     m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID); 
3655 }
3656
3657 static OptionSet<IPC::SendOption> printingSendOptions(bool isPerformingDOMPrintOperation)
3658 {
3659     if (isPerformingDOMPrintOperation)
3660         return IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply;
3661
3662     return { };
3663 }
3664
3665 void WebPageProxy::preferencesDidChange()
3666 {
3667     if (!isValid())
3668         return;
3669
3670     updateThrottleState();
3671     updateHiddenPageThrottlingAutoIncreases();
3672
3673     pageClient().preferencesDidChange();
3674
3675     // FIXME: It probably makes more sense to send individual preference changes.
3676     // However, WebKitTestRunner depends on getting a preference change notification
3677     // even if nothing changed in UI process, so that overrides get removed.
3678
3679     // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
3680     m_process->send(Messages::WebPage::PreferencesDidChange(preferencesStore()), m_pageID, printingSendOptions(m_isPerformingDOMPrintOperation));
3681 }
3682
3683 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
3684 {
3685     // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateMainFrame one.
3686     // When this happens, decidePolicyForNavigationActionSync() calls didCreateMainFrame() and we need to ignore the DidCreateMainFrame
3687     // IPC when it later gets processed.
3688     if (m_mainFrame && m_mainFrame->frameID() == frameID)
3689         return;
3690
3691     PageClientProtector protector(pageClient());
3692
3693     MESSAGE_CHECK(!m_mainFrame);
3694     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3695
3696     m_mainFrame = WebFrameProxy::create(*this, frameID);
3697
3698     // Add the frame to the process wide map.
3699     m_process->frameCreated(frameID, *m_mainFrame);
3700
3701     if (m_mainFrameCreationHandler) {
3702         m_mainFrameCreationHandler();
3703         m_mainFrameCreationHandler = nullptr;
3704     }
3705 }
3706
3707 void WebPageProxy::didCreateSubframe(uint64_t frameID)
3708 {
3709     PageClientProtector protector(pageClient());
3710
3711     MESSAGE_CHECK(m_mainFrame);
3712
3713     // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateSubframe one.
3714     // When this happens, decidePolicyForNavigationActionSync() calls didCreateSubframe() and we need to ignore the DidCreateSubframe
3715     // IPC when it later gets processed.
3716     if (m_process->webFrame(frameID))
3717         return;
3718
3719     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
3720     
3721     auto subFrame = WebFrameProxy::create(*this, frameID);
3722
3723     // Add the frame to the process wide map.
3724     m_process->frameCreated(frameID, subFrame.get());
3725 }
3726
3727 void WebPageProxy::didCreateWindow(uint64_t frameID, GlobalWindowIdentifier&& windowIdentifier)
3728 {
3729     if (m_mainFrame && m_mainFrame->frameID() == frameID) {
3730         if (auto mainFrameWindowCreationHandler = WTFMove(m_mainFrameWindowCreationHandler))
3731             mainFrameWindowCreationHandler(windowIdentifier);
3732     }
3733 }
3734
3735 double WebPageProxy::estimatedProgress() const
3736 {
3737     return m_pageLoadState.estimatedProgress();
3738 }
3739
3740 void WebPageProxy::didStartProgress()
3741 {
3742     PageClientProtector protector(pageClient());
3743
3744     auto transaction = m_pageLoadState.transaction();
3745     m_pageLoadState.didStartProgress(transaction);
3746
3747     m_pageLoadState.commitChanges();
3748 }
3749
3750 void WebPageProxy::didChangeProgress(double value)
3751 {
3752     PageClientProtector protector(pageClient());
3753
3754     auto transaction = m_pageLoadState.transaction();
3755     m_pageLoadState.didChangeProgress(transaction, value);
3756
3757     m_pageLoadState.commitChanges();
3758 }
3759
3760 void WebPageProxy::didFinishProgress()
3761 {
3762     PageClientProtector protector(pageClient());
3763
3764     auto transaction = m_pageLoadState.transaction();
3765     m_pageLoadState.didFinishProgress(transaction);
3766
3767     m_pageLoadState.commitChanges();
3768 }
3769
3770 void WebPageProxy::setNetworkRequestsInProgress(bool networkRequestsInProgress)
3771 {
3772     auto transaction = m_pageLoadState.transaction();
3773     m_pageLoadState.setNetworkRequestsInProgress(transaction, networkRequestsInProgress);
3774 }
3775
3776 void WebPageProxy::hasInsecureContent(HasInsecureContent& hasInsecureContent)
3777 {
3778     hasInsecureContent = m_pageLoadState.committedHasInsecureContent() ? HasInsecureContent::Yes : HasInsecureContent::No;
3779 }
3780
3781 void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
3782 {
3783     PageClientProtector protector(pageClient());
3784
3785     // FIXME: Message check the navigationID.
3786     m_navigationState->didDestroyNavigation(navigationID);
3787 }
3788
3789 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
3790 {
3791     PageClientProtector protector(pageClient());
3792
3793     WebFrameProxy* frame = m_process->webFrame(frameID);
3794     MESSAGE_CHECK(frame);
3795     MESSAGE_CHECK_URL(url);
3796
3797     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3798     RefPtr<API::Navigation> navigation;
3799     if (frame->isMainFrame() && navigationID)
3800         navigation = navigationState().navigation(navigationID);
3801
3802     // If this seemingly new load is actually continuing a server redirect for a previous navigation in a new process,
3803     // then we ignore this notification.
3804     if (navigation && navigation->currentRequestIsRedirect()) {
3805         auto navigationProcessIdentifier = navigation->currentRequestProcessIdentifier();
3806         if (navigationProcessIdentifier && *navigationProcessIdentifier != m_process->coreProcessIdentifier())
3807             return;
3808     }
3809
3810     LOG(Loading, "WebPageProxy %" PRIu64 " in process pid %i didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", m_pageID, m_process->processIdentifier(), frameID, navigationID, url.string().utf8().data());
3811     RELEASE_LOG_IF_ALLOWED(Loading, "didStartProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
3812
3813     auto transaction = m_pageLoadState.transaction();
3814
3815     m_pageLoadState.clearPendingAPIRequestURL(transaction);
3816
3817     if (frame->isMainFrame()) {
3818         reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
3819         m_pageLoadStart = MonotonicTime::now();
3820         m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
3821         pageClient().didStartProvisionalLoadForMainFrame();
3822         closeOverlayedViews();
3823     }
3824
3825     frame->setUnreachableURL(unreachableURL);
3826     frame->didStartProvisionalLoad(url);
3827
3828     m_pageLoadState.commitChanges();
3829     if (m_loaderClient)
3830         m_loaderClient->didStartProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3831     else if (frame->isMainFrame())
3832         m_navigationClient->didStartProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3833 }
3834
3835 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, ResourceRequest&& request, const UserData& userData)
3836 {
3837     LOG(Loading, "WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", frameID, navigationID, request.url().string().utf8().data());
3838     RELEASE_LOG_IF_ALLOWED(Loading, "didReceiveServerRedirectForProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
3839
3840     PageClientProtector protector(pageClient());
3841
3842     WebFrameProxy* frame = m_process->webFrame(frameID);
3843     MESSAGE_CHECK(frame);
3844     MESSAGE_CHECK_URL(request.url());
3845
3846     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3847     RefPtr<API::Navigation> navigation = navigationID ? navigationState().navigation(navigationID) : nullptr;
3848     if (navigation)
3849         navigation->appendRedirectionURL(request.url());
3850
3851     auto transaction = m_pageLoadState.transaction();
3852
3853     if (frame->isMainFrame())
3854         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, request.url());
3855
3856     frame->didReceiveServerRedirectForProvisionalLoad(request.url());
3857
3858     m_pageLoadState.commitChanges();
3859     if (m_loaderClient)
3860         m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(*this, *frame, frame->isMainFrame() ? navigation.get() : nullptr, m_process->transformHandlesToObjects(userData.object()).get());
3861     else if (frame->isMainFrame())
3862         m_navigationClient->didReceiveServerRedirectForProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
3863 }
3864
3865 void WebPageProxy::willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay, WebCore::LockBackForwardList)
3866 {
3867     RELEASE_LOG_IF_ALLOWED(Loading, "willPerformClientRedirectForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
3868
3869     PageClientProtector protector(pageClient());
3870
3871     WebFrameProxy* frame = m_process->webFrame(frameID);
3872     MESSAGE_CHECK(frame);
3873
3874     if (frame->isMainFrame())
3875         m_navigationClient->willPerformClientRedirect(*this, url, delay);
3876 }
3877
3878 void WebPageProxy::didCancelClientRedirectForFrame(uint64_t frameID)
3879 {
3880     RELEASE_LOG_IF_ALLOWED(Loading, "didCancelClientRedirectForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
3881
3882     PageClientProtector protector(pageClient());
3883
3884     WebFrameProxy* frame = m_process->webFrame(frameID);
3885     MESSAGE_CHECK(frame);
3886
3887     if (frame->isMainFrame())
3888         m_navigationClient->didCancelClientRedirect(*this);
3889 }
3890
3891 void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t, URL&& url)
3892 {
3893     PageClientProtector protector(pageClient());
3894
3895     WebFrameProxy* frame = m_process->webFrame(frameID);
3896     MESSAGE_CHECK(frame);
3897     MESSAGE_CHECK(frame->frameLoadState().state() == FrameLoadState::State::Provisional);
3898     MESSAGE_CHECK_URL(url);
3899
3900     auto transaction = m_pageLoadState.transaction();
3901
3902     // Internally, we handle this the same way we handle a server redirect. There are no client callbacks
3903     // for this, but if this is the main frame, clients may observe a change to the page's URL.
3904     if (frame->isMainFrame())
3905         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
3906
3907     frame->didReceiveServerRedirectForProvisionalLoad(url);
3908 }
3909
3910 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
3911 {
3912     LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " in web process pid %i didFailProvisionalLoadForFrame to provisionalURL %s", m_pageID, m_process->processIdentifier(), provisionalURL.utf8().data());
3913     RELEASE_LOG_IF_ALLOWED(Process, "didFailProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64 ", domain = %s, code = %d", m_process->processIdentifier(), m_pageID, frameID, error.domain().utf8().data(), error.errorCode());
3914
3915     PageClientProtector protector(pageClient());
3916
3917     WebFrameProxy* frame = m_process->webFrame(frameID);
3918     MESSAGE_CHECK(frame);
3919
3920     if (m_controlledByAutomation) {
3921         if (auto* automationSession = process().processPool().automationSession())
3922             automationSession->navigationOccurredForFrame(*frame);
3923     }
3924
3925     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3926     RefPtr<API::Navigation> navigation;
3927     if (frame->isMainFrame() && navigationID)
3928         navigation = navigationState().takeNavigation(navigationID);
3929
3930     auto transaction = m_pageLoadState.transaction();
3931
3932     if (frame->isMainFrame()) {
3933         reportPageLoadResult(error);
3934         m_pageLoadState.didFailProvisionalLoad(transaction);
3935         pageClient().didFailProvisionalLoadForMainFrame();
3936     }
3937
3938     frame->didFailProvisionalLoad();
3939
3940     m_pageLoadState.commitChanges();
3941
3942     ASSERT(!m_failingProvisionalLoadURL);
3943     m_failingProvisionalLoadURL = provisionalURL;
3944
3945     if (m_loaderClient)
3946         m_loaderClient->didFailProvisionalLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3947     else if (frame->isMainFrame())
3948         m_navigationClient->didFailProvisionalNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
3949     else {
3950             // FIXME: Get the main frame's current navigation.
3951             m_navigationClient->didFailProvisionalLoadInSubframeWithError(*this, *frame, frameSecurityOrigin, nullptr, error, m_process->transformHandlesToObjects(userData.object()).get());
3952     }
3953
3954     m_failingProvisionalLoadURL = { };
3955 }
3956
3957 void WebPageProxy::clearLoadDependentCallbacks()
3958 {
3959     HashSet<CallbackID> loadDependentStringCallbackIDs = WTFMove(m_loadDependentStringCallbackIDs);
3960     for (auto& callbackID : loadDependentStringCallbackIDs) {
3961         if (auto callback = m_callbacks.take<StringCallback>(callbackID))
3962             callback->invalidate();
3963     }
3964 }
3965
3966 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)
3967 {
3968     LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " didCommitLoadForFrame in navigation %" PRIu64, m_pageID, m_navigationID);
3969     LOG(BackForward, "(Back/Forward) After load commit, back/forward list is now:%s", m_backForwardList->loggingString());
3970     RELEASE_LOG_IF_ALLOWED(Loading, "didCommitLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
3971
3972     PageClientProtector protector(pageClient());
3973
3974     WebFrameProxy* frame = m_process->webFrame(frameID);
3975     MESSAGE_CHECK(frame);
3976
3977     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
3978     RefPtr<API::Navigation> navigation;
3979     if (frame->isMainFrame() && navigationID)
3980         navigation = navigationState().navigation(navigationID);
3981
3982     m_hasCommittedAnyProvisionalLoads = true;
3983     m_process->didCommitProvisionalLoad();
3984
3985 #if PLATFORM(IOS_FAMILY)
3986     if (frame->isMainFrame()) {
3987         m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = false;
3988         m_firstLayerTreeTransactionIdAfterDidCommitLoad = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).nextLayerTreeTransactionID();
3989     }
3990 #endif
3991
3992     auto transaction = m_pageLoadState.transaction();
3993     Ref<WebCertificateInfo> webCertificateInfo = WebCertificateInfo::create(certificateInfo);
3994     bool markPageInsecure = hasInsecureContent ? hasInsecureContent.value() == HasInsecureContent::Yes : m_treatsSHA1CertificatesAsInsecure && certificateInfo.containsNonRootSHA1SignedCertificate();
3995
3996     if (frame->isMainFrame()) {
3997         m_pageLoadState.didCommitLoad(transaction, webCertificateInfo, markPageInsecure);
3998         m_shouldSuppressNextAutomaticNavigationSnapshot = false;
3999     } else if (markPageInsecure)
4000         m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
4001
4002 #if USE(APPKIT)
4003     // FIXME (bug 59111): didCommitLoadForFrame comes too late when restoring a page from b/f cache, making us disable secure event mode in password fields.
4004     // FIXME: A load going on in one frame shouldn't affect text editing in other frames on the page.
4005     pageClient().resetSecureInputState();
4006 #endif
4007
4008     clearLoadDependentCallbacks();
4009
4010     frame->didCommitLoad(mimeType, webCertificateInfo, containsPluginDocument);
4011
4012     if (frame->isMainFrame()) {
4013         m_mainFrameHasCustomContentProvider = frameHasCustomContentProvider;
4014
4015         if (m_mainFrameHasCustomContentProvider) {
4016             // Always assume that the main frame is pinned here, since the custom representation view will handle
4017             // any wheel events and dispatch them to the WKView when necessary.
4018             m_mainFrameIsPinnedToLeftSide = true;
4019             m_mainFrameIsPinnedToRightSide = true;
4020             m_mainFrameIsPinnedToTopSide = true;
4021             m_mainFrameIsPinnedToBottomSide = true;
4022
4023             m_uiClient->pinnedStateDidChange(*this);
4024         }
4025         pageClient().didCommitLoadForMainFrame(mimeType, frameHasCustomContentProvider);
4026     }
4027
4028     // Even if WebPage has the default pageScaleFactor (and therefore doesn't reset it),
4029     // WebPageProxy's cache of the value can get out of sync (e.g. in the case where a
4030     // plugin is handling page scaling itself) so we should reset it to the default
4031     // for standard main frame loads.
4032     if (frame->isMainFrame()) {
4033         if (static_cast<FrameLoadType>(opaqueFrameLoadType) == FrameLoadType::Standard) {
4034             m_pageScaleFactor = 1;
4035             m_pluginScaleFactor = 1;
4036             m_mainFramePluginHandlesPageScaleGesture = false;
4037         }
4038     }
4039
4040 #if ENABLE(POINTER_LOCK)
4041     if (frame->isMainFrame())
4042         requestPointerUnlock();
4043 #endif
4044
4045     m_pageLoadState.commitChanges();
4046     if (m_loaderClient)
4047         m_loaderClient->didCommitLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4048     else if (frame->isMainFrame())
4049         m_navigationClient->didCommitNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4050
4051 #if ENABLE(ATTACHMENT_ELEMENT)
4052     if (frame->isMainFrame())
4053         invalidateAllAttachments();
4054 #endif
4055
4056 #if ENABLE(REMOTE_INSPECTOR)
4057     if (frame->isMainFrame())
4058         remoteInspectorInformationDidChange();
4059 #endif
4060 }
4061
4062 void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
4063 {
4064     RELEASE_LOG_IF_ALLOWED(Loading, "didFinishDocumentLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
4065
4066     PageClientProtector protector(pageClient());
4067
4068     WebFrameProxy* frame = m_process->webFrame(frameID);
4069     MESSAGE_CHECK(frame);
4070
4071     if (m_controlledByAutomation) {
4072         if (auto* automationSession = process().processPool().automationSession())
4073             automationSession->documentLoadedForFrame(*frame);
4074     }
4075
4076     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
4077     RefPtr<API::Navigation> navigation;
4078     if (frame->isMainFrame() && navigationID)
4079         navigation = navigationState().navigation(navigationID);
4080
4081     if (frame->isMainFrame())
4082         m_navigationClient->didFinishDocumentLoad(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4083 }
4084
4085 void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
4086 {
4087     LOG(Loading, "WebPageProxy::didFinishLoadForFrame - WebPageProxy %p with navigationID %" PRIu64 " didFinishLoad", this, navigationID);
4088     RELEASE_LOG_IF_ALLOWED(Loading, "didFinishLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
4089
4090     PageClientProtector protector(pageClient());
4091
4092     WebFrameProxy* frame = m_process->webFrame(frameID);
4093     MESSAGE_CHECK(frame);
4094
4095     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
4096     RefPtr<API::Navigation> navigation;
4097     if (frame->isMainFrame() && navigationID)
4098         navigation = navigationState().navigation(navigationID);
4099
4100     auto transaction = m_pageLoadState.transaction();
4101
4102     bool isMainFrame = frame->isMainFrame();
4103     if (isMainFrame)
4104         m_pageLoadState.didFinishLoad(transaction);
4105
4106     if (m_controlledByAutomation) {
4107         if (auto* automationSession = process().processPool().automationSession())
4108             automationSession->navigationOccurredForFrame(*frame);
4109     }
4110
4111     frame->didFinishLoad();
4112
4113     m_pageLoadState.commitChanges();
4114     if (m_loaderClient)
4115         m_loaderClient->didFinishLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4116     else if (isMainFrame)
4117         m_navigationClient->didFinishNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
4118
4119     if (isMainFrame) {
4120         reportPageLoadResult();
4121         pageClient().didFinishLoadForMainFrame();
4122
4123         resetRecentCrashCountSoon();
4124
4125         notifyProcessPoolToPrewarm();
4126     }
4127
4128     m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = false;
4129 }
4130
4131 void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, const UserData& userData)
4132 {
4133     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());
4134
4135     PageClientProtector protector(pageClient());
4136
4137     WebFrameProxy* frame = m_process->webFrame(frameID);
4138     MESSAGE_CHECK(frame);
4139
4140     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
4141     RefPtr<API::Navigation> navigation;
4142     if (frame->isMainFrame() && navigationID)
4143         navigation = navigationState().navigation(navigationID);
4144
4145     clearLoadDependentCallbacks();
4146
4147     auto transaction = m_pageLoadState.transaction();
4148
4149     bool isMainFrame = frame->isMainFrame();
4150
4151     if (isMainFrame)
4152         m_pageLoadState.didFailLoad(transaction);
4153
4154     if (m_controlledByAutomation) {
4155         if (auto* automationSession = process().processPool().automationSession())
4156             automationSession->navigationOccurredForFrame(*frame);
4157     }
4158
4159     frame->didFailLoad();
4160
4161     m_pageLoadState.commitChanges();
4162     if (m_loaderClient)
4163         m_loaderClient->didFailLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
4164     else if (frame->isMainFrame())
4165         m_navigationClient->didFailNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
4166
4167     if (isMainFrame) {
4168         reportPageLoadResult(error);
4169         pageClient().didFailLoadForMainFrame();
4170     }
4171 }
4172
4173 void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint64_t navigationID, uint32_t opaqueSameDocumentNavigationType, URL&& url, const UserData& userData)
4174 {
4175     RELEASE_LOG_IF_ALLOWED(Loading, "didSameDocumentNavigationForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
4176
4177     PageClientProtector protector(pageClient())