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