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