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