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