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