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