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