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