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