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