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