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