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