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