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