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