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