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