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