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