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