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