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