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