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