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