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