[PSON] Introduce a WebContent Process cache
[WebKit-https.git] / Source / WebKit / UIProcess / WebPageProxy.cpp
1 /*
2  * Copyright (C) 2010-2018 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 "APIAttachment.h"
32 #include "APIContextMenuClient.h"
33 #include "APIFindClient.h"
34 #include "APIFindMatchesClient.h"
35 #include "APIFormClient.h"
36 #include "APIFrameInfo.h"
37 #include "APIFullscreenClient.h"
38 #include "APIGeometry.h"
39 #include "APIHistoryClient.h"
40 #include "APIHitTestResult.h"
41 #include "APIIconLoadingClient.h"
42 #include "APILegacyContextHistoryClient.h"
43 #include "APILoaderClient.h"
44 #include "APINavigation.h"
45 #include "APINavigationAction.h"
46 #include "APINavigationClient.h"
47 #include "APINavigationResponse.h"
48 #include "APIOpenPanelParameters.h"
49 #include "APIPageConfiguration.h"
50 #include "APIPolicyClient.h"
51 #include "APISecurityOrigin.h"
52 #include "APIUIClient.h"
53 #include "APIURLRequest.h"
54 #include "APIWebsitePolicies.h"
55 #include "AuthenticationChallengeProxy.h"
56 #include "AuthenticationDecisionListener.h"
57 #include "DataReference.h"
58 #include "DownloadProxy.h"
59 #include "DrawingAreaMessages.h"
60 #include "DrawingAreaProxy.h"
61 #include "EventDispatcherMessages.h"
62 #include "FormDataReference.h"
63 #include "FrameInfoData.h"
64 #include "LoadParameters.h"
65 #include "Logging.h"
66 #include "NativeWebGestureEvent.h"
67 #include "NativeWebKeyboardEvent.h"
68 #include "NativeWebMouseEvent.h"
69 #include "NativeWebWheelEvent.h"
70 #include "NavigationActionData.h"
71 #include "NetworkProcessMessages.h"
72 #include "NetworkProcessProxy.h"
73 #include "NotificationPermissionRequest.h"
74 #include "NotificationPermissionRequestManager.h"
75 #include "OptionalCallbackID.h"
76 #include "PageClient.h"
77 #include "PluginInformation.h"
78 #include "PluginProcessManager.h"
79 #include "PrintInfo.h"
80 #include "ProvisionalPageProxy.h"
81 #include "SafeBrowsingWarning.h"
82 #include "ShareSheetCallbackID.h"
83 #include "SharedBufferDataReference.h"
84 #include "TextChecker.h"
85 #include "TextCheckerState.h"
86 #include "UIMessagePortChannelProvider.h"
87 #include "URLSchemeTaskParameters.h"
88 #include "UndoOrRedo.h"
89 #include "UserMediaPermissionRequestProxy.h"
90 #include "UserMediaProcessManager.h"
91 #include "WKContextPrivate.h"
92 #include "WebAutomationSession.h"
93 #include "WebBackForwardList.h"
94 #include "WebBackForwardListItem.h"
95 #include "WebCertificateInfo.h"
96 #include "WebContextMenuItem.h"
97 #include "WebContextMenuProxy.h"
98 #include "WebCoreArgumentCoders.h"
99 #include "WebEditCommandProxy.h"
100 #include "WebEvent.h"
101 #include "WebEventConversion.h"
102 #include "WebFramePolicyListenerProxy.h"
103 #include "WebFullScreenManagerProxy.h"
104 #include "WebFullScreenManagerProxyMessages.h"
105 #include "WebImage.h"
106 #include "WebInspectorProxy.h"
107 #include "WebInspectorUtilities.h"
108 #include "WebNavigationDataStore.h"
109 #include "WebNavigationState.h"
110 #include "WebNotificationManagerProxy.h"
111 #include "WebOpenPanelResultListenerProxy.h"
112 #include "WebPageCreationParameters.h"
113 #include "WebPageDebuggable.h"
114 #include "WebPageGroup.h"
115 #include "WebPageGroupData.h"
116 #include "WebPageInspectorController.h"
117 #include "WebPageMessages.h"
118 #include "WebPageProxyMessages.h"
119 #include "WebPaymentCoordinatorProxy.h"
120 #include "WebPopupItem.h"
121 #include "WebPopupMenuProxy.h"
122 #include "WebPreferences.h"
123 #include "WebPreferencesKeys.h"
124 #include "WebProcessMessages.h"
125 #include "WebProcessPool.h"
126 #include "WebProcessProxy.h"
127 #include "WebProtectionSpace.h"
128 #include "WebResourceLoadStatisticsStore.h"
129 #include "WebURLSchemeHandler.h"
130 #include "WebUserContentControllerProxy.h"
131 #include "WebsiteDataStore.h"
132 #include <WebCore/AdClickAttribution.h>
133 #include <WebCore/BitmapImage.h>
134 #include <WebCore/DeprecatedGlobalSettings.h>
135 #include <WebCore/DiagnosticLoggingClient.h>
136 #include <WebCore/DiagnosticLoggingKeys.h>
137 #include <WebCore/DragController.h>
138 #include <WebCore/DragData.h>
139 #include <WebCore/EventNames.h>
140 #include <WebCore/FloatRect.h>
141 #include <WebCore/FocusDirection.h>
142 #include <WebCore/FontAttributeChanges.h>
143 #include <WebCore/FrameLoader.h>
144 #include <WebCore/GlobalFrameIdentifier.h>
145 #include <WebCore/GlobalWindowIdentifier.h>
146 #include <WebCore/JSDOMBinding.h>
147 #include <WebCore/JSDOMExceptionHandling.h>
148 #include <WebCore/LengthBox.h>
149 #include <WebCore/MIMETypeRegistry.h>
150 #include <WebCore/MediaStreamRequest.h>
151 #include <WebCore/PerformanceLoggingClient.h>
152 #include <WebCore/PlatformEvent.h>
153 #include <WebCore/PublicSuffix.h>
154 #include <WebCore/RenderEmbeddedObject.h>
155 #include <WebCore/ResourceLoadStatistics.h>
156 #include <WebCore/SSLKeyGenerator.h>
157 #include <WebCore/SerializedCryptoKeyWrap.h>
158 #include <WebCore/ShareData.h>
159 #include <WebCore/SharedBuffer.h>
160 #include <WebCore/ShouldTreatAsContinuingLoad.h>
161 #include <WebCore/TextCheckerClient.h>
162 #include <WebCore/TextIndicator.h>
163 #include <WebCore/ValidationBubble.h>
164 #include <WebCore/WindowFeatures.h>
165 #include <WebCore/WritingDirection.h>
166 #include <stdio.h>
167 #include <wtf/NeverDestroyed.h>
168 #include <wtf/SystemTracing.h>
169 #include <wtf/URL.h>
170 #include <wtf/URLParser.h>
171 #include <wtf/text/StringView.h>
172 #include <wtf/text/TextStream.h>
173
174 #if ENABLE(APPLICATION_MANIFEST)
175 #include "APIApplicationManifest.h"
176 #endif
177
178 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
179 #include "RemoteScrollingCoordinatorProxy.h"
180 #endif
181
182 #ifndef NDEBUG
183 #include <wtf/RefCountedLeakCounter.h>
184 #endif
185
186 #if PLATFORM(COCOA)
187 #include "RemoteLayerTreeDrawingAreaProxy.h"
188 #include "RemoteLayerTreeScrollingPerformanceData.h"
189 #include "TouchBarMenuData.h"
190 #include "TouchBarMenuItemData.h"
191 #include "VideoFullscreenManagerProxy.h"
192 #include "VideoFullscreenManagerProxyMessages.h"
193 #include <WebCore/RunLoopObserver.h>
194 #include <WebCore/TextIndicatorWindow.h>
195 #include <wtf/MachSendRight.h>
196 #endif
197
198 #if PLATFORM(COCOA) || PLATFORM(GTK)
199 #include "ViewSnapshotStore.h"
200 #endif
201
202 #if PLATFORM(GTK)
203 #include "WebSelectionData.h"
204 #endif
205
206 #if USE(CAIRO)
207 #include <WebCore/CairoUtilities.h>
208 #endif
209
210 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
211 #include <WebCore/MediaPlaybackTarget.h>
212 #include <WebCore/WebMediaSessionManager.h>
213 #endif
214
215 #if ENABLE(MEDIA_SESSION)
216 #include "WebMediaSessionFocusManager.h"
217 #include "WebMediaSessionMetadata.h"
218 #include <WebCore/MediaSessionMetadata.h>
219 #endif
220
221 #if PLATFORM(IOS_FAMILY) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
222 #include "PlaybackSessionManagerProxy.h"
223 #endif
224
225 #if ENABLE(WEB_AUTHN)
226 #include "WebAuthenticatorCoordinatorProxy.h"
227 #endif
228
229 #if ENABLE(REMOTE_INSPECTOR)
230 #include <JavaScriptCore/RemoteInspector.h>
231 #endif
232
233 #if HAVE(SEC_KEY_PROXY)
234 #include "SecKeyProxyStore.h"
235 #endif
236
237 #if HAVE(PENCILKIT)
238 #include "EditableImageController.h"
239 #endif
240
241 // This controls what strategy we use for mouse wheel coalescing.
242 #define MERGE_WHEEL_EVENTS 1
243
244 #define MESSAGE_CHECK(process, assertion) MESSAGE_CHECK_BASE(assertion, process->connection())
245 #define MESSAGE_CHECK_URL(process, url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(process, url), process->connection())
246
247 #define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - WebPageProxy::" fmt, this, ##__VA_ARGS__)
248
249 // Represents the number of wheel events we can hold in the queue before we start pushing them preemptively.
250 static const unsigned wheelEventQueueSizeThreshold = 10;
251
252 static const Seconds resetRecentCrashCountDelay = 30_s;
253 static unsigned maximumWebProcessRelaunchAttempts = 1;
254
255 namespace WebKit {
256 using namespace WebCore;
257
258 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageProxyCounter, ("WebPageProxy"));
259
260 class ExceededDatabaseQuotaRecords {
261     WTF_MAKE_NONCOPYABLE(ExceededDatabaseQuotaRecords); WTF_MAKE_FAST_ALLOCATED;
262     friend NeverDestroyed<ExceededDatabaseQuotaRecords>;
263 public:
264     struct Record {
265         uint64_t frameID;
266         String originIdentifier;
267         String databaseName;
268         String displayName;
269         uint64_t currentQuota;
270         uint64_t currentOriginUsage;
271         uint64_t currentDatabaseUsage;
272         uint64_t expectedUsage;
273         Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply reply;
274     };
275
276     static ExceededDatabaseQuotaRecords& singleton();
277
278     std::unique_ptr<Record> createRecord(uint64_t frameID, String originIdentifier,
279         String databaseName, String displayName, uint64_t currentQuota,
280         uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage, 
281         Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply&&);
282
283     void add(std::unique_ptr<Record>);
284     bool areBeingProcessed() const { return !!m_currentRecord; }
285     Record* next();
286
287 private:
288     ExceededDatabaseQuotaRecords() { }
289     ~ExceededDatabaseQuotaRecords() { }
290
291     Deque<std::unique_ptr<Record>> m_records;
292     std::unique_ptr<Record> m_currentRecord;
293 };
294
295 ExceededDatabaseQuotaRecords& ExceededDatabaseQuotaRecords::singleton()
296 {
297     static NeverDestroyed<ExceededDatabaseQuotaRecords> records;
298     return records;
299 }
300
301 std::unique_ptr<ExceededDatabaseQuotaRecords::Record> ExceededDatabaseQuotaRecords::createRecord(
302     uint64_t frameID, String originIdentifier, String databaseName, String displayName,
303     uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage,
304     uint64_t expectedUsage, Messages::WebPageProxy::ExceededDatabaseQuota::DelayedReply&& reply)
305 {
306     auto record = std::make_unique<Record>();
307     record->frameID = frameID;
308     record->originIdentifier = originIdentifier;
309     record->databaseName = databaseName;
310     record->displayName = displayName;
311     record->currentQuota = currentQuota;
312     record->currentOriginUsage = currentOriginUsage;
313     record->currentDatabaseUsage = currentDatabaseUsage;
314     record->expectedUsage = expectedUsage;
315     record->reply = WTFMove(reply);
316     return record;
317 }
318
319 void ExceededDatabaseQuotaRecords::add(std::unique_ptr<ExceededDatabaseQuotaRecords::Record> record)
320 {
321     m_records.append(WTFMove(record));
322 }
323
324 ExceededDatabaseQuotaRecords::Record* ExceededDatabaseQuotaRecords::next()
325 {
326     m_currentRecord = nullptr;
327     if (!m_records.isEmpty())
328         m_currentRecord = m_records.takeFirst();
329     return m_currentRecord.get();
330 }
331
332 #if !LOG_DISABLED
333 static const char* webMouseEventTypeString(WebEvent::Type type)
334 {
335     switch (type) {
336     case WebEvent::MouseDown:
337         return "MouseDown";
338     case WebEvent::MouseUp:
339         return "MouseUp";
340     case WebEvent::MouseMove:
341         return "MouseMove";
342     case WebEvent::MouseForceChanged:
343         return "MouseForceChanged";
344     case WebEvent::MouseForceDown:
345         return "MouseForceDown";
346     case WebEvent::MouseForceUp:
347         return "MouseForceUp";
348     default:
349         ASSERT_NOT_REACHED();
350         return "<unknown>";
351     }
352 }
353
354 static const char* webKeyboardEventTypeString(WebEvent::Type type)
355 {
356     switch (type) {
357     case WebEvent::KeyDown:
358         return "KeyDown";
359     case WebEvent::KeyUp:
360         return "KeyUp";
361     case WebEvent::RawKeyDown:
362         return "RawKeyDown";
363     case WebEvent::Char:
364         return "Char";
365     default:
366         ASSERT_NOT_REACHED();
367         return "<unknown>";
368     }
369 }
370 #endif // !LOG_DISABLED
371
372 class PageClientProtector {
373     WTF_MAKE_NONCOPYABLE(PageClientProtector);
374 public:
375     PageClientProtector(PageClient& pageClient)
376         : m_pageClient(makeWeakPtr(pageClient))
377     {
378         m_pageClient->refView();
379     }
380
381     ~PageClientProtector()
382     {
383         ASSERT(m_pageClient);
384         m_pageClient->derefView();
385     }
386
387 private:
388     WeakPtr<PageClient> m_pageClient;
389 };
390
391 Ref<WebPageProxy> WebPageProxy::create(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
392 {
393     return adoptRef(*new WebPageProxy(pageClient, process, pageID, WTFMove(configuration)));
394 }
395
396 WebPageProxy::WebPageProxy(PageClient& pageClient, WebProcessProxy& process, uint64_t pageID, Ref<API::PageConfiguration>&& configuration)
397     : m_pageClient(makeWeakPtr(pageClient))
398     , m_configuration(WTFMove(configuration))
399     , m_navigationClient(makeUniqueRef<API::NavigationClient>())
400     , m_historyClient(makeUniqueRef<API::HistoryClient>())
401     , m_iconLoadingClient(std::make_unique<API::IconLoadingClient>())
402     , m_formClient(std::make_unique<API::FormClient>())
403     , m_uiClient(std::make_unique<API::UIClient>())
404     , m_findClient(std::make_unique<API::FindClient>())
405     , m_findMatchesClient(std::make_unique<API::FindMatchesClient>())
406 #if ENABLE(CONTEXT_MENUS)
407     , m_contextMenuClient(std::make_unique<API::ContextMenuClient>())
408 #endif
409     , m_navigationState(std::make_unique<WebNavigationState>())
410     , m_process(process)
411     , m_pageGroup(*m_configuration->pageGroup())
412     , m_preferences(*m_configuration->preferences())
413     , m_userContentController(*m_configuration->userContentController())
414     , m_visitedLinkStore(*m_configuration->visitedLinkStore())
415     , m_websiteDataStore(m_configuration->websiteDataStore()->websiteDataStore())
416     , m_userAgent(standardUserAgent())
417     , m_overrideContentSecurityPolicy { m_configuration->overrideContentSecurityPolicy() }
418     , m_treatsSHA1CertificatesAsInsecure(m_configuration->treatsSHA1SignedCertificatesAsInsecure())
419 #if ENABLE(FULLSCREEN_API)
420     , m_fullscreenClient(std::make_unique<API::FullscreenClient>())
421 #endif
422     , m_geolocationPermissionRequestManager(*this)
423     , m_notificationPermissionRequestManager(*this)
424 #if PLATFORM(IOS_FAMILY)
425     , m_alwaysRunsAtForegroundPriority(m_configuration->alwaysRunsAtForegroundPriority())
426 #endif
427     , m_initialCapitalizationEnabled(m_configuration->initialCapitalizationEnabled())
428     , m_cpuLimit(m_configuration->cpuLimit())
429     , m_backForwardList(WebBackForwardList::create(*this))
430     , m_waitsForPaintAfterViewDidMoveToWindow(m_configuration->waitsForPaintAfterViewDidMoveToWindow())
431     , m_drawsBackground(m_configuration->drawsBackground())
432     , m_pageID(pageID)
433     , m_controlledByAutomation(m_configuration->isControlledByAutomation())
434 #if PLATFORM(COCOA)
435     , m_isSmartInsertDeleteEnabled(TextChecker::isSmartInsertDeleteEnabled())
436 #endif
437     , m_pageLoadState(*this)
438     , m_configurationPreferenceValues(m_configuration->preferenceValues())
439     , m_inspectorController(std::make_unique<WebPageInspectorController>(*this))
440 #if ENABLE(REMOTE_INSPECTOR)
441     , m_inspectorDebuggable(std::make_unique<WebPageDebuggable>(*this))
442 #endif
443     , m_resetRecentCrashCountTimer(RunLoop::main(), this, &WebPageProxy::resetRecentCrashCount)
444 #if HAVE(PENCILKIT)
445     , m_editableImageController(std::make_unique<EditableImageController>(*this))
446 #endif
447 {
448     RELEASE_LOG_IF_ALLOWED(Loading, "constructor: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
449
450     m_webProcessLifetimeTracker.addObserver(m_visitedLinkStore);
451     m_webProcessLifetimeTracker.addObserver(m_websiteDataStore);
452
453     updateActivityState();
454     updateThrottleState();
455     updateHiddenPageThrottlingAutoIncreases();
456     
457 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
458     m_layerHostingMode = m_activityState & ActivityState::IsInWindow ? WebPageProxy::pageClient().viewLayerHostingMode() : LayerHostingMode::OutOfProcess;
459 #endif
460
461     platformInitialize();
462
463 #ifndef NDEBUG
464     webPageProxyCounter.increment();
465 #endif
466
467     WebProcessPool::statistics().wkPageCount++;
468
469     m_preferences->addPage(*this);
470     m_pageGroup->addPage(this);
471
472     m_inspector = WebInspectorProxy::create(this);
473 #if ENABLE(FULLSCREEN_API)
474     m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, WebPageProxy::pageClient().fullScreenManagerProxyClient());
475 #endif
476 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
477     m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
478     m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
479 #endif
480
481 #if ENABLE(APPLE_PAY)
482     m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
483 #endif
484
485 #if USE(SYSTEM_PREVIEW)
486     m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
487 #endif
488
489 #if ENABLE(WEB_AUTHN)
490     m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
491 #endif
492
493     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
494
495 #if PLATFORM(IOS_FAMILY)
496     DeprecatedGlobalSettings::setDisableScreenSizeOverride(preferencesStore().getBoolValueForKey(WebPreferencesKey::disableScreenSizeOverrideKey()));
497 #endif
498
499 #if PLATFORM(COCOA)
500     m_activityStateChangeDispatcher = std::make_unique<RunLoopObserver>(static_cast<CFIndex>(RunLoopObserver::WellKnownRunLoopOrders::ActivityStateChange), [this] {
501         this->dispatchActivityStateChange();
502     });
503 #endif
504
505 #if ENABLE(REMOTE_INSPECTOR)
506     m_inspectorDebuggable->setRemoteDebuggingAllowed(true);
507     m_inspectorDebuggable->init();
508 #endif
509
510     createInspectorTargets();
511 }
512
513 WebPageProxy::~WebPageProxy()
514 {
515     RELEASE_LOG_IF_ALLOWED(Loading, "destructor: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
516
517     ASSERT(m_process->webPage(m_pageID) != this);
518 #if !ASSERT_DISABLED
519     for (WebPageProxy* page : m_process->pages())
520         ASSERT(page != this);
521 #endif
522
523     if (!m_isClosed)
524         close();
525
526     WebProcessPool::statistics().wkPageCount--;
527
528     if (m_spellDocumentTag)
529         TextChecker::closeSpellDocumentWithTag(m_spellDocumentTag.value());
530
531     m_preferences->removePage(*this);
532     m_pageGroup->removePage(this);
533
534 #ifndef NDEBUG
535     webPageProxyCounter.decrement();
536 #endif
537 }
538
539 // FIXME: Should return a const PageClient& and add a separate non-const
540 // version of this function, but several PageClient methods will need to become
541 // const for this to be possible.
542 PageClient& WebPageProxy::pageClient() const
543 {
544     ASSERT(m_pageClient);
545     return *m_pageClient;
546 }
547
548 PAL::SessionID WebPageProxy::sessionID() const
549 {
550     return m_websiteDataStore->sessionID();
551 }
552
553 DrawingAreaProxy* WebPageProxy::provisionalDrawingArea() const
554 {
555     if (m_provisionalPage && m_provisionalPage->drawingArea())
556         return m_provisionalPage->drawingArea();
557     return drawingArea();
558 }
559
560 void WebPageProxy::changeWebsiteDataStore(WebsiteDataStore& websiteDataStore)
561 {
562     m_process->processPool().pageEndUsingWebsiteDataStore(*this);
563     m_websiteDataStore = websiteDataStore;
564     m_process->processPool().pageBeginUsingWebsiteDataStore(*this);
565 }
566
567 const API::PageConfiguration& WebPageProxy::configuration() const
568 {
569     return m_configuration.get();
570 }
571
572 ProcessID WebPageProxy::processIdentifier() const
573 {
574     if (m_isClosed)
575         return 0;
576
577     return m_process->processIdentifier();
578 }
579
580 bool WebPageProxy::isValid() const
581 {
582     // A page that has been explicitly closed is never valid.
583     if (m_isClosed)
584         return false;
585
586     return m_isValid;
587 }
588
589 void WebPageProxy::notifyProcessPoolToPrewarm()
590 {
591     m_process->processPool().didReachGoodTimeToPrewarm();
592 }
593
594 void WebPageProxy::setPreferences(WebPreferences& preferences)
595 {
596     if (&preferences == m_preferences.ptr())
597         return;
598
599     m_preferences->removePage(*this);
600     m_preferences = preferences;
601     m_preferences->addPage(*this);
602
603     preferencesDidChange();
604 }
605     
606 void WebPageProxy::setHistoryClient(UniqueRef<API::HistoryClient>&& historyClient)
607 {
608     m_historyClient = WTFMove(historyClient);
609 }
610
611 void WebPageProxy::setNavigationClient(UniqueRef<API::NavigationClient>&& navigationClient)
612 {
613     m_navigationClient = WTFMove(navigationClient);
614 }
615
616 void WebPageProxy::setLoaderClient(std::unique_ptr<API::LoaderClient>&& loaderClient)
617 {
618     m_loaderClient = WTFMove(loaderClient);
619 }
620
621 void WebPageProxy::setPolicyClient(std::unique_ptr<API::PolicyClient>&& policyClient)
622 {
623     m_policyClient = WTFMove(policyClient);
624 }
625
626 void WebPageProxy::setFormClient(std::unique_ptr<API::FormClient>&& formClient)
627 {
628     if (!formClient) {
629         m_formClient = std::make_unique<API::FormClient>();
630         return;
631     }
632
633     m_formClient = WTFMove(formClient);
634 }
635
636 void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient>&& uiClient)
637 {
638     if (!uiClient) {
639         m_uiClient = std::make_unique<API::UIClient>();
640         return;
641     }
642
643     m_uiClient = WTFMove(uiClient);
644
645     if (!isValid())
646         return;
647
648     m_process->send(Messages::WebPage::SetCanRunBeforeUnloadConfirmPanel(m_uiClient->canRunBeforeUnloadConfirmPanel()), m_pageID);
649     setCanRunModal(m_uiClient->canRunModal());
650     setNeedsFontAttributes(m_uiClient->needsFontAttributes());
651 }
652
653 void WebPageProxy::setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&& iconLoadingClient)
654 {
655     bool hasClient = iconLoadingClient.get();
656     if (!iconLoadingClient)
657         m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
658     else
659         m_iconLoadingClient = WTFMove(iconLoadingClient);
660
661     if (!isValid())
662         return;
663
664     m_process->send(Messages::WebPage::SetUseIconLoadingClient(hasClient), m_pageID);
665 }
666
667 void WebPageProxy::setFindClient(std::unique_ptr<API::FindClient>&& findClient)
668 {
669     if (!findClient) {
670         m_findClient = std::make_unique<API::FindClient>();
671         return;
672     }
673     
674     m_findClient = WTFMove(findClient);
675 }
676
677 void WebPageProxy::setFindMatchesClient(std::unique_ptr<API::FindMatchesClient>&& findMatchesClient)
678 {
679     if (!findMatchesClient) {
680         m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
681         return;
682     }
683
684     m_findMatchesClient = WTFMove(findMatchesClient);
685 }
686
687 void WebPageProxy::setDiagnosticLoggingClient(std::unique_ptr<API::DiagnosticLoggingClient>&& diagnosticLoggingClient)
688 {
689     m_diagnosticLoggingClient = WTFMove(diagnosticLoggingClient);
690 }
691
692 #if ENABLE(CONTEXT_MENUS)
693 void WebPageProxy::setContextMenuClient(std::unique_ptr<API::ContextMenuClient>&& contextMenuClient)
694 {
695     if (!contextMenuClient) {
696         m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
697         return;
698     }
699
700     m_contextMenuClient = WTFMove(contextMenuClient);
701 }
702 #endif
703
704 void WebPageProxy::setInjectedBundleClient(const WKPageInjectedBundleClientBase* client)
705 {
706     if (!client) {
707         m_injectedBundleClient = nullptr;
708         return;
709     }
710
711     m_injectedBundleClient = std::make_unique<WebPageInjectedBundleClient>();
712     m_injectedBundleClient->initialize(client);
713 }
714
715 void WebPageProxy::handleMessage(IPC::Connection& connection, const String& messageName, const WebKit::UserData& messageBody)
716 {
717     ASSERT(m_process->connection() == &connection);
718
719     if (!m_injectedBundleClient)
720         return;
721
722     m_injectedBundleClient->didReceiveMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get());
723 }
724
725 void WebPageProxy::handleSynchronousMessage(IPC::Connection& connection, const String& messageName, const UserData& messageBody, UserData& returnUserData)
726 {
727     ASSERT(m_process->connection() == &connection);
728
729     if (!m_injectedBundleClient)
730         return;
731
732     RefPtr<API::Object> returnData;
733     m_injectedBundleClient->didReceiveSynchronousMessageFromInjectedBundle(this, messageName, m_process->transformHandlesToObjects(messageBody.object()).get(), returnData);
734     returnUserData = UserData(m_process->transformObjectsToHandles(returnData.get()));
735 }
736
737 void WebPageProxy::reattachToWebProcess()
738 {
739     ASSERT(!m_isClosed);
740     ASSERT(!isValid());
741
742     RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
743
744     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::Yes);
745     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
746
747     auto& processPool = m_process->processPool();
748     m_process = processPool.createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get());
749     m_isValid = true;
750
751     m_process->addExistingWebPage(*this, m_pageID, WebProcessProxy::BeginsUsingDataStore::Yes);
752     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
753
754     finishAttachingToWebProcess();
755 }
756
757 bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, Optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient processSwapRequestedByClient)
758 {
759     if (!mainFrameID)
760         return false;
761
762     // If the client forced a swap then it may not be Web-compatible to suspend the previous page because other windows may have an opener link to the page.
763     if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes)
764         return false;
765
766     if (isPageOpenedByDOMShowingInitialEmptyDocument())
767         return false;
768
769     auto* fromItem = navigation.fromItem();
770     if (!fromItem) {
771         LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " unable to create suspended page for process pid %i - No current back/forward item", pageID(), m_process->processIdentifier());
772         return false;
773     }
774
775     // If the source and the destination back / forward list items are the same, then this is a client-side redirect. In this case,
776     // there is no need to suspend the previous page as there will be no way to get back to it.
777     if (fromItem == m_backForwardList->currentItem())
778         return false;
779
780     auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *fromItem, *mainFrameID);
781
782     LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " created suspended page %s for process pid %i, back/forward item %s" PRIu64, pageID(), suspendedPage->loggingString(), m_process->processIdentifier(), fromItem->itemID().logString());
783
784     m_process->processPool().addSuspendedPage(WTFMove(suspendedPage));
785     return true;
786 }
787
788 void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, std::unique_ptr<DrawingAreaProxy>&& drawingArea, RefPtr<WebFrameProxy>&& mainFrame)
789 {
790     ASSERT(!m_isClosed);
791     RELEASE_LOG_IF_ALLOWED(Loading, "swapToWebProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
792
793     m_process = WTFMove(process);
794     ASSERT(!m_drawingArea);
795     setDrawingArea(WTFMove(drawingArea));
796     ASSERT(!m_mainFrame);
797     m_mainFrame = WTFMove(mainFrame);
798     m_isValid = true;
799
800     m_process->addExistingWebPage(*this, m_pageID, WebProcessProxy::BeginsUsingDataStore::No);
801     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
802
803     // No need to initialize the WebPage since it was created when we created the ProvisionalPageProxy.
804     finishAttachingToWebProcess(ShouldInitializeWebPage::No);
805 }
806
807 void WebPageProxy::finishAttachingToWebProcess(ShouldInitializeWebPage shouldInitializePage)
808 {
809     ASSERT(m_process->state() != AuxiliaryProcessProxy::State::Terminated);
810
811     if (m_process->state() == AuxiliaryProcessProxy::State::Running) {
812         m_webProcessLifetimeTracker.webPageEnteringWebProcess();
813         processDidFinishLaunching();
814     }
815
816     updateActivityState();
817     updateThrottleState();
818
819 #if ENABLE(FULLSCREEN_API)
820     m_fullScreenManager = std::make_unique<WebFullScreenManagerProxy>(*this, pageClient().fullScreenManagerProxyClient());
821 #endif
822 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
823     m_playbackSessionManager = PlaybackSessionManagerProxy::create(*this);
824     m_videoFullscreenManager = VideoFullscreenManagerProxy::create(*this, *m_playbackSessionManager);
825 #endif
826
827 #if ENABLE(APPLE_PAY)
828     m_paymentCoordinator = std::make_unique<WebPaymentCoordinatorProxy>(*this);
829 #endif
830
831 #if USE(SYSTEM_PREVIEW)
832     m_systemPreviewController = std::make_unique<SystemPreviewController>(*this);
833 #endif
834
835 #if ENABLE(WEB_AUTHN)
836     m_credentialsMessenger = std::make_unique<WebAuthenticatorCoordinatorProxy>(*this);
837 #endif
838
839 #if HAVE(PENCILKIT)
840     m_editableImageController = std::make_unique<EditableImageController>(*this);
841 #endif
842
843     if (shouldInitializePage == ShouldInitializeWebPage::Yes)
844         initializeWebPage();
845
846     m_inspector->updateForNewPageProcess(this);
847
848 #if ENABLE(REMOTE_INSPECTOR)
849     remoteInspectorInformationDidChange();
850 #endif
851
852     clearInspectorTargets();
853     createInspectorTargets();
854
855     pageClient().didRelaunchProcess();
856     m_pageLoadState.didSwapWebProcesses();
857     m_drawingArea->waitForBackingStoreUpdateOnNextPaint();
858 }
859
860 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessForReload()
861 {
862     RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessForReload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
863
864     if (m_isClosed) {
865         RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessForReload: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
866         return nullptr;
867     }
868     
869     ASSERT(!isValid());
870     reattachToWebProcess();
871
872     if (!m_backForwardList->currentItem()) {
873         RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessForReload: no current item to reload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
874         return nullptr;
875     }
876
877     auto navigation = m_navigationState->createReloadNavigation();
878
879     // We allow stale content when reloading a WebProcess that's been killed or crashed.
880     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
881     m_process->responsivenessTimer().start();
882
883     return WTFMove(navigation);
884 }
885
886 RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwardListItem& item)
887 {
888     RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessWithItem: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
889
890     if (m_isClosed) {
891         RELEASE_LOG_IF_ALLOWED(Loading, "reattachToWebProcessWithItem: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
892         return nullptr;
893     }
894
895     ASSERT(!isValid());
896     reattachToWebProcess();
897
898     if (&item != m_backForwardList->currentItem())
899         m_backForwardList->goToItem(item);
900
901     auto navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), FrameLoadType::IndexedBackForward);
902
903     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item.itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
904     m_process->responsivenessTimer().start();
905
906     return WTFMove(navigation);
907 }
908
909 void WebPageProxy::setDrawingArea(std::unique_ptr<DrawingAreaProxy>&& drawingArea)
910 {
911     m_drawingArea = WTFMove(drawingArea);
912     if (!m_drawingArea)
913         return;
914
915 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
916     if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) {
917         m_scrollingCoordinatorProxy = std::make_unique<RemoteScrollingCoordinatorProxy>(*this);
918 #if PLATFORM(IOS_FAMILY)
919         // On iOS, main frame scrolls are sent in terms of visible rect updates.
920         m_scrollingCoordinatorProxy->setPropagatesMainFrameScrolls(false);
921 #endif
922     }
923 #endif
924 }
925
926 void WebPageProxy::initializeWebPage()
927 {
928     ASSERT(isValid());
929
930     setDrawingArea(pageClient().createDrawingAreaProxy(m_process));
931     ASSERT(m_drawingArea);
932
933     process().send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters(m_process)), 0);
934
935     m_needsToFinishInitializingWebPageAfterProcessLaunch = true;
936     finishInitializingWebPageAfterProcessLaunch();
937 }
938
939 void WebPageProxy::finishInitializingWebPageAfterProcessLaunch()
940 {
941     if (!m_needsToFinishInitializingWebPageAfterProcessLaunch)
942         return;
943     if (m_process->state() != WebProcessProxy::State::Running)
944         return;
945
946     m_needsToFinishInitializingWebPageAfterProcessLaunch = false;
947     m_process->addVisitedLinkStore(m_visitedLinkStore);
948 }
949
950 void WebPageProxy::close()
951 {
952     if (m_isClosed)
953         return;
954
955     RELEASE_LOG_IF_ALLOWED(Loading, "close: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
956
957     m_isClosed = true;
958
959 #if ENABLE(MEDIA_STREAM)
960     m_userMediaPermissionRequestManager = nullptr;
961 #endif
962
963     reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
964
965     if (m_activePopupMenu)
966         m_activePopupMenu->cancelTracking();
967
968     if (m_controlledByAutomation) {
969         if (auto* automationSession = process().processPool().automationSession())
970             automationSession->willClosePage(*this);
971     }
972
973 #if ENABLE(CONTEXT_MENUS)
974     m_activeContextMenu = nullptr;
975 #endif
976
977     m_provisionalPage = nullptr;
978
979     m_inspector->invalidate();
980
981     m_backForwardList->pageClosed();
982     m_inspectorController->pageClosed();
983 #if ENABLE(REMOTE_INSPECTOR)
984     m_inspectorDebuggable = nullptr;
985 #endif
986     pageClient().pageClosed();
987
988     m_process->disconnectFramesFromPage(this);
989
990     resetState(ResetStateReason::PageInvalidated);
991
992     m_loaderClient = nullptr;
993     m_navigationClient = makeUniqueRef<API::NavigationClient>();
994     m_policyClient = nullptr;
995     m_iconLoadingClient = std::make_unique<API::IconLoadingClient>();
996     m_formClient = std::make_unique<API::FormClient>();
997     m_uiClient = std::make_unique<API::UIClient>();
998     m_findClient = std::make_unique<API::FindClient>();
999     m_findMatchesClient = std::make_unique<API::FindMatchesClient>();
1000     m_diagnosticLoggingClient = nullptr;
1001 #if ENABLE(CONTEXT_MENUS)
1002     m_contextMenuClient = std::make_unique<API::ContextMenuClient>();
1003 #endif
1004 #if ENABLE(FULLSCREEN_API)
1005     m_fullscreenClient = std::make_unique<API::FullscreenClient>();
1006 #endif
1007
1008     m_webProcessLifetimeTracker.pageWasInvalidated();
1009
1010     m_process->processPool().removeAllSuspendedPagesForPage(*this);
1011
1012     m_process->send(Messages::WebPage::Close(), m_pageID);
1013     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::Yes);
1014     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
1015     m_process->processPool().supplement<WebNotificationManagerProxy>()->clearNotifications(this);
1016
1017     // Null out related WebPageProxy to avoid leaks.
1018     m_configuration->setRelatedPage(nullptr);
1019
1020 #if PLATFORM(IOS_FAMILY)
1021     // Make sure we don't hold a process assertion after getting closed.
1022     m_activityToken = nullptr;
1023 #endif
1024
1025     stopAllURLSchemeTasks();
1026 }
1027
1028 bool WebPageProxy::tryClose()
1029 {
1030     if (!isValid())
1031         return true;
1032
1033     RELEASE_LOG_IF_ALLOWED(Loading, "tryClose: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1034
1035     // Close without delay if the process allows it. Our goal is to terminate
1036     // the process, so we check a per-process status bit.
1037     if (m_process->isSuddenTerminationEnabled())
1038         return true;
1039
1040     m_process->send(Messages::WebPage::TryClose(), m_pageID);
1041     m_process->responsivenessTimer().start();
1042     return false;
1043 }
1044
1045 bool WebPageProxy::maybeInitializeSandboxExtensionHandle(WebProcessProxy& process, const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
1046 {
1047     if (!url.isLocalFile())
1048         return false;
1049
1050     if (process.hasAssumedReadAccessToURL(url))
1051         return false;
1052
1053     // Inspector resources are in a directory with assumed access.
1054     ASSERT_WITH_SECURITY_IMPLICATION(!WebKit::isInspectorPage(*this));
1055
1056     SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, sandboxExtensionHandle);
1057     return true;
1058 }
1059
1060 #if !PLATFORM(COCOA)
1061 void WebPageProxy::addPlatformLoadParameters(LoadParameters&)
1062 {
1063 }
1064 #endif
1065
1066 RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData)
1067 {
1068     if (m_isClosed)
1069         return nullptr;
1070
1071     RELEASE_LOG_IF_ALLOWED(Loading, "loadRequest: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1072
1073     if (!isValid())
1074         reattachToWebProcess();
1075
1076     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
1077     loadRequestWithNavigationShared(m_process.copyRef(), navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, ShouldTreatAsContinuingLoad::No);
1078     return WTFMove(navigation);
1079 }
1080
1081 void WebPageProxy::loadRequestWithNavigationShared(Ref<WebProcessProxy>&& process, API::Navigation& navigation, ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
1082 {
1083     ASSERT(!m_isClosed);
1084
1085     RELEASE_LOG_IF_ALLOWED(Loading, "loadRequestWithNavigation: webPID = %i, pageID = %" PRIu64, process->processIdentifier(), m_pageID);
1086
1087     auto transaction = m_pageLoadState.transaction();
1088
1089     auto url = request.url();
1090     if (shouldTreatAsContinuingLoad != ShouldTreatAsContinuingLoad::Yes)
1091         m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1092
1093     LoadParameters loadParameters;
1094     loadParameters.navigationID = navigation.navigationID();
1095     loadParameters.request = WTFMove(request);
1096     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
1097     loadParameters.userData = UserData(process->transformObjectsToHandles(userData).get());
1098     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1099     loadParameters.websitePolicies = WTFMove(websitePolicies);
1100     loadParameters.lockHistory = navigation.lockHistory();
1101     loadParameters.lockBackForwardList = navigation.lockBackForwardList();
1102     loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
1103     bool createdExtension = maybeInitializeSandboxExtensionHandle(process, url, loadParameters.sandboxExtensionHandle);
1104     if (createdExtension)
1105         willAcquireUniversalFileReadSandboxExtension(process);
1106     addPlatformLoadParameters(loadParameters);
1107
1108     process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1109     process->responsivenessTimer().start();
1110 }
1111
1112 RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
1113 {
1114     RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1115
1116     if (m_isClosed) {
1117         RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1118         return nullptr;
1119     }
1120
1121     if (!isValid())
1122         reattachToWebProcess();
1123
1124     URL fileURL = URL(URL(), fileURLString);
1125     if (!fileURL.isLocalFile()) {
1126         RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: file is not local: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1127         return nullptr;
1128     }
1129
1130     URL resourceDirectoryURL;
1131     if (resourceDirectoryURLString.isNull())
1132         resourceDirectoryURL = URL({ }, "file:///"_s);
1133     else {
1134         resourceDirectoryURL = URL(URL(), resourceDirectoryURLString);
1135         if (!resourceDirectoryURL.isLocalFile()) {
1136             RELEASE_LOG_IF_ALLOWED(Loading, "loadFile: resource URL is not local: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1137             return nullptr;
1138         }
1139     }
1140
1141     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(fileURL), m_backForwardList->currentItem());
1142
1143     auto transaction = m_pageLoadState.transaction();
1144
1145     m_pageLoadState.setPendingAPIRequestURL(transaction, fileURLString);
1146
1147     String resourceDirectoryPath = resourceDirectoryURL.fileSystemPath();
1148
1149     LoadParameters loadParameters;
1150     loadParameters.navigationID = navigation->navigationID();
1151     loadParameters.request = fileURL;
1152     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1153     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1154     SandboxExtension::createHandle(resourceDirectoryPath, SandboxExtension::Type::ReadOnly, loadParameters.sandboxExtensionHandle);
1155     addPlatformLoadParameters(loadParameters);
1156
1157     m_process->assumeReadAccessToBaseURL(*this, resourceDirectoryURL);
1158     m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
1159     m_process->responsivenessTimer().start();
1160
1161     return WTFMove(navigation);
1162 }
1163
1164 RefPtr<API::Navigation> WebPageProxy::loadData(const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData)
1165 {
1166     RELEASE_LOG_IF_ALLOWED(Loading, "loadData: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1167
1168     if (m_isClosed) {
1169         RELEASE_LOG_IF_ALLOWED(Loading, "loadData: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1170         return nullptr;
1171     }
1172
1173     if (!isValid())
1174         reattachToWebProcess();
1175
1176     auto navigation = m_navigationState->createLoadDataNavigation(std::make_unique<API::SubstituteData>(data.vector(), MIMEType, encoding, baseURL, userData));
1177     loadDataWithNavigationShared(m_process.copyRef(), navigation, data, MIMEType, encoding, baseURL, userData, ShouldTreatAsContinuingLoad::No);
1178     return WTFMove(navigation);
1179 }
1180
1181 void WebPageProxy::loadDataWithNavigationShared(Ref<WebProcessProxy>&& process, API::Navigation& navigation, const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
1182 {
1183     RELEASE_LOG_IF_ALLOWED(Loading, "loadDataWithNavigation: webPID = %i, pageID = %" PRIu64, process->processIdentifier(), m_pageID);
1184
1185     ASSERT(!m_isClosed);
1186
1187     auto transaction = m_pageLoadState.transaction();
1188
1189     m_pageLoadState.setPendingAPIRequestURL(transaction, !baseURL.isEmpty() ? baseURL : WTF::blankURL().string());
1190
1191     LoadParameters loadParameters;
1192     loadParameters.navigationID = navigation.navigationID();
1193     loadParameters.data = data;
1194     loadParameters.MIMEType = MIMEType;
1195     loadParameters.encodingName = encoding;
1196     loadParameters.baseURLString = baseURL;
1197     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
1198     loadParameters.userData = UserData(process->transformObjectsToHandles(userData).get());
1199     loadParameters.websitePolicies = WTFMove(websitePolicies);
1200     addPlatformLoadParameters(loadParameters);
1201
1202     process->assumeReadAccessToBaseURL(*this, baseURL);
1203     process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1204     process->responsivenessTimer().start();
1205 }
1206
1207 void WebPageProxy::loadAlternateHTML(const IPC::DataReference& htmlData, const String& encoding, const URL& baseURL, const URL& unreachableURL, API::Object* userData)
1208 {
1209     RELEASE_LOG_IF_ALLOWED(Loading, "loadAlternateHTML: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1210
1211     // When the UIProcess is in the process of handling a failing provisional load, do not attempt to
1212     // start a second alternative HTML load as this will prevent the page load state from being
1213     // handled properly.
1214     if (m_isClosed || m_isLoadingAlternateHTMLStringForFailingProvisionalLoad) {
1215         RELEASE_LOG_IF_ALLOWED(Loading, "loadAlternateHTML: page is closed (or other): webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1216         return;
1217     }
1218
1219     if (!m_failingProvisionalLoadURL.isEmpty())
1220         m_isLoadingAlternateHTMLStringForFailingProvisionalLoad = true;
1221
1222     if (!isValid())
1223         reattachToWebProcess();
1224
1225     auto transaction = m_pageLoadState.transaction();
1226
1227     m_pageLoadState.setPendingAPIRequestURL(transaction, unreachableURL);
1228     m_pageLoadState.setUnreachableURL(transaction, unreachableURL);
1229
1230     if (m_mainFrame)
1231         m_mainFrame->setUnreachableURL(unreachableURL);
1232
1233     LoadParameters loadParameters;
1234     loadParameters.navigationID = 0;
1235     loadParameters.data = htmlData;
1236     loadParameters.MIMEType = "text/html"_s;
1237     loadParameters.encodingName = encoding;
1238     loadParameters.baseURLString = baseURL;
1239     loadParameters.unreachableURLString = unreachableURL;
1240     loadParameters.provisionalLoadErrorURLString = m_failingProvisionalLoadURL;
1241     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1242     addPlatformLoadParameters(loadParameters);
1243
1244     m_process->assumeReadAccessToBaseURL(*this, baseURL);
1245     m_process->assumeReadAccessToBaseURL(*this, unreachableURL);
1246     m_process->send(Messages::WebPage::LoadAlternateHTML(loadParameters), m_pageID);
1247     m_process->responsivenessTimer().start();
1248 }
1249
1250 void WebPageProxy::loadWebArchiveData(API::Data* webArchiveData, API::Object* userData)
1251 {
1252     RELEASE_LOG_IF_ALLOWED(Loading, "loadWebArchiveData: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1253
1254     if (m_isClosed) {
1255         RELEASE_LOG_IF_ALLOWED(Loading, "loadWebArchiveData: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1256         return;
1257     }
1258
1259     if (!isValid())
1260         reattachToWebProcess();
1261
1262     auto transaction = m_pageLoadState.transaction();
1263     m_pageLoadState.setPendingAPIRequestURL(transaction, WTF::blankURL().string());
1264
1265     LoadParameters loadParameters;
1266     loadParameters.navigationID = 0;
1267     loadParameters.data = webArchiveData->dataReference();
1268     loadParameters.MIMEType = "application/x-webarchive"_s;
1269     loadParameters.encodingName = "utf-16"_s;
1270     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
1271     addPlatformLoadParameters(loadParameters);
1272
1273     m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
1274     m_process->responsivenessTimer().start();
1275 }
1276
1277 void WebPageProxy::navigateToPDFLinkWithSimulatedClick(const String& url, IntPoint documentPoint, IntPoint screenPoint)
1278 {
1279     RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1280
1281     if (m_isClosed) {
1282         RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: page is closed: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1283         return;
1284     }
1285
1286     if (WTF::protocolIsJavaScript(url))
1287         return;
1288
1289     if (!isValid())
1290         reattachToWebProcess();
1291
1292     m_process->send(Messages::WebPage::NavigateToPDFLinkWithSimulatedClick(url, documentPoint, screenPoint), m_pageID);
1293     m_process->responsivenessTimer().start();
1294 }
1295
1296 void WebPageProxy::stopLoading()
1297 {
1298     RELEASE_LOG_IF_ALLOWED(Loading, "stopLoading: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1299
1300     if (!isValid()) {
1301         RELEASE_LOG_IF_ALLOWED(Loading, "navigateToPDFLinkWithSimulatedClick: page is not valid: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1302         return;
1303     }
1304
1305     m_process->send(Messages::WebPage::StopLoading(), m_pageID);
1306     if (m_provisionalPage) {
1307         m_provisionalPage->cancel();
1308         m_provisionalPage = nullptr;
1309     }
1310     m_process->responsivenessTimer().start();
1311 }
1312
1313 RefPtr<API::Navigation> WebPageProxy::reload(OptionSet<WebCore::ReloadOption> options)
1314 {
1315     RELEASE_LOG_IF_ALLOWED(Loading, "reload: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1316
1317     SandboxExtension::Handle sandboxExtensionHandle;
1318
1319     String url = currentURL();
1320     if (!url.isEmpty()) {
1321         auto transaction = m_pageLoadState.transaction();
1322         m_pageLoadState.setPendingAPIRequestURL(transaction, url);
1323
1324         // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
1325         bool createdExtension = maybeInitializeSandboxExtensionHandle(m_process, URL(URL(), url), sandboxExtensionHandle);
1326         if (createdExtension)
1327             willAcquireUniversalFileReadSandboxExtension(m_process);
1328     }
1329
1330     if (!isValid())
1331         return reattachToWebProcessForReload();
1332     
1333     auto navigation = m_navigationState->createReloadNavigation();
1334
1335     m_process->send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle), m_pageID);
1336     m_process->responsivenessTimer().start();
1337
1338     return WTFMove(navigation);
1339 }
1340
1341 void WebPageProxy::recordAutomaticNavigationSnapshot()
1342 {
1343     if (m_shouldSuppressNextAutomaticNavigationSnapshot)
1344         return;
1345
1346     if (WebBackForwardListItem* item = m_backForwardList->currentItem())
1347         recordNavigationSnapshot(*item);
1348 }
1349
1350 void WebPageProxy::recordNavigationSnapshot(WebBackForwardListItem& item)
1351 {
1352     if (!m_shouldRecordNavigationSnapshots)
1353         return;
1354
1355 #if PLATFORM(COCOA) || PLATFORM(GTK)
1356     ViewSnapshotStore::singleton().recordSnapshot(*this, item);
1357 #else
1358     UNUSED_PARAM(item);
1359 #endif
1360 }
1361
1362 RefPtr<API::Navigation> WebPageProxy::goForward()
1363 {
1364     WebBackForwardListItem* forwardItem = m_backForwardList->forwardItem();
1365     if (!forwardItem)
1366         return nullptr;
1367
1368     return goToBackForwardItem(*forwardItem, FrameLoadType::Forward);
1369 }
1370
1371 RefPtr<API::Navigation> WebPageProxy::goBack()
1372 {
1373     WebBackForwardListItem* backItem = m_backForwardList->backItem();
1374     if (!backItem)
1375         return nullptr;
1376
1377     return goToBackForwardItem(*backItem, FrameLoadType::Back);
1378 }
1379
1380 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item)
1381 {
1382     return goToBackForwardItem(item, FrameLoadType::IndexedBackForward);
1383 }
1384
1385 RefPtr<API::Navigation> WebPageProxy::goToBackForwardItem(WebBackForwardListItem& item, FrameLoadType frameLoadType)
1386 {
1387     RELEASE_LOG_IF_ALLOWED(Loading, "goToBackForwardItem: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1388     LOG(Loading, "WebPageProxy %p goToBackForwardItem to item URL %s", this, item.url().utf8().data());
1389
1390     if (!isValid())
1391         return reattachToWebProcessWithItem(item);
1392
1393     auto transaction = m_pageLoadState.transaction();
1394
1395     m_pageLoadState.setPendingAPIRequestURL(transaction, item.url());
1396
1397     RefPtr<API::Navigation> navigation;
1398     if (!m_backForwardList->currentItem()->itemIsInSameDocument(item))
1399         navigation = m_navigationState->createBackForwardNavigation(item, m_backForwardList->currentItem(), frameLoadType);
1400
1401     m_process->send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, WTF::nullopt), m_pageID);
1402     m_process->responsivenessTimer().start();
1403
1404     return navigation;
1405 }
1406
1407 void WebPageProxy::tryRestoreScrollPosition()
1408 {
1409     RELEASE_LOG_IF_ALLOWED(Loading, "tryRestoreScrollPosition: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1410
1411     if (!isValid()) {
1412         RELEASE_LOG_IF_ALLOWED(Loading, "tryRestoreScrollPosition: page is not valid: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
1413         return;
1414     }
1415
1416     m_process->send(Messages::WebPage::TryRestoreScrollPosition(), m_pageID);
1417 }
1418
1419 void WebPageProxy::didChangeBackForwardList(WebBackForwardListItem* added, Vector<Ref<WebBackForwardListItem>>&& removed)
1420 {
1421     PageClientProtector protector(pageClient());
1422
1423     if (!m_navigationClient->didChangeBackForwardList(*this, added, removed) && m_loaderClient)
1424         m_loaderClient->didChangeBackForwardList(*this, added, WTFMove(removed));
1425
1426     auto transaction = m_pageLoadState.transaction();
1427
1428     m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
1429     m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
1430 }
1431
1432 void WebPageProxy::willGoToBackForwardListItem(const BackForwardItemIdentifier& itemID, bool inPageCache)
1433 {
1434     PageClientProtector protector(pageClient());
1435
1436     if (auto* item = m_backForwardList->itemForID(itemID))
1437         m_navigationClient->willGoToBackForwardListItem(*this, *item, inPageCache);
1438 }
1439
1440 bool WebPageProxy::shouldKeepCurrentBackForwardListItemInList(WebBackForwardListItem& item)
1441 {
1442     PageClientProtector protector(pageClient());
1443
1444     return !m_loaderClient || m_loaderClient->shouldKeepCurrentBackForwardListItemInList(*this, item);
1445 }
1446
1447 bool WebPageProxy::canShowMIMEType(const String& mimeType)
1448 {
1449     if (MIMETypeRegistry::canShowMIMEType(mimeType))
1450         return true;
1451
1452 #if ENABLE(NETSCAPE_PLUGIN_API)
1453     String newMimeType = mimeType;
1454     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL());
1455     if (!plugin.path.isNull() && m_preferences->pluginsEnabled())
1456         return true;
1457 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1458
1459 #if PLATFORM(COCOA)
1460     // On Mac, we can show PDFs.
1461     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType) && !WebProcessPool::omitPDFSupport())
1462         return true;
1463 #endif // PLATFORM(COCOA)
1464
1465     return false;
1466 }
1467
1468 void WebPageProxy::setControlledByAutomation(bool controlled)
1469 {
1470     if (m_controlledByAutomation == controlled)
1471         return;
1472
1473     m_controlledByAutomation = controlled;
1474
1475     if (!isValid())
1476         return;
1477
1478     m_process->send(Messages::WebPage::SetControlledByAutomation(controlled), m_pageID);
1479     m_process->processPool().sendToNetworkingProcess(Messages::NetworkProcess::SetSessionIsControlledByAutomation(m_websiteDataStore->sessionID(), m_controlledByAutomation));
1480 }
1481
1482 void WebPageProxy::createInspectorTarget(const String& targetId, Inspector::InspectorTargetType type)
1483 {
1484     m_inspectorController->createInspectorTarget(targetId, type);
1485 }
1486
1487 void WebPageProxy::destroyInspectorTarget(const String& targetId)
1488 {
1489     m_inspectorController->destroyInspectorTarget(targetId);
1490 }
1491
1492 void WebPageProxy::sendMessageToInspectorFrontend(const String& targetId, const String& message)
1493 {
1494     m_inspectorController->sendMessageToInspectorFrontend(targetId, message);
1495 }
1496
1497 #if ENABLE(REMOTE_INSPECTOR)
1498 void WebPageProxy::setIndicating(bool indicating)
1499 {
1500     if (!isValid())
1501         return;
1502
1503     m_process->send(Messages::WebPage::SetIndicating(indicating), m_pageID);
1504 }
1505
1506 bool WebPageProxy::allowsRemoteInspection() const
1507 {
1508     return m_inspectorDebuggable->remoteDebuggingAllowed();
1509 }
1510
1511 void WebPageProxy::setAllowsRemoteInspection(bool allow)
1512 {
1513     m_inspectorDebuggable->setRemoteDebuggingAllowed(allow);
1514 }
1515
1516 String WebPageProxy::remoteInspectionNameOverride() const
1517 {
1518     return m_inspectorDebuggable->nameOverride();
1519 }
1520
1521 void WebPageProxy::setRemoteInspectionNameOverride(const String& name)
1522 {
1523     m_inspectorDebuggable->setNameOverride(name);
1524 }
1525
1526 void WebPageProxy::remoteInspectorInformationDidChange()
1527 {
1528     m_inspectorDebuggable->update();
1529 }
1530 #endif
1531
1532 void WebPageProxy::clearInspectorTargets()
1533 {
1534     m_inspectorController->clearTargets();
1535 }
1536
1537 void WebPageProxy::createInspectorTargets()
1538 {
1539     String pageTargetId = makeString("page-", m_pageID);
1540     m_inspectorController->createInspectorTarget(pageTargetId, Inspector::InspectorTargetType::Page);
1541 }
1542
1543 void WebPageProxy::setDrawsBackground(bool drawsBackground)
1544 {
1545     if (m_drawsBackground == drawsBackground)
1546         return;
1547
1548     m_drawsBackground = drawsBackground;
1549
1550     if (isValid())
1551         m_process->send(Messages::WebPage::SetDrawsBackground(drawsBackground), m_pageID);
1552 }
1553
1554 void WebPageProxy::setTopContentInset(float contentInset)
1555 {
1556     if (m_topContentInset == contentInset)
1557         return;
1558
1559     m_topContentInset = contentInset;
1560
1561     if (!isValid())
1562         return;
1563 #if PLATFORM(COCOA)
1564     MachSendRight fence = m_drawingArea->createFence();
1565
1566     auto fenceAttachment = IPC::Attachment(fence.leakSendRight(), MACH_MSG_TYPE_MOVE_SEND);
1567     m_process->send(Messages::WebPage::SetTopContentInsetFenced(contentInset, fenceAttachment), m_pageID);
1568 #else
1569     m_process->send(Messages::WebPage::SetTopContentInset(contentInset), m_pageID);
1570 #endif
1571 }
1572
1573 void WebPageProxy::setUnderlayColor(const Color& color)
1574 {
1575     if (m_underlayColor == color)
1576         return;
1577
1578     m_underlayColor = color;
1579
1580     if (isValid())
1581         m_process->send(Messages::WebPage::SetUnderlayColor(color), m_pageID);
1582 }
1583
1584 void WebPageProxy::viewWillStartLiveResize()
1585 {
1586     if (!isValid())
1587         return;
1588
1589     closeOverlayedViews();
1590     m_process->send(Messages::WebPage::ViewWillStartLiveResize(), m_pageID);
1591 }
1592
1593 void WebPageProxy::viewWillEndLiveResize()
1594 {
1595     if (!isValid())
1596         return;
1597     m_process->send(Messages::WebPage::ViewWillEndLiveResize(), m_pageID);
1598 }
1599
1600 void WebPageProxy::setViewNeedsDisplay(const Region& region)
1601 {
1602     pageClient().setViewNeedsDisplay(region);
1603 }
1604
1605 void WebPageProxy::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin, bool isProgrammaticScroll)
1606 {
1607     pageClient().requestScroll(scrollPosition, scrollOrigin, isProgrammaticScroll);
1608 }
1609
1610 WebCore::FloatPoint WebPageProxy::viewScrollPosition() const
1611 {
1612     return pageClient().viewScrollPosition();
1613 }
1614
1615 void WebPageProxy::setSuppressVisibilityUpdates(bool flag)
1616 {
1617     if (m_suppressVisibilityUpdates == flag)
1618         return;
1619     m_suppressVisibilityUpdates = flag;
1620
1621     if (!m_suppressVisibilityUpdates) {
1622 #if PLATFORM(COCOA)
1623         m_activityStateChangeDispatcher->schedule();
1624 #else
1625         dispatchActivityStateChange();
1626 #endif
1627     }
1628 }
1629
1630 void WebPageProxy::updateActivityState(OptionSet<ActivityState::Flag> flagsToUpdate)
1631 {
1632     m_activityState.remove(flagsToUpdate);
1633     if (flagsToUpdate & ActivityState::IsFocused && pageClient().isViewFocused())
1634         m_activityState.add(ActivityState::IsFocused);
1635     if (flagsToUpdate & ActivityState::WindowIsActive && pageClient().isViewWindowActive())
1636         m_activityState.add(ActivityState::WindowIsActive);
1637     if (flagsToUpdate & ActivityState::IsVisible && pageClient().isViewVisible())
1638         m_activityState.add(ActivityState::IsVisible);
1639     if (flagsToUpdate & ActivityState::IsVisibleOrOccluded && pageClient().isViewVisibleOrOccluded())
1640         m_activityState.add(ActivityState::IsVisibleOrOccluded);
1641     if (flagsToUpdate & ActivityState::IsInWindow && pageClient().isViewInWindow())
1642         m_activityState.add(ActivityState::IsInWindow);
1643     if (flagsToUpdate & ActivityState::IsVisuallyIdle && pageClient().isVisuallyIdle())
1644         m_activityState.add(ActivityState::IsVisuallyIdle);
1645     if (flagsToUpdate & ActivityState::IsAudible && m_mediaState & MediaProducer::IsPlayingAudio && !(m_mutedState & MediaProducer::AudioIsMuted))
1646         m_activityState.add(ActivityState::IsAudible);
1647     if (flagsToUpdate & ActivityState::IsLoading && m_pageLoadState.isLoading())
1648         m_activityState.add(ActivityState::IsLoading);
1649     if (flagsToUpdate & ActivityState::IsCapturingMedia && m_mediaState & (MediaProducer::HasActiveAudioCaptureDevice | MediaProducer::HasActiveVideoCaptureDevice))
1650         m_activityState.add(ActivityState::IsCapturingMedia);
1651 }
1652
1653 void WebPageProxy::activityStateDidChange(OptionSet<ActivityState::Flag> mayHaveChanged, bool wantsSynchronousReply, ActivityStateChangeDispatchMode dispatchMode)
1654 {
1655     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " activityStateDidChange - mayHaveChanged " << mayHaveChanged);
1656
1657     m_potentiallyChangedActivityStateFlags.add(mayHaveChanged);
1658     m_activityStateChangeWantsSynchronousReply = m_activityStateChangeWantsSynchronousReply || wantsSynchronousReply;
1659
1660     if (m_suppressVisibilityUpdates && dispatchMode != ActivityStateChangeDispatchMode::Immediate)
1661         return;
1662
1663 #if PLATFORM(COCOA)
1664     bool isNewlyInWindow = !isInWindow() && (mayHaveChanged & ActivityState::IsInWindow) && pageClient().isViewInWindow();
1665     if (dispatchMode == ActivityStateChangeDispatchMode::Immediate || isNewlyInWindow) {
1666         dispatchActivityStateChange();
1667         return;
1668     }
1669     m_activityStateChangeDispatcher->schedule();
1670 #else
1671     UNUSED_PARAM(dispatchMode);
1672     dispatchActivityStateChange();
1673 #endif
1674 }
1675
1676 void WebPageProxy::viewDidLeaveWindow()
1677 {
1678     closeOverlayedViews();
1679 #if PLATFORM(IOS_FAMILY) && HAVE(AVKIT) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
1680     // When leaving the current page, close the video fullscreen.
1681     if (m_videoFullscreenManager)
1682         m_videoFullscreenManager->requestHideAndExitFullscreen();
1683 #endif
1684 }
1685
1686 void WebPageProxy::viewDidEnterWindow()
1687 {
1688     LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1689     if (m_layerHostingMode != layerHostingMode) {
1690         m_layerHostingMode = layerHostingMode;
1691         m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1692     }
1693 }
1694
1695 void WebPageProxy::dispatchActivityStateChange()
1696 {
1697 #if PLATFORM(COCOA)
1698     m_activityStateChangeDispatcher->invalidate();
1699 #endif
1700
1701     if (!isValid())
1702         return;
1703
1704     LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange - potentiallyChangedActivityStateFlags " << m_potentiallyChangedActivityStateFlags);
1705
1706     // If the visibility state may have changed, then so may the visually idle & occluded agnostic state.
1707     if (m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible)
1708         m_potentiallyChangedActivityStateFlags.add({ ActivityState::IsVisibleOrOccluded, ActivityState::IsVisuallyIdle });
1709
1710     // Record the prior view state, update the flags that may have changed,
1711     // and check which flags have actually changed.
1712     auto previousActivityState = m_activityState;
1713     updateActivityState(m_potentiallyChangedActivityStateFlags);
1714     auto changed = m_activityState ^ previousActivityState;
1715
1716     if (changed)
1717         LOG_WITH_STREAM(ActivityState, stream << "WebPageProxy " << pageID() << " dispatchActivityStateChange: state changed from " << previousActivityState << " to " << m_activityState);
1718
1719     if ((changed & ActivityState::WindowIsActive) && isViewWindowActive())
1720         updateCurrentModifierState();
1721
1722     if ((m_potentiallyChangedActivityStateFlags & ActivityState::IsVisible) && isViewVisible())
1723         viewIsBecomingVisible();
1724
1725     bool isNowInWindow = (changed & ActivityState::IsInWindow) && isInWindow();
1726     // We always want to wait for the Web process to reply if we've been in-window before and are coming back in-window.
1727     if (m_viewWasEverInWindow && isNowInWindow) {
1728         if (m_drawingArea->hasVisibleContent() && m_waitsForPaintAfterViewDidMoveToWindow && !m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow)
1729             m_activityStateChangeWantsSynchronousReply = true;
1730         m_shouldSkipWaitingForPaintAfterNextViewDidMoveToWindow = false;
1731     }
1732
1733     // Don't wait synchronously if the view state is not visible. (This matters in particular on iOS, where a hidden page may be suspended.)
1734     if (!(m_activityState & ActivityState::IsVisible))
1735         m_activityStateChangeWantsSynchronousReply = false;
1736
1737     auto activityStateChangeID = m_activityStateChangeWantsSynchronousReply ? takeNextActivityStateChangeID() : static_cast<ActivityStateChangeID>(ActivityStateChangeAsynchronous);
1738
1739     if (changed || activityStateChangeID != ActivityStateChangeAsynchronous || !m_nextActivityStateChangeCallbacks.isEmpty())
1740         m_process->send(Messages::WebPage::SetActivityState(m_activityState, activityStateChangeID, m_nextActivityStateChangeCallbacks), m_pageID);
1741
1742     m_nextActivityStateChangeCallbacks.clear();
1743
1744     // This must happen after the SetActivityState message is sent, to ensure the page visibility event can fire.
1745     updateThrottleState();
1746
1747 #if ENABLE(POINTER_LOCK)
1748     if (((changed & ActivityState::IsVisible) && !isViewVisible()) || ((changed & ActivityState::WindowIsActive) && !pageClient().isViewWindowActive())
1749         || ((changed & ActivityState::IsFocused) && !(m_activityState & ActivityState::IsFocused)))
1750         requestPointerUnlock();
1751 #endif
1752
1753     if (changed & ActivityState::IsVisible) {
1754         if (isViewVisible())
1755             m_visiblePageToken = m_process->visiblePageToken();
1756         else {
1757             m_visiblePageToken = nullptr;
1758
1759             // If we've started the responsiveness timer as part of telling the web process to update the backing store
1760             // state, it might not send back a reply (since it won't paint anything if the web page is hidden) so we
1761             // stop the unresponsiveness timer here.
1762             m_process->responsivenessTimer().stop();
1763         }
1764     }
1765
1766     if (changed & ActivityState::IsInWindow) {
1767         if (isInWindow())
1768             viewDidEnterWindow();
1769         else
1770             viewDidLeaveWindow();
1771     }
1772
1773     updateBackingStoreDiscardableState();
1774
1775     if (activityStateChangeID != ActivityStateChangeAsynchronous)
1776         waitForDidUpdateActivityState(activityStateChangeID);
1777
1778     m_potentiallyChangedActivityStateFlags = { };
1779     m_activityStateChangeWantsSynchronousReply = false;
1780     m_viewWasEverInWindow |= isNowInWindow;
1781 }
1782
1783 bool WebPageProxy::isAlwaysOnLoggingAllowed() const
1784 {
1785     return sessionID().isAlwaysOnLoggingAllowed();
1786 }
1787
1788 void WebPageProxy::updateThrottleState()
1789 {
1790     bool processSuppressionEnabled = m_preferences->pageVisibilityBasedProcessSuppressionEnabled();
1791
1792     // If process suppression is not enabled take a token on the process pool to disable suppression of support processes.
1793     if (!processSuppressionEnabled)
1794         m_preventProcessSuppressionCount = m_process->processPool().processSuppressionDisabledForPageCount();
1795     else if (!m_preventProcessSuppressionCount)
1796         m_preventProcessSuppressionCount = nullptr;
1797
1798     if (m_activityState & ActivityState::IsVisuallyIdle)
1799         m_pageIsUserObservableCount = nullptr;
1800     else if (!m_pageIsUserObservableCount)
1801         m_pageIsUserObservableCount = m_process->processPool().userObservablePageCount();
1802
1803 #if PLATFORM(IOS_FAMILY)
1804     bool isCapturingMedia = m_activityState.contains(ActivityState::IsCapturingMedia);
1805     bool isAudible = m_activityState.contains(ActivityState::IsAudible);
1806     if (!isViewVisible() && !m_alwaysRunsAtForegroundPriority && !isCapturingMedia && !isAudible) {
1807         if (m_activityToken) {
1808             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is releasing a foreground assertion because the view is no longer visible");
1809             m_activityToken = nullptr;
1810         }
1811     } else if (!m_activityToken) {
1812         if (isViewVisible())
1813             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion because the view is visible");
1814         else if (isAudible)
1815             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion because we are playing audio");
1816         else if (isCapturingMedia)
1817             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion because media capture is active");
1818         else
1819             RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "updateThrottleState: UIProcess is taking a foreground assertion even though the view is not visible because m_alwaysRunsAtForegroundPriority is true");
1820         m_activityToken = m_process->throttler().foregroundActivityToken();
1821     }
1822 #endif
1823 }
1824
1825 void WebPageProxy::updateHiddenPageThrottlingAutoIncreases()
1826 {
1827     if (!m_preferences->hiddenPageDOMTimerThrottlingAutoIncreases())
1828         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = nullptr;
1829     else if (!m_hiddenPageDOMTimerThrottlingAutoIncreasesCount)
1830         m_hiddenPageDOMTimerThrottlingAutoIncreasesCount = m_process->processPool().hiddenPageThrottlingAutoIncreasesCount();
1831 }
1832
1833 void WebPageProxy::layerHostingModeDidChange()
1834 {
1835     if (!isValid())
1836         return;
1837
1838     LayerHostingMode layerHostingMode = pageClient().viewLayerHostingMode();
1839     if (m_layerHostingMode == layerHostingMode)
1840         return;
1841
1842     m_layerHostingMode = layerHostingMode;
1843     m_process->send(Messages::WebPage::SetLayerHostingMode(layerHostingMode), m_pageID);
1844 }
1845
1846 void WebPageProxy::waitForDidUpdateActivityState(ActivityStateChangeID activityStateChangeID)
1847 {
1848     if (!isValid())
1849         return;
1850
1851     if (m_process->state() != WebProcessProxy::State::Running)
1852         return;
1853
1854     // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
1855     if (m_waitingForDidUpdateActivityState)
1856         return;
1857
1858 #if PLATFORM(IOS_FAMILY)
1859     // Hail Mary check. Should not be possible (dispatchActivityStateChange should force async if not visible,
1860     // and if visible we should be holding an assertion) - but we should never block on a suspended process.
1861     if (!m_activityToken) {
1862         ASSERT_NOT_REACHED();
1863         return;
1864     }
1865 #endif
1866
1867     m_waitingForDidUpdateActivityState = true;
1868
1869     m_drawingArea->waitForDidUpdateActivityState(activityStateChangeID);
1870 }
1871
1872 IntSize WebPageProxy::viewSize() const
1873 {
1874     return pageClient().viewSize();
1875 }
1876
1877 void WebPageProxy::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& keyboardEvent, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
1878 {
1879     if (!isValid()) {
1880         callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
1881         return;
1882     }
1883
1884     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1885     m_process->send(Messages::WebPage::SetInitialFocus(forward, isKeyboardEventValid, keyboardEvent, callbackID), m_pageID);
1886 }
1887
1888 void WebPageProxy::clearSelection()
1889 {
1890     if (!isValid())
1891         return;
1892     m_process->send(Messages::WebPage::ClearSelection(), m_pageID);
1893 }
1894
1895 void WebPageProxy::restoreSelectionInFocusedEditableElement()
1896 {
1897     if (!isValid())
1898         return;
1899     m_process->send(Messages::WebPage::RestoreSelectionInFocusedEditableElement(), m_pageID);
1900 }
1901
1902 void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void (const String&, bool, int32_t, CallbackBase::Error)>&& callbackFunction)
1903 {
1904     if (!isValid()) {
1905         callbackFunction(String(), false, 0, CallbackBase::Error::Unknown);
1906         return;
1907     }
1908
1909     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1910     m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
1911 }
1912
1913 void WebPageProxy::increaseListLevel()
1914 {
1915     if (!isValid())
1916         return;
1917
1918     m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
1919 }
1920
1921 void WebPageProxy::decreaseListLevel()
1922 {
1923     if (!isValid())
1924         return;
1925
1926     m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
1927 }
1928
1929 void WebPageProxy::changeListType()
1930 {
1931     if (!isValid())
1932         return;
1933
1934     m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
1935 }
1936
1937 void WebPageProxy::setBaseWritingDirection(WritingDirection direction)
1938 {
1939     if (!isValid())
1940         return;
1941
1942     m_process->send(Messages::WebPage::SetBaseWritingDirection(direction), m_pageID);
1943 }
1944
1945 void WebPageProxy::updateFontAttributesAfterEditorStateChange()
1946 {
1947     m_cachedFontAttributesAtSelectionStart.reset();
1948
1949     if (m_editorState.isMissingPostLayoutData)
1950         return;
1951
1952     if (auto fontAttributes = m_editorState.postLayoutData().fontAttributes) {
1953         m_uiClient->didChangeFontAttributes(*fontAttributes);
1954         m_cachedFontAttributesAtSelectionStart = WTFMove(fontAttributes);
1955     }
1956 }
1957
1958 void WebPageProxy::setNeedsFontAttributes(bool needsFontAttributes)
1959 {
1960     if (m_needsFontAttributes == needsFontAttributes)
1961         return;
1962
1963     m_needsFontAttributes = needsFontAttributes;
1964
1965     if (isValid())
1966         m_process->send(Messages::WebPage::SetNeedsFontAttributes(needsFontAttributes), m_pageID);
1967 }
1968
1969 bool WebPageProxy::maintainsInactiveSelection() const
1970 {
1971     // Regardless of what the client wants to do, keep selections if a local Inspector is open.
1972     // Otherwise, there is no way to use the console to inspect the state of a selection.
1973     if (inspector() && inspector()->isVisible())
1974         return true;
1975
1976     return m_maintainsInactiveSelection;
1977 }
1978
1979 void WebPageProxy::setMaintainsInactiveSelection(bool newValue)
1980 {
1981     m_maintainsInactiveSelection = newValue;
1982 }
1983
1984 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
1985 {
1986     if (!isValid()) {
1987         callbackFunction(CallbackBase::Error::Unknown);
1988         return;
1989     }
1990
1991     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
1992     m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, argument, callbackID), m_pageID);
1993 }
1994     
1995 void WebPageProxy::executeEditCommand(const String& commandName, const String& argument)
1996 {
1997     static NeverDestroyed<String> ignoreSpellingCommandName(MAKE_STATIC_STRING_IMPL("ignoreSpelling"));
1998
1999     if (!isValid())
2000         return;
2001
2002     if (commandName == ignoreSpellingCommandName)
2003         ++m_pendingLearnOrIgnoreWordMessageCount;
2004
2005     m_process->send(Messages::WebPage::ExecuteEditCommand(commandName, argument), m_pageID);
2006 }
2007
2008 void WebPageProxy::requestFontAttributesAtSelectionStart(Function<void(const WebCore::FontAttributes&, CallbackBase::Error)>&& callback)
2009 {
2010     if (!isValid()) {
2011         callback({ }, CallbackBase::Error::Unknown);
2012         return;
2013     }
2014
2015     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
2016     m_process->send(Messages::WebPage::RequestFontAttributesAtSelectionStart(callbackID), m_pageID);
2017 }
2018
2019 void WebPageProxy::fontAttributesCallback(const WebCore::FontAttributes& attributes, CallbackID callbackID)
2020 {
2021     m_cachedFontAttributesAtSelectionStart = attributes;
2022
2023     if (auto callback = m_callbacks.take<FontAttributesCallback>(callbackID))
2024         callback->performCallbackWithReturnValue(attributes);
2025 }
2026
2027 void WebPageProxy::setEditable(bool editable)
2028 {
2029     if (editable == m_isEditable)
2030         return;
2031     if (!isValid())
2032         return;
2033
2034     m_isEditable = editable;
2035     m_process->send(Messages::WebPage::SetEditable(editable), m_pageID);
2036 }
2037     
2038 void WebPageProxy::setMediaStreamCaptureMuted(bool muted)
2039 {
2040     if (muted)
2041         setMuted(m_mutedState | WebCore::MediaProducer::CaptureDevicesAreMuted);
2042     else
2043         setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
2044 }
2045
2046 void WebPageProxy::activateMediaStreamCaptureInPage()
2047 {
2048 #if ENABLE(MEDIA_STREAM)
2049     UserMediaProcessManager::singleton().muteCaptureMediaStreamsExceptIn(*this);
2050 #endif
2051     setMuted(m_mutedState & ~WebCore::MediaProducer::CaptureDevicesAreMuted);
2052 }
2053
2054 #if !PLATFORM(IOS_FAMILY)
2055 void WebPageProxy::didCommitLayerTree(const RemoteLayerTreeTransaction&)
2056 {
2057 }
2058
2059 void WebPageProxy::layerTreeCommitComplete()
2060 {
2061 }
2062 #endif
2063
2064 #if ENABLE(DRAG_SUPPORT)
2065 void WebPageProxy::dragEntered(DragData& dragData, const String& dragStorageName)
2066 {
2067     performDragControllerAction(DragControllerAction::Entered, dragData, dragStorageName, { }, { });
2068 }
2069
2070 void WebPageProxy::dragUpdated(DragData& dragData, const String& dragStorageName)
2071 {
2072     performDragControllerAction(DragControllerAction::Updated, dragData, dragStorageName, { }, { });
2073 }
2074
2075 void WebPageProxy::dragExited(DragData& dragData, const String& dragStorageName)
2076 {
2077     performDragControllerAction(DragControllerAction::Exited, dragData, dragStorageName, { }, { });
2078 }
2079
2080 void WebPageProxy::performDragOperation(DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2081 {
2082     performDragControllerAction(DragControllerAction::PerformDragOperation, dragData, dragStorageName, WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionsForUpload));
2083 }
2084
2085 void WebPageProxy::performDragControllerAction(DragControllerAction action, DragData& dragData, const String& dragStorageName, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsForUpload)
2086 {
2087     if (!isValid())
2088         return;
2089 #if PLATFORM(GTK)
2090     UNUSED_PARAM(dragStorageName);
2091     UNUSED_PARAM(sandboxExtensionHandle);
2092     UNUSED_PARAM(sandboxExtensionsForUpload);
2093
2094     String url = dragData.asURL();
2095     if (!url.isEmpty())
2096         m_process->assumeReadAccessToBaseURL(*this, url);
2097
2098     ASSERT(dragData.platformData());
2099     WebSelectionData selection(*dragData.platformData());
2100     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData.clientPosition(), dragData.globalPosition(), dragData.draggingSourceOperationMask(), selection, dragData.flags()), m_pageID);
2101 #else
2102     m_process->send(Messages::WebPage::PerformDragControllerAction(action, dragData, sandboxExtensionHandle, sandboxExtensionsForUpload), m_pageID);
2103 #endif
2104 }
2105
2106 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect, const IntRect& editableElementRect)
2107 {
2108     MESSAGE_CHECK(m_process, dragOperation <= DragOperationDelete);
2109
2110     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
2111     m_currentDragHandlingMethod = dragHandlingMethod;
2112     m_currentDragIsOverFileInput = mouseIsOverFileInput;
2113     m_currentDragNumberOfFilesToBeAccepted = numberOfItemsToBeAccepted;
2114     m_currentDragCaretEditableElementRect = editableElementRect;
2115     setDragCaretRect(insertionRect);
2116 }
2117
2118 #if PLATFORM(GTK)
2119 void WebPageProxy::startDrag(WebSelectionData&& selection, uint64_t dragOperation, const ShareableBitmap::Handle& dragImageHandle)
2120 {
2121     RefPtr<ShareableBitmap> dragImage = !dragImageHandle.isNull() ? ShareableBitmap::create(dragImageHandle) : nullptr;
2122     pageClient().startDrag(WTFMove(selection.selectionData), static_cast<WebCore::DragOperation>(dragOperation), WTFMove(dragImage));
2123
2124     didStartDrag();
2125 }
2126 #endif
2127
2128 void WebPageProxy::dragEnded(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t operation)
2129 {
2130     if (!isValid())
2131         return;
2132     m_process->send(Messages::WebPage::DragEnded(clientPosition, globalPosition, operation), m_pageID);
2133     setDragCaretRect({ });
2134 }
2135
2136 void WebPageProxy::didPerformDragOperation(bool handled)
2137 {
2138     pageClient().didPerformDragOperation(handled);
2139 }
2140
2141 void WebPageProxy::didStartDrag()
2142 {
2143     if (isValid())
2144         m_process->send(Messages::WebPage::DidStartDrag(), m_pageID);
2145 }
2146     
2147 void WebPageProxy::dragCancelled()
2148 {
2149     if (isValid())
2150         m_process->send(Messages::WebPage::DragCancelled(), m_pageID);
2151 }
2152
2153 void WebPageProxy::didEndDragging()
2154 {
2155     resetCurrentDragInformation();
2156 }
2157
2158 void WebPageProxy::resetCurrentDragInformation()
2159 {
2160     m_currentDragOperation = WebCore::DragOperationNone;
2161     m_currentDragHandlingMethod = DragHandlingMethod::None;
2162     m_currentDragIsOverFileInput = false;
2163     m_currentDragNumberOfFilesToBeAccepted = 0;
2164     setDragCaretRect({ });
2165 }
2166
2167 #if !ENABLE(DATA_INTERACTION)
2168
2169 void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect)
2170 {
2171     m_currentDragCaretRect = dragCaretRect;
2172 }
2173
2174 #endif
2175
2176 #endif // ENABLE(DRAG_SUPPORT)
2177
2178 static bool removeOldRedundantEvent(Deque<NativeWebMouseEvent>& queue, WebEvent::Type incomingEventType)
2179 {
2180     if (incomingEventType != WebEvent::MouseMove && incomingEventType != WebEvent::MouseForceChanged)
2181         return false;
2182
2183     auto it = queue.rbegin();
2184     auto end = queue.rend();
2185
2186     // Must not remove the first event in the deque, since it is already being dispatched.
2187     if (it != end)
2188         --end;
2189
2190     for (; it != end; ++it) {
2191         auto type = it->type();
2192         if (type == incomingEventType) {
2193             queue.remove(--it.base());
2194             return true;
2195         }
2196         if (type != WebEvent::MouseMove && type != WebEvent::MouseForceChanged)
2197             break;
2198     }
2199     return false;
2200 }
2201
2202 void WebPageProxy::handleMouseEvent(const NativeWebMouseEvent& event)
2203 {
2204     if (!isValid())
2205         return;
2206
2207 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2208     if (m_scrollingCoordinatorProxy)
2209         m_scrollingCoordinatorProxy->handleMouseEvent(platform(event));
2210 #endif
2211
2212     // If we receive multiple mousemove or mouseforcechanged events and the most recent mousemove or mouseforcechanged event
2213     // (respectively) has not yet been sent to WebProcess for processing, remove the pending mouse event and insert the new
2214     // event in the queue.
2215     bool didRemoveEvent = removeOldRedundantEvent(m_mouseEventQueue, event.type());
2216     m_mouseEventQueue.append(event);
2217
2218 #if LOG_DISABLED
2219     UNUSED_PARAM(didRemoveEvent);
2220 #else
2221     LOG(MouseHandling, "UIProcess: %s mouse event %s (queue size %zu)", didRemoveEvent ? "replaced" : "enqueued", webMouseEventTypeString(event.type()), m_mouseEventQueue.size());
2222 #endif
2223
2224     if (m_mouseEventQueue.size() == 1) // Otherwise, called from DidReceiveEvent message handler.
2225         processNextQueuedMouseEvent();
2226 }
2227     
2228 void WebPageProxy::processNextQueuedMouseEvent()
2229 {
2230     if (!isValid())
2231         return;
2232
2233     ASSERT(!m_mouseEventQueue.isEmpty());
2234
2235     const NativeWebMouseEvent& event = m_mouseEventQueue.first();
2236
2237     if (pageClient().windowIsFrontWindowUnderMouse(event))
2238         setToolTip(String());
2239
2240     WebEvent::Type eventType = event.type();
2241     if (eventType == WebEvent::MouseDown || eventType == WebEvent::MouseForceChanged || eventType == WebEvent::MouseForceDown)
2242         m_process->responsivenessTimer().startWithLazyStop();
2243     else if (eventType != WebEvent::MouseMove) {
2244         // NOTE: This does not start the responsiveness timer because mouse move should not indicate interaction.
2245         m_process->responsivenessTimer().start();
2246     }
2247
2248     LOG(MouseHandling, "UIProcess: sent mouse event %s (queue size %zu)", webMouseEventTypeString(eventType), m_mouseEventQueue.size());
2249     m_process->send(Messages::WebPage::MouseEvent(event), m_pageID);
2250 }
2251
2252 #if MERGE_WHEEL_EVENTS
2253 static bool canCoalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2254 {
2255     if (a.position() != b.position())
2256         return false;
2257     if (a.globalPosition() != b.globalPosition())
2258         return false;
2259     if (a.modifiers() != b.modifiers())
2260         return false;
2261     if (a.granularity() != b.granularity())
2262         return false;
2263 #if PLATFORM(COCOA)
2264     if (a.phase() != b.phase())
2265         return false;
2266     if (a.momentumPhase() != b.momentumPhase())
2267         return false;
2268     if (a.hasPreciseScrollingDeltas() != b.hasPreciseScrollingDeltas())
2269         return false;
2270 #endif
2271
2272     return true;
2273 }
2274
2275 static WebWheelEvent coalesce(const WebWheelEvent& a, const WebWheelEvent& b)
2276 {
2277     ASSERT(canCoalesce(a, b));
2278
2279     FloatSize mergedDelta = a.delta() + b.delta();
2280     FloatSize mergedWheelTicks = a.wheelTicks() + b.wheelTicks();
2281
2282 #if PLATFORM(COCOA)
2283     FloatSize mergedUnacceleratedScrollingDelta = a.unacceleratedScrollingDelta() + b.unacceleratedScrollingDelta();
2284
2285     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());
2286 #else
2287     return WebWheelEvent(WebEvent::Wheel, b.position(), b.globalPosition(), mergedDelta, mergedWheelTicks, b.granularity(), b.modifiers(), b.timestamp());
2288 #endif
2289 }
2290 #endif // MERGE_WHEEL_EVENTS
2291
2292 static WebWheelEvent coalescedWheelEvent(Deque<NativeWebWheelEvent>& queue, Vector<NativeWebWheelEvent>& coalescedEvents)
2293 {
2294     ASSERT(!queue.isEmpty());
2295     ASSERT(coalescedEvents.isEmpty());
2296
2297 #if MERGE_WHEEL_EVENTS
2298     NativeWebWheelEvent firstEvent = queue.takeFirst();
2299     coalescedEvents.append(firstEvent);
2300
2301     WebWheelEvent event = firstEvent;
2302     while (!queue.isEmpty() && canCoalesce(event, queue.first())) {
2303         NativeWebWheelEvent firstEvent = queue.takeFirst();
2304         coalescedEvents.append(firstEvent);
2305         event = coalesce(event, firstEvent);
2306     }
2307
2308     return event;
2309 #else
2310     while (!queue.isEmpty())
2311         coalescedEvents.append(queue.takeFirst());
2312     return coalescedEvents.last();
2313 #endif
2314 }
2315
2316 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event)
2317 {
2318 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2319     if (m_scrollingCoordinatorProxy && m_scrollingCoordinatorProxy->handleWheelEvent(platform(event)))
2320         return;
2321 #endif
2322
2323     if (!isValid())
2324         return;
2325
2326     closeOverlayedViews();
2327
2328     if (!m_currentlyProcessedWheelEvents.isEmpty()) {
2329         m_wheelEventQueue.append(event);
2330         if (!shouldProcessWheelEventNow(event))
2331             return;
2332         // The queue has too many wheel events, so push a new event.
2333     }
2334
2335     if (!m_wheelEventQueue.isEmpty()) {
2336         processNextQueuedWheelEvent();
2337         return;
2338     }
2339
2340     auto coalescedWheelEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2341     coalescedWheelEvent->append(event);
2342     m_currentlyProcessedWheelEvents.append(WTFMove(coalescedWheelEvent));
2343     sendWheelEvent(event);
2344 }
2345
2346 void WebPageProxy::processNextQueuedWheelEvent()
2347 {
2348     auto nextCoalescedEvent = std::make_unique<Vector<NativeWebWheelEvent>>();
2349     WebWheelEvent nextWheelEvent = coalescedWheelEvent(m_wheelEventQueue, *nextCoalescedEvent.get());
2350     m_currentlyProcessedWheelEvents.append(WTFMove(nextCoalescedEvent));
2351     sendWheelEvent(nextWheelEvent);
2352 }
2353
2354 void WebPageProxy::sendWheelEvent(const WebWheelEvent& event)
2355 {
2356     m_process->send(
2357         Messages::EventDispatcher::WheelEvent(
2358             m_pageID,
2359             event,
2360             shouldUseImplicitRubberBandControl() ? !m_backForwardList->backItem() : rubberBandsAtLeft(),
2361             shouldUseImplicitRubberBandControl() ? !m_backForwardList->forwardItem() : rubberBandsAtRight(),
2362             rubberBandsAtTop(),
2363             rubberBandsAtBottom()
2364         ), 0);
2365
2366     // Manually ping the web process to check for responsiveness since our wheel
2367     // event will dispatch to a non-main thread, which always responds.
2368     m_process->isResponsiveWithLazyStop();
2369 }
2370
2371 bool WebPageProxy::shouldProcessWheelEventNow(const WebWheelEvent& event) const
2372 {
2373 #if PLATFORM(GTK)
2374     // Don't queue events representing a non-trivial scrolling phase to
2375     // avoid having them trapped in the queue, potentially preventing a
2376     // scrolling session to beginning or end correctly.
2377     // This is only needed by platforms whose WebWheelEvent has this phase
2378     // information (Cocoa and GTK+) but Cocoa was fine without it.
2379     if (event.phase() == WebWheelEvent::Phase::PhaseNone
2380         || event.phase() == WebWheelEvent::Phase::PhaseChanged
2381         || event.momentumPhase() == WebWheelEvent::Phase::PhaseNone
2382         || event.momentumPhase() == WebWheelEvent::Phase::PhaseChanged)
2383         return true;
2384 #else
2385     UNUSED_PARAM(event);
2386 #endif
2387     if (m_wheelEventQueue.size() >= wheelEventQueueSizeThreshold)
2388         return true;
2389     return false;
2390 }
2391
2392 void WebPageProxy::handleKeyboardEvent(const NativeWebKeyboardEvent& event)
2393 {
2394     if (!isValid())
2395         return;
2396     
2397     LOG(KeyHandling, "WebPageProxy::handleKeyboardEvent: %s", webKeyboardEventTypeString(event.type()));
2398
2399     m_keyEventQueue.append(event);
2400
2401     ResponsivenessTimer& responsivenessTimer = m_process->responsivenessTimer();
2402     if (event.type() == WebEvent::KeyDown)
2403         responsivenessTimer.startWithLazyStop();
2404     else
2405         responsivenessTimer.start();
2406
2407     if (m_keyEventQueue.size() == 1) { // Otherwise, sent from DidReceiveEvent message handler.
2408         LOG(KeyHandling, " UI process: sent keyEvent from handleKeyboardEvent");
2409         m_process->send(Messages::WebPage::KeyEvent(event), m_pageID);
2410     }
2411 }
2412
2413 WebPreferencesStore WebPageProxy::preferencesStore() const
2414 {
2415     if (m_configurationPreferenceValues.isEmpty())
2416         return m_preferences->store();
2417
2418     WebPreferencesStore store = m_preferences->store();
2419     for (const auto& preference : m_configurationPreferenceValues)
2420         store.m_values.set(preference.key, preference.value);
2421
2422     return store;
2423 }
2424
2425 #if ENABLE(NETSCAPE_PLUGIN_API)
2426 void WebPageProxy::findPlugin(const String& mimeType, uint32_t processType, const String& urlString, const String& frameURLString, const String& pageURLString, bool allowOnlyApplicationPlugins, Messages::WebPageProxy::FindPlugin::DelayedReply&& reply)
2427 {
2428     PageClientProtector protector(pageClient());
2429
2430     MESSAGE_CHECK_URL(m_process, urlString);
2431
2432     URL pluginURL = URL { URL(), urlString };
2433     String newMimeType = mimeType.convertToASCIILowercase();
2434
2435     PluginData::AllowedPluginTypes allowedPluginTypes = allowOnlyApplicationPlugins ? PluginData::OnlyApplicationPlugins : PluginData::AllPlugins;
2436
2437     URL pageURL = URL { URL(), pageURLString };
2438     if (!m_process->processPool().pluginInfoStore().isSupportedPlugin(mimeType, pluginURL, frameURLString, pageURL)) {
2439         reply(0, newMimeType, PluginModuleLoadNormally, { }, true);
2440         return;
2441     }
2442
2443     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, pluginURL, allowedPluginTypes);
2444     if (!plugin.path) {
2445         reply(0, newMimeType, PluginModuleLoadNormally, { }, false);
2446         return;
2447     }
2448
2449     uint32_t pluginLoadPolicy = PluginInfoStore::defaultLoadPolicyForPlugin(plugin);
2450
2451 #if PLATFORM(COCOA)
2452     auto pluginInformation = createPluginInformationDictionary(plugin, frameURLString, String(), pageURLString, String(), String());
2453 #endif
2454
2455     auto findPluginCompletion = [processType, reply = WTFMove(reply), newMimeType = WTFMove(newMimeType), plugin = WTFMove(plugin)] (uint32_t pluginLoadPolicy, const String& unavailabilityDescription) mutable {
2456         PluginProcessSandboxPolicy pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2457         switch (pluginLoadPolicy) {
2458         case PluginModuleLoadNormally:
2459             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyNormal;
2460             break;
2461         case PluginModuleLoadUnsandboxed:
2462             pluginProcessSandboxPolicy = PluginProcessSandboxPolicyUnsandboxed;
2463             break;
2464
2465         case PluginModuleBlockedForSecurity:
2466         case PluginModuleBlockedForCompatibility:
2467             reply(0, newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2468             return;
2469         }
2470
2471         reply(PluginProcessManager::singleton().pluginProcessToken(plugin, static_cast<PluginProcessType>(processType), pluginProcessSandboxPolicy), newMimeType, pluginLoadPolicy, unavailabilityDescription, false);
2472     };
2473
2474 #if PLATFORM(COCOA)
2475     m_navigationClient->decidePolicyForPluginLoad(*this, static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy), pluginInformation.get(), WTFMove(findPluginCompletion));
2476 #else
2477     findPluginCompletion(pluginLoadPolicy, { });
2478 #endif
2479 }
2480
2481 #endif // ENABLE(NETSCAPE_PLUGIN_API)
2482
2483 #if ENABLE(TOUCH_EVENTS)
2484
2485 static TrackingType mergeTrackingTypes(TrackingType a, TrackingType b)
2486 {
2487     if (static_cast<uintptr_t>(b) > static_cast<uintptr_t>(a))
2488         return b;
2489     return a;
2490 }
2491
2492 void WebPageProxy::updateTouchEventTracking(const WebTouchEvent& touchStartEvent)
2493 {
2494 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
2495     const EventNames& names = eventNames();
2496     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2497         IntPoint location = touchPoint.location();
2498         auto updateTrackingType = [this, location](TrackingType& trackingType, const AtomicString& eventName) {
2499             if (trackingType == TrackingType::Synchronous)
2500                 return;
2501
2502             TrackingType trackingTypeForLocation = m_scrollingCoordinatorProxy->eventTrackingTypeForPoint(eventName, location);
2503
2504             trackingType = mergeTrackingTypes(trackingType, trackingTypeForLocation);
2505         };
2506         updateTrackingType(m_touchAndPointerEventTracking.touchForceChangedTracking, names.touchforcechangeEvent);
2507         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.touchstartEvent);
2508         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.touchmoveEvent);
2509         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.touchendEvent);
2510         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.pointerdownEvent);
2511         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.pointermoveEvent);
2512         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.pointerupEvent);
2513         updateTrackingType(m_touchAndPointerEventTracking.touchStartTracking, names.mousedownEvent);
2514         updateTrackingType(m_touchAndPointerEventTracking.touchMoveTracking, names.mousemoveEvent);
2515         updateTrackingType(m_touchAndPointerEventTracking.touchEndTracking, names.mouseupEvent);
2516     }
2517 #else
2518     UNUSED_PARAM(touchStartEvent);
2519     m_touchAndPointerEventTracking.touchForceChangedTracking = TrackingType::Synchronous;
2520     m_touchAndPointerEventTracking.touchStartTracking = TrackingType::Synchronous;
2521     m_touchAndPointerEventTracking.touchMoveTracking = TrackingType::Synchronous;
2522     m_touchAndPointerEventTracking.touchEndTracking = TrackingType::Synchronous;
2523 #endif // ENABLE(ASYNC_SCROLLING)
2524 }
2525
2526 TrackingType WebPageProxy::touchEventTrackingType(const WebTouchEvent& touchStartEvent) const
2527 {
2528     // We send all events if any type is needed, we just do it asynchronously for the types that are not tracked.
2529     //
2530     // Touch events define a sequence with strong dependencies. For example, we can expect
2531     // a TouchMove to only appear after a TouchStart, and the ids of the touch points is consistent between
2532     // the two.
2533     //
2534     // WebCore should not have to set up its state correctly after some events were dismissed.
2535     // For example, we don't want to send a TouchMoved without a TouchPressed.
2536     // We send everything, WebCore updates its internal state and dispatch what is needed to the page.
2537     TrackingType globalTrackingType = m_touchAndPointerEventTracking.isTrackingAnything() ? TrackingType::Asynchronous : TrackingType::NotTracking;
2538
2539     globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchForceChangedTracking);
2540     for (auto& touchPoint : touchStartEvent.touchPoints()) {
2541         switch (touchPoint.state()) {
2542         case WebPlatformTouchPoint::TouchReleased:
2543             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchEndTracking);
2544             break;
2545         case WebPlatformTouchPoint::TouchPressed:
2546             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchStartTracking);
2547             break;
2548         case WebPlatformTouchPoint::TouchMoved:
2549         case WebPlatformTouchPoint::TouchStationary:
2550             globalTrackingType = mergeTrackingTypes(globalTrackingType, m_touchAndPointerEventTracking.touchMoveTracking);
2551             break;
2552         case WebPlatformTouchPoint::TouchCancelled:
2553             globalTrackingType = mergeTrackingTypes(globalTrackingType, TrackingType::Asynchronous);
2554             break;
2555         }
2556     }
2557
2558     return globalTrackingType;
2559 }
2560
2561 #endif
2562
2563 #if ENABLE(MAC_GESTURE_EVENTS)
2564 void WebPageProxy::handleGestureEvent(const NativeWebGestureEvent& event)
2565 {
2566     if (!isValid())
2567         return;
2568
2569     m_gestureEventQueue.append(event);
2570     // FIXME: Consider doing some coalescing here.
2571
2572     ResponsivenessTimer& responsivenessTimer = m_process->responsivenessTimer();
2573     if (event.type() == WebEvent::GestureStart || event.type() == WebEvent::GestureChange)
2574         responsivenessTimer.startWithLazyStop();
2575     else
2576         responsivenessTimer.start();
2577
2578     m_process->send(Messages::EventDispatcher::GestureEvent(m_pageID, event), 0);
2579 }
2580 #endif
2581
2582 #if ENABLE(IOS_TOUCH_EVENTS)
2583 void WebPageProxy::handleTouchEventSynchronously(NativeWebTouchEvent& event)
2584 {
2585     if (!isValid())
2586         return;
2587
2588     TraceScope scope(SyncTouchEventStart, SyncTouchEventEnd);
2589
2590     updateTouchEventTracking(event);
2591
2592     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2593     if (touchEventsTrackingType == TrackingType::NotTracking)
2594         return;
2595
2596     if (touchEventsTrackingType == TrackingType::Asynchronous) {
2597         // We can end up here if a native gesture has not started but the event handlers are passive.
2598         //
2599         // The client of WebPageProxy asks the event to be sent synchronously since the touch event
2600         // can prevent a native gesture.
2601         // But, here we know that all events handlers that can handle this events are passive.
2602         // We can use asynchronous dispatch and pretend to the client that the page does nothing with the events.
2603         event.setCanPreventNativeGestures(false);
2604         handleTouchEventAsynchronously(event);
2605         didReceiveEvent(event.type(), false);
2606         return;
2607     }
2608
2609     m_process->responsivenessTimer().start();
2610     bool handled = false;
2611     bool replyReceived = m_process->sendSync(Messages::WebPage::TouchEventSync(event), Messages::WebPage::TouchEventSync::Reply(handled), m_pageID, 1_s);
2612     // If the sync request has timed out, we should consider the event handled. The Web Process is too busy to answer any questions, so the default action is also likely to have issues.
2613     if (!replyReceived)
2614         handled = true;
2615     didReceiveEvent(event.type(), handled);
2616     pageClient().doneWithTouchEvent(event, handled);
2617     m_process->responsivenessTimer().stop();
2618
2619     if (event.allTouchPointsAreReleased())
2620         m_touchAndPointerEventTracking.reset();
2621 }
2622
2623 void WebPageProxy::handleTouchEventAsynchronously(const NativeWebTouchEvent& event)
2624 {
2625     if (!isValid())
2626         return;
2627
2628     TrackingType touchEventsTrackingType = touchEventTrackingType(event);
2629     if (touchEventsTrackingType == TrackingType::NotTracking)
2630         return;
2631
2632     m_process->send(Messages::EventDispatcher::TouchEvent(m_pageID, event), 0);
2633
2634     if (event.allTouchPointsAreReleased())
2635         m_touchAndPointerEventTracking.reset();
2636 }
2637
2638 #elif ENABLE(TOUCH_EVENTS)
2639 void WebPageProxy::handleTouchEvent(const NativeWebTouchEvent& event)
2640 {
2641     if (!isValid())
2642         return;
2643
2644     updateTouchEventTracking(event);
2645
2646     if (touchEventTrackingType(event) == TrackingType::NotTracking)
2647         return;
2648
2649     // If the page is suspended, which should be the case during panning, pinching
2650     // and animation on the page itself (kinetic scrolling, tap to zoom) etc, then
2651     // we do not send any of the events to the page even if is has listeners.
2652     if (!m_isPageSuspended) {
2653         m_touchEventQueue.append(event);
2654         m_process->responsivenessTimer().start();
2655         m_process->send(Messages::WebPage::TouchEvent(event), m_pageID);
2656     } else {
2657         if (m_touchEventQueue.isEmpty()) {
2658             bool isEventHandled = false;
2659             pageClient().doneWithTouchEvent(event, isEventHandled);
2660         } else {
2661             // We attach the incoming events to the newest queued event so that all
2662             // the events are delivered in the correct order when the event is dequed.
2663             QueuedTouchEvents& lastEvent = m_touchEventQueue.last();
2664             lastEvent.deferredTouchEvents.append(event);
2665         }
2666     }
2667
2668     if (event.allTouchPointsAreReleased())
2669         m_touchAndPointerEventTracking.reset();
2670 }
2671 #endif // ENABLE(TOUCH_EVENTS)
2672
2673 #if ENABLE(POINTER_EVENTS)
2674 void WebPageProxy::cancelPointer(WebCore::PointerID pointerId, const WebCore::IntPoint& documentPoint)
2675 {
2676     m_process->send(Messages::WebPage::CancelPointer(pointerId, documentPoint), m_pageID);
2677 }
2678 #endif
2679
2680 void WebPageProxy::scrollBy(ScrollDirection direction, ScrollGranularity granularity)
2681 {
2682     if (!isValid())
2683         return;
2684
2685     m_process->send(Messages::WebPage::ScrollBy(direction, granularity), m_pageID);
2686 }
2687
2688 void WebPageProxy::centerSelectionInVisibleArea()
2689 {
2690     if (!isValid())
2691         return;
2692
2693     m_process->send(Messages::WebPage::CenterSelectionInVisibleArea(), m_pageID);
2694 }
2695
2696 class WebPageProxy::PolicyDecisionSender : public RefCounted<PolicyDecisionSender> {
2697 public:
2698     using SendFunction = CompletionHandler<void(PolicyCheckIdentifier, PolicyAction, uint64_t newNavigationID, DownloadID, Optional<WebsitePoliciesData>)>;
2699
2700     static Ref<PolicyDecisionSender> create(PolicyCheckIdentifier identifier, SendFunction&& sendFunction)
2701     {
2702         return adoptRef(*new PolicyDecisionSender(identifier, WTFMove(sendFunction)));
2703     }
2704
2705     template<typename... Args> void send(Args... args)
2706     {
2707         if (m_sendFunction)
2708             m_sendFunction(m_identifier, std::forward<Args>(args)...);
2709     }
2710 private:
2711     PolicyDecisionSender(PolicyCheckIdentifier identifier, SendFunction sendFunction)
2712         : m_sendFunction(WTFMove(sendFunction))
2713         , m_identifier(identifier)
2714         { }
2715
2716     SendFunction m_sendFunction;
2717     PolicyCheckIdentifier m_identifier;
2718 };
2719
2720 void WebPageProxy::receivedNavigationPolicyDecision(PolicyAction policyAction, API::Navigation* navigation, ProcessSwapRequestedByClient processSwapRequestedByClient, WebFrameProxy& frame, API::WebsitePolicies* policies, Ref<PolicyDecisionSender>&& sender)
2721 {
2722     Optional<WebsitePoliciesData> data;
2723     if (policies) {
2724         data = policies->data();
2725         if (policies->websiteDataStore())
2726             changeWebsiteDataStore(policies->websiteDataStore()->websiteDataStore());
2727     }
2728
2729     if (policyAction == PolicyAction::Use && navigation && (navigation->isSystemPreview() || navigation->shouldForceDownload()))
2730         policyAction = PolicyAction::Download;
2731
2732     if (policyAction != PolicyAction::Use || !frame.isMainFrame() || !navigation) {
2733         receivedPolicyDecision(policyAction, navigation, WTFMove(data), WTFMove(sender));
2734         return;
2735     }
2736
2737     process().processPool().processForNavigation(*this, *navigation, processSwapRequestedByClient, [this, protectedThis = makeRef(*this), policyAction, navigation = makeRef(*navigation),
2738         data = WTFMove(data), sender = WTFMove(sender), processSwapRequestedByClient] (Ref<WebProcessProxy>&& processForNavigation, SuspendedPageProxy* destinationSuspendedPage, const String& reason) mutable {
2739         // If the navigation has been destroyed, then no need to proceed.
2740         if (isClosed() || !navigationState().hasNavigation(navigation->navigationID())) {
2741             receivedPolicyDecision(policyAction, navigation.ptr(), WTFMove(data), WTFMove(sender));
2742             return;
2743         }
2744
2745         if (processForNavigation.ptr() != &process()) {
2746             policyAction = PolicyAction::StopAllLoads;
2747             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction, swapping process %i with process %i for navigation, reason: %{public}s", processIdentifier(), processForNavigation->processIdentifier(), reason.utf8().data());
2748             LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), processForNavigation->processIdentifier(), navigation->navigationID(), navigation->loggingString());
2749         } else
2750             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction: keep using process %i for navigation, reason: %{public}s", processIdentifier(), reason.utf8().data());
2751
2752         bool shouldProcessSwap = processForNavigation.ptr() != &process();
2753         receivedPolicyDecision(policyAction, navigation.ptr(), shouldProcessSwap ? WTF::nullopt : WTFMove(data), WTFMove(sender), shouldProcessSwap ? WillContinueLoadInNewProcess::Yes : WillContinueLoadInNewProcess::No);
2754
2755         if (!shouldProcessSwap)
2756             return;
2757
2758         // FIXME: Architecturally we do not currently support multiple WebPage's with the same ID in a given WebProcess.
2759         // In the case where the destination WebProcess has a SuspendedPageProxy for this WebPage, we should have thrown
2760         // it away to support WebProcess re-use.
2761         ASSERT(destinationSuspendedPage || !process().processPool().hasSuspendedPageFor(processForNavigation, this));
2762
2763         auto suspendedPage = destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr;
2764         if (suspendedPage && suspendedPage->failedToSuspend())
2765             suspendedPage = nullptr;
2766
2767         continueNavigationInNewProcess(navigation, WTFMove(suspendedPage), WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
2768     });
2769 }
2770
2771 void WebPageProxy::receivedPolicyDecision(PolicyAction action, API::Navigation* navigation, Optional<WebsitePoliciesData>&& websitePolicies, Ref<PolicyDecisionSender>&& sender, WillContinueLoadInNewProcess willContinueLoadInNewProcess)
2772 {
2773     if (!isValid()) {
2774         sender->send(PolicyAction::Ignore, 0, DownloadID(), WTF::nullopt);
2775         return;
2776     }
2777
2778     auto transaction = m_pageLoadState.transaction();
2779
2780     if (action == PolicyAction::Ignore && willContinueLoadInNewProcess == WillContinueLoadInNewProcess::No)
2781         m_pageLoadState.clearPendingAPIRequestURL(transaction);
2782
2783     DownloadID downloadID = { };
2784     if (action == PolicyAction::Download) {
2785         // Create a download proxy.
2786         auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
2787         if (navigation) {
2788             download->setWasUserInitiated(navigation->wasUserInitiated());
2789             download->setRedirectChain(navigation->takeRedirectChain());
2790         }
2791
2792         downloadID = download->downloadID();
2793         handleDownloadRequest(download);
2794         m_decidePolicyForResponseRequest = { };
2795     }
2796
2797     sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
2798 }
2799
2800 void WebPageProxy::commitProvisionalPage(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData& userData)
2801 {
2802     ASSERT(m_provisionalPage);
2803     RELEASE_LOG_IF_ALLOWED(Loading, "commitProvisionalPage: previousPID = %i, newPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_provisionalPage->process().processIdentifier(), m_pageID);
2804
2805     Optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? makeOptional(m_mainFrame->frameID()) : WTF::nullopt;
2806
2807     ASSERT(m_process.ptr() != &m_provisionalPage->process());
2808
2809     processDidTerminate(ProcessTerminationReason::NavigationSwap);
2810
2811     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
2812     auto* navigation = navigationState().navigation(m_provisionalPage->navigationID());
2813     bool didSuspendPreviousPage = navigation ? suspendCurrentPageIfPossible(*navigation, mainFrameIDInPreviousProcess, m_provisionalPage->processSwapRequestedByClient()) : false;
2814     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::No);
2815
2816     // There is no way we'll be able to return to the page in the previous page so close it.
2817     if (!didSuspendPreviousPage)
2818         m_process->send(Messages::WebPage::Close(), pageID());
2819
2820     swapToWebProcess(m_provisionalPage->process(), m_provisionalPage->takeDrawingArea(), m_provisionalPage->mainFrame());
2821
2822 #if PLATFORM(COCOA)
2823     auto accessibilityToken = m_provisionalPage->takeAccessibilityToken();
2824     if (!accessibilityToken.isEmpty())
2825         registerWebProcessAccessibilityToken({ accessibilityToken.data(), accessibilityToken.size() });
2826 #endif
2827
2828     didCommitLoadForFrame(frameID, navigationID, mimeType, frameHasCustomContentProvider, frameLoadType, certificateInfo, containsPluginDocument, forcedHasInsecureContent, userData);
2829
2830     m_provisionalPage = nullptr;
2831 }
2832
2833 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& newProcess, ProcessSwapRequestedByClient processSwapRequestedByClient, Optional<WebsitePoliciesData>&& websitePolicies)
2834 {
2835     RELEASE_LOG_IF_ALLOWED(Loading, "continueNavigationInNewProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
2836     LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
2837
2838     if (m_provisionalPage) {
2839         if (m_provisionalPage->navigationID() != navigation.navigationID())
2840             m_provisionalPage->cancel();
2841         m_provisionalPage = nullptr;
2842     }
2843
2844     m_provisionalPage = std::make_unique<ProvisionalPageProxy>(*this, newProcess.copyRef(), WTFMove(suspendedPageProxy), navigation.navigationID(), navigation.currentRequestIsRedirect(), navigation.currentRequest(), processSwapRequestedByClient);
2845
2846     if (auto* item = navigation.targetItem()) {
2847         LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
2848
2849         auto transaction = m_pageLoadState.transaction();
2850         m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
2851
2852         m_provisionalPage->goToBackForwardItem(navigation, *item, WTFMove(websitePolicies));
2853         return;
2854     }
2855
2856     if (m_backForwardList->currentItem() && (navigation.lockBackForwardList() == LockBackForwardList::Yes || navigation.lockHistory() == LockHistory::Yes)) {
2857         // If WebCore is supposed to lock the history for this load, then the new process needs to know about the current history item so it can update
2858         // it instead of creating a new one.
2859         newProcess->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
2860     }
2861
2862     // FIXME: Work out timing of responding with the last policy delegate, etc
2863     ASSERT(!navigation.currentRequest().isEmpty());
2864     if (auto& substituteData = navigation.substituteData())
2865         m_provisionalPage->loadData(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get(), WTFMove(websitePolicies));
2866     else
2867         m_provisionalPage->loadRequest(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, WTFMove(websitePolicies));
2868 }
2869
2870 bool WebPageProxy::isPageOpenedByDOMShowingInitialEmptyDocument() const
2871 {
2872     return openedByDOM() && !hasCommittedAnyProvisionalLoads();
2873 }
2874
2875 // MSVC gives a redeclaration error if noreturn is used on the definition and not the declaration, while
2876 // Cocoa tests segfault if it is moved to the declaration site (even if we move the definition with it!).
2877 #if !COMPILER(MSVC)
2878 NO_RETURN_DUE_TO_ASSERT
2879 #endif
2880 void WebPageProxy::didFailToSuspendAfterProcessSwap()
2881 {
2882     // Only the SuspendedPageProxy should be getting this call.
2883     ASSERT_NOT_REACHED();
2884 }
2885
2886 #if !COMPILER(MSVC)
2887 NO_RETURN_DUE_TO_ASSERT
2888 #endif
2889 void WebPageProxy::didSuspendAfterProcessSwap()
2890 {
2891     // Only the SuspendedPageProxy should be getting this call.
2892     ASSERT_NOT_REACHED();
2893 }
2894
2895 void WebPageProxy::setUserAgent(String&& userAgent)
2896 {
2897     if (m_userAgent == userAgent)
2898         return;
2899     m_userAgent = WTFMove(userAgent);
2900
2901 #if ENABLE(SERVICE_WORKER)
2902     // We update the service worker there at the moment to be sure we use values used by actual web pages.
2903     // FIXME: Refactor this when we have a better User-Agent story.
2904     process().processPool().updateServiceWorkerUserAgent(m_userAgent);
2905 #endif
2906
2907     if (!isValid())
2908         return;
2909     m_process->send(Messages::WebPage::SetUserAgent(m_userAgent), m_pageID);
2910 }
2911
2912 void WebPageProxy::setApplicationNameForUserAgent(const String& applicationName)
2913 {
2914     if (m_applicationNameForUserAgent == applicationName)
2915         return;
2916
2917     m_applicationNameForUserAgent = applicationName;
2918     if (!m_customUserAgent.isEmpty())
2919         return;
2920
2921     setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2922 }
2923
2924 void WebPageProxy::setCustomUserAgent(const String& customUserAgent)
2925 {
2926     if (m_customUserAgent == customUserAgent)
2927         return;
2928
2929     m_customUserAgent = customUserAgent;
2930
2931     if (m_customUserAgent.isEmpty()) {
2932         setUserAgent(standardUserAgent(m_applicationNameForUserAgent));
2933         return;
2934     }
2935
2936     setUserAgent(String { m_customUserAgent });
2937 }
2938
2939 void WebPageProxy::resumeActiveDOMObjectsAndAnimations()
2940 {
2941     if (!isValid() || !m_isPageSuspended)
2942         return;
2943
2944     m_isPageSuspended = false;
2945
2946     m_process->send(Messages::WebPage::ResumeActiveDOMObjectsAndAnimations(), m_pageID);
2947 }
2948
2949 void WebPageProxy::suspendActiveDOMObjectsAndAnimations()
2950 {
2951     if (!isValid() || m_isPageSuspended)
2952         return;
2953
2954     m_isPageSuspended = true;
2955
2956     m_process->send(Messages::WebPage::SuspendActiveDOMObjectsAndAnimations(), m_pageID);
2957 }
2958
2959 bool WebPageProxy::supportsTextEncoding() const
2960 {
2961     // FIXME (118840): We should probably only support this for text documents, not all non-image documents.
2962     return m_mainFrame && !m_mainFrame->isDisplayingStandaloneImageDocument();
2963 }
2964
2965 void WebPageProxy::setCustomTextEncodingName(const String& encodingName)
2966 {
2967     if (m_customTextEncodingName == encodingName)
2968         return;
2969     m_customTextEncodingName = encodingName;
2970
2971     if (!isValid())
2972         return;
2973     m_process->send(Messages::WebPage::SetCustomTextEncodingName(encodingName), m_pageID);
2974 }
2975
2976 SessionState WebPageProxy::sessionState(WTF::Function<bool (WebBackForwardListItem&)>&& filter) const
2977 {
2978     SessionState sessionState;
2979
2980     sessionState.backForwardListState = m_backForwardList->backForwardListState(WTFMove(filter));
2981
2982     String provisionalURLString = m_pageLoadState.pendingAPIRequestURL();
2983     if (provisionalURLString.isEmpty())
2984         provisionalURLString = m_pageLoadState.provisionalURL();
2985
2986     if (!provisionalURLString.isEmpty())
2987         sessionState.provisionalURL = URL(URL(), provisionalURLString);
2988
2989     sessionState.renderTreeSize = renderTreeSize();
2990     return sessionState;
2991 }
2992
2993 RefPtr<API::Navigation> WebPageProxy::restoreFromSessionState(SessionState sessionState, bool navigate)
2994 {
2995     RELEASE_LOG_IF_ALLOWED(Loading, "restoreFromSessionState: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
2996
2997     m_sessionRestorationRenderTreeSize = 0;
2998     m_hitRenderTreeSizeThreshold = false;
2999
3000     bool hasBackForwardList = !!sessionState.backForwardListState.currentIndex;
3001
3002     if (hasBackForwardList) {
3003         m_backForwardList->restoreFromState(WTFMove(sessionState.backForwardListState));
3004         process().send(Messages::WebPage::RestoreSession(m_backForwardList->itemStates()), m_pageID);
3005
3006         auto transaction = m_pageLoadState.transaction();
3007         m_pageLoadState.setCanGoBack(transaction, m_backForwardList->backItem());
3008         m_pageLoadState.setCanGoForward(transaction, m_backForwardList->forwardItem());
3009
3010         // The back / forward list was restored from a sessionState so we don't want to snapshot the current
3011         // page when navigating away. Suppress navigation snapshotting until the next load has committed
3012         suppressNextAutomaticNavigationSnapshot();
3013     }
3014
3015     // FIXME: Navigating should be separate from state restoration.
3016     if (navigate) {
3017         m_sessionRestorationRenderTreeSize = sessionState.renderTreeSize;
3018         if (!m_sessionRestorationRenderTreeSize)
3019             m_hitRenderTreeSizeThreshold = true; // If we didn't get data on renderTreeSize, just don't fire the milestone.
3020
3021         if (!sessionState.provisionalURL.isNull())
3022             return loadRequest(sessionState.provisionalURL);
3023
3024         if (hasBackForwardList) {
3025             if (WebBackForwardListItem* item = m_backForwardList->currentItem())
3026                 return goToBackForwardItem(*item);
3027         }
3028     }
3029
3030     return nullptr;
3031 }
3032
3033 bool WebPageProxy::supportsTextZoom() const
3034 {
3035     // FIXME (118840): This should also return false for standalone media and plug-in documents.
3036     if (!m_mainFrame || m_mainFrame->isDisplayingStandaloneImageDocument())
3037         return false;
3038
3039     return true;
3040 }
3041  
3042 void WebPageProxy::setTextZoomFactor(double zoomFactor)
3043 {
3044     if (!isValid())
3045         return;
3046
3047     if (m_textZoomFactor == zoomFactor)
3048         return;
3049
3050     m_textZoomFactor = zoomFactor;
3051     m_process->send(Messages::WebPage::SetTextZoomFactor(m_textZoomFactor), m_pageID); 
3052 }
3053
3054 void WebPageProxy::setPageZoomFactor(double zoomFactor)
3055 {
3056     if (!isValid())
3057         return;
3058
3059     if (m_pageZoomFactor == zoomFactor)
3060         return;
3061
3062     closeOverlayedViews();
3063
3064     m_pageZoomFactor = zoomFactor;
3065     m_process->send(Messages::WebPage::SetPageZoomFactor(m_pageZoomFactor), m_pageID); 
3066 }
3067
3068 void WebPageProxy::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
3069 {
3070     if (!isValid())
3071         return;
3072
3073     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
3074         return;
3075
3076     closeOverlayedViews();
3077
3078     m_pageZoomFactor = pageZoomFactor;
3079     m_textZoomFactor = textZoomFactor;
3080     m_process->send(Messages::WebPage::SetPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor), m_pageID); 
3081 }
3082
3083 double WebPageProxy::pageZoomFactor() const
3084 {
3085     // Zoom factor for non-PDF pages persists across page loads. We maintain a separate member variable for PDF
3086     // zoom which ensures that we don't use the PDF zoom for a normal page.
3087     if (m_mainFramePluginHandlesPageScaleGesture)
3088         return m_pluginZoomFactor;
3089     return m_pageZoomFactor;
3090 }
3091
3092 double WebPageProxy::pageScaleFactor() const
3093 {
3094     // PDF documents use zoom and scale factors to size themselves appropriately in the window. We store them
3095     // separately but decide which to return based on the main frame.
3096     if (m_mainFramePluginHandlesPageScaleGesture)
3097         return m_pluginScaleFactor;
3098     return m_pageScaleFactor;
3099 }
3100
3101 void WebPageProxy::scalePage(double scale, const IntPoint& origin)
3102 {
3103     ASSERT(scale > 0);
3104
3105     if (!isValid())
3106         return;
3107
3108     m_pageScaleFactor = scale;
3109     m_process->send(Messages::WebPage::ScalePage(scale, origin), m_pageID);
3110 }
3111
3112 void WebPageProxy::scalePageInViewCoordinates(double scale, const IntPoint& centerInViewCoordinates)
3113 {
3114     ASSERT(scale > 0);
3115
3116     if (!isValid())
3117         return;
3118
3119     m_pageScaleFactor = scale;
3120     m_process->send(Messages::WebPage::ScalePageInViewCoordinates(scale, centerInViewCoordinates), m_pageID);
3121 }
3122
3123 void WebPageProxy::scaleView(double scale)
3124 {
3125     ASSERT(scale > 0);
3126
3127     if (!isValid())
3128         return;
3129
3130     m_viewScaleFactor = scale;
3131     m_process->send(Messages::WebPage::ScaleView(scale), m_pageID);
3132 }
3133
3134 void WebPageProxy::setIntrinsicDeviceScaleFactor(float scaleFactor)
3135 {
3136     if (m_intrinsicDeviceScaleFactor == scaleFactor)
3137         return;
3138
3139     m_intrinsicDeviceScaleFactor = scaleFactor;
3140
3141     if (m_drawingArea)
3142         m_drawingArea->deviceScaleFactorDidChange();
3143 }
3144
3145 void WebPageProxy::windowScreenDidChange(PlatformDisplayID displayID)
3146 {
3147     if (!isValid())
3148         return;
3149
3150     m_process->send(Messages::WebPage::WindowScreenDidChange(displayID), m_pageID);
3151 }
3152
3153 float WebPageProxy::deviceScaleFactor() const
3154 {
3155     return m_customDeviceScaleFactor.valueOr(m_intrinsicDeviceScaleFactor);
3156 }
3157
3158 void WebPageProxy::setCustomDeviceScaleFactor(float customScaleFactor)
3159 {
3160     if (!isValid())
3161         return;
3162
3163     // FIXME: Remove this once we bump cairo requirements to support HiDPI.
3164     // https://bugs.webkit.org/show_bug.cgi?id=133378
3165 #if USE(CAIRO) && !HAVE(CAIRO_SURFACE_SET_DEVICE_SCALE)
3166     return;
3167 #endif
3168
3169     if (m_customDeviceScaleFactor && m_customDeviceScaleFactor.value() == customScaleFactor)
3170         return;
3171
3172     float oldScaleFactor = deviceScaleFactor();
3173
3174     // A value of 0 clears the customScaleFactor.
3175     if (customScaleFactor)
3176         m_customDeviceScaleFactor = customScaleFactor;
3177     else
3178         m_customDeviceScaleFactor = WTF::nullopt;
3179
3180     if (deviceScaleFactor() != oldScaleFactor)
3181         m_drawingArea->deviceScaleFactorDidChange();
3182 }
3183
3184 void WebPageProxy::accessibilitySettingsDidChange()
3185 {
3186     if (!isValid())
3187         return;
3188
3189     m_process->send(Messages::WebPage::AccessibilitySettingsDidChange(), m_pageID);
3190 }
3191
3192 #if ENABLE(ACCESSIBILITY_EVENTS)
3193 void WebPageProxy::updateAccessibilityEventsEnabled(bool enabled)
3194 {
3195     if (!isValid())
3196         return;
3197
3198     m_process->send(Messages::WebPage::UpdateAccessibilityEventsEnabled(enabled), m_pageID);
3199 }
3200 #endif
3201
3202 void WebPageProxy::setUseFixedLayout(bool fixed)
3203 {
3204     if (!isValid())
3205         return;
3206
3207     // This check is fine as the value is initialized in the web
3208     // process as part of the creation parameters.
3209     if (fixed == m_useFixedLayout)
3210         return;
3211
3212     m_useFixedLayout = fixed;
3213     if (!fixed)
3214         m_fixedLayoutSize = IntSize();
3215     m_process->send(Messages::WebPage::SetUseFixedLayout(fixed), m_pageID);
3216 }
3217
3218 void WebPageProxy::setFixedLayoutSize(const IntSize& size)
3219 {
3220     if (!isValid())
3221         return;
3222
3223     if (size == m_fixedLayoutSize)
3224         return;
3225
3226     m_fixedLayoutSize = size;
3227     m_process->send(Messages::WebPage::SetFixedLayoutSize(size), m_pageID);
3228 }
3229
3230 void WebPageProxy::setAlwaysShowsHorizontalScroller(bool alwaysShowsHorizontalScroller)
3231 {
3232     if (!isValid())
3233         return;
3234
3235     if (alwaysShowsHorizontalScroller == m_alwaysShowsHorizontalScroller)
3236         return;
3237
3238     m_alwaysShowsHorizontalScroller = alwaysShowsHorizontalScroller;
3239     m_process->send(Messages::WebPage::SetAlwaysShowsHorizontalScroller(alwaysShowsHorizontalScroller), m_pageID);
3240 }
3241
3242 void WebPageProxy::setAlwaysShowsVerticalScroller(bool alwaysShowsVerticalScroller)
3243 {
3244     if (!isValid())
3245         return;
3246
3247     if (alwaysShowsVerticalScroller == m_alwaysShowsVerticalScroller)
3248         return;
3249
3250     m_alwaysShowsVerticalScroller = alwaysShowsVerticalScroller;
3251     m_process->send(Messages::WebPage::SetAlwaysShowsVerticalScroller(alwaysShowsVerticalScroller), m_pageID);
3252 }
3253
3254 void WebPageProxy::listenForLayoutMilestones(OptionSet<WebCore::LayoutMilestone> milestones)
3255 {
3256     if (!isValid())
3257         return;
3258     
3259     if (milestones == m_observedLayoutMilestones)
3260         return;
3261
3262     m_observedLayoutMilestones = milestones;
3263     m_process->send(Messages::WebPage::ListenForLayoutMilestones(milestones), m_pageID);
3264 }
3265
3266 void WebPageProxy::setSuppressScrollbarAnimations(bool suppressAnimations)
3267 {
3268     if (!isValid())
3269         return;
3270
3271     if (suppressAnimations == m_suppressScrollbarAnimations)
3272         return;
3273
3274     m_suppressScrollbarAnimations = suppressAnimations;
3275     m_process->send(Messages::WebPage::SetSuppressScrollbarAnimations(suppressAnimations), m_pageID);
3276 }
3277
3278 bool WebPageProxy::rubberBandsAtLeft() const
3279 {
3280     return m_rubberBandsAtLeft;
3281 }
3282
3283 void WebPageProxy::setRubberBandsAtLeft(bool rubberBandsAtLeft)
3284 {
3285     m_rubberBandsAtLeft = rubberBandsAtLeft;
3286 }
3287
3288 bool WebPageProxy::rubberBandsAtRight() const
3289 {
3290     return m_rubberBandsAtRight;
3291 }
3292
3293 void WebPageProxy::setRubberBandsAtRight(bool rubberBandsAtRight)
3294 {
3295     m_rubberBandsAtRight = rubberBandsAtRight;
3296 }
3297
3298 bool WebPageProxy::rubberBandsAtTop() const
3299 {
3300     return m_rubberBandsAtTop;
3301 }
3302
3303 void WebPageProxy::setRubberBandsAtTop(bool rubberBandsAtTop)
3304 {
3305     m_rubberBandsAtTop = rubberBandsAtTop;
3306 }
3307
3308 bool WebPageProxy::rubberBandsAtBottom() const
3309 {
3310     return m_rubberBandsAtBottom;
3311 }
3312
3313 void WebPageProxy::setRubberBandsAtBottom(bool rubberBandsAtBottom)
3314 {
3315     m_rubberBandsAtBottom = rubberBandsAtBottom;
3316 }
3317     
3318 void WebPageProxy::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
3319 {
3320     if (enableVerticalRubberBanding == m_enableVerticalRubberBanding)
3321         return;
3322
3323     m_enableVerticalRubberBanding = enableVerticalRubberBanding;
3324
3325     if (!isValid())
3326         return;
3327     m_process->send(Messages::WebPage::SetEnableVerticalRubberBanding(enableVerticalRubberBanding), m_pageID);
3328 }
3329     
3330 bool WebPageProxy::verticalRubberBandingIsEnabled() const
3331 {
3332     return m_enableVerticalRubberBanding;
3333 }
3334     
3335 void WebPageProxy::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
3336 {
3337     if (enableHorizontalRubberBanding == m_enableHorizontalRubberBanding)
3338         return;
3339
3340     m_enableHorizontalRubberBanding = enableHorizontalRubberBanding;
3341
3342     if (!isValid())
3343         return;
3344     m_process->send(Messages::WebPage::SetEnableHorizontalRubberBanding(enableHorizontalRubberBanding), m_pageID);
3345 }
3346     
3347 bool WebPageProxy::horizontalRubberBandingIsEnabled() const
3348 {
3349     return m_enableHorizontalRubberBanding;
3350 }
3351
3352 void WebPageProxy::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
3353 {
3354     if (backgroundExtendsBeyondPage == m_backgroundExtendsBeyondPage)
3355         return;
3356
3357     m_backgroundExtendsBeyondPage = backgroundExtendsBeyondPage;
3358
3359     if (!isValid())
3360         return;
3361     m_process->send(Messages::WebPage::SetBackgroundExtendsBeyondPage(backgroundExtendsBeyondPage), m_pageID);
3362 }
3363
3364 bool WebPageProxy::backgroundExtendsBeyondPage() const
3365 {
3366     return m_backgroundExtendsBeyondPage;
3367 }
3368
3369 void WebPageProxy::setPaginationMode(WebCore::Pagination::Mode mode)
3370 {
3371     if (mode == m_paginationMode)
3372         return;
3373
3374     m_paginationMode = mode;
3375
3376     if (!isValid())
3377         return;
3378     m_process->send(Messages::WebPage::SetPaginationMode(mode), m_pageID);
3379 }
3380
3381 void WebPageProxy::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
3382 {
3383     if (behavesLikeColumns == m_paginationBehavesLikeColumns)
3384         return;
3385
3386     m_paginationBehavesLikeColumns = behavesLikeColumns;
3387
3388     if (!isValid())
3389         return;
3390     m_process->send(Messages::WebPage::SetPaginationBehavesLikeColumns(behavesLikeColumns), m_pageID);
3391 }
3392
3393 void WebPageProxy::setPageLength(double pageLength)
3394 {
3395     if (pageLength == m_pageLength)
3396         return;
3397
3398     m_pageLength = pageLength;
3399
3400     if (!isValid())
3401         return;
3402     m_process->send(Messages::WebPage::SetPageLength(pageLength), m_pageID);
3403 }
3404
3405 void WebPageProxy::setGapBetweenPages(double gap)
3406 {
3407     if (gap == m_gapBetweenPages)
3408         return;
3409
3410     m_gapBetweenPages = gap;
3411
3412     if (!isValid())
3413         return;
3414     m_process->send(Messages::WebPage::SetGapBetweenPages(gap), m_pageID);
3415 }
3416
3417 void WebPageProxy::setPaginationLineGridEnabled(bool lineGridEnabled)
3418 {
3419     if (lineGridEnabled == m_paginationLineGridEnabled)
3420         return;
3421     
3422     m_paginationLineGridEnabled = lineGridEnabled;
3423     
3424     if (!isValid())
3425         return;
3426     m_process->send(Messages::WebPage::SetPaginationLineGridEnabled(lineGridEnabled), m_pageID);
3427 }
3428
3429 void WebPageProxy::pageScaleFactorDidChange(double scaleFactor)
3430 {
3431     m_pageScaleFactor = scaleFactor;
3432 }
3433
3434 void WebPageProxy::pluginScaleFactorDidChange(double pluginScaleFactor)
3435 {
3436     m_pluginScaleFactor = pluginScaleFactor;
3437 }
3438
3439 void WebPageProxy::pluginZoomFactorDidChange(double pluginZoomFactor)
3440 {
3441     m_pluginZoomFactor = pluginZoomFactor;
3442 }
3443
3444 void WebPageProxy::findStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3445 {
3446     if (string.isEmpty()) {
3447         didFindStringMatches(string, Vector<Vector<WebCore::IntRect>> (), 0);
3448         return;
3449     }
3450
3451     m_process->send(Messages::WebPage::FindStringMatches(string, options, maxMatchCount), m_pageID);
3452 }
3453
3454 void WebPageProxy::findString(const String& string, FindOptions options, unsigned maxMatchCount)
3455 {
3456     m_process->send(Messages::WebPage::FindString(string, options, maxMatchCount), m_pageID);
3457 }
3458
3459 void WebPageProxy::getImageForFindMatch(int32_t matchIndex)
3460 {
3461     m_process->send(Messages::WebPage::GetImageForFindMatch(matchIndex), m_pageID);
3462 }
3463
3464 void WebPageProxy::selectFindMatch(int32_t matchIndex)
3465 {
3466     m_process->send(Messages::WebPage::SelectFindMatch(matchIndex), m_pageID);
3467 }
3468
3469 void WebPageProxy::hideFindUI()
3470 {
3471     m_process->send(Messages::WebPage::HideFindUI(), m_pageID);
3472 }
3473
3474 void WebPageProxy::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount)
3475 {
3476     if (!isValid())
3477         return;
3478
3479     m_process->send(Messages::WebPage::CountStringMatches(string, options, maxMatchCount), m_pageID);
3480 }
3481
3482 void WebPageProxy::replaceMatches(Vector<uint32_t>&& matchIndices, const String& replacementText, bool selectionOnly, Function<void(uint64_t, CallbackBase::Error)>&& callback)
3483 {
3484     if (!isValid()) {
3485         callback(0, CallbackBase::Error::Unknown);
3486         return;
3487     }
3488
3489     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
3490     m_process->send(Messages::WebPage::ReplaceMatches(WTFMove(matchIndices), replacementText, selectionOnly, callbackID), m_pageID);
3491 }
3492
3493 void WebPageProxy::runJavaScriptInMainFrame(const String& script, bool forceUserGesture, WTF::Function<void (API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3494 {
3495     if (!isValid()) {
3496         callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3497         return;
3498     }
3499
3500     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3501     m_process->send(Messages::WebPage::RunJavaScriptInMainFrame(script, forceUserGesture, callbackID), m_pageID);
3502 }
3503
3504 void WebPageProxy::runJavaScriptInMainFrameScriptWorld(const String& script, bool forceUserGesture, const String& worldName, WTF::Function<void(API::SerializedScriptValue*, bool hadException, const ExceptionDetails&, CallbackBase::Error)>&& callbackFunction)
3505 {
3506     if (!isValid()) {
3507         callbackFunction(nullptr, false, { }, CallbackBase::Error::Unknown);
3508         return;
3509     }
3510
3511     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3512     m_process->send(Messages::WebPage::RunJavaScriptInMainFrameScriptWorld(script, forceUserGesture, worldName, callbackID), m_pageID);
3513 }
3514
3515 void WebPageProxy::getRenderTreeExternalRepresentation(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3516 {
3517     if (!isValid()) {
3518         callbackFunction(String(), CallbackBase::Error::Unknown);
3519         return;
3520     }
3521     
3522     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3523     m_process->send(Messages::WebPage::GetRenderTreeExternalRepresentation(callbackID), m_pageID);
3524 }
3525
3526 void WebPageProxy::getSourceForFrame(WebFrameProxy* frame, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3527 {
3528     if (!isValid()) {
3529         callbackFunction(String(), CallbackBase::Error::Unknown);
3530         return;
3531     }
3532     
3533     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3534     m_loadDependentStringCallbackIDs.add(callbackID);
3535     m_process->send(Messages::WebPage::GetSourceForFrame(frame->frameID(), callbackID), m_pageID);
3536 }
3537
3538 void WebPageProxy::getContentsAsString(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3539 {
3540     if (!isValid()) {
3541         callbackFunction(String(), CallbackBase::Error::Unknown);
3542         return;
3543     }
3544     
3545     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3546     m_loadDependentStringCallbackIDs.add(callbackID);
3547     m_process->send(Messages::WebPage::GetContentsAsString(callbackID), m_pageID);
3548 }
3549
3550 void WebPageProxy::getBytecodeProfile(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3551 {
3552     if (!isValid()) {
3553         callbackFunction(String(), CallbackBase::Error::Unknown);
3554         return;
3555     }
3556     
3557     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3558     m_loadDependentStringCallbackIDs.add(callbackID);
3559     m_process->send(Messages::WebPage::GetBytecodeProfile(callbackID), m_pageID);
3560 }
3561
3562 void WebPageProxy::getSamplingProfilerOutput(WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
3563 {
3564     if (!isValid()) {
3565         callbackFunction(String(), CallbackBase::Error::Unknown);
3566         return;
3567     }
3568     
3569     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
3570     m_loadDependentStringCallbackIDs.add(callbackID);
3571     m_process->send(Messages::WebPage::GetSamplingProfilerOutput(callbackID), m_pageID);
3572 }
3573
3574 #if ENABLE(MHTML)