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