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