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