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