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