0e560ab97ac5794752a925cad80cf973d64ab544
[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 = m_backForwardList->currentItem()->itemIsInSameDocument(*forwardItem) ? 0 : 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 = m_backForwardList->currentItem()->itemIsInSameDocument(*backItem) ? 0 : 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 = m_backForwardList->currentItem()->itemIsInSameDocument(*item) ? 0 : 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 || m_viewStateChangeWantsReply)
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 !PLATFORM(IOS)
1318 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
1319 {
1320 }
1321 #endif
1322
1323 #if USE(TILED_BACKING_STORE)
1324 void WebPageProxy::commitPageTransitionViewport()
1325 {
1326     if (!isValid())
1327         return;
1328
1329     process().send(Messages::WebPage::CommitPageTransitionViewport(), m_pageID);
1330 }
1331 #endif
1332
1333 #if ENABLE(DRAG_SUPPORT)
1334 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
1335 {
1336     SandboxExtension::Handle sandboxExtensionHandle;
1337     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1338     performDragControllerAction(DragControllerActionEntered, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1339 }
1340
1341 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
1342 {
1343     SandboxExtension::Handle sandboxExtensionHandle;
1344     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1345     performDragControllerAction(DragControllerActionUpdated, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1346 }
1347
1348 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
1349 {
1350     SandboxExtension::Handle sandboxExtensionHandle;
1351     SandboxExtension::HandleArray sandboxExtensionHandleEmptyArray;
1352     performDragControllerAction(DragControllerActionExited, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionHandleEmptyArray);
1353 }
1354
1355 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1356 {
1357     performDragControllerAction(DragControllerActionPerformDragOperation, dragData, dragStorageName, sandboxExtensionHandle, sandboxExtensionsForUpload);
1358 }
1359
1360 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, const SandboxExtension::Handle& sandboxExtensionHandle, const SandboxExtension::HandleArray& sandboxExtensionsForUpload)
1361 {
1362     if (!isValid())
1363         return;
1364 #if PLATFORM(GTK)
1365     UNUSED_PARAM(dragStorageName);
1366     UNUSED_PARAM(sandboxExtensionHandle);
1367     UNUSED_PARAM(sandboxExtensionsForUpload);
1368     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData), m_pageID);
1369 #else
1370     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), dragStorageName, dragData.flags(), sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
1371 #endif
1372 }
1373
1374 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted)
1375 {
1376     MESSAGE_CHECK(dragOperation <= DragOperationDelete);
1377
1378     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
1379     m_currentDragIsOverFileInput = mouseIsOverFileInput;
1380     m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
1381 }
1382
1383 #if PLATFORM(GTK)
1384 void WebPageProxy::startDrag(const DragData& dragData, const ShareableBitmap::Handle& dragImageHandle)
1385 {
1386     RefPtr<ShareableBitmap> dragImage = 0;
1387     if (!dragImageHandle.isNull()) {
1388         dragImage = ShareableBitmap::create(dragImageHandle);
1389         if (!dragImage)
1390             return;
1391     }
1392
1393     m_pageClient.startDrag(dragData, dragImage.release());
1394 }
1395 #endif
1396
1397 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
1398 {
1399     if (!isValid())
1400         return;
1401     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
1402 }
1403 #endif // ENABLE(DRAG_SUPPORT)
1404
1405 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
1406 {
1407     if (!isValid())
1408         return;
1409
1410     // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
1411     if (event.type() != WebEvent::MouseMove)
1412         m_process->responsivenessTimer()->start();
1413     else {
1414         if (m_processingMouseMoveEvent) {
1415             m_nextMouseMoveEvent = std::make_unique<NativeWebMouseEvent>(event);
1416             return;
1417         }
1418
1419         m_processingMouseMoveEvent = true;
1420     }
1421
1422     // <https://bugs.webkit.org/show_bug.cgi?id=57904> We need to keep track of the mouse down event in the case where we
1423     // display a popup menu for select elements. When the user changes the selected item,
1424     // we fake a mouse up event by using this stored down event. This event gets cleared
1425     // when the mouse up message is received from WebProcess.
1426     if (event.type() == WebEvent::MouseDown)
1427         m_currentlyProcessedMouseDownEvent = std::make_unique<NativeWebMouseEvent>(event);
1428
1429     if (m_shouldSendEventsSynchronously) {
1430         bool handled = false;
1431         m_process->sendSync(Messages::WebPage::MouseEventSyncForTesting(event), Messages::WebPage::MouseEventSyncForTesting::Reply(handled), m_pageID);
1432         didReceiveEvent(event.type(), handled);
1433     } else
1434         m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
1435 }
1436
1437 #if MERGE_WHEEL_EVENTS
1438 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1439 {
1440     if (a.position() != b.position())
1441         return false;
1442     if (a.globalPosition() != b.globalPosition())
1443         return false;
1444     if (a.modifiers() != b.modifiers())
1445         return false;
1446     if (a.granularity() != b.granularity())
1447         return false;
1448 #if PLATFORM(COCOA)
1449     if (a.phase() != b.phase())
1450         return false;
1451     if (a.momentumPhase() != b.momentumPhase())
1452         return false;
1453     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
1454         return false;
1455 #endif
1456
1457     return true;
1458 }
1459
1460 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
1461 {
1462     ASSERT(canCoalesce(a, b));
1463
1464     FloatSize mergedDelta = a.delta() + b.delta();
1465     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
1466
1467 #if PLATFORM(COCOA)
1468     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
1469
1470     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());
1471 #else
1472     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
1473 #endif
1474 }
1475 #endif // MERGE_WHEEL_EVENTS
1476
1477 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
1478 {
1479     ASSERT(!queue.isEmpty());
1480     ASSERT(coalescedEvents.isEmpty());
1481
1482 #if MERGE_WHEEL_EVENTS
1483     NativeWebWheelEvent firstEvent = queue.takeFirst();
1484     coalescedEvents.append(firstEvent);
1485
1486     WebWheelEvent event = firstEvent;
1487     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
1488         NativeWebWheelEvent firstEvent = queue.takeFirst();
1489         coalescedEvents.append(firstEvent);
1490         event = coalesce(event, firstEvent);
1491     }
1492
1493     return event;
1494 #else
1495     while (!queue.isEmpty())
1496         coalescedEvents.append(queue.takeFirst());
1497     return coalescedEvents.last();
1498 #endif
1499 }
1500
1501 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
1502 {
1503 #if ENABLE(ASYNC_SCROLLING)
1504     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
1505         return;
1506 #endif
1507
1508     if (!isValid())
1509         return;
1510
1511     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
1512         m_wheelEventQueue.append(event);
1513         if (m_wheelEventQueue.size() < wheelEventQueueSizeThreshold)
1514             return;
1515         // The queue has too many wheel events, so push a new event.
1516     }
1517
1518     if (!m_wheelEventQueue.isEmpty()) {
1519         processNextQueuedWheelEvent();
1520         return;
1521     }
1522
1523     auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
1524     coalescedWheelEvent->append(event);
1525     m_currentlyProcessedWheelEvents.append(WTF::move(coalescedWheelEvent));
1526     sendWheelEvent(event);
1527 }
1528
1529 void WebPageProxy::processNextQueuedWheelEvent()
1530 {
1531     auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
1532     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
1533     m_currentlyProcessedWheelEvents.append(WTF::move(nextCoalescedEvent));
1534     sendWheelEvent(nextWheelEvent);
1535 }
1536
1537 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
1538 {
1539     m_process->responsivenessTimer()->start();
1540
1541     if (m_shouldSendEventsSynchronously) {
1542         bool handled = false;
1543         m_process->sendSync(Messages::WebPage::WheelEventSyncForTesting(event), Messages::WebPage::WheelEventSyncForTesting::Reply(handled), m_pageID);
1544         didReceiveEvent(event.type(), handled);
1545         return;
1546     }
1547
1548     m_process->send(
1549         Messages::EventDispatcher::WheelEvent(
1550             m_pageID,
1551             event,
1552             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
1553             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
1554             rubberBandsAtTop(),
1555             rubberBandsAtBottom()
1556         ), 0);
1557 }
1558
1559 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
1560 {
1561     if (!isValid())
1562         return;
1563     
1564     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
1565
1566     m_keyEventQueue.append(event);
1567
1568     m_process->responsivenessTimer()->start();
1569     if (m_shouldSendEventsSynchronously) {
1570         bool handled = false;
1571         m_process->sendSync(Messages::WebPage::KeyEventSyncForTesting(event), Messages::WebPage::KeyEventSyncForTesting::Reply(handled), m_pageID);
1572         didReceiveEvent(event.type(), handled);
1573     } else if (m_keyEventQueue.size() == 1) // Otherwise, sent from DidReceiveEvent message handler.
1574         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
1575 }
1576
1577 uint64_t WebPageProxy::generateNavigationID()
1578 {
1579     return ++m_navigationID;
1580 }
1581
1582 WebPreferencesStore WebPageProxy::preferencesStore() const
1583 {
1584     if (m_configurationPreferenceValues.isEmpty())
1585         return m_preferences->store();
1586
1587     WebPreferencesStore store = m_preferences->store();
1588     for (const auto& preference : m_configurationPreferenceValues)
1589         store.m_values.set(preference.key, preference.value);
1590
1591     return store;
1592 }
1593
1594 #if ENABLE(NETSCAPE_PLUGIN_API)
1595 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)
1596 {
1597     MESSAGE_CHECK_URL(urlString);
1598
1599     newMimeType = mimeType.lower();
1600     pluginLoadPolicy = PluginModuleLoadNormally;
1601
1602     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
1603     PluginModuleInfo plugin = m_process->context().pluginInfoStore().findPlugin(newMimeType, URL(URL(), urlString), allowedPluginTypes);
1604     if (!plugin.path) {
1605         pluginProcessToken = 0;
1606         return;
1607     }
1608
1609     pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
1610
1611 #if PLATFORM(COCOA)
1612     RefPtr<ImmutableDictionary> pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
1613     pluginLoadPolicy = m_loaderClient->pluginLoadPolicy(this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), unavailabilityDescription);
1614 #else
1615     UNUSED_PARAM(frameURLString);
1616     UNUSED_PARAM(pageURLString);
1617     UNUSED_PARAM(unavailabilityDescription);
1618 #endif
1619
1620     PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
1621     switch (pluginLoadPolicy) {
1622     case PluginModuleLoadNormally:
1623         pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
1624         break;
1625     case PluginModuleLoadUnsandboxed:
1626         pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
1627         break;
1628
1629     case PluginModuleBlocked:
1630         pluginProcessToken = 0;
1631         return;
1632     }
1633
1634     pluginProcessToken = PluginProcessManager::shared().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy);
1635 }
1636
1637 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1638
1639 #if ENABLE(TOUCH_EVENTS)
1640
1641 bool WebPageProxy::shouldStartTrackingTouchEvents(const WebTouchEvent& touchStartEvent) const
1642 {
1643 #if ENABLE(ASYNC_SCROLLING)
1644     for (auto& touchPoint : touchStartEvent.touchPoints()) {
1645         if (m_scrollingCoordinatorProxy->isPointInNonFastScrollableRegion(touchPoint.location()))
1646             return true;
1647     }
1648
1649     return false;
1650 #else
1651     UNUSED_PARAM(touchStartEvent);
1652 #endif // ENABLE(ASYNC_SCROLLING)
1653     return true;
1654 }
1655
1656 #endif
1657
1658 #if ENABLE(IOS_TOUCH_EVENTS)
1659 void WebPageProxy::handleTouchEventSynchronously(const NativeWebTouchEvent& event)
1660 {
1661     if (!isValid())
1662         return;
1663
1664     if (event.type() == WebEvent::TouchStart)
1665         m_isTrackingTouchEvents = shouldStartTrackingTouchEvents(event);
1666
1667     if (!m_isTrackingTouchEvents)
1668         return;
1669
1670     m_process->responsivenessTimer()->start();
1671     bool handled = false;
1672     m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID);
1673     didReceiveEvent(event.type(), handled);
1674     m_pageClient.doneWithTouchEvent(event, handled);
1675     m_process->responsivenessTimer()->stop();
1676
1677     if (event.allTouchPointsAreReleased())
1678         m_isTrackingTouchEvents = false;
1679 }
1680
1681 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
1682 {
1683     if (!isValid())
1684         return;
1685
1686     if (!m_isTrackingTouchEvents)
1687         return;
1688
1689     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
1690
1691     if (event.allTouchPointsAreReleased())
1692         m_isTrackingTouchEvents = false;
1693 }
1694
1695 #elif ENABLE(TOUCH_EVENTS)
1696 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
1697 {
1698     if (!isValid())
1699         return;
1700
1701     if (event.type() == WebEvent::TouchStart)
1702         m_isTrackingTouchEvents = shouldStartTrackingTouchEvents(event);
1703
1704     if (!m_isTrackingTouchEvents)
1705         return;
1706
1707     // If the page is suspended, which should be the case during panning, pinching
1708     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
1709     // we do not send any of the events to the page even if is has listeners.
1710     if (!m_isPageSuspended) {
1711         m_touchEventQueue.append(event);
1712         m_process->responsivenessTimer()->start();
1713         if (m_shouldSendEventsSynchronously) {
1714             bool handled = false;
1715             m_process->sendSync(Messages::WebPage::TouchEventSyncForTesting(event), Messages::WebPage::TouchEventSyncForTesting::Reply(handled), m_pageID);
1716             didReceiveEvent(event.type(), handled);
1717         } else
1718             m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
1719     } else {
1720         if (m_touchEventQueue.isEmpty()) {
1721             bool isEventHandled = false;
1722             m_pageClient.doneWithTouchEvent(event, isEventHandled);
1723         } else {
1724             // We attach the incoming events to the newest queued event so that all
1725             // the events are delivered in the correct order when the event is dequed.
1726             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
1727             lastEvent.deferredTouchEvents.append(event);
1728         }
1729     }
1730
1731     if (event.allTouchPointsAreReleased())
1732         m_isTrackingTouchEvents = false;
1733 }
1734 #endif // ENABLE(TOUCH_EVENTS)
1735
1736 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
1737 {
1738     if (!isValid())
1739         return;
1740
1741     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
1742 }
1743
1744 void WebPageProxy::centerSelectionInVisibleArea()
1745 {
1746     if (!isValid())
1747         return;
1748
1749     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
1750 }
1751
1752 void WebPageProxy::receivedPolicyDecision(PolicyAction action, WebFrameProxy* frame, uint64_t listenerID, uint64_t navigationID)
1753 {
1754     if (!isValid())
1755         return;
1756
1757     auto transaction = m_pageLoadState.transaction();
1758
1759     if (action == PolicyIgnore)
1760         m_pageLoadState.clearPendingAPIRequestURL(transaction);
1761
1762     uint64_t downloadID = 0;
1763     if (action == PolicyDownload) {
1764         // Create a download proxy.
1765         DownloadProxy* download = m_process->context().createDownloadProxy();
1766         downloadID = download->downloadID();
1767         handleDownloadRequest(download);
1768     }
1769
1770     // If we received a policy decision while in decidePolicyForResponse the decision will
1771     // be sent back to the web process by decidePolicyForResponse.
1772     if (m_inDecidePolicyForResponseSync) {
1773         m_syncMimeTypePolicyActionIsValid = true;
1774         m_syncMimeTypePolicyAction = action;
1775         m_syncMimeTypePolicyDownloadID = downloadID;
1776         return;
1777     }
1778
1779     // If we received a policy decision while in decidePolicyForNavigationAction the decision will 
1780     // be sent back to the web process by decidePolicyForNavigationAction. 
1781     if (m_inDecidePolicyForNavigationAction) {
1782         m_syncNavigationActionPolicyActionIsValid = true;
1783         m_syncNavigationActionPolicyAction = action;
1784         m_syncNavigationActionPolicyDownloadID = downloadID;
1785         return;
1786     }
1787     
1788     m_process->send(Messages::WebPage::DidReceivePolicyDecision(frame->frameID(), listenerID, action, navigationID, downloadID), m_pageID);
1789 }
1790
1791 void WebPageProxy::setUserAgent(const String& userAgent)
1792 {
1793     if (m_userAgent == userAgent)
1794         return;
1795     m_userAgent = userAgent;
1796
1797     if (!isValid())
1798         return;
1799     m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
1800 }
1801
1802 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
1803 {
1804     if (m_applicationNameForUserAgent == applicationName)
1805         return;
1806
1807     m_applicationNameForUserAgent = applicationName;
1808     if (!m_customUserAgent.isEmpty())
1809         return;
1810
1811     setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
1812 }
1813
1814 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
1815 {
1816     if (m_customUserAgent == customUserAgent)
1817         return;
1818
1819     m_customUserAgent = customUserAgent;
1820
1821     if (m_customUserAgent.isEmpty()) {
1822         setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
1823         return;
1824     }
1825
1826     setUserAgent(m_customUserAgent);
1827 }
1828
1829 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
1830 {
1831     if (!isValid() || !m_isPageSuspended)
1832         return;
1833
1834     m_isPageSuspended = false;
1835
1836     m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
1837 }
1838
1839 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
1840 {
1841     if (!isValid() || m_isPageSuspended)
1842         return;
1843
1844     m_isPageSuspended = true;
1845
1846     m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
1847 }
1848
1849 bool WebPageProxy::supportsTextEncoding() const
1850 {
1851     // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
1852     return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
1853 }
1854
1855 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
1856 {
1857     if (m_customTextEncodingName == encodingName)
1858         return;
1859     m_customTextEncodingName = encodingName;
1860
1861     if (!isValid())
1862         return;
1863     m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
1864 }
1865
1866 void WebPageProxy::terminateProcess()
1867 {
1868     // NOTE: This uses a check of m_isValid rather than calling isValid() since
1869     // we want this to run even for pages being closed or that already closed.
1870     if (!m_isValid)
1871         return;
1872
1873     m_process->requestTermination();
1874     resetStateAfterProcessExited();
1875 }
1876
1877 SessionState WebPageProxy::sessionState(const std::function<bool (WebBackForwardListItem&)>& filter) const
1878 {
1879     SessionState sessionState;
1880
1881     sessionState.backForwardListState = m_backForwardList->backForwardListState(filter);
1882
1883     String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
1884     if (provisionalURLString.isEmpty())
1885         provisionalURLString = m_pageLoadState.provisionalURL();
1886
1887     if (!provisionalURLString.isEmpty())
1888         sessionState.provisionalURL = URL(URL(), provisionalURLString);
1889
1890     return sessionState;
1891 }
1892
1893 uint64_t WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
1894 {
1895     bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
1896
1897     if (hasBackForwardList) {
1898         m_backForwardList->restoreFromState(WTF::move(sessionState.backForwardListState));
1899
1900         for (const auto& entry : m_backForwardList->entries())
1901             process().registerNewWebBackForwardListItem(entry.get());
1902
1903         process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
1904     }
1905
1906     if (navigate) {
1907         // FIXME: Navigating should be separate from state restoration.
1908
1909         if (!sessionState.provisionalURL.isNull())
1910             return loadRequest(sessionState.provisionalURL);
1911
1912         if (hasBackForwardList) {
1913             // FIXME: Do we have to null check the back forward list item here?
1914             if (WebBackForwardListItem* item = m_backForwardList->currentItem())
1915                 return goToBackForwardItem(item);
1916         }
1917     }
1918
1919     return 0;
1920 }
1921
1922 bool WebPageProxy::supportsTextZoom() const
1923 {
1924     // FIXME (118840): This should also return false for standalone media and plug-in documents.
1925     if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
1926         return false;
1927
1928     return true;
1929 }
1930  
1931 void WebPageProxy::setTextZoomFactor(double zoomFactor)
1932 {
1933     if (!isValid())
1934         return;
1935
1936     if (m_textZoomFactor == zoomFactor)
1937         return;
1938
1939     m_textZoomFactor = zoomFactor;
1940     m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID); 
1941 }
1942
1943 void WebPageProxy::setPageZoomFactor(double zoomFactor)
1944 {
1945     if (!isValid())
1946         return;
1947
1948     if (m_pageZoomFactor == zoomFactor)
1949         return;
1950
1951     m_pageZoomFactor = zoomFactor;
1952     m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID); 
1953 }
1954
1955 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
1956 {
1957     if (!isValid())
1958         return;
1959
1960     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
1961         return;
1962
1963     m_pageZoomFactor = pageZoomFactor;
1964     m_textZoomFactor = textZoomFactor;
1965     m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID); 
1966 }
1967
1968 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
1969 {
1970     if (!isValid())
1971         return;
1972
1973     m_pageScaleFactor = scale;
1974     m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
1975 }
1976
1977 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
1978 {
1979     if (!isValid())
1980         return;
1981
1982     m_pageScaleFactor = scale;
1983     m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
1984 }
1985
1986 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
1987 {
1988     if (m_intrinsicDeviceScaleFactor == scaleFactor)
1989         return;
1990
1991     m_intrinsicDeviceScaleFactor = scaleFactor;
1992
1993     if (m_drawingArea)
1994         m_drawingArea->deviceScaleFactorDidChange();
1995 }
1996
1997 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
1998 {
1999     if (!isValid())
2000         return;
2001
2002     m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
2003 }
2004
2005 float WebPageProxy::deviceScaleFactor() const
2006 {
2007     if (m_customDeviceScaleFactor)
2008         return m_customDeviceScaleFactor;
2009     return m_intrinsicDeviceScaleFactor;
2010 }
2011
2012 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
2013 {
2014     if (!isValid())
2015         return;
2016
2017     // FIXME: Remove this once we bump cairo requirements to support HiDPI.
2018     // https://bugs.webkit.org/show_bug.cgi?id=133378
2019 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
2020     return;
2021 #endif
2022
2023     if (m_customDeviceScaleFactor == customScaleFactor)
2024         return;
2025
2026     float oldScaleFactor = deviceScaleFactor();
2027
2028     m_customDeviceScaleFactor = customScaleFactor;
2029
2030     if (deviceScaleFactor() != oldScaleFactor)
2031         m_drawingArea->deviceScaleFactorDidChange();
2032 }
2033
2034 void WebPageProxy::setUseFixedLayout(bool fixed)
2035 {
2036     if (!isValid())
2037         return;
2038
2039     // This check is fine as the value is initialized in the web
2040     // process as part of the creation parameters.
2041     if (fixed == m_useFixedLayout)
2042         return;
2043
2044     m_useFixedLayout = fixed;
2045     if (!fixed)
2046         m_fixedLayoutSize = IntSize();
2047     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
2048 }
2049
2050 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
2051 {
2052     if (!isValid())
2053         return;
2054
2055     if (size == m_fixedLayoutSize)
2056         return;
2057
2058     m_fixedLayoutSize = size;
2059     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
2060 }
2061
2062 void WebPageProxy::listenForLayoutMilestones(WebCore::LayoutMilestones milestones)
2063 {
2064     if (!isValid())
2065         return;
2066
2067     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
2068 }
2069
2070 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
2071 {
2072     if (!isValid())
2073         return;
2074
2075     if (suppressAnimations == m_suppressScrollbarAnimations)
2076         return;
2077
2078     m_suppressScrollbarAnimations = suppressAnimations;
2079     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
2080 }
2081
2082 bool WebPageProxy::rubberBandsAtLeft() const
2083 {
2084     return m_rubberBandsAtLeft;
2085 }
2086
2087 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
2088 {
2089     m_rubberBandsAtLeft = rubberBandsAtLeft;
2090 }
2091
2092 bool WebPageProxy::rubberBandsAtRight() const
2093 {
2094     return m_rubberBandsAtRight;
2095 }
2096
2097 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
2098 {
2099     m_rubberBandsAtRight = rubberBandsAtRight;
2100 }
2101
2102 bool WebPageProxy::rubberBandsAtTop() const
2103 {
2104     return m_rubberBandsAtTop;
2105 }
2106
2107 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
2108 {
2109     m_rubberBandsAtTop = rubberBandsAtTop;
2110 }
2111
2112 bool WebPageProxy::rubberBandsAtBottom() const
2113 {
2114     return m_rubberBandsAtBottom;
2115 }
2116
2117 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
2118 {
2119     m_rubberBandsAtBottom = rubberBandsAtBottom;
2120 }
2121     
2122 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
2123 {
2124     if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
2125         return;
2126
2127     m_enableVerticalRubberBanding = enableVerticalRubberBanding;
2128
2129     if (!isValid())
2130         return;
2131     m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
2132 }
2133     
2134 bool WebPageProxy::verticalRubberBandingIsEnabled() const
2135 {
2136     return m_enableVerticalRubberBanding;
2137 }
2138     
2139 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
2140 {
2141     if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
2142         return;
2143
2144     m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
2145
2146     if (!isValid())
2147         return;
2148     m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
2149 }
2150     
2151 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
2152 {
2153     return m_enableHorizontalRubberBanding;
2154 }
2155
2156 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
2157 {
2158     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
2159         return;
2160
2161     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
2162
2163     if (!isValid())
2164         return;
2165     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
2166 }
2167
2168 bool WebPageProxy::backgroundExtendsBeyondPage() const
2169 {
2170     return m_backgroundExtendsBeyondPage;
2171 }
2172
2173 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
2174 {
2175     if (mode == m_paginationMode)
2176         return;
2177
2178     m_paginationMode = mode;
2179
2180     if (!isValid())
2181         return;
2182     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
2183 }
2184
2185 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
2186 {
2187     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
2188         return;
2189
2190     m_paginationBehavesLikeColumns = behavesLikeColumns;
2191
2192     if (!isValid())
2193         return;
2194     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
2195 }
2196
2197 void WebPageProxy::setPageLength(double pageLength)
2198 {
2199     if (pageLength == m_pageLength)
2200         return;
2201
2202     m_pageLength = pageLength;
2203
2204     if (!isValid())
2205         return;
2206     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
2207 }
2208
2209 void WebPageProxy::setGapBetweenPages(double gap)
2210 {
2211     if (gap == m_gapBetweenPages)
2212         return;
2213
2214     m_gapBetweenPages = gap;
2215
2216     if (!isValid())
2217         return;
2218     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
2219 }
2220
2221 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
2222 {
2223     m_pageScaleFactor = scaleFactor;
2224 }
2225
2226 void WebPageProxy::pageZoomFactorDidChange(double zoomFactor)
2227 {
2228     m_pageZoomFactor = zoomFactor;
2229 }
2230
2231 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
2232 {
2233     if (string.isEmpty()) {
2234         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
2235         return;
2236     }
2237
2238     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
2239 }
2240
2241 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
2242 {
2243     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
2244 }
2245
2246 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
2247 {
2248     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
2249 }
2250
2251 void WebPageProxy::selectFindMatch(int32_t matchIndex)
2252 {
2253     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
2254 }
2255
2256 void WebPageProxy::hideFindUI()
2257 {
2258     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
2259 }
2260
2261 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
2262 {
2263     if (!isValid())
2264         return;
2265
2266     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
2267 }
2268
2269 void WebPageProxy::runJavaScriptInMainFrame(const String& script, std::function<void (WebSerializedScriptValue*, CallbackBase::Error)> callbackFunction)
2270 {
2271     if (!isValid()) {
2272         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2273         return;
2274     }
2275
2276     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2277     m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, callbackID), m_pageID);
2278 }
2279
2280 void WebPageProxy::getRenderTreeExternalRepresentation(std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2281 {
2282     if (!isValid()) {
2283         callbackFunction(String(), CallbackBase::Error::Unknown);
2284         return;
2285     }
2286     
2287     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2288     m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
2289 }
2290
2291 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2292 {
2293     if (!isValid()) {
2294         callbackFunction(String(), CallbackBase::Error::Unknown);
2295         return;
2296     }
2297     
2298     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2299     m_loadDependentStringCallbackIDs.add(callbackID);
2300     m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
2301 }
2302
2303 void WebPageProxy::getContentsAsString(std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2304 {
2305     if (!isValid()) {
2306         callbackFunction(String(), CallbackBase::Error::Unknown);
2307         return;
2308     }
2309     
2310     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2311     m_loadDependentStringCallbackIDs.add(callbackID);
2312     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
2313 }
2314
2315 void WebPageProxy::getBytecodeProfile(std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2316 {
2317     if (!isValid()) {
2318         callbackFunction(String(), CallbackBase::Error::Unknown);
2319         return;
2320     }
2321     
2322     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2323     m_loadDependentStringCallbackIDs.add(callbackID);
2324     m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
2325 }
2326     
2327 #if ENABLE(MHTML)
2328 void WebPageProxy::getContentsAsMHTMLData(std::function<void (API::Data*, CallbackBase::Error)> callbackFunction, bool useBinaryEncoding)
2329 {
2330     if (!isValid()) {
2331         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2332         return;
2333     }
2334
2335     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2336     m_process->send(Messages::WebPage::GetContentsAsMHTMLData(callbackID, useBinaryEncoding), m_pageID);
2337 }
2338 #endif
2339
2340 void WebPageProxy::getSelectionOrContentsAsString(std::function<void (const String&, CallbackBase::Error)> callbackFunction)
2341 {
2342     if (!isValid()) {
2343         callbackFunction(String(), CallbackBase::Error::Unknown);
2344         return;
2345     }
2346     
2347     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2348     m_process->send(Messages::WebPage::GetSelectionOrContentsAsString(callbackID), m_pageID);
2349 }
2350
2351 void WebPageProxy::getSelectionAsWebArchiveData(std::function<void (API::Data*, CallbackBase::Error)> callbackFunction)
2352 {
2353     if (!isValid()) {
2354         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2355         return;
2356     }
2357     
2358     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2359     m_process->send(Messages::WebPage::GetSelectionAsWebArchiveData(callbackID), m_pageID);
2360 }
2361
2362 void WebPageProxy::getMainResourceDataOfFrame(WebFrameProxy* frame, std::function<void (API::Data*, CallbackBase::Error)> callbackFunction)
2363 {
2364     if (!isValid() || !frame) {
2365         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2366         return;
2367     }
2368     
2369     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2370     m_process->send(Messages::WebPage::GetMainResourceDataOfFrame(frame->frameID(), callbackID), m_pageID);
2371 }
2372
2373 void WebPageProxy::getResourceDataFromFrame(WebFrameProxy* frame, API::URL* resourceURL, std::function<void (API::Data*, CallbackBase::Error)> callbackFunction)
2374 {
2375     if (!isValid()) {
2376         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2377         return;
2378     }
2379     
2380     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2381     m_process->send(Messages::WebPage::GetResourceDataFromFrame(frame->frameID(), resourceURL->string(), callbackID), m_pageID);
2382 }
2383
2384 void WebPageProxy::getWebArchiveOfFrame(WebFrameProxy* frame, std::function<void (API::Data*, CallbackBase::Error)> callbackFunction)
2385 {
2386     if (!isValid()) {
2387         callbackFunction(nullptr, CallbackBase::Error::Unknown);
2388         return;
2389     }
2390     
2391     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
2392     m_process->send(Messages::WebPage::GetWebArchiveOfFrame(frame->frameID(), callbackID), m_pageID);
2393 }
2394
2395 void WebPageProxy::forceRepaint(PassRefPtr<VoidCallback> prpCallback)
2396 {
2397     RefPtr<VoidCallback> callback = prpCallback;
2398     if (!isValid()) {
2399         // FIXME: If the page is invalid we should not call the callback. It'd be better to just return false from forceRepaint.
2400         callback->invalidate(CallbackBase::Error::OwnerWasInvalidated);
2401         return;
2402     }
2403
2404     uint64_t callbackID = callback->callbackID();
2405     m_callbacks.put(callback);
2406     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
2407     m_process->send(Messages::WebPage::ForceRepaint(callbackID), m_pageID); 
2408 }
2409
2410 void WebPageProxy::preferencesDidChange()
2411 {
2412     if (!isValid())
2413         return;
2414
2415 #if ENABLE(INSPECTOR_SERVER)
2416     if (m_preferences->developerExtrasEnabled())
2417         inspector()->enableRemoteInspection();
2418 #endif
2419
2420     m_process->pagePreferencesChanged(this);
2421
2422     m_pageClient.preferencesDidChange();
2423
2424     // FIXME: It probably makes more sense to send individual preference changes.
2425     // However, WebKitTestRunner depends on getting a preference change notification
2426     // even if nothing changed in UI process, so that overrides get removed.
2427
2428     // Preferences need to be updated during synchronous printing to make "print backgrounds" preference work when toggled from a print dialog checkbox.
2429     m_process->send(Messages::WebPage::PreferencesDidChange(preferencesStore()), m_pageID, m_isPerformingDOMPrintOperation ? IPC::DispatchMessageEvenWhenWaitingForSyncReply : 0);
2430 }
2431
2432 void WebPageProxy::didCreateMainFrame(uint64_t frameID)
2433 {
2434     MESSAGE_CHECK(!m_mainFrame);
2435     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
2436
2437     m_mainFrame = WebFrameProxy::create(this, frameID);
2438
2439     // Add the frame to the process wide map.
2440     m_process->frameCreated(frameID, m_mainFrame.get());
2441 }
2442
2443 void WebPageProxy::didCreateSubframe(uint64_t frameID)
2444 {
2445     MESSAGE_CHECK(m_mainFrame);
2446     MESSAGE_CHECK(m_process->canCreateFrame(frameID));
2447     
2448     RefPtr<WebFrameProxy> subFrame = WebFrameProxy::create(this, frameID);
2449
2450     // Add the frame to the process wide map.
2451     m_process->frameCreated(frameID, subFrame.get());
2452 }
2453
2454 double WebPageProxy::estimatedProgress() const
2455 {
2456     return m_pageLoadState.estimatedProgress();
2457 }
2458
2459 void WebPageProxy::didStartProgress()
2460 {
2461     auto transaction = m_pageLoadState.transaction();
2462     m_pageLoadState.didStartProgress(transaction);
2463
2464     m_pageLoadState.commitChanges();
2465     m_loaderClient->didStartProgress(this);
2466 }
2467
2468 void WebPageProxy::didChangeProgress(double value)
2469 {
2470     auto transaction = m_pageLoadState.transaction();
2471     m_pageLoadState.didChangeProgress(transaction, value);
2472
2473     m_pageLoadState.commitChanges();
2474     m_loaderClient->didChangeProgress(this);
2475 }
2476
2477 void WebPageProxy::didFinishProgress()
2478 {
2479     auto transaction = m_pageLoadState.transaction();
2480     m_pageLoadState.didFinishProgress(transaction);
2481
2482     m_pageLoadState.commitChanges();
2483     m_loaderClient->didFinishProgress(this);
2484 }
2485
2486 void WebPageProxy::setNetworkRequestsInProgress(bool networkRequestsInProgress)
2487 {
2488     auto transaction = m_pageLoadState.transaction();
2489     m_pageLoadState.setNetworkRequestsInProgress(transaction, networkRequestsInProgress);
2490 }
2491
2492 void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
2493 {
2494     m_loaderClient->didDestroyNavigation(this, navigationID);
2495 }
2496
2497 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& url, const String& unreachableURL, IPC::MessageDecoder& decoder)
2498 {
2499     auto transaction = m_pageLoadState.transaction();
2500
2501     m_pageLoadState.clearPendingAPIRequestURL(transaction);
2502
2503     RefPtr<API::Object> userData;
2504     WebContextUserMessageDecoder messageDecoder(userData, process());
2505     if (!decoder.decode(messageDecoder))
2506         return;
2507
2508     WebFrameProxy* frame = m_process->webFrame(frameID);
2509     MESSAGE_CHECK(frame);
2510     MESSAGE_CHECK_URL(url);
2511
2512     if (frame->isMainFrame())
2513         m_pageLoadState.didStartProvisionalLoad(transaction, url, unreachableURL);
2514
2515     frame->setUnreachableURL(unreachableURL);
2516     frame->didStartProvisionalLoad(url);
2517
2518     m_pageLoadState.commitChanges();
2519     m_loaderClient->didStartProvisionalLoadForFrame(this, frame, navigationID, userData.get());
2520 }
2521
2522 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& url, IPC::MessageDecoder& decoder)
2523 {
2524     RefPtr<API::Object> userData;
2525     WebContextUserMessageDecoder messageDecoder(userData, process());
2526     if (!decoder.decode(messageDecoder))
2527         return;
2528
2529     WebFrameProxy* frame = m_process->webFrame(frameID);
2530     MESSAGE_CHECK(frame);
2531     MESSAGE_CHECK_URL(url);
2532
2533     auto transaction = m_pageLoadState.transaction();
2534
2535     if (frame->isMainFrame())
2536         m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
2537
2538     frame->didReceiveServerRedirectForProvisionalLoad(url);
2539
2540     m_pageLoadState.commitChanges();
2541     m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(this, frame, navigationID, userData.get());
2542 }
2543
2544 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, IPC::MessageDecoder& decoder)
2545 {
2546     RefPtr<API::Object> userData;
2547     WebContextUserMessageDecoder messageDecoder(userData, process());
2548     if (!decoder.decode(messageDecoder))
2549         return;
2550
2551     WebFrameProxy* frame = m_process->webFrame(frameID);
2552     MESSAGE_CHECK(frame);
2553
2554     auto transaction = m_pageLoadState.transaction();
2555
2556     if (frame->isMainFrame())
2557         m_pageLoadState.didFailProvisionalLoad(transaction);
2558
2559     frame->didFailProvisionalLoad();
2560
2561     m_pageLoadState.commitChanges();
2562     m_loaderClient->didFailProvisionalLoadWithErrorForFrame(this, frame, navigationID, error, userData.get());
2563 }
2564
2565 void WebPageProxy::clearLoadDependentCallbacks()
2566 {
2567     Vector<uint64_t> callbackIDsCopy;
2568     copyToVector(m_loadDependentStringCallbackIDs, callbackIDsCopy);
2569     m_loadDependentStringCallbackIDs.clear();
2570
2571     for (size_t i = 0; i < callbackIDsCopy.size(); ++i) {
2572         auto callback = m_callbacks.take<StringCallback>(callbackIDsCopy[i]);
2573         if (callback)
2574             callback->invalidate();
2575     }
2576 }
2577
2578 void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t opaqueFrameLoadType, const WebCore::CertificateInfo& certificateInfo, IPC::MessageDecoder& decoder)
2579 {
2580     RefPtr<API::Object> userData;
2581     WebContextUserMessageDecoder messageDecoder(userData, process());
2582     if (!decoder.decode(messageDecoder))
2583         return;
2584
2585     WebFrameProxy* frame = m_process->webFrame(frameID);
2586     MESSAGE_CHECK(frame);
2587
2588     auto transaction = m_pageLoadState.transaction();
2589
2590     if (frame->isMainFrame())
2591         m_pageLoadState.didCommitLoad(transaction);
2592
2593 #if USE(APPKIT)
2594     // FIXME (bug 59111): didCommitLoadForFrame comes too late when restoring a page from b/f cache, making us disable secure event mode in password fields.
2595     // FIXME: A load going on in one frame shouldn't affect text editing in other frames on the page.
2596     m_pageClient.resetSecureInputState();
2597     dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored);
2598     m_pageClient.dismissDictionaryLookupPanel();
2599 #endif
2600
2601     clearLoadDependentCallbacks();
2602
2603     frame->didCommitLoad(mimeType, certificateInfo);
2604
2605     if (frame->isMainFrame()) {
2606         m_mainFrameHasCustomContentProvider = frameHasCustomContentProvider;
2607
2608         if (m_mainFrameHasCustomContentProvider) {
2609             // Always assume that the main frame is pinned here, since the custom representation view will handle
2610             // any wheel events and dispatch them to the WKView when necessary.
2611             m_mainFrameIsPinnedToLeftSide = true;
2612             m_mainFrameIsPinnedToRightSide = true;
2613             m_mainFrameIsPinnedToTopSide = true;
2614             m_mainFrameIsPinnedToBottomSide = true;
2615
2616             m_uiClient->pinnedStateDidChange(*this);
2617         }
2618         m_pageClient.didCommitLoadForMainFrame(mimeType, frameHasCustomContentProvider);
2619     }
2620
2621     // Even if WebPage has the default pageScaleFactor (and therefore doesn't reset it),
2622     // WebPageProxy's cache of the value can get out of sync (e.g. in the case where a
2623     // plugin is handling page scaling itself) so we should reset it to the default
2624     // for standard main frame loads.
2625     if (frame->isMainFrame() && static_cast<FrameLoadType>(opaqueFrameLoadType) == FrameLoadType::Standard)
2626         m_pageScaleFactor = 1;
2627
2628     m_pageLoadState.commitChanges();
2629     m_loaderClient->didCommitLoadForFrame(this, frame, navigationID, userData.get());
2630 }
2631
2632 void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, IPC::MessageDecoder& decoder)
2633 {
2634     RefPtr<API::Object> userData;
2635     WebContextUserMessageDecoder messageDecoder(userData, process());
2636     if (!decoder.decode(messageDecoder))
2637         return;
2638
2639     WebFrameProxy* frame = m_process->webFrame(frameID);
2640     MESSAGE_CHECK(frame);
2641
2642     m_loaderClient->didFinishDocumentLoadForFrame(this, frame, navigationID, userData.get());
2643 }
2644
2645 void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, IPC::MessageDecoder& decoder)
2646 {
2647     RefPtr<API::Object> userData;
2648     WebContextUserMessageDecoder messageDecoder(userData, process());
2649     if (!decoder.decode(messageDecoder))
2650         return;
2651
2652     WebFrameProxy* frame = m_process->webFrame(frameID);
2653     MESSAGE_CHECK(frame);
2654
2655     auto transaction = m_pageLoadState.transaction();
2656
2657     if (frame->isMainFrame())
2658         m_pageLoadState.didFinishLoad(transaction);
2659
2660     frame->didFinishLoad();
2661
2662     m_pageLoadState.commitChanges();
2663     m_loaderClient->didFinishLoadForFrame(this, frame, navigationID, userData.get());
2664 }
2665
2666 void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID, const ResourceError& error, IPC::MessageDecoder& decoder)
2667 {
2668     RefPtr<API::Object> userData;
2669     WebContextUserMessageDecoder messageDecoder(userData, process());
2670     if (!decoder.decode(messageDecoder))
2671         return;
2672
2673     WebFrameProxy* frame = m_process->webFrame(frameID);
2674     MESSAGE_CHECK(frame);
2675
2676     clearLoadDependentCallbacks();
2677
2678     auto transaction = m_pageLoadState.transaction();
2679
2680     if (frame->isMainFrame())
2681         m_pageLoadState.didFailLoad(transaction);
2682
2683     frame->didFailLoad();
2684
2685     m_pageLoadState.commitChanges();
2686     m_loaderClient->didFailLoadWithErrorForFrame(this, frame, navigationID, error, userData.get());
2687 }
2688
2689 void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint64_t navigationID, uint32_t opaqueSameDocumentNavigationType, const String& url, IPC::MessageDecoder& decoder)
2690 {
2691     RefPtr<API::Object> userData;
2692     WebContextUserMessageDecoder messageDecoder(userData, process());
2693     if (!decoder.decode(messageDecoder))
2694         return;
2695
2696     WebFrameProxy* frame = m_process->webFrame(frameID);
2697     MESSAGE_CHECK(frame);
2698     MESSAGE_CHECK_URL(url);
2699
2700     auto transaction = m_pageLoadState.transaction();
2701
2702     if (frame->isMainFrame())
2703         m_pageLoadState.didSameDocumentNavigation(transaction, url);
2704
2705     m_pageLoadState.clearPendingAPIRequestURL(transaction);
2706     frame->didSameDocumentNavigation(url);
2707
2708     m_pageLoadState.commitChanges();
2709     m_loaderClient->didSameDocumentNavigationForFrame(this, frame, navigationID, static_cast<SameDocumentNavigationType>(opaqueSameDocumentNavigationType), userData.get());
2710 }
2711
2712 void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title, IPC::MessageDecoder& decoder)
2713 {
2714     RefPtr<API::Object> userData;
2715     WebContextUserMessageDecoder messageDecoder(userData, process());
2716     if (!decoder.decode(messageDecoder))
2717         return;
2718
2719     WebFrameProxy* frame = m_process->webFrame(frameID);
2720     MESSAGE_CHECK(frame);
2721
2722     auto transaction = m_pageLoadState.transaction();
2723
2724     if (frame->isMainFrame())
2725         m_pageLoadState.setTitle(transaction, title);
2726
2727     frame->didChangeTitle(title);
2728     
2729     m_pageLoadState.commitChanges();
2730     m_loaderClient->didReceiveTitleForFrame(this, title, frame, userData.get());
2731 }
2732
2733 void WebPageProxy::didFirstLayoutForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2734 {
2735     RefPtr<API::Object> userData;
2736     WebContextUserMessageDecoder messageDecoder(userData, process());
2737     if (!decoder.decode(messageDecoder))
2738         return;
2739
2740     WebFrameProxy* frame = m_process->webFrame(frameID);
2741     MESSAGE_CHECK(frame);
2742
2743     m_loaderClient->didFirstLayoutForFrame(this, frame, userData.get());
2744 }
2745
2746 void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2747 {
2748     RefPtr<API::Object> userData;
2749     WebContextUserMessageDecoder messageDecoder(userData, process());
2750     if (!decoder.decode(messageDecoder))
2751         return;
2752
2753     WebFrameProxy* frame = m_process->webFrame(frameID);
2754     MESSAGE_CHECK(frame);
2755
2756     m_loaderClient->didFirstVisuallyNonEmptyLayoutForFrame(this, frame, userData.get());
2757 }
2758
2759 void WebPageProxy::didLayout(uint32_t layoutMilestones, IPC::MessageDecoder& decoder)
2760 {
2761     RefPtr<API::Object> userData;
2762     WebContextUserMessageDecoder messageDecoder(userData, process());
2763     if (!decoder.decode(messageDecoder))
2764         return;
2765
2766     m_loaderClient->didLayout(this, static_cast<LayoutMilestones>(layoutMilestones), userData.get());
2767 }
2768
2769 void WebPageProxy::didRemoveFrameFromHierarchy(uint64_t frameID, IPC::MessageDecoder& decoder)
2770 {
2771     RefPtr<API::Object> userData;
2772     WebContextUserMessageDecoder messageDecoder(userData, process());
2773     if (!decoder.decode(messageDecoder))
2774         return;
2775
2776     WebFrameProxy* frame = m_process->webFrame(frameID);
2777     MESSAGE_CHECK(frame);
2778
2779     m_loaderClient->didRemoveFrameFromHierarchy(this, frame, userData.get());
2780 }
2781
2782 void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2783 {
2784     RefPtr<API::Object> userData;
2785     WebContextUserMessageDecoder messageDecoder(userData, process());
2786     if (!decoder.decode(messageDecoder))
2787         return;
2788
2789     WebFrameProxy* frame = m_process->webFrame(frameID);
2790     MESSAGE_CHECK(frame);
2791
2792     auto transaction = m_pageLoadState.transaction();
2793     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
2794
2795     m_pageLoadState.commitChanges();
2796     m_loaderClient->didDisplayInsecureContentForFrame(this, frame, userData.get());
2797 }
2798
2799 void WebPageProxy::didRunInsecureContentForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2800 {
2801     RefPtr<API::Object> userData;
2802     WebContextUserMessageDecoder messageDecoder(userData, process());
2803     if (!decoder.decode(messageDecoder))
2804         return;
2805
2806     WebFrameProxy* frame = m_process->webFrame(frameID);
2807     MESSAGE_CHECK(frame);
2808
2809     auto transaction = m_pageLoadState.transaction();
2810     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
2811
2812     m_pageLoadState.commitChanges();
2813     m_loaderClient->didRunInsecureContentForFrame(this, frame, userData.get());
2814 }
2815
2816 void WebPageProxy::didDetectXSSForFrame(uint64_t frameID, IPC::MessageDecoder& decoder)
2817 {
2818     RefPtr<API::Object> userData;
2819     WebContextUserMessageDecoder messageDecoder(userData, process());
2820     if (!decoder.decode(messageDecoder))
2821         return;
2822
2823     WebFrameProxy* frame = m_process->webFrame(frameID);
2824     MESSAGE_CHECK(frame);
2825
2826     m_loaderClient->didDetectXSSForFrame(this, frame, userData.get());
2827 }
2828
2829 void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value)
2830 {
2831     WebFrameProxy* frame = m_process->webFrame(frameID);
2832     MESSAGE_CHECK(frame);
2833
2834     frame->setIsFrameSet(value);
2835     if (frame->isMainFrame())
2836         m_frameSetLargestFrame = value ? m_mainFrame : 0;
2837 }
2838
2839 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)
2840 {
2841     RefPtr<API::Object> userData;
2842     WebContextUserMessageDecoder messageDecoder(userData, process());
2843     if (!decoder.decode(messageDecoder))
2844         return;
2845
2846     auto transaction = m_pageLoadState.transaction();
2847
2848     if (request.url() != m_pageLoadState.pendingAPIRequestURL())
2849         m_pageLoadState.clearPendingAPIRequestURL(transaction);
2850
2851     WebFrameProxy* frame = m_process->webFrame(frameID);
2852     MESSAGE_CHECK(frame);
2853     MESSAGE_CHECK_URL(request.url());
2854     MESSAGE_CHECK_URL(originalRequest.url());
2855
2856     WebFrameProxy* originatingFrame = m_process->webFrame(originatingFrameID);
2857     
2858     RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
2859     if (!navigationID && frame->isMainFrame()) {
2860         newNavigationID = generateNavigationID();
2861         listener->setNavigationID(newNavigationID);
2862     }
2863
2864 #if ENABLE(CONTENT_FILTERING)
2865     if (frame->contentFilterDidHandleNavigationAction(request)) {
2866         receivedPolicyAction = true;
2867         policyAction = PolicyIgnore;
2868         return;
2869     }
2870 #endif
2871
2872     ASSERT(!m_inDecidePolicyForNavigationAction);
2873
2874     m_inDecidePolicyForNavigationAction = true;
2875     m_syncNavigationActionPolicyActionIsValid = false;
2876
2877     m_policyClient->decidePolicyForNavigationAction(this, frame, navigationActionData, originatingFrame, originalRequest, request, WTF::move(listener), userData.get());
2878
2879     m_inDecidePolicyForNavigationAction = false;
2880
2881     // Check if we received a policy decision already. If we did, we can just pass it back.
2882     receivedPolicyAction = m_syncNavigationActionPolicyActionIsValid;
2883     if (m_syncNavigationActionPolicyActionIsValid) {
2884         policyAction = m_syncNavigationActionPolicyAction;
2885         downloadID = m_syncNavigationActionPolicyDownloadID;
2886     }
2887 }
2888
2889 void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, const NavigationActionData& navigationActionData, const ResourceRequest& request, const String& frameName, uint64_t listenerID, IPC::MessageDecoder& decoder)
2890 {
2891     RefPtr<API::Object> userData;
2892     WebContextUserMessageDecoder messageDecoder(userData, process());
2893     if (!decoder.decode(messageDecoder))
2894         return;
2895
2896     WebFrameProxy* frame = m_process->webFrame(frameID);
2897     MESSAGE_CHECK(frame);
2898     MESSAGE_CHECK_URL(request.url());
2899
2900     RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
2901
2902     m_policyClient->decidePolicyForNewWindowAction(this, frame, navigationActionData, request, frameName, WTF::move(listener), userData.get());
2903 }
2904
2905 void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, IPC::MessageDecoder& decoder)
2906 {
2907     RefPtr<API::Object> userData;
2908     WebContextUserMessageDecoder messageDecoder(userData, process());
2909     if (!decoder.decode(messageDecoder))
2910         return;
2911
2912     WebFrameProxy* frame = m_process->webFrame(frameID);
2913     MESSAGE_CHECK(frame);
2914     MESSAGE_CHECK_URL(request.url());
2915     MESSAGE_CHECK_URL(response.url());
2916
2917     RefPtr<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
2918
2919     m_policyClient->decidePolicyForResponse(this, frame, response, request, canShowMIMEType, WTF::move(listener), userData.get());
2920 }
2921
2922 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)
2923 {
2924     ASSERT(!m_inDecidePolicyForResponseSync);
2925
2926     m_inDecidePolicyForResponseSync = true;
2927     m_decidePolicyForResponseRequest = &request;
2928     m_syncMimeTypePolicyActionIsValid = false;
2929
2930     decidePolicyForResponse(frameID, response, request, canShowMIMEType, listenerID, decoder);
2931
2932     m_inDecidePolicyForResponseSync = false;
2933     m_decidePolicyForResponseRequest = 0;
2934
2935     // Check if we received a policy decision already. If we did, we can just pass it back.
2936     receivedPolicyAction = m_syncMimeTypePolicyActionIsValid;
2937     if (m_syncMimeTypePolicyActionIsValid) {
2938         policyAction = m_syncMimeTypePolicyAction;
2939         downloadID = m_syncMimeTypePolicyDownloadID;
2940     }
2941 }
2942
2943 void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError& error, IPC::MessageDecoder& decoder)
2944 {
2945     RefPtr<API::Object> userData;
2946     WebContextUserMessageDecoder messageDecoder(userData, process());
2947     if (!decoder.decode(messageDecoder))
2948         return;
2949     
2950     WebFrameProxy* frame = m_process->webFrame(frameID);
2951     MESSAGE_CHECK(frame);
2952
2953     m_policyClient->unableToImplementPolicy(this, frame, error, userData.get());
2954 }
2955
2956 // FormClient
2957
2958 void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, IPC::MessageDecoder& decoder)
2959 {
2960     RefPtr<API::Object> userData;
2961     WebContextUserMessageDecoder messageDecoder(userData, process());
2962     if (!decoder.decode(messageDecoder))
2963         return;
2964
2965     WebFrameProxy* frame = m_process->webFrame(frameID);
2966     MESSAGE_CHECK(frame);
2967
2968     WebFrameProxy* sourceFrame = m_process->webFrame(sourceFrameID);
2969     MESSAGE_CHECK(sourceFrame);
2970
2971     RefPtr<WebFormSubmissionListenerProxy> listener = frame->setUpFormSubmissionListenerProxy(listenerID);
2972     if (!m_formClient->willSubmitForm(this, frame, sourceFrame, textFieldValues, userData.get(), listener.get()))
2973         listener->continueSubmission();
2974 }
2975
2976 // UIClient
2977
2978 void WebPageProxy::createNewPage(uint64_t frameID, const ResourceRequest& request, const WindowFeatures& windowFeatures, const NavigationActionData& navigationActionData, uint64_t& newPageID, WebPageCreationParameters& newPageParameters)
2979 {
2980     WebFrameProxy* frame = m_process->webFrame(frameID);
2981     MESSAGE_CHECK(frame);
2982
2983     RefPtr<WebPageProxy> newPage = m_uiClient->createNewPage(this, frame, request, windowFeatures, navigationActionData);
2984     if (!newPage) {
2985         newPageID = 0;
2986         return;
2987     }
2988
2989     newPageID = newPage->pageID();
2990     newPageParameters = newPage->creationParameters();
2991     process().context().storageManager().cloneSessionStorageNamespace(m_pageID, newPage->pageID());
2992 }
2993     
2994 void WebPageProxy::showPage()
2995 {
2996     m_uiClient->showPage(this);
2997 }
2998
2999 void WebPageProxy::closePage(bool stopResponsivenessTimer)
3000 {
3001     if (stopResponsivenessTimer)
3002         m_process->responsivenessTimer()->stop();
3003
3004     m_pageClient.clearAllEditCommands();
3005     m_uiClient->close(this);
3006 }
3007
3008 void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const String& message, RefPtr<Messages::WebPageProxy::RunJavaScriptAlert::DelayedReply> reply)
3009 {
3010     WebFrameProxy* frame = m_process->webFrame(frameID);
3011     MESSAGE_CHECK(frame);
3012
3013     // Since runJavaScriptAlert() can spin a nested run loop we need to turn off the responsiveness timer.
3014     m_process->responsivenessTimer()->stop();
3015
3016     m_uiClient->runJavaScriptAlert(this, message, frame, [reply]{ reply->send(); });
3017 }
3018
3019 void WebPageProxy::runJavaScriptConfirm(uint64_t frameID, const String& message, RefPtr<Messages::WebPageProxy::RunJavaScriptConfirm::DelayedReply> reply)
3020 {
3021     WebFrameProxy* frame = m_process->webFrame(frameID);
3022     MESSAGE_CHECK(frame);
3023
3024     // Since runJavaScriptConfirm() can spin a nested run loop we need to turn off the responsiveness timer.
3025     m_process->responsivenessTimer()->stop();
3026
3027     m_uiClient->runJavaScriptConfirm(this, message, frame, [reply](bool result) { reply->send(result); });
3028 }
3029
3030 void WebPageProxy::runJavaScriptPrompt(uint64_t frameID, const String& message, const String& defaultValue, RefPtr<Messages::WebPageProxy::RunJavaScriptPrompt::DelayedReply> reply)
3031 {
3032     WebFrameProxy* frame = m_process->webFrame(frameID);
3033     MESSAGE_CHECK(frame);
3034
3035     // Since runJavaScriptPrompt() can spin a nested run loop we need to turn off the responsiveness timer.
3036     m_process->responsivenessTimer()->stop();
3037
3038     m_uiClient->runJavaScriptPrompt(this, message, defaultValue, frame, [reply](const String& result) { reply->send(result); });
3039 }
3040
3041 void WebPageProxy::shouldInterruptJavaScript(bool& result)
3042 {
3043     // Since shouldInterruptJavaScript() can spin a nested run loop we need to turn off the responsiveness timer.
3044     m_process->responsivenessTimer()->stop();
3045
3046     result = m_uiClient->shouldInterruptJavaScript(this);
3047 }
3048
3049 void WebPageProxy::setStatusText(const String& text)
3050 {
3051     m_uiClient->setStatusText(this, text);
3052 }
3053
3054 void WebPageProxy::mouseDidMoveOverElement(const WebHitTestResult::Data& hitTestResultData, uint32_t opaqueModifiers, IPC::MessageDecoder& decoder)
3055 {
3056     RefPtr<API::Object> userData;
3057     WebContextUserMessageDecoder messageDecoder(userData, process());
3058     if (!decoder.decode(messageDecoder))
3059         return;
3060
3061     WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(opaqueModifiers);
3062
3063     m_uiClient->mouseDidMoveOverElement(this, hitTestResultData, modifiers, userData.get());
3064 }
3065
3066 void WebPageProxy::connectionWillOpen(IPC::Connection* connection)
3067 {
3068     ASSERT(connection == m_process->connection());
3069
3070     m_process->context().storageManager().setAllowedSessionStorageNamespaceConnection(m_pageID, connection);
3071 }
3072
3073 void WebPageProxy::connectionWillClose(IPC::Connection* connection)
3074 {
3075     ASSERT_UNUSED(connection, connection == m_process->connection());
3076
3077     m_process->context().storageManager().setAllowedSessionStorageNamespaceConnection(m_pageID, 0);
3078 }
3079
3080 void WebPageProxy::processDidFinishLaunching()
3081 {
3082     if (m_userContentController)
3083         m_userContentController->addProcess(m_process.get());
3084     m_visitedLinkProvider->addProcess(m_process.get());
3085 }
3086
3087 #if ENABLE(NETSCAPE_PLUGIN_API)
3088 void WebPageProxy::unavailablePluginButtonClicked(uint32_t opaquePluginUnavailabilityReason, const String& mimeType, const String& pluginURLString, const String& pluginspageAttributeURLString, const String& frameURLString, const String& pageURLString)
3089 {
3090     MESSAGE_CHECK_URL(pluginURLString);
3091     MESSAGE_CHECK_URL(pluginspageAttributeURLString);
3092     MESSAGE_CHECK_URL(frameURLString);
3093     MESSAGE_CHECK_URL(pageURLString);
3094
3095     RefPtr<ImmutableDictionary> pluginInformation;
3096     String newMimeType = mimeType;
3097     PluginModuleInfo plugin = m_process->context().pluginInfoStore().findPlugin(newMimeType, URL(URL(), pluginURLString));
3098     pluginInformation = createPluginInformationDictionary(plugin, frameURLString, mimeType, pageURLString, pluginspageAttributeURLString, pluginURLString);
3099
3100     WKPluginUnavailabilityReason pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
3101     switch (static_cast<RenderEmbeddedObject::PluginUnavailabilityReason>(opaquePluginUnavailabilityReason)) {
3102     case RenderEmbeddedObject::PluginMissing:
3103         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginMissing;
3104         break;
3105     case RenderEmbeddedObject::InsecurePluginVersion:
3106         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonInsecurePluginVersion;
3107         break;
3108     case RenderEmbeddedObject::PluginCrashed:
3109         pluginUnavailabilityReason = kWKPluginUnavailabilityReasonPluginCrashed;
3110         break;
3111     case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy:
3112         ASSERT_NOT_REACHED();
3113     }
3114
3115     m_uiClient->unavailablePluginButtonClicked(this, pluginUnavailabilityReason, pluginInformation.get());
3116 }
3117 #endif // ENABLE(NETSCAPE_PLUGIN_API)
3118
3119 #if ENABLE(WEBGL)
3120 void WebPageProxy::webGLPolicyForURL(const String& url, uint32_t& loadPolicy)
3121 {
3122     loadPolicy = static_cast<uint32_t>(m_loaderClient->webGLLoadPolicy(this, url));
3123 }
3124
3125 void WebPageProxy::resolveWebGLPolicyForURL(const String& url, uint32_t& loadPolicy)
3126 {
3127     loadPolicy = static_cast<uint32_t>(m_loaderClient->resolveWebGLLoadPolicy(this, url));
3128 }
3129 #endif // ENABLE(WEBGL)
3130
3131 void WebPageProxy::setToolbarsAreVisible(bool toolbarsAreVisible)
3132 {
3133     m_uiClient->setToolbarsAreVisible(this, toolbarsAreVisible);
3134 }
3135
3136 void WebPageProxy::getToolbarsAreVisible(bool& toolbarsAreVisible)
3137 {
3138     toolbarsAreVisible = m_uiClient->toolbarsAreVisible(this);
3139 }
3140
3141 void WebPageProxy::setMenuBarIsVisible(bool menuBarIsVisible)
3142 {
3143     m_uiClient->setMenuBarIsVisible(this, menuBarIsVisible);
3144 }
3145
3146 void WebPageProxy::getMenuBarIsVisible(bool& menuBarIsVisible)
3147 {
3148     menuBarIsVisible = m_uiClient->menuBarIsVisible(this);
3149 }
3150
3151 void WebPageProxy::setStatusBarIsVisible(bool statusBarIsVisible)
3152 {
3153     m_uiClient->setStatusBarIsVisible(this, statusBarIsVisible);
3154 }
3155
3156 void WebPageProxy::getStatusBarIsVisible(bool& statusBarIsVisible)
3157 {
3158     statusBarIsVisible = m_uiClient->statusBarIsVisible(this);
3159 }
3160
3161 void WebPageProxy::setIsResizable(bool isResizable)
3162 {
3163     m_uiClient->setIsResizable(this, isResizable);
3164 }
3165
3166 void WebPageProxy::getIsResizable(bool& isResizable)
3167 {
3168     isResizable = m_uiClient->isResizable(this);
3169 }
3170
3171 void WebPageProxy::setWindowFrame(const FloatRect& newWindowFrame)
3172 {
3173     m_uiClient->setWindowFrame(this, m_pageClient.convertToDeviceSpace(newWindowFrame));
3174 }
3175
3176 void WebPageProxy::getWindowFrame(FloatRect& newWindowFrame)
3177 {
3178     newWindowFrame = m_pageClient.convertToUserSpace(m_uiClient->windowFrame(this));
3179 }
3180     
3181 void WebPageProxy::screenToRootView(const IntPoint& screenPoint, IntPoint& windowPoint)
3182 {
3183     windowPoint = m_pageClient.screenToRootView(screenPoint);
3184 }
3185     
3186 void WebPageProxy::rootViewToScreen(const IntRect& viewRect, IntRect& result)
3187 {
3188     result = m_pageClient.rootViewToScreen(viewRect);
3189 }
3190     
3191 #if PLATFORM(IOS)
3192 void WebPageProxy::accessibilityScreenToRootView(const IntPoint& screenPoint, IntPoint& windowPoint)
3193 {
3194     windowPoint = m_pageClient.accessibilityScreenToRootView(screenPoint);
3195 }
3196
3197 void WebPageProxy::rootViewToAccessibilityScreen(const IntRect& viewRect, IntRect& result)
3198 {
3199     result = m_pageClient.rootViewToAccessibilityScreen(viewRect);
3200 }
3201 #endif
3202     
3203 void WebPageProxy::runBeforeUnloadConfirmPanel(const String& message, uint64_t frameID, bool& shouldClose)
3204 {
3205     WebFrameProxy* frame = m_process->webFrame(frameID);
3206     MESSAGE_CHECK(frame);
3207
3208     // Since runBeforeUnloadConfirmPanel() can spin a nested run loop we need to turn off the responsiveness timer.
3209     m_process->responsivenessTimer()->stop();
3210
3211     shouldClose = m_uiClient->runBeforeUnloadConfirmPanel(this, message, frame);
3212 }
3213
3214 #if USE(TILED_BACKING_STORE)
3215 void WebPageProxy::pageDidRequestScroll(const IntPoint& point)
3216 {
3217     m_pageClient.pageDidRequestScroll(point);
3218 }
3219
3220 void WebPageProxy::pageTransitionViewportReady()
3221 {
3222     m_pageClient.pageTransitionViewportReady();
3223 }
3224
3225 void WebPageProxy::didRenderFrame(const WebCore::IntSize& contentsSize, const WebCore::IntRect& coveredRect)
3226 {
3227     m_pageClient.didRenderFrame(contentsSize, coveredRect);
3228 }
3229
3230 #endif
3231
3232 void WebPageProxy::didChangeViewportProperties(const ViewportAttributes& attr)
3233 {
3234     m_pageClient.didChangeViewportProperties(attr);
3235 }
3236
3237 void WebPageProxy::pageDidScroll()
3238 {
3239     m_uiClient->pageDidScroll(this);
3240 #if PLATFORM(MAC)
3241     dismissCorrectionPanel(ReasonForDismissingAlternativeTextIgnored);
3242 #endif
3243 }
3244
3245 void WebPageProxy::runOpenPanel(uint64_t frameID, const FileChooserSettings& settings)
3246 {
3247     if (m_openPanelResultListener) {
3248         m_openPanelResultListener->invalidate();
3249         m_openPanelResultListener = 0;
3250     }
3251
3252     WebFrameProxy* frame = m_process->webFrame(frameID);
3253     MESSAGE_CHECK(frame);
3254
3255     RefPtr<WebOpenPanelParameters> parameters = WebOpenPanelParameters::create(settings);
3256     m_openPanelResultListener = WebOpenPanelResultListenerProxy::create(this);
3257
3258     // Since runOpenPanel() can spin a nested run loop we need to turn off the responsiveness timer.
3259     m_process->responsivenessTimer()->stop();
3260
3261     if (!m_uiClient->runOpenPanel(this, frame, parameters.get(), m_openPanelResultListener.get())) {
3262         if (!m_pageClient.handleRunOpenPanel(this, frame, parameters.get(), m_openPanelResultListener.get()))
3263             didCancelForOpenPanel();
3264     }
3265 }
3266
3267 void WebPageProxy::printFrame(uint64_t frameID)
3268 {
3269     ASSERT(!m_isPerformingDOMPrintOperation);
3270     m_isPerformingDOMPrintOperation = true;
3271
3272     WebFrameProxy* frame = m_process->webFrame(frameID);
3273     MESSAGE_CHECK(frame);
3274
3275     m_uiClient->printFrame(this, frame);
3276
3277     endPrinting(); // Send a message synchronously while m_isPerformingDOMPrintOperation is still true.
3278     m_isPerformingDOMPrintOperation = false;
3279 }
3280
3281 void WebPageProxy::printMainFrame()
3282 {
3283     printFrame(m_mainFrame->frameID());
3284 }
3285
3286 void WebPageProxy::setMediaVolume(float volume)
3287 {
3288     if (volume == m_mediaVolume)
3289         return;
3290     
3291     m_mediaVolume = volume;
3292     
3293     if (!isValid())
3294         return;
3295     
3296     m_process->send(Messages::WebPage::SetMediaVolume(volume), m_pageID);    
3297 }
3298
3299 void WebPageProxy::setMayStartMediaWhenInWindow(bool mayStartMedia)
3300 {
3301     if (mayStartMedia == m_mayStartMediaWhenInWindow)
3302         return;
3303
3304     m_mayStartMediaWhenInWindow = mayStartMedia;
3305
3306     if (!isValid())
3307         return;
3308
3309     process().send(Messages::WebPage::SetMayStartMediaWhenInWindow(mayStartMedia), m_pageID);
3310 }
3311
3312 void WebPageProxy::handleDownloadRequest(DownloadProxy* download)
3313 {
3314     m_pageClient.handleDownloadRequest(download);
3315 }
3316
3317 #if PLATFORM(EFL)
3318 void WebPageProxy::didChangeContentSize(const IntSize& size)
3319 {
3320     m_pageClient.didChangeContentSize(size);
3321 }
3322 #endif
3323
3324 #if ENABLE(INPUT_TYPE_COLOR)
3325 void WebPageProxy::showColorPicker(const WebCore::Color& initialColor, const IntRect& elementRect)
3326 {
3327 #if ENABLE(INPUT_TYPE_COLOR_POPOVER)
3328     // A new popover color well needs to be created (and the previous one destroyed) for
3329     // each activation of a color element.
3330     m_colorPicker = 0;
3331 #endif
3332     if (!m_colorPicker)
3333         m_colorPicker = m_pageClient.createColorPicker(this, initialColor, elementRect);
3334     m_colorPicker->showColorPicker(initialColor);
3335 }
3336
3337 void WebPageProxy::setColorPickerColor(const WebCore::Color& color)
3338 {
3339     ASSERT(m_colorPicker);
3340
3341     m_colorPicker->setSelectedColor(color);
3342 }
3343
3344 void WebPageProxy::endColorPicker()
3345 {
3346     ASSERT(m_colorPicker);
3347
3348     m_colorPicker->endPicker();
3349 }
3350
3351 void WebPageProxy::didChooseColor(const WebCore::Color& color)
3352 {
3353     if (!isValid())
3354         return;
3355
3356     m_process->send(Messages::WebPage::DidChooseColor(color), m_pageID);
3357 }
3358
3359 void WebPageProxy::didEndColorPicker()
3360 {
3361     if (!isValid())
3362         return;
3363
3364     if (m_colorPicker) {
3365         m_colorPicker->invalidate();
3366         m_colorPicker = nullptr;
3367     }
3368
3369     m_process->send(Messages::WebPage::DidEndColorPicker(), m_pageID);
3370 }
3371 #endif
3372
3373 void WebPageProxy::didDraw()
3374 {
3375     m_uiClient->didDraw(this);
3376 }
3377
3378 // Inspector
3379
3380 #if ENABLE(INSPECTOR)
3381
3382 WebInspectorProxy* WebPageProxy::inspector()
3383 {
3384     if (isClosed() || !isValid())
3385         return 0;
3386     return m_inspector.get();
3387 }
3388
3389 #endif
3390
3391 #if ENABLE(FULLSCREEN_API)
3392 WebFullScreenManagerProxy* WebPageProxy::fullScreenManager()
3393 {
3394     return m_fullScreenManager.get();
3395 }
3396 #endif
3397     
3398 #if PLATFORM(IOS)
3399 RefPtr<WebVideoFullscreenManagerProxy> WebPageProxy::videoFullscreenManager()
3400 {
3401     return m_videoFullscreenManager;
3402 }
3403 #endif
3404
3405 // BackForwardList
3406
3407 void WebPageProxy::backForwardAddItem(uint64_t itemID)
3408 {
3409     m_backForwardList->addItem(m_process->webBackForwardItem(itemID));
3410 }
3411
3412 void WebPageProxy::backForwardGoToItem(uint64_t itemID, SandboxExtension::Handle& sandboxExtensionHandle)
3413 {
3414     WebBackForwardListItem* item = m_process->webBackForwardItem(itemID);
3415     if (!item)
3416         return;
3417
3418     bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), item->url()), sandboxExtensionHandle);
3419     if (createdExtension)
3420         m_process->willAcquireUniversalFileReadSandboxExtension();
3421     m_backForwardList->goToItem(item);
3422 }
3423
3424 void WebPageProxy::backForwardItemAtIndex(int32_t index, uint64_t& itemID)
3425 {
3426     WebBackForwardListItem* item = m_backForwardList->itemAtIndex(index);
3427     itemID = item ? item->itemID() : 0;
3428 }
3429
3430 void WebPageProxy::backForwardBackListCount(int32_t& count)
3431 {
3432     count = m_backForwardList->backListCount();
3433 }
3434
3435 void WebPageProxy::backForwardForwardListCount(int32_t& count)
3436 {
3437     count = m_backForwardList->forwardListCount();
3438 }
3439
3440 void WebPageProxy::editorStateChanged(const EditorState& editorState)
3441 {
3442 #if PLATFORM(COCOA)
3443     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
3444 #endif
3445 #if PLATFORM(MAC) && !USE(ASYNC_NSTEXTINPUTCLIENT)
3446     bool closedComposition = !editorState.shouldIgnoreCompositionSelectionChange && !editorState.hasComposition && (m_editorState.hasComposition || m_temporarilyClosedComposition);
3447     m_temporarilyClosedComposition = editorState.shouldIgnoreCompositionSelectionChange && (m_temporarilyClosedComposition || m_editorState.hasComposition) && !editorState.hasComposition;
3448 #endif
3449
3450     m_editorState = editorState;
3451
3452 #if PLATFORM(COCOA)
3453     // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
3454     if (couldChangeSecureInputState && !editorState.selectionIsNone)
3455         m_pageClient.updateSecureInputState();
3456 #endif
3457
3458     if (editorState.shouldIgnoreCompositionSelectionChange)
3459         return;
3460
3461 #if PLATFORM(MAC) && !USE(ASYNC_NSTEXTINPUTCLIENT)
3462     if (closedComposition)
3463         m_pageClient.notifyInputContextAboutDiscardedComposition();
3464     if (editorState.hasComposition) {
3465         // Abandon the current inline input session if selection changed for any other reason but an input method changing the composition.
3466         // FIXME: This logic should be in WebCore, no need to round-trip to UI process to cancel the composition.
3467         cancelComposition();
3468         m_pageClient.notifyInputContextAboutDiscardedComposition();
3469     }
3470 #elif PLATFORM(IOS)
3471     // We always need to notify the client on iOS to make sure the selection is redrawn,
3472     // even during composition to support phrase boundary gesture.
3473     notifyRevealedSelection();
3474 #elif PLATFORM(EFL) || PLATFORM(GTK)
3475     m_pageClient.updateTextInputState();
3476 #endif
3477 }
3478
3479 void WebPageProxy::compositionWasCanceled(const EditorState& editorState)
3480 {
3481 #if PLATFORM(COCOA)
3482     m_pageClient.notifyInputContextAboutDiscardedComposition();
3483 #endif
3484     editorStateChanged(editorState);
3485 }
3486
3487 // Undo management
3488
3489 void WebPageProxy::registerEditCommandForUndo(uint64_t commandID, uint32_t editAction)
3490 {
3491     registerEditCommand(WebEditCommandProxy::create(commandID, static_cast<EditAction>(editAction), this), Undo);
3492 }
3493     
3494 void WebPageProxy::registerInsertionUndoGrouping()
3495 {
3496 #if USE(INSERTION_UNDO_GROUPING)
3497     m_pageClient.registerInsertionUndoGrouping();
3498 #endif
3499 }
3500
3501 void WebPageProxy::canUndoRedo(uint32_t action, bool& result)
3502 {
3503     result = m_pageClient.canUndoRedo(static_cast<UndoOrRedo>(action));
3504 }
3505
3506 void WebPageProxy::executeUndoRedo(uint32_t action, bool& result)
3507 {
3508     m_pageClient.executeUndoRedo(static_cast<UndoOrRedo>(action));
3509     result = true;
3510 }
3511
3512 void WebPageProxy::clearAllEditCommands()
3513 {
3514     m_pageClient.clearAllEditCommands();
3515 }
3516
3517 void WebPageProxy::didCountStringMatches(const String& string, uint32_t matchCount)
3518 {
3519     m_findClient->didCountStringMatches(this, string, matchCount);
3520 }
3521
3522 void WebPageProxy::didGetImageForFindMatch(const ShareableBitmap::Handle& contentImageHandle, uint32_t matchIndex)
3523 {
3524     m_findMatchesClient.didGetImageForMatchResult(this, WebImage::create(ShareableBitmap::create(contentImageHandle)).get(), matchIndex);
3525 }
3526
3527 void WebPageProxy::setFindIndicator(const FloatRect& selectionRectInWindowCoordinates, const Vector<FloatRect>& textRectsInSelectionRectCoordinates, float contentImageScaleFactor, const ShareableBitmap::Handle& contentImageHandle, bool fadeOut, bool animate)
3528 {
3529     RefPtr<FindIndicator> findIndicator = FindIndicator::create(selectionRectInWindowCoordinates, textRectsInSelectionRectCoordinates, contentImageScaleFactor, contentImageHandle);
3530     m_pageClient.setFindIndicator(findIndicator.release(), fadeOut, animate);
3531 }
3532
3533 void WebPageProxy::didFindString(const String& string, uint32_t matchCount, int32_t matchIndex)
3534 {
3535     m_findClient->didFindString(this, string, matchCount, matchIndex);
3536 }
3537
3538 void WebPageProxy::didFindStringMatches(const String& string, const Vector<Vector<WebCore::IntRect>>& matchRects, int32_t firstIndexAfterSelection)
3539 {
3540     Vector<RefPtr<API::Object>> matches;
3541     matches.reserveInitialCapacity(matchRects.size());
3542
3543     for (const auto& rects : matchRects) {
3544         Vector<RefPtr<API::Object>> apiRects;
3545         apiRects.reserveInitialCapacity(rects.size());
3546
3547         for (const auto& rect : rects)
3548             apiRects.uncheckedAppend(API::Rect::create(toAPI(rect)));
3549
3550         matches.uncheckedAppend(API::Array::create(WTF::move(apiRects)));
3551     }
3552
3553     m_findMatchesClient.didFindStringMatches(this, string, API::Array::create(WTF::move(matches)).get(), firstIndexAfterSelection);
3554 }
3555
3556 void WebPageProxy::didFailToFindString(const String& string)
3557 {
3558     m_findClient->didFailToFindString(this, string);
3559 }
3560
3561 bool WebPageProxy::sendMessage(std::unique_ptr<IPC::MessageEncoder> encoder, unsigned messageSendFlags)
3562 {
3563     return m_process->sendMessage(WTF::move(encoder), messageSendFlags);
3564 }
3565
3566 IPC::Connection* WebPageProxy::messageSenderConnection()
3567 {
3568     return m_process->connection();
3569 }
3570
3571 uint64_t WebPageProxy::messageSenderDestinationID()
3572 {
3573     return m_pageID;
3574 }
3575
3576 void WebPageProxy::valueChangedForPopupMenu(WebPopupMenuProxy*, int32_t newSelectedIndex)
3577 {
3578     m_process->send(Messages::WebPage::DidChangeSelectedIndexForActivePopupMenu(newSelectedIndex), m_pageID);
3579 }
3580
3581 void WebPageProxy::setTextFromItemForPopupMenu(WebPopupMenuProxy*, int32_t index)
3582 {
3583     m_process->send(Messages::WebPage::SetTextForActivePopupMenu(index), m_pageID);
3584 }
3585
3586 NativeWebMouseEvent* WebPageProxy::currentlyProcessedMouseDownEvent()
3587 {
3588     return m_currentlyProcessedMouseDownEvent.get();
3589 }
3590
3591 void WebPageProxy::postMessageToInjectedBundle(const String& messageName, API::Object* messageBody)
3592 {
3593     process().send(Messages::WebPage::PostInjectedBundleMessage(messageName, WebContextUserMessageEncoder(messageBody, process())), m_pageID);
3594 }
3595
3596 #if PLATFORM(GTK)
3597 void WebPageProxy::failedToShowPopupMenu()
3598 {
3599     m_process->send(Messages::WebPage::FailedToShowPopupMenu(), m_pageID);
3600 }
3601 #endif
3602
3603 void WebPageProxy::showPopupMenu(const IntRect& rect, uint64_t textDirection, const Vector<WebPopupItem>& items, int32_t selectedIndex, const PlatformPopupMenuData& data)
3604 {
3605     if (m_activePopupMenu) {
3606 #if PLATFORM(EFL)
3607         m_uiPopupMenuClient.hidePopupMenu(this);
3608 #else
3609         m_activePopupMenu->hidePopupMenu();
3610 #endif
3611         m_activePopupMenu->invalidate();
3612         m_activePopupMenu = 0;
3613     }
3614
3615     m_activePopupMenu = m_pageClient.createPopupMenuProxy(this);
3616
3617     if (!m_activePopupMenu)
3618         return;
3619
3620     // Since showPopupMenu() can spin a nested run loop we need to turn off the responsiveness timer.
3621     m_process->responsivenessTimer()->stop();
3622
3623 #if PLATFORM(EFL)
3624     UNUSED_PARAM(data);
3625     m_uiPopupMenuClient.showPopupMenu(this, m_activePopupMenu.get(), rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, selectedIndex);
3626 #else
3627     RefPtr<WebPopupMenuProxy> protectedActivePopupMenu = m_activePopupMenu;
3628
3629     protectedActivePopupMenu->showPopupMenu(rect, static_cast<TextDirection>(textDirection), m_pageScaleFactor, items, data, selectedIndex);
3630
3631     // Since Efl doesn't use a nested mainloop to show the popup and get the answer, we need to keep the client pointer valid.
3632     // FIXME: The above comment doesn't make any sense since this code is compiled out for EFL.
3633     protectedActivePopupMenu->invalidate();
3634     protectedActivePopupMenu = 0;
3635 #endif
3636 }
3637
3638 void WebPageProxy::hidePopupMenu()
3639 {
3640     if (!m_activePopupMenu)
3641         return;
3642
3643 #if PLATFORM(EFL)
3644     m_uiPopupMenuClient.hidePopupMenu(this);