260a0e2acb4be9ea7b3d0f3abcfd0602f51472b5
[WebKit-https.git] / Source / WebKit / WebProcess / WebPage / WebPage.cpp
1 /*
2  * Copyright (C) 2010-2020 Apple Inc. All rights reserved.
3  * Copyright (C) 2012 Intel Corporation. All rights reserved.
4  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "WebPage.h"
30
31 #include "APIArray.h"
32 #include "APIGeometry.h"
33 #include "DataReference.h"
34 #include "DragControllerAction.h"
35 #include "DrawingArea.h"
36 #include "DrawingAreaMessages.h"
37 #include "EditorState.h"
38 #include "EventDispatcher.h"
39 #include "FindController.h"
40 #include "FormDataReference.h"
41 #include "FrameTreeNodeData.h"
42 #include "GeolocationPermissionRequestManager.h"
43 #include "InjectUserScriptImmediately.h"
44 #include "InjectedBundle.h"
45 #include "InjectedBundleScriptWorld.h"
46 #include "LibWebRTCProvider.h"
47 #include "LoadParameters.h"
48 #include "Logging.h"
49 #include "MediaRecorderProvider.h"
50 #include "NetscapePlugin.h"
51 #include "NetworkConnectionToWebProcessMessages.h"
52 #include "NetworkProcessConnection.h"
53 #include "NotificationPermissionRequestManager.h"
54 #include "PageBanner.h"
55 #include "PluginProcessAttributes.h"
56 #include "PluginProxy.h"
57 #include "PluginView.h"
58 #include "PrintInfo.h"
59 #include "RemoteWebInspectorUI.h"
60 #include "RemoteWebInspectorUIMessages.h"
61 #include "SessionState.h"
62 #include "SessionStateConversion.h"
63 #include "ShareableBitmap.h"
64 #include "SharedBufferDataReference.h"
65 #include "UserMediaPermissionRequestManager.h"
66 #include "ViewGestureGeometryCollector.h"
67 #include "VisitedLinkTableController.h"
68 #include "WKBundleAPICast.h"
69 #include "WKRetainPtr.h"
70 #include "WKSharedAPICast.h"
71 #include "WebAlternativeTextClient.h"
72 #include "WebBackForwardListItem.h"
73 #include "WebBackForwardListProxy.h"
74 #include "WebCacheStorageProvider.h"
75 #include "WebChromeClient.h"
76 #include "WebColorChooser.h"
77 #include "WebContextMenu.h"
78 #include "WebContextMenuClient.h"
79 #include "WebCookieJar.h"
80 #include "WebCoreArgumentCoders.h"
81 #include "WebDataListSuggestionPicker.h"
82 #include "WebDatabaseProvider.h"
83 #include "WebDateTimeChooser.h"
84 #include "WebDiagnosticLoggingClient.h"
85 #include "WebDocumentLoader.h"
86 #include "WebDragClient.h"
87 #include "WebEditorClient.h"
88 #include "WebEventConversion.h"
89 #include "WebEventFactory.h"
90 #include "WebFrame.h"
91 #include "WebFrameLoaderClient.h"
92 #include "WebFullScreenManager.h"
93 #include "WebFullScreenManagerMessages.h"
94 #include "WebGamepadProvider.h"
95 #include "WebGeolocationClient.h"
96 #include "WebImage.h"
97 #include "WebInspector.h"
98 #include "WebInspectorClient.h"
99 #include "WebInspectorMessages.h"
100 #include "WebInspectorUI.h"
101 #include "WebInspectorUIMessages.h"
102 #include "WebKeyboardEvent.h"
103 #include "WebLoaderStrategy.h"
104 #include "WebMediaKeyStorageManager.h"
105 #include "WebMediaStrategy.h"
106 #include "WebMouseEvent.h"
107 #include "WebNotificationClient.h"
108 #include "WebOpenPanelResultListener.h"
109 #include "WebPageCreationParameters.h"
110 #include "WebPageGroupProxy.h"
111 #include "WebPageInspectorTargetController.h"
112 #include "WebPageMessages.h"
113 #include "WebPageOverlay.h"
114 #include "WebPageProxyMessages.h"
115 #include "WebPaymentCoordinator.h"
116 #include "WebPerformanceLoggingClient.h"
117 #include "WebPlugInClient.h"
118 #include "WebPluginInfoProvider.h"
119 #include "WebPopupMenu.h"
120 #include "WebPreferencesDefinitions.h"
121 #include "WebPreferencesKeys.h"
122 #include "WebPreferencesStore.h"
123 #include "WebProcess.h"
124 #include "WebProcessPoolMessages.h"
125 #include "WebProcessProxyMessages.h"
126 #include "WebProgressTrackerClient.h"
127 #include "WebServiceWorkerProvider.h"
128 #include "WebSocketProvider.h"
129 #include "WebSpeechSynthesisClient.h"
130 #include "WebStorageNamespaceProvider.h"
131 #include "WebTouchEvent.h"
132 #include "WebURLSchemeHandlerProxy.h"
133 #include "WebUndoStep.h"
134 #include "WebUserContentController.h"
135 #include "WebUserMediaClient.h"
136 #include "WebValidationMessageClient.h"
137 #include "WebWheelEvent.h"
138 #include "WebsiteDataStoreParameters.h"
139 #include <JavaScriptCore/APICast.h>
140 #include <JavaScriptCore/JSCInlines.h>
141 #include <JavaScriptCore/JSCJSValue.h>
142 #include <JavaScriptCore/JSLock.h>
143 #include <JavaScriptCore/ProfilerDatabase.h>
144 #include <JavaScriptCore/SamplingProfiler.h>
145 #include <WebCore/ApplicationCacheStorage.h>
146 #include <WebCore/ArchiveResource.h>
147 #include <WebCore/BackForwardCache.h>
148 #include <WebCore/BackForwardController.h>
149 #include <WebCore/Chrome.h>
150 #include <WebCore/CommonVM.h>
151 #include <WebCore/ContextMenuController.h>
152 #include <WebCore/DOMPasteAccess.h>
153 #include <WebCore/DataTransfer.h>
154 #include <WebCore/DatabaseManager.h>
155 #include <WebCore/DeprecatedGlobalSettings.h>
156 #include <WebCore/DocumentFragment.h>
157 #include <WebCore/DocumentLoader.h>
158 #include <WebCore/DocumentMarkerController.h>
159 #include <WebCore/DocumentStorageAccess.h>
160 #include <WebCore/DragController.h>
161 #include <WebCore/DragData.h>
162 #include <WebCore/Editing.h>
163 #include <WebCore/Editor.h>
164 #include <WebCore/ElementIterator.h>
165 #include <WebCore/EventHandler.h>
166 #include <WebCore/EventNames.h>
167 #include <WebCore/File.h>
168 #include <WebCore/FocusController.h>
169 #include <WebCore/FontAttributeChanges.h>
170 #include <WebCore/FontAttributes.h>
171 #include <WebCore/FormState.h>
172 #include <WebCore/Frame.h>
173 #include <WebCore/FrameLoadRequest.h>
174 #include <WebCore/FrameLoaderTypes.h>
175 #include <WebCore/FrameView.h>
176 #include <WebCore/FullscreenManager.h>
177 #include <WebCore/GraphicsContextGLOpenGL.h>
178 #include <WebCore/HTMLAttachmentElement.h>
179 #include <WebCore/HTMLFormElement.h>
180 #include <WebCore/HTMLImageElement.h>
181 #include <WebCore/HTMLInputElement.h>
182 #include <WebCore/HTMLMenuElement.h>
183 #include <WebCore/HTMLMenuItemElement.h>
184 #include <WebCore/HTMLPlugInElement.h>
185 #include <WebCore/HTMLPlugInImageElement.h>
186 #include <WebCore/HTMLSelectElement.h>
187 #include <WebCore/HTMLTextFormControlElement.h>
188 #include <WebCore/HistoryController.h>
189 #include <WebCore/HistoryItem.h>
190 #include <WebCore/HitTestResult.h>
191 #include <WebCore/InspectorController.h>
192 #include <WebCore/JSDOMExceptionHandling.h>
193 #include <WebCore/JSDOMWindow.h>
194 #include <WebCore/KeyboardEvent.h>
195 #include <WebCore/LegacySchemeRegistry.h>
196 #include <WebCore/LocalizedStrings.h>
197 #include <WebCore/MIMETypeRegistry.h>
198 #include <WebCore/MouseEvent.h>
199 #include <WebCore/NotImplemented.h>
200 #include <WebCore/Page.h>
201 #include <WebCore/PageConfiguration.h>
202 #include <WebCore/PingLoader.h>
203 #include <WebCore/PlatformKeyboardEvent.h>
204 #include <WebCore/PlatformMediaSessionManager.h>
205 #include <WebCore/PlatformStrategies.h>
206 #include <WebCore/PluginDocument.h>
207 #include <WebCore/PointerCaptureController.h>
208 #include <WebCore/PrintContext.h>
209 #include <WebCore/PromisedAttachmentInfo.h>
210 #include <WebCore/Quirks.h>
211 #include <WebCore/Range.h>
212 #include <WebCore/RegistrableDomain.h>
213 #include <WebCore/RemoteDOMWindow.h>
214 #include <WebCore/RemoteFrame.h>
215 #include <WebCore/RenderLayer.h>
216 #include <WebCore/RenderTheme.h>
217 #include <WebCore/RenderTreeAsText.h>
218 #include <WebCore/RenderView.h>
219 #include <WebCore/ResourceLoadStatistics.h>
220 #include <WebCore/ResourceRequest.h>
221 #include <WebCore/ResourceResponse.h>
222 #include <WebCore/RunJavaScriptParameters.h>
223 #include <WebCore/RuntimeEnabledFeatures.h>
224 #include <WebCore/SWClientConnection.h>
225 #include <WebCore/ScriptController.h>
226 #include <WebCore/SecurityPolicy.h>
227 #include <WebCore/SerializedScriptValue.h>
228 #include <WebCore/Settings.h>
229 #include <WebCore/ShadowRoot.h>
230 #include <WebCore/SharedBuffer.h>
231 #include <WebCore/StyleProperties.h>
232 #include <WebCore/SubframeLoader.h>
233 #include <WebCore/SubstituteData.h>
234 #include <WebCore/TextIterator.h>
235 #include <WebCore/UserContentURLPattern.h>
236 #include <WebCore/UserGestureIndicator.h>
237 #include <WebCore/UserInputBridge.h>
238 #include <WebCore/UserScript.h>
239 #include <WebCore/UserStyleSheet.h>
240 #include <WebCore/UserTypingGestureIndicator.h>
241 #include <WebCore/VisiblePosition.h>
242 #include <WebCore/VisibleUnits.h>
243 #include <WebCore/WebGLStateTracker.h>
244 #include <WebCore/WritingDirection.h>
245 #include <WebCore/markup.h>
246 #include <pal/SessionID.h>
247 #include <wtf/ProcessID.h>
248 #include <wtf/RunLoop.h>
249 #include <wtf/SetForScope.h>
250 #include <wtf/text/TextStream.h>
251
252 #if ENABLE(DATA_DETECTION)
253 #include "DataDetectionResult.h"
254 #endif
255
256 #if ENABLE(MHTML)
257 #include <WebCore/MHTMLArchive.h>
258 #endif
259
260 #if ENABLE(POINTER_LOCK)
261 #include <WebCore/PointerLockController.h>
262 #endif
263
264 #if PLATFORM(COCOA)
265 #include "InsertTextOptions.h"
266 #include "PDFPlugin.h"
267 #include "PlaybackSessionManager.h"
268 #include "RemoteLayerTreeTransaction.h"
269 #include "RemoteObjectRegistryMessages.h"
270 #include "TextCheckingControllerProxy.h"
271 #include "UserMediaCaptureManager.h"
272 #include "VideoFullscreenManager.h"
273 #include "WKStringCF.h"
274 #include "WebRemoteObjectRegistry.h"
275 #include <WebCore/LegacyWebArchive.h>
276 #include <WebCore/UTIRegistry.h>
277 #include <wtf/MachSendRight.h>
278 #include <wtf/spi/darwin/SandboxSPI.h>
279 #endif
280
281 #if HAVE(TOUCH_BAR)
282 #include "TouchBarMenuData.h"
283 #include "TouchBarMenuItemData.h"
284 #endif
285
286 #if PLATFORM(GTK)
287 #include "WebPrintOperationGtk.h"
288 #include <WebCore/SelectionData.h>
289 #include <gtk/gtk.h>
290 #endif
291
292 #if PLATFORM(IOS_FAMILY)
293 #include "InteractionInformationAtPosition.h"
294 #include "InteractionInformationRequest.h"
295 #include "RemoteLayerTreeDrawingArea.h"
296 #include "WebAutocorrectionContext.h"
297 #include <CoreGraphics/CoreGraphics.h>
298 #include <WebCore/Icon.h>
299 #include <pal/spi/cocoa/CoreTextSPI.h>
300 #endif
301
302 #if PLATFORM(MAC)
303 #include <WebCore/LocalDefaultSystemAppearance.h>
304 #include <pal/spi/cf/CFUtilitiesSPI.h>
305 #endif
306
307 #ifndef NDEBUG
308 #include <wtf/RefCountedLeakCounter.h>
309 #endif
310
311 #if ENABLE(DATA_DETECTION)
312 #include <WebCore/DataDetection.h>
313 #endif
314
315 #if ENABLE(VIDEO) && USE(GSTREAMER)
316 #include <WebCore/MediaPlayerRequestInstallMissingPluginsCallback.h>
317 #endif
318
319 #if ENABLE(WEB_AUTHN)
320 #include "WebAuthenticatorCoordinator.h"
321 #include <WebCore/AuthenticatorCoordinator.h>
322 #endif
323
324 #if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION)
325 #include "WebDeviceOrientationUpdateProvider.h"
326 #endif
327
328 #if ENABLE(GPU_PROCESS)
329 #include "RemoteMediaPlayerManager.h"
330 #if ENABLE(ENCRYPTED_MEDIA)
331 #include "RemoteCDMFactory.h"
332 #endif
333 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
334 #include "RemoteLegacyCDMFactory.h"
335 #endif
336 #endif
337
338 namespace WebKit {
339 using namespace JSC;
340 using namespace WebCore;
341
342 static const Seconds pageScrollHysteresisDuration { 300_ms };
343 static const Seconds initialLayerVolatilityTimerInterval { 20_ms };
344 static const Seconds maximumLayerVolatilityTimerInterval { 2_s };
345
346 #define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - [webPageID=%" PRIu64 "] WebPage::" fmt, this, m_identifier.toUInt64(), ##__VA_ARGS__)
347 #define RELEASE_LOG_ERROR_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_ERROR_IF(isAlwaysOnLoggingAllowed(), channel, "%p - [webPageID=%" PRIu64 "] WebPage::" fmt, this, m_identifier.toUInt64(), ##__VA_ARGS__)
348
349 class SendStopResponsivenessTimer {
350 public:
351     ~SendStopResponsivenessTimer()
352     {
353         WebProcess::singleton().parentProcessConnection()->send(Messages::WebProcessProxy::StopResponsivenessTimer(), 0);
354     }
355 };
356
357 class DeferredPageDestructor {
358 public:
359     static void createDeferredPageDestructor(std::unique_ptr<Page> page, WebPage* webPage)
360     {
361         new DeferredPageDestructor(WTFMove(page), webPage);
362     }
363
364 private:
365     DeferredPageDestructor(std::unique_ptr<Page> page, WebPage* webPage)
366         : m_page(WTFMove(page))
367         , m_webPage(webPage)
368     {
369         tryDestruction();
370     }
371
372     void tryDestruction()
373     {
374         if (m_page->insideNestedRunLoop()) {
375             m_page->whenUnnested([this] { tryDestruction(); });
376             return;
377         }
378
379         m_page = nullptr;
380         m_webPage = nullptr;
381         delete this;
382     }
383
384     std::unique_ptr<Page> m_page;
385     RefPtr<WebPage> m_webPage;
386 };
387
388 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageCounter, ("WebPage"));
389
390 Ref<WebPage> WebPage::create(PageIdentifier pageID, WebPageCreationParameters&& parameters)
391 {
392     Ref<WebPage> page = adoptRef(*new WebPage(pageID, WTFMove(parameters)));
393
394     if (WebProcess::singleton().injectedBundle())
395         WebProcess::singleton().injectedBundle()->didCreatePage(page.ptr());
396
397     return page;
398 }
399
400 static Vector<UserContentURLPattern> parseAndAllowAccessToCORSDisablingPatterns(const Vector<String>& input)
401 {
402     Vector<UserContentURLPattern> parsedPatterns;
403     parsedPatterns.reserveInitialCapacity(input.size());
404     for (const auto& pattern : input) {
405         UserContentURLPattern parsedPattern(pattern);
406         if (parsedPattern.isValid()) {
407             WebCore::SecurityPolicy::allowAccessTo(parsedPattern);
408             parsedPatterns.uncheckedAppend(WTFMove(parsedPattern));
409         }
410     }
411     parsedPatterns.shrinkToFit();
412     return parsedPatterns;
413 }
414
415 WebPage::WebPage(PageIdentifier pageID, WebPageCreationParameters&& parameters)
416     : m_identifier(pageID)
417     , m_mainFrame(WebFrame::create())
418     , m_viewSize(parameters.viewSize)
419     , m_alwaysShowsHorizontalScroller { parameters.alwaysShowsHorizontalScroller }
420     , m_alwaysShowsVerticalScroller { parameters.alwaysShowsVerticalScroller }
421     , m_shouldRenderCanvasInGPUProcess { parameters.shouldRenderCanvasInGPUProcess }
422 #if ENABLE(APP_BOUND_DOMAINS)
423     , m_needsInAppBrowserPrivacyQuirks { parameters.needsInAppBrowserPrivacyQuirks }
424 #endif
425 #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
426     , m_determinePrimarySnapshottedPlugInTimer(RunLoop::main(), this, &WebPage::determinePrimarySnapshottedPlugInTimerFired)
427 #endif
428     , m_layerHostingMode(parameters.layerHostingMode)
429 #if ENABLE(PLATFORM_DRIVEN_TEXT_CHECKING)
430     , m_textCheckingControllerProxy(makeUniqueRef<TextCheckingControllerProxy>(*this))
431 #endif
432 #if PLATFORM(COCOA) || (PLATFORM(GTK) && !USE(GTK4))
433     , m_viewGestureGeometryCollector(makeUnique<ViewGestureGeometryCollector>(*this))
434 #elif ENABLE(ACCESSIBILITY) && PLATFORM(GTK)
435     , m_accessibilityObject(nullptr)
436 #endif
437 #if PLATFORM(WIN)
438     , m_nativeWindowHandle(parameters.nativeWindowHandle)
439 #endif
440     , m_setCanStartMediaTimer(RunLoop::main(), this, &WebPage::setCanStartMediaTimerFired)
441 #if ENABLE(CONTEXT_MENUS)
442     , m_contextMenuClient(makeUnique<API::InjectedBundle::PageContextMenuClient>())
443 #endif
444     , m_editorClient { makeUnique<API::InjectedBundle::EditorClient>() }
445     , m_formClient(makeUnique<API::InjectedBundle::FormClient>())
446     , m_loaderClient(makeUnique<API::InjectedBundle::PageLoaderClient>())
447     , m_resourceLoadClient(makeUnique<API::InjectedBundle::ResourceLoadClient>())
448     , m_uiClient(makeUnique<API::InjectedBundle::PageUIClient>())
449     , m_findController(makeUniqueRef<FindController>(this))
450     , m_inspectorTargetController(makeUnique<WebPageInspectorTargetController>(*this))
451     , m_userContentController(WebUserContentController::getOrCreate(parameters.userContentControllerParameters.identifier))
452 #if ENABLE(GEOLOCATION)
453     , m_geolocationPermissionRequestManager(makeUniqueRef<GeolocationPermissionRequestManager>(*this))
454 #endif
455 #if ENABLE(MEDIA_STREAM)
456     , m_userMediaPermissionRequestManager { makeUniqueRef<UserMediaPermissionRequestManager>(*this) }
457 #endif
458     , m_pageScrolledHysteresis([this](PAL::HysteresisState state) { if (state == PAL::HysteresisState::Stopped) pageStoppedScrolling(); }, pageScrollHysteresisDuration)
459     , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel)
460     , m_canRunModal(parameters.canRunModal)
461 #if ENABLE(META_VIEWPORT)
462     , m_forceAlwaysUserScalable(parameters.ignoresViewportScaleLimits)
463 #endif
464 #if PLATFORM(IOS_FAMILY)
465     , m_screenSize(parameters.screenSize)
466     , m_availableScreenSize(parameters.availableScreenSize)
467     , m_overrideScreenSize(parameters.overrideScreenSize)
468     , m_deviceOrientation(parameters.deviceOrientation)
469     , m_keyboardIsAttached(parameters.keyboardIsAttached)
470     , m_canShowWhileLocked(parameters.canShowWhileLocked)
471 #endif
472     , m_layerVolatilityTimer(*this, &WebPage::layerVolatilityTimerFired)
473     , m_activityState(parameters.activityState)
474     , m_userActivity("App nap disabled for page due to user activity")
475     , m_userInterfaceLayoutDirection(parameters.userInterfaceLayoutDirection)
476     , m_overrideContentSecurityPolicy { parameters.overrideContentSecurityPolicy }
477     , m_cpuLimit(parameters.cpuLimit)
478 #if USE(WPE_RENDERER)
479     , m_hostFileDescriptor(WTFMove(parameters.hostFileDescriptor))
480 #endif
481     , m_webPageProxyIdentifier(parameters.webPageProxyIdentifier)
482 #if ENABLE(TEXT_AUTOSIZING)
483     , m_textAutoSizingAdjustmentTimer(*this, &WebPage::textAutoSizingAdjustmentTimerFired)
484 #endif
485     , m_overriddenMediaType(parameters.overriddenMediaType)
486     , m_processDisplayName(parameters.processDisplayName)
487 #if ENABLE(APP_BOUND_DOMAINS)
488     , m_limitsNavigationsToAppBoundDomains(parameters.limitsNavigationsToAppBoundDomains)
489 #endif
490 {
491     ASSERT(m_identifier);
492
493     m_pageGroup = WebProcess::singleton().webPageGroup(parameters.pageGroupData);
494
495     PageConfiguration pageConfiguration(
496         WebProcess::singleton().sessionID(),
497         makeUniqueRef<WebEditorClient>(this),
498         WebSocketProvider::create(),
499         makeUniqueRef<WebKit::LibWebRTCProvider>(),
500         WebProcess::singleton().cacheStorageProvider(),
501         WebBackForwardListProxy::create(*this),
502         WebProcess::singleton().cookieJar(),
503         makeUniqueRef<WebProgressTrackerClient>(*this),
504         makeUniqueRef<WebFrameLoaderClient>(m_mainFrame.copyRef()),
505         makeUniqueRef<MediaRecorderProvider>()
506     );
507     pageConfiguration.chromeClient = new WebChromeClient(*this);
508 #if ENABLE(CONTEXT_MENUS)
509     pageConfiguration.contextMenuClient = new WebContextMenuClient(this);
510 #endif
511 #if ENABLE(DRAG_SUPPORT)
512     pageConfiguration.dragClient = makeUnique<WebDragClient>(this);
513 #endif
514     pageConfiguration.inspectorClient = new WebInspectorClient(this);
515 #if USE(AUTOCORRECTION_PANEL)
516     pageConfiguration.alternativeTextClient = makeUnique<WebAlternativeTextClient>(this);
517 #endif
518
519     pageConfiguration.plugInClient = makeUnique<WebPlugInClient>(*this);
520     pageConfiguration.diagnosticLoggingClient = makeUnique<WebDiagnosticLoggingClient>(*this);
521     pageConfiguration.performanceLoggingClient = makeUnique<WebPerformanceLoggingClient>(*this);
522
523 #if ENABLE(WEBGL)
524     pageConfiguration.webGLStateTracker = makeUnique<WebGLStateTracker>([this](bool isUsingHighPerformanceWebGL) {
525         send(Messages::WebPageProxy::SetIsUsingHighPerformanceWebGL(isUsingHighPerformanceWebGL));
526     });
527 #endif
528
529 #if ENABLE(SPEECH_SYNTHESIS)
530     pageConfiguration.speechSynthesisClient = makeUnique<WebSpeechSynthesisClient>(*this);
531 #endif
532
533 #if PLATFORM(COCOA)
534     pageConfiguration.validationMessageClient = makeUnique<WebValidationMessageClient>(*this);
535 #endif
536
537     pageConfiguration.applicationCacheStorage = &WebProcess::singleton().applicationCacheStorage();
538     pageConfiguration.databaseProvider = WebDatabaseProvider::getOrCreate(m_pageGroup->pageGroupID());
539     pageConfiguration.pluginInfoProvider = &WebPluginInfoProvider::singleton();
540     pageConfiguration.storageNamespaceProvider = WebStorageNamespaceProvider::getOrCreate(*m_pageGroup);
541     pageConfiguration.userContentProvider = m_userContentController.ptr();
542     pageConfiguration.visitedLinkStore = VisitedLinkTableController::getOrCreate(parameters.visitedLinkTableID);
543
544 #if ENABLE(APPLE_PAY)
545     pageConfiguration.paymentCoordinatorClient = new WebPaymentCoordinator(*this);
546 #endif
547
548 #if ENABLE(WEB_AUTHN)
549     pageConfiguration.authenticatorCoordinatorClient = makeUnique<WebAuthenticatorCoordinator>(*this);
550 #endif
551
552 #if ENABLE(APPLICATION_MANIFEST)
553     pageConfiguration.applicationManifest = parameters.applicationManifest;
554 #endif
555     
556 #if PLATFORM(IOS_FAMILY) && ENABLE(DEVICE_ORIENTATION)
557     pageConfiguration.deviceOrientationUpdateProvider = WebDeviceOrientationUpdateProvider::create(*this);
558 #endif
559
560     m_corsDisablingPatterns = WTFMove(parameters.corsDisablingPatterns);
561     if (!m_corsDisablingPatterns.isEmpty())
562         synchronizeCORSDisablingPatternsWithNetworkProcess();
563     pageConfiguration.corsDisablingPatterns = parseAndAllowAccessToCORSDisablingPatterns(m_corsDisablingPatterns);
564
565     pageConfiguration.userScriptsShouldWaitUntilNotification = parameters.userScriptsShouldWaitUntilNotification;
566     pageConfiguration.loadsSubresources = parameters.loadsSubresources;
567     pageConfiguration.loadsFromNetwork = parameters.loadsFromNetwork;
568     pageConfiguration.shouldRelaxThirdPartyCookieBlocking = parameters.shouldRelaxThirdPartyCookieBlocking;
569
570     if (!parameters.crossOriginAccessControlCheckEnabled)
571         CrossOriginAccessControlCheckDisabler::singleton().setCrossOriginAccessControlCheckEnabled(false);
572
573 #if ENABLE(ATTACHMENT_ELEMENT) && PLATFORM(IOS_FAMILY)
574     if (parameters.frontboardExtensionHandle)
575         SandboxExtension::consumePermanently(*parameters.frontboardExtensionHandle);
576     if (parameters.iconServicesExtensionHandle)
577         SandboxExtension::consumePermanently(*parameters.iconServicesExtensionHandle);
578 #endif
579
580     m_page = makeUnique<Page>(WTFMove(pageConfiguration));
581
582     updatePreferences(parameters.store);
583
584 #if PLATFORM(IOS_FAMILY) || ENABLE(ROUTING_ARBITRATION)
585     DeprecatedGlobalSettings::setShouldManageAudioSessionCategory(true);
586 #endif
587
588     m_backgroundColor = parameters.backgroundColor;
589
590     m_drawingArea = DrawingArea::create(*this, parameters);
591     m_drawingArea->setShouldScaleViewToFitDocument(parameters.shouldScaleViewToFitDocument);
592
593     if (parameters.isProcessSwap)
594         freezeLayerTree(LayerTreeFreezeReason::ProcessSwap);
595
596 #if ENABLE(ASYNC_SCROLLING)
597     m_useAsyncScrolling = parameters.store.getBoolValueForKey(WebPreferencesKey::threadedScrollingEnabledKey());
598     if (!m_drawingArea->supportsAsyncScrolling())
599         m_useAsyncScrolling = false;
600     m_page->settings().setScrollingCoordinatorEnabled(m_useAsyncScrolling);
601 #endif
602
603     // Disable Back/Forward cache expiration in the WebContent process since management happens in the UIProcess
604     // in modern WebKit.
605     m_page->settings().setBackForwardCacheExpirationInterval(Seconds::infinity());
606
607     m_mainFrame->initWithCoreMainFrame(*this, m_page->mainFrame());
608
609     m_drawingArea->updatePreferences(parameters.store);
610
611     setBackgroundExtendsBeyondPage(parameters.backgroundExtendsBeyondPage);
612     setPageAndTextZoomFactors(parameters.pageZoomFactor, parameters.textZoomFactor);
613
614 #if ENABLE(GEOLOCATION)
615     WebCore::provideGeolocationTo(m_page.get(), *new WebGeolocationClient(*this));
616 #endif
617 #if ENABLE(NOTIFICATIONS)
618     WebCore::provideNotification(m_page.get(), new WebNotificationClient(this));
619 #endif
620 #if ENABLE(MEDIA_STREAM)
621     WebCore::provideUserMediaTo(m_page.get(), new WebUserMediaClient(*this));
622 #endif
623
624     m_page->setControlledByAutomation(parameters.controlledByAutomation);
625     m_page->setHasResourceLoadClient(parameters.hasResourceLoadClient);
626
627     m_page->setCanStartMedia(false);
628     m_mayStartMediaWhenInWindow = parameters.mayStartMediaWhenInWindow;
629     if (parameters.mediaPlaybackIsSuspended)
630         m_page->suspendAllMediaPlayback();
631
632     m_page->setGroupName(m_pageGroup->identifier());
633     m_page->setDeviceScaleFactor(parameters.deviceScaleFactor);
634     m_page->setUserInterfaceLayoutDirection(m_userInterfaceLayoutDirection);
635 #if PLATFORM(IOS_FAMILY)
636     m_page->setTextAutosizingWidth(parameters.textAutosizingWidth);
637     setOverrideViewportArguments(parameters.overrideViewportArguments);
638 #endif
639
640     platformInitialize();
641
642     setUseFixedLayout(parameters.useFixedLayout);
643
644     setUnderlayColor(parameters.underlayColor);
645
646     setPaginationMode(parameters.paginationMode);
647     setPaginationBehavesLikeColumns(parameters.paginationBehavesLikeColumns);
648     setPageLength(parameters.pageLength);
649     setGapBetweenPages(parameters.gapBetweenPages);
650     setPaginationLineGridEnabled(parameters.paginationLineGridEnabled);
651
652 #if PLATFORM(GTK)
653     themeDidChange(WTFMove(parameters.themeName));
654 #endif
655
656     effectiveAppearanceDidChange(parameters.useDarkAppearance, parameters.useElevatedUserInterfaceLevel);
657
658     if (parameters.isEditable)
659         setEditable(true);
660
661 #if PLATFORM(MAC)
662     setUseSystemAppearance(parameters.useSystemAppearance);
663 #endif
664
665     // If the page is created off-screen, its visibilityState should be prerender.
666     m_page->setActivityState(m_activityState);
667     if (!isVisible())
668         m_page->setIsPrerender();
669
670     updateIsInWindow(true);
671
672     setMinimumSizeForAutoLayout(parameters.minimumSizeForAutoLayout);
673     setSizeToContentAutoSizeMaximumSize(parameters.sizeToContentAutoSizeMaximumSize);
674     setAutoSizingShouldExpandToViewHeight(parameters.autoSizingShouldExpandToViewHeight);
675     setViewportSizeForCSSViewportUnits(parameters.viewportSizeForCSSViewportUnits);
676     
677     setScrollPinningBehavior(parameters.scrollPinningBehavior);
678     if (parameters.scrollbarOverlayStyle)
679         m_scrollbarOverlayStyle = static_cast<ScrollbarOverlayStyle>(parameters.scrollbarOverlayStyle.value());
680     else
681         m_scrollbarOverlayStyle = Optional<ScrollbarOverlayStyle>();
682
683     setTopContentInset(parameters.topContentInset);
684
685     m_userAgent = parameters.userAgent;
686     
687     if (!parameters.itemStates.isEmpty())
688         restoreSessionInternal(parameters.itemStates, parameters.itemStatesWereRestoredByAPIRequest ? WasRestoredByAPIRequest::Yes : WasRestoredByAPIRequest::No, WebBackForwardListProxy::OverwriteExistingItem::Yes);
689
690     m_drawingArea->enablePainting();
691     
692     setMediaVolume(parameters.mediaVolume);
693
694     setMuted(parameters.muted);
695
696     // We use the DidFirstVisuallyNonEmptyLayout milestone to determine when to unfreeze the layer tree.
697     m_page->addLayoutMilestones({ DidFirstLayout, DidFirstVisuallyNonEmptyLayout });
698
699     auto& webProcess = WebProcess::singleton();
700     webProcess.addMessageReceiver(Messages::WebPage::messageReceiverName(), m_identifier, *this);
701
702     // FIXME: This should be done in the object constructors, and the objects themselves should be message receivers.
703     webProcess.addMessageReceiver(Messages::WebInspector::messageReceiverName(), m_identifier, *this);
704     webProcess.addMessageReceiver(Messages::WebInspectorUI::messageReceiverName(), m_identifier, *this);
705     webProcess.addMessageReceiver(Messages::RemoteWebInspectorUI::messageReceiverName(), m_identifier, *this);
706 #if ENABLE(FULLSCREEN_API)
707     webProcess.addMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_identifier, *this);
708 #endif
709
710 #ifndef NDEBUG
711     webPageCounter.increment();
712 #endif
713
714 #if ENABLE(SCROLLING_THREAD)
715     if (m_useAsyncScrolling)
716         webProcess.eventDispatcher().addScrollingTreeForPage(this);
717 #endif
718
719     for (auto& mimeType : parameters.mimeTypesWithCustomContentProviders)
720         m_mimeTypesWithCustomContentProviders.add(mimeType);
721
722
723 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
724     if (WebMediaKeyStorageManager* manager = webProcess.supplement<WebMediaKeyStorageManager>())
725         m_page->settings().setMediaKeysStorageDirectory(manager->mediaKeyStorageDirectory());
726 #endif
727     m_page->settings().setAppleMailPaginationQuirkEnabled(parameters.appleMailPaginationQuirkEnabled);
728     
729     if (parameters.viewScaleFactor != 1)
730         scaleView(parameters.viewScaleFactor);
731
732     m_page->addLayoutMilestones(parameters.observedLayoutMilestones);
733
734 #if PLATFORM(COCOA)
735     m_page->settings().setContentDispositionAttachmentSandboxEnabled(true);
736     setSmartInsertDeleteEnabled(parameters.smartInsertDeleteEnabled);
737     WebCore::setAdditionalSupportedImageTypes(parameters.additionalSupportedImageTypes);
738 #endif
739
740 #if HAVE(APP_ACCENT_COLORS)
741     setAccentColor(parameters.accentColor);
742 #endif
743
744     m_needsFontAttributes = parameters.needsFontAttributes;
745
746 #if ENABLE(WEB_RTC)
747     if (!parameters.iceCandidateFilteringEnabled)
748         m_page->disableICECandidateFiltering();
749 #if USE(LIBWEBRTC)
750     if (parameters.enumeratingAllNetworkInterfacesEnabled)
751         m_page->libWebRTCProvider().enableEnumeratingAllNetworkInterfaces();
752 #endif
753 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
754     if (auto* captureManager = WebProcess::singleton().supplement<UserMediaCaptureManager>())
755         captureManager->setupCaptureProcesses(parameters.shouldCaptureAudioInUIProcess, parameters.shouldCaptureAudioInGPUProcess, parameters.shouldCaptureVideoInUIProcess, parameters.shouldCaptureVideoInGPUProcess, parameters.shouldCaptureDisplayInUIProcess);
756 #endif
757 #endif
758
759     for (const auto& iterator : parameters.urlSchemeHandlers)
760         registerURLSchemeHandler(iterator.value, iterator.key);
761
762     m_userContentController->addContentWorlds(parameters.userContentControllerParameters.userContentWorlds);
763     m_userContentController->addUserScripts(WTFMove(parameters.userContentControllerParameters.userScripts), InjectUserScriptImmediately::No);
764     m_userContentController->addUserStyleSheets(parameters.userContentControllerParameters.userStyleSheets);
765     m_userContentController->addUserScriptMessageHandlers(parameters.userContentControllerParameters.messageHandlers);
766 #if ENABLE(CONTENT_EXTENSIONS)
767     m_userContentController->addContentRuleLists(WTFMove(parameters.userContentControllerParameters.contentRuleLists));
768 #endif
769
770 #if PLATFORM(IOS_FAMILY)
771     setViewportConfigurationViewLayoutSize(parameters.viewportConfigurationViewLayoutSize, parameters.viewportConfigurationLayoutSizeScaleFactor, parameters.viewportConfigurationMinimumEffectiveDeviceWidth);
772     setMaximumUnobscuredSize(parameters.maximumUnobscuredSize);
773 #endif
774
775 #if USE(AUDIO_SESSION)
776     PlatformMediaSessionManager::setShouldDeactivateAudioSession(true);
777 #endif
778
779 #if HAVE(VISIBILITY_PROPAGATION_VIEW)
780     m_contextForVisibilityPropagation = LayerHostingContext::createForExternalHostingProcess({
781         m_canShowWhileLocked
782     });
783     RELEASE_LOG_IF_ALLOWED(Process, "WebPage: Created context with ID %d for visibility propagation from UIProcess", m_contextForVisibilityPropagation->contextID());
784     send(Messages::WebPageProxy::DidCreateContextForVisibilityPropagation(m_contextForVisibilityPropagation->contextID()));
785 #endif
786
787 #if ENABLE(GPU_PROCESS)
788     if (m_page->settings().useGPUProcessForMediaEnabled())
789         WebProcess::singleton().ensureGPUProcessConnection().updateParameters(parameters);
790 #endif
791
792 #if ENABLE(VP9)
793     if (parameters.shouldEnableVP9Decoder)
794         WebProcess::singleton().enableVP9Decoder();
795
796     if (parameters.shouldEnableVP9SWDecoder)
797         WebProcess::singleton().enableVP9SWDecoder();
798 #endif
799
800     m_page->setCanUseCredentialStorage(parameters.canUseCredentialStorage);
801
802     updateThrottleState();
803 }
804
805 void WebPage::stopAllMediaPlayback()
806 {
807     m_page->stopAllMediaPlayback();
808 }
809
810 void WebPage::suspendAllMediaPlayback()
811 {
812     m_page->suspendAllMediaPlayback();
813 }
814
815 void WebPage::resumeAllMediaPlayback()
816 {
817     m_page->resumeAllMediaPlayback();
818 }
819
820 void WebPage::suspendAllMediaBuffering()
821 {
822     m_page->suspendAllMediaBuffering();
823 }
824
825 void WebPage::resumeAllMediaBuffering()
826 {
827     m_page->resumeAllMediaBuffering();
828 }
829
830
831 void WebPage::reinitializeWebPage(WebPageCreationParameters&& parameters)
832 {
833     ASSERT(m_drawingArea);
834
835     setSize(parameters.viewSize);
836
837     // If the UIProcess created a new DrawingArea, then we need to do the same.
838     if (m_drawingArea->identifier() != parameters.drawingAreaIdentifier) {
839         auto oldDrawingArea = std::exchange(m_drawingArea, nullptr);
840         oldDrawingArea->removeMessageReceiverIfNeeded();
841
842         m_drawingArea = DrawingArea::create(*this, parameters);
843         m_drawingArea->setShouldScaleViewToFitDocument(parameters.shouldScaleViewToFitDocument);
844         m_drawingArea->updatePreferences(parameters.store);
845         m_drawingArea->enablePainting();
846
847         m_drawingArea->adoptLayersFromDrawingArea(*oldDrawingArea);
848         m_drawingArea->adoptDisplayRefreshMonitorsFromDrawingArea(*oldDrawingArea);
849
850         unfreezeLayerTree(LayerTreeFreezeReason::PageSuspended);
851     }
852
853     setMinimumSizeForAutoLayout(parameters.minimumSizeForAutoLayout);
854     setSizeToContentAutoSizeMaximumSize(parameters.sizeToContentAutoSizeMaximumSize);
855
856     if (m_activityState != parameters.activityState)
857         setActivityState(parameters.activityState, ActivityStateChangeAsynchronous, Vector<CallbackID>());
858     if (m_layerHostingMode != parameters.layerHostingMode)
859         setLayerHostingMode(parameters.layerHostingMode);
860
861     platformReinitialize();
862 }
863
864 void WebPage::updateThrottleState()
865 {
866     bool isThrottleable = this->isThrottleable();
867
868     // The UserActivity prevents App Nap. So if we want to allow App Nap of the page, stop the activity.
869     // If the page should not be app nap'd, start it.
870     if (isThrottleable)
871         m_userActivity.stop();
872     else
873         m_userActivity.start();
874
875 #if ENABLE(SERVICE_WORKER)
876     if (RuntimeEnabledFeatures::sharedFeatures().serviceWorkerEnabled()) {
877         RunLoop::main().dispatch([isThrottleable] {
878             WebServiceWorkerProvider::singleton().updateThrottleState(isThrottleable);
879         });
880     }
881 #endif
882 }
883
884 bool WebPage::isThrottleable() const
885 {
886     bool isActive = m_activityState.containsAny({ ActivityState::IsLoading, ActivityState::IsAudible, ActivityState::IsCapturingMedia, ActivityState::WindowIsActive });
887     bool isVisuallyIdle = m_activityState.contains(ActivityState::IsVisuallyIdle);
888
889     return m_isAppNapEnabled && !isActive && isVisuallyIdle;
890 }
891
892 WebPage::~WebPage()
893 {
894     ASSERT(!m_page);
895
896     if (!m_corsDisablingPatterns.isEmpty()) {
897         m_corsDisablingPatterns.clear();
898         synchronizeCORSDisablingPatternsWithNetworkProcess();
899     }
900
901     platformDetach();
902     
903     m_sandboxExtensionTracker.invalidate();
904
905     for (auto* pluginView : m_pluginViews)
906         pluginView->webPageDestroyed();
907
908 #if !PLATFORM(IOS_FAMILY)
909     if (m_headerBanner)
910         m_headerBanner->detachFromPage();
911     if (m_footerBanner)
912         m_footerBanner->detachFromPage();
913 #endif // !PLATFORM(IOS_FAMILY)
914
915 #ifndef NDEBUG
916     webPageCounter.decrement();
917 #endif
918     
919 #if ENABLE(VIDEO_PRESENTATION_MODE)
920     if (m_playbackSessionManager)
921         m_playbackSessionManager->invalidate();
922
923     if (m_videoFullscreenManager)
924         m_videoFullscreenManager->invalidate();
925 #endif
926
927     for (auto& completionHandler : std::exchange(m_markLayersAsVolatileCompletionHandlers, { }))
928         completionHandler(false);
929 }
930
931 IPC::Connection* WebPage::messageSenderConnection() const
932 {
933     return WebProcess::singleton().parentProcessConnection();
934 }
935
936 uint64_t WebPage::messageSenderDestinationID() const
937 {
938     return identifier().toUInt64();
939 }
940
941 #if ENABLE(CONTEXT_MENUS)
942 void WebPage::setInjectedBundleContextMenuClient(std::unique_ptr<API::InjectedBundle::PageContextMenuClient>&& contextMenuClient)
943 {
944     if (!contextMenuClient) {
945         m_contextMenuClient = makeUnique<API::InjectedBundle::PageContextMenuClient>();
946         return;
947     }
948
949     m_contextMenuClient = WTFMove(contextMenuClient);
950 }
951 #endif
952
953 void WebPage::setInjectedBundleEditorClient(std::unique_ptr<API::InjectedBundle::EditorClient>&& editorClient)
954 {
955     if (!editorClient) {
956         m_editorClient = makeUnique<API::InjectedBundle::EditorClient>();
957         return;
958     }
959
960     m_editorClient = WTFMove(editorClient);
961 }
962
963 void WebPage::setInjectedBundleFormClient(std::unique_ptr<API::InjectedBundle::FormClient>&& formClient)
964 {
965     if (!formClient) {
966         m_formClient = makeUnique<API::InjectedBundle::FormClient>();
967         return;
968     }
969
970     m_formClient = WTFMove(formClient);
971 }
972
973 void WebPage::setInjectedBundlePageLoaderClient(std::unique_ptr<API::InjectedBundle::PageLoaderClient>&& loaderClient)
974 {
975     if (!loaderClient) {
976         m_loaderClient = makeUnique<API::InjectedBundle::PageLoaderClient>();
977         return;
978     }
979
980     m_loaderClient = WTFMove(loaderClient);
981
982     // It would be nice to get rid of this code and transition all clients to using didLayout instead of
983     // didFirstLayoutInFrame and didFirstVisuallyNonEmptyLayoutInFrame. In the meantime, this is required
984     // for backwards compatibility.
985     if (auto milestones = m_loaderClient->layoutMilestones())
986         listenForLayoutMilestones(milestones);
987 }
988
989 void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClientBase* client)
990 {
991     m_policyClient.initialize(client);
992 }
993
994 void WebPage::setInjectedBundleResourceLoadClient(std::unique_ptr<API::InjectedBundle::ResourceLoadClient>&& client)
995 {
996     if (!m_resourceLoadClient)
997         m_resourceLoadClient = makeUnique<API::InjectedBundle::ResourceLoadClient>();
998     else
999         m_resourceLoadClient = WTFMove(client);
1000 }
1001
1002 void WebPage::setInjectedBundleUIClient(std::unique_ptr<API::InjectedBundle::PageUIClient>&& uiClient)
1003 {
1004     if (!uiClient) {
1005         m_uiClient = makeUnique<API::InjectedBundle::PageUIClient>();
1006         return;
1007     }
1008
1009     m_uiClient = WTFMove(uiClient);
1010 }
1011
1012 #if ENABLE(FULLSCREEN_API)
1013 void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClientBase* client)
1014 {
1015     m_fullScreenClient.initialize(client);
1016 }
1017 #endif
1018
1019 #if ENABLE(NETSCAPE_PLUGIN_API)
1020
1021 constexpr int smallPluginDimensionThreshold = 5;
1022
1023 static bool pluginIsSmall(WebCore::HTMLPlugInElement& pluginElement)
1024 {
1025     auto* renderer = pluginElement.renderer();
1026     if (!is<RenderEmbeddedObject>(*renderer))
1027         return false;
1028
1029     auto& box = downcast<RenderBox>(*renderer);
1030     return box.contentWidth() <= smallPluginDimensionThreshold && box.contentHeight() <= smallPluginDimensionThreshold;
1031 }
1032
1033 RefPtr<Plugin> WebPage::createPlugin(WebFrame* frame, HTMLPlugInElement* pluginElement, const Plugin::Parameters& parameters, String& newMIMEType)
1034 {
1035     String frameURLString = frame->coreFrame()->loader().documentLoader()->responseURL().string();
1036     String pageURLString = m_page->mainFrame().loader().documentLoader()->responseURL().string();
1037
1038 #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
1039     HTMLPlugInImageElement& pluginImageElement = downcast<HTMLPlugInImageElement>(*pluginElement);
1040     unsigned pluginArea = 0;
1041     PluginProcessType processType = pluginElement->displayState() == HTMLPlugInElement::WaitingForSnapshot && !(plugInIsPrimarySize(pluginImageElement, pluginArea) && !plugInIntersectsSearchRect(pluginImageElement)) ? PluginProcessType::Snapshot : PluginProcessType::Normal;
1042 #else
1043     PluginProcessType processType = pluginElement->displayState() == HTMLPlugInElement::WaitingForSnapshot ? PluginProcessType::Snapshot : PluginProcessType::Normal;
1044 #endif
1045
1046     bool allowOnlyApplicationPlugins = !frame->coreFrame()->loader().arePluginsEnabled();
1047
1048     uint64_t pluginProcessToken;
1049     uint32_t pluginLoadPolicy;
1050     String unavailabilityDescription;
1051     bool isUnsupported;
1052     if (!sendSync(Messages::WebPageProxy::FindPlugin(parameters.mimeType, processType, parameters.url.string(), frameURLString, pageURLString, allowOnlyApplicationPlugins), Messages::WebPageProxy::FindPlugin::Reply(pluginProcessToken, newMIMEType, pluginLoadPolicy, unavailabilityDescription, isUnsupported)))
1053         return nullptr;
1054
1055     PluginModuleLoadPolicy loadPolicy = static_cast<PluginModuleLoadPolicy>(pluginLoadPolicy);
1056     bool isBlockedPlugin = (loadPolicy == PluginModuleBlockedForSecurity) || (loadPolicy == PluginModuleBlockedForCompatibility);
1057
1058     if (isUnsupported || isBlockedPlugin || !pluginProcessToken) {
1059 #if ENABLE(PDFKIT_PLUGIN)
1060         auto path = parameters.url.path();
1061         if (shouldUsePDFPlugin() && (MIMETypeRegistry::isPDFOrPostScriptMIMEType(parameters.mimeType) || (parameters.mimeType.isEmpty() && (path.endsWithIgnoringASCIICase(".pdf") || path.endsWithIgnoringASCIICase(".ps")))))
1062             return PDFPlugin::create(*frame);
1063 #endif
1064     }
1065
1066     if (isUnsupported) {
1067         pluginElement->setReplacement(RenderEmbeddedObject::UnsupportedPlugin, unavailabilityDescription);
1068         return nullptr;
1069     }
1070
1071     if (isBlockedPlugin) {
1072         bool isReplacementObscured = pluginElement->setReplacement(RenderEmbeddedObject::InsecurePluginVersion, unavailabilityDescription);
1073         send(Messages::WebPageProxy::DidBlockInsecurePluginVersion(parameters.mimeType, parameters.url.string(), frameURLString, pageURLString, isReplacementObscured));
1074         return nullptr;
1075     }
1076
1077     if (!pluginProcessToken)
1078         return nullptr;
1079
1080     if (m_page->settings().blockingOfSmallPluginsEnabled() && pluginIsSmall(*pluginElement)) {
1081         RELEASE_LOG_IF_ALLOWED(Plugins, "createPlugin: Blocking a plugin because it is too small");
1082         pluginElement->setReplacement(RenderEmbeddedObject::PluginTooSmall, pluginTooSmallText());
1083         return nullptr;
1084     }
1085
1086     bool isRestartedProcess = (pluginElement->displayState() == HTMLPlugInElement::Restarting || pluginElement->displayState() == HTMLPlugInElement::RestartingWithPendingMouseClick);
1087     return PluginProxy::create(pluginProcessToken, isRestartedProcess);
1088 }
1089 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1090
1091 #if ENABLE(WEBGL) && !PLATFORM(MAC)
1092 WebCore::WebGLLoadPolicy WebPage::webGLPolicyForURL(WebFrame*, const URL&)
1093 {
1094     return WebGLLoadPolicy::WebGLAllowCreation;
1095 }
1096
1097 WebCore::WebGLLoadPolicy WebPage::resolveWebGLPolicyForURL(WebFrame*, const URL&)
1098 {
1099     return WebGLLoadPolicy::WebGLAllowCreation;
1100 }
1101 #endif
1102
1103 EditorState WebPage::editorState(ShouldPerformLayout shouldPerformLayout) const
1104 {
1105     // Ref the frame because this function may perform layout, which may cause frame destruction.
1106     Ref<Frame> frame = m_page->focusController().focusedOrMainFrame();
1107
1108     EditorState result;
1109
1110     if (PluginView* pluginView = focusedPluginViewForFrame(frame)) {
1111         if (!pluginView->getSelectionString().isNull()) {
1112             result.selectionIsNone = false;
1113             result.selectionIsRange = true;
1114             result.isInPlugin = true;
1115             return result;
1116         }
1117     }
1118
1119     const VisibleSelection& selection = frame->selection().selection();
1120     const Editor& editor = frame->editor();
1121
1122     result.selectionIsNone = selection.isNone();
1123     result.selectionIsRange = selection.isRange();
1124     result.isContentEditable = selection.isContentEditable();
1125     result.isContentRichlyEditable = selection.isContentRichlyEditable();
1126     result.isInPasswordField = selection.isInPasswordField();
1127     result.hasComposition = editor.hasComposition();
1128     result.shouldIgnoreSelectionChanges = editor.ignoreSelectionChanges() || (editor.client() && !editor.client()->shouldRevealCurrentSelectionAfterInsertion());
1129
1130     Ref<Document> document = *frame->document();
1131     result.originIdentifierForPasteboard = document->originIdentifierForPasteboard();
1132
1133     if (shouldPerformLayout == ShouldPerformLayout::Yes || platformNeedsLayoutForEditorState(frame))
1134         document->updateLayout(); // May cause document destruction
1135
1136     if (auto* frameView = document->view(); frameView && !frameView->needsLayout()) {
1137         result.isMissingPostLayoutData = false;
1138
1139         auto& postLayoutData = result.postLayoutData();
1140         postLayoutData.canCut = editor.canCut();
1141         postLayoutData.canCopy = editor.canCopy();
1142         postLayoutData.canPaste = editor.canPaste();
1143
1144         if (m_needsFontAttributes)
1145             postLayoutData.fontAttributes = editor.fontAttributesAtSelectionStart();
1146     }
1147
1148     getPlatformEditorState(frame, result);
1149
1150     m_lastEditorStateWasContentEditable = result.isContentEditable ? EditorStateIsContentEditable::Yes : EditorStateIsContentEditable::No;
1151
1152     return result;
1153 }
1154
1155 void WebPage::changeFontAttributes(WebCore::FontAttributeChanges&& changes)
1156 {
1157     auto& frame = m_page->focusController().focusedOrMainFrame();
1158     if (frame.selection().selection().isContentEditable())
1159         frame.editor().applyStyleToSelection(changes.createEditingStyle(), changes.editAction(), Editor::ColorFilterMode::InvertColor);
1160 }
1161
1162 void WebPage::changeFont(WebCore::FontChanges&& changes)
1163 {
1164     auto& frame = m_page->focusController().focusedOrMainFrame();
1165     if (frame.selection().selection().isContentEditable())
1166         frame.editor().applyStyleToSelection(changes.createEditingStyle(), EditAction::SetFont, Editor::ColorFilterMode::InvertColor);
1167 }
1168
1169 void WebPage::executeEditCommandWithCallback(const String& commandName, const String& argument, CompletionHandler<void()>&& completionHandler)
1170 {
1171     executeEditCommand(commandName, argument);
1172     completionHandler();
1173 }
1174
1175 void WebPage::selectAll()
1176 {
1177     executeEditingCommand("SelectAll"_s, { });
1178     platformDidSelectAll();
1179 }
1180
1181 bool WebPage::shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const
1182 {
1183     auto* document = m_page->mainFrame().document();
1184     return document && document->quirks().shouldDispatchSyntheticMouseEventsWhenModifyingSelection();
1185 }
1186
1187 #if !PLATFORM(IOS_FAMILY)
1188
1189 void WebPage::platformDidSelectAll()
1190 {
1191 }
1192
1193 #endif // !PLATFORM(IOS_FAMILY)
1194
1195 void WebPage::updateEditorStateAfterLayoutIfEditabilityChanged()
1196 {
1197     // FIXME: We should update EditorStateIsContentEditable to track whether the state is richly
1198     // editable or plainttext-only.
1199     if (m_lastEditorStateWasContentEditable == EditorStateIsContentEditable::Unset)
1200         return;
1201
1202     Frame& frame = m_page->focusController().focusedOrMainFrame();
1203     EditorStateIsContentEditable editorStateIsContentEditable = frame.selection().selection().isContentEditable() ? EditorStateIsContentEditable::Yes : EditorStateIsContentEditable::No;
1204     if (m_lastEditorStateWasContentEditable != editorStateIsContentEditable)
1205         scheduleFullEditorStateUpdate();
1206 }
1207
1208 static OptionSet<RenderAsTextFlag> toRenderAsTextFlags(unsigned options)
1209 {
1210     OptionSet<RenderAsTextFlag> flags;
1211
1212     if (options & RenderTreeShowAllLayers)
1213         flags.add(RenderAsTextFlag::ShowAllLayers);
1214     if (options & RenderTreeShowLayerNesting)
1215         flags.add(RenderAsTextFlag::ShowLayerNesting);
1216     if (options & RenderTreeShowCompositedLayers)
1217         flags.add(RenderAsTextFlag::ShowCompositedLayers);
1218     if (options & RenderTreeShowOverflow)
1219         flags.add(RenderAsTextFlag::ShowOverflow);
1220     if (options & RenderTreeShowSVGGeometry)
1221         flags.add(RenderAsTextFlag::ShowSVGGeometry);
1222     if (options & RenderTreeShowLayerFragments)
1223         flags.add(RenderAsTextFlag::ShowLayerFragments);
1224
1225     return flags;
1226 }
1227
1228 String WebPage::renderTreeExternalRepresentation(unsigned options) const
1229 {
1230     return externalRepresentation(m_mainFrame->coreFrame(), toRenderAsTextFlags(options));
1231 }
1232
1233 String WebPage::renderTreeExternalRepresentationForPrinting() const
1234 {
1235     return externalRepresentation(m_mainFrame->coreFrame(), { RenderAsTextFlag::PrintingMode });
1236 }
1237
1238 uint64_t WebPage::renderTreeSize() const
1239 {
1240     if (!m_page)
1241         return 0;
1242     return m_page->renderTreeSize();
1243 }
1244
1245 void WebPage::setHasResourceLoadClient(bool has)
1246 {
1247     if (m_page)
1248         m_page->setHasResourceLoadClient(has);
1249 }
1250
1251 void WebPage::setCanUseCredentialStorage(bool has)
1252 {
1253     if (m_page)
1254         m_page->setCanUseCredentialStorage(has);
1255 }
1256
1257 void WebPage::setTracksRepaints(bool trackRepaints)
1258 {
1259     if (FrameView* view = mainFrameView())
1260         view->setTracksRepaints(trackRepaints);
1261 }
1262
1263 bool WebPage::isTrackingRepaints() const
1264 {
1265     if (FrameView* view = mainFrameView())
1266         return view->isTrackingRepaints();
1267
1268     return false;
1269 }
1270
1271 void WebPage::resetTrackedRepaints()
1272 {
1273     if (FrameView* view = mainFrameView())
1274         view->resetTrackedRepaints();
1275 }
1276
1277 Ref<API::Array> WebPage::trackedRepaintRects()
1278 {
1279     FrameView* view = mainFrameView();
1280     if (!view)
1281         return API::Array::create();
1282
1283     Vector<RefPtr<API::Object>> repaintRects;
1284     repaintRects.reserveInitialCapacity(view->trackedRepaintRects().size());
1285
1286     for (const auto& repaintRect : view->trackedRepaintRects())
1287         repaintRects.uncheckedAppend(API::Rect::create(toAPI(repaintRect)));
1288
1289     return API::Array::create(WTFMove(repaintRects));
1290 }
1291
1292 PluginView* WebPage::focusedPluginViewForFrame(Frame& frame)
1293 {
1294     if (!is<PluginDocument>(frame.document()))
1295         return nullptr;
1296
1297     auto& pluginDocument = downcast<PluginDocument>(*frame.document());
1298     if (pluginDocument.focusedElement() != pluginDocument.pluginElement())
1299         return nullptr;
1300
1301     return pluginViewForFrame(&frame);
1302 }
1303
1304 PluginView* WebPage::pluginViewForFrame(Frame* frame)
1305 {
1306     if (!frame || !is<PluginDocument>(frame->document()))
1307         return nullptr;
1308
1309     auto& document = downcast<PluginDocument>(*frame->document());
1310     return static_cast<PluginView*>(document.pluginWidget());
1311 }
1312
1313 void WebPage::executeEditingCommand(const String& commandName, const String& argument)
1314 {
1315     platformWillPerformEditingCommand();
1316
1317     auto& frame = m_page->focusController().focusedOrMainFrame();
1318
1319     if (PluginView* pluginView = focusedPluginViewForFrame(frame)) {
1320         pluginView->handleEditingCommand(commandName, argument);
1321         return;
1322     }
1323     
1324     frame.editor().command(commandName).execute(argument);
1325 }
1326
1327 void WebPage::setEditable(bool editable)
1328 {
1329     m_page->setEditable(editable);
1330     m_page->setTabKeyCyclesThroughElements(!editable);
1331     Frame& frame = m_page->focusController().focusedOrMainFrame();
1332     if (editable) {
1333         frame.editor().applyEditingStyleToBodyElement();
1334         // If the page is made editable and the selection is empty, set it to something.
1335         if (frame.selection().isNone())
1336             frame.selection().setSelectionFromNone();
1337     }
1338 }
1339
1340 void WebPage::increaseListLevel()
1341 {
1342     m_page->focusController().focusedOrMainFrame().editor().increaseSelectionListLevel();
1343 }
1344
1345 void WebPage::decreaseListLevel()
1346 {
1347     m_page->focusController().focusedOrMainFrame().editor().decreaseSelectionListLevel();
1348 }
1349
1350 void WebPage::changeListType()
1351 {
1352     m_page->focusController().focusedOrMainFrame().editor().changeSelectionListType();
1353 }
1354
1355 void WebPage::setBaseWritingDirection(WritingDirection direction)
1356 {
1357     m_page->focusController().focusedOrMainFrame().editor().setBaseWritingDirection(direction);
1358 }
1359
1360 bool WebPage::isEditingCommandEnabled(const String& commandName)
1361 {
1362     Frame& frame = m_page->focusController().focusedOrMainFrame();
1363
1364     if (PluginView* pluginView = focusedPluginViewForFrame(frame))
1365         return pluginView->isEditingCommandEnabled(commandName);
1366     
1367     Editor::Command command = frame.editor().command(commandName);
1368     return command.isSupported() && command.isEnabled();
1369 }
1370     
1371 void WebPage::clearMainFrameName()
1372 {
1373     if (Frame* frame = mainFrame())
1374         frame->tree().clearName();
1375 }
1376
1377 void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
1378 {
1379     m_drawingArea->setRootCompositingLayer(layer);
1380 }
1381
1382 void WebPage::exitAcceleratedCompositingMode()
1383 {
1384     m_drawingArea->setRootCompositingLayer(nullptr);
1385 }
1386
1387 void WebPage::close()
1388 {
1389     if (m_isClosed)
1390         return;
1391
1392 #if ENABLE(RESOURCE_LOAD_STATISTICS)
1393     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ClearPageSpecificDataForResourceLoadStatistics(m_identifier), 0);
1394 #endif
1395
1396     m_isClosed = true;
1397
1398     // If there is still no URL, then we never loaded anything in this page, so nothing to report.
1399     if (!mainWebFrame().url().isEmpty())
1400         reportUsedFeatures();
1401
1402     if (WebProcess::singleton().injectedBundle())
1403         WebProcess::singleton().injectedBundle()->willDestroyPage(this);
1404
1405     if (m_inspector) {
1406         m_inspector->disconnectFromPage();
1407         m_inspector = nullptr;
1408     }
1409
1410     m_page->inspectorController().disconnectAllFrontends();
1411
1412 #if ENABLE(FULLSCREEN_API)
1413     m_fullScreenManager = nullptr;
1414 #endif
1415
1416     if (m_activePopupMenu) {
1417         m_activePopupMenu->disconnectFromPage();
1418         m_activePopupMenu = nullptr;
1419     }
1420
1421     if (m_activeOpenPanelResultListener) {
1422         m_activeOpenPanelResultListener->disconnectFromPage();
1423         m_activeOpenPanelResultListener = nullptr;
1424     }
1425
1426 #if ENABLE(INPUT_TYPE_COLOR)
1427     if (m_activeColorChooser) {
1428         m_activeColorChooser->disconnectFromPage();
1429         m_activeColorChooser = nullptr;
1430     }
1431 #endif
1432
1433 #if PLATFORM(GTK)
1434     if (m_printOperation) {
1435         m_printOperation->disconnectFromPage();
1436         m_printOperation = nullptr;
1437     }
1438 #endif
1439
1440 #if ENABLE(VIDEO) && USE(GSTREAMER)
1441     if (m_installMediaPluginsCallback) {
1442         m_installMediaPluginsCallback->invalidate();
1443         m_installMediaPluginsCallback = nullptr;
1444     }
1445 #endif
1446
1447     m_sandboxExtensionTracker.invalidate();
1448
1449 #if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
1450     m_determinePrimarySnapshottedPlugInTimer.stop();
1451 #endif
1452
1453 #if ENABLE(TEXT_AUTOSIZING)
1454     m_textAutoSizingAdjustmentTimer.stop();
1455 #endif
1456
1457 #if ENABLE(CONTEXT_MENUS)
1458     m_contextMenuClient = makeUnique<API::InjectedBundle::PageContextMenuClient>();
1459 #endif
1460     m_editorClient = makeUnique<API::InjectedBundle::EditorClient>();
1461     m_formClient = makeUnique<API::InjectedBundle::FormClient>();
1462     m_loaderClient = makeUnique<API::InjectedBundle::PageLoaderClient>();
1463     m_policyClient.initialize(0);
1464     m_resourceLoadClient = makeUnique<API::InjectedBundle::ResourceLoadClient>();
1465     m_uiClient = makeUnique<API::InjectedBundle::PageUIClient>();
1466 #if ENABLE(FULLSCREEN_API)
1467     m_fullScreenClient.initialize(0);
1468 #endif
1469
1470     m_printContext = nullptr;
1471     m_mainFrame->coreFrame()->loader().detachFromParent();
1472     m_drawingArea = nullptr;
1473
1474     DeferredPageDestructor::createDeferredPageDestructor(WTFMove(m_page), this);
1475
1476     bool isRunningModal = m_isRunningModal;
1477     m_isRunningModal = false;
1478
1479     auto& webProcess = WebProcess::singleton();
1480 #if PLATFORM(COCOA)
1481     if (m_remoteObjectRegistry)
1482         m_remoteObjectRegistry->close();
1483     ASSERT(!m_remoteObjectRegistry);
1484 #endif
1485 #if ENABLE(SCROLLING_THREAD)
1486     if (m_useAsyncScrolling)
1487         webProcess.eventDispatcher().removeScrollingTreeForPage(this);
1488 #endif
1489     webProcess.removeMessageReceiver(Messages::WebPage::messageReceiverName(), m_identifier);
1490     // FIXME: This should be done in the object destructors, and the objects themselves should be message receivers.
1491     webProcess.removeMessageReceiver(Messages::WebInspector::messageReceiverName(), m_identifier);
1492     webProcess.removeMessageReceiver(Messages::WebInspectorUI::messageReceiverName(), m_identifier);
1493     webProcess.removeMessageReceiver(Messages::RemoteWebInspectorUI::messageReceiverName(), m_identifier);
1494 #if ENABLE(FULLSCREEN_API)
1495     webProcess.removeMessageReceiver(Messages::WebFullScreenManager::messageReceiverName(), m_identifier);
1496 #endif
1497 #if PLATFORM(COCOA) || (PLATFORM(GTK) && !USE(GTK4))
1498     m_viewGestureGeometryCollector = nullptr;
1499 #endif
1500
1501     // The WebPage can be destroyed by this call.
1502     WebProcess::singleton().removeWebPage(m_identifier);
1503
1504     WebProcess::singleton().updateActivePages(m_processDisplayName);
1505
1506     if (isRunningModal)
1507         RunLoop::main().stop();
1508 }
1509
1510 void WebPage::tryClose(CompletionHandler<void(bool)>&& completionHandler)
1511 {
1512     bool shouldClose = corePage()->userInputBridge().tryClosePage();
1513     completionHandler(shouldClose);
1514 }
1515
1516 void WebPage::sendClose()
1517 {
1518     send(Messages::WebPageProxy::ClosePage());
1519 }
1520
1521 void WebPage::suspendForProcessSwap()
1522 {
1523     auto failedToSuspend = [this, protectedThis = makeRef(*this)] {
1524         send(Messages::WebPageProxy::DidFailToSuspendAfterProcessSwap());
1525     };
1526
1527     auto* currentHistoryItem = m_mainFrame->coreFrame()->loader().history().currentItem();
1528     if (!currentHistoryItem) {
1529         failedToSuspend();
1530         return;
1531     }
1532
1533     if (!BackForwardCache::singleton().addIfCacheable(*currentHistoryItem, corePage())) {
1534         failedToSuspend();
1535         return;
1536     }
1537
1538     // Back/forward cache does not break the opener link for the main frame (only does so for the subframes) because the
1539     // main frame is normally re-used for the navigation. However, in the case of process-swapping, the main frame
1540     // is now hosted in another process and the one in this process is in the cache.
1541     if (m_mainFrame->coreFrame())
1542         m_mainFrame->coreFrame()->loader().detachFromAllOpenedFrames();
1543
1544     send(Messages::WebPageProxy::DidSuspendAfterProcessSwap());
1545 }
1546
1547 void WebPage::loadURLInFrame(URL&& url, const String& referrer, FrameIdentifier frameID)
1548 {
1549     WebFrame* frame = WebProcess::singleton().webFrame(frameID);
1550     if (!frame)
1551         return;
1552
1553     frame->coreFrame()->loader().load(FrameLoadRequest(*frame->coreFrame(), ResourceRequest(url, referrer)));
1554 }
1555
1556 void WebPage::loadDataInFrame(IPC::DataReference&& data, String&& MIMEType, String&& encodingName, URL&& baseURL, FrameIdentifier frameID)
1557 {
1558     auto* frame = WebProcess::singleton().webFrame(frameID);
1559     if (!frame)
1560         return;
1561     ASSERT(&mainWebFrame() != frame);
1562
1563     auto sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(data.data()), data.size());
1564     ResourceResponse response(baseURL, MIMEType, sharedBuffer->size(), encodingName);
1565     SubstituteData substituteData(WTFMove(sharedBuffer), baseURL, WTFMove(response), SubstituteData::SessionHistoryVisibility::Hidden);
1566     frame->coreFrame()->loader().load(FrameLoadRequest(*frame->coreFrame(), ResourceRequest(baseURL), WTFMove(substituteData)));
1567 }
1568
1569 #if !PLATFORM(COCOA)
1570 void WebPage::platformDidReceiveLoadParameters(const LoadParameters& loadParameters)
1571 {
1572 }
1573 #endif
1574
1575 void WebPage::loadRequest(LoadParameters&& loadParameters)
1576 {
1577 #if ENABLE(APP_BOUND_DOMAINS)
1578     setIsNavigatingToAppBoundDomain(loadParameters.isNavigatingToAppBoundDomain, &m_mainFrame.get());
1579 #endif
1580
1581     SendStopResponsivenessTimer stopper;
1582
1583     m_pendingNavigationID = loadParameters.navigationID;
1584     m_pendingWebsitePolicies = WTFMove(loadParameters.websitePolicies);
1585
1586     m_sandboxExtensionTracker.beginLoad(m_mainFrame.ptr(), WTFMove(loadParameters.sandboxExtensionHandle));
1587
1588     // Let the InjectedBundle know we are about to start the load, passing the user data from the UIProcess
1589     // to all the client to set up any needed state.
1590     m_loaderClient->willLoadURLRequest(*this, loadParameters.request, WebProcess::singleton().transformHandlesToObjects(loadParameters.userData.object()).get());
1591
1592     platformDidReceiveLoadParameters(loadParameters);
1593
1594     // Initate the load in WebCore.
1595     FrameLoadRequest frameLoadRequest { *m_mainFrame->coreFrame(), loadParameters.request };
1596     frameLoadRequest.setShouldOpenExternalURLsPolicy(loadParameters.shouldOpenExternalURLsPolicy);
1597     frameLoadRequest.setShouldTreatAsContinuingLoad(loadParameters.shouldTreatAsContinuingLoad);
1598     frameLoadRequest.setLockHistory(loadParameters.lockHistory);
1599     frameLoadRequest.setLockBackForwardList(loadParameters.lockBackForwardList);
1600     frameLoadRequest.setClientRedirectSourceForHistory(loadParameters.clientRedirectSourceForHistory);
1601     frameLoadRequest.setIsRequestFromClientOrUserInput();
1602
1603     corePage()->userInputBridge().loadRequest(WTFMove(frameLoadRequest));
1604
1605     ASSERT(!m_pendingNavigationID);
1606     ASSERT(!m_pendingWebsitePolicies);
1607 }
1608
1609 // LoadRequestWaitingForProcessLaunch should never be sent to the WebProcess. It must always be converted to a LoadRequest message.
1610 NO_RETURN void WebPage::loadRequestWaitingForProcessLaunch(LoadParameters&&, URL&&, WebPageProxyIdentifier, bool)
1611 {
1612     RELEASE_ASSERT_NOT_REACHED();
1613 }
1614
1615 void WebPage::loadDataImpl(uint64_t navigationID, bool shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies, Ref<SharedBuffer>&& sharedBuffer, const String& MIMEType, const String& encodingName, const URL& baseURL, const URL& unreachableURL, const UserData& userData, Optional<NavigatingToAppBoundDomain> isNavigatingToAppBoundDomain, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy)
1616 {
1617 #if ENABLE(APP_BOUND_DOMAINS)
1618     setIsNavigatingToAppBoundDomain(isNavigatingToAppBoundDomain, &m_mainFrame.get());
1619 #endif
1620
1621     SendStopResponsivenessTimer stopper;
1622
1623     m_pendingNavigationID = navigationID;
1624     m_pendingWebsitePolicies = WTFMove(websitePolicies);
1625
1626     ResourceRequest request(baseURL);
1627     ResourceResponse response(URL(), MIMEType, sharedBuffer->size(), encodingName);
1628     SubstituteData substituteData(WTFMove(sharedBuffer), unreachableURL, response, SubstituteData::SessionHistoryVisibility::Hidden);
1629
1630     // Let the InjectedBundle know we are about to start the load, passing the user data from the UIProcess
1631     // to all the client to set up any needed state.
1632     m_loaderClient->willLoadDataRequest(*this, request, const_cast<SharedBuffer*>(substituteData.content()), substituteData.mimeType(), substituteData.textEncoding(), substituteData.failingURL(), WebProcess::singleton().transformHandlesToObjects(userData.object()).get());
1633
1634     // Initate the load in WebCore.
1635     FrameLoadRequest frameLoadRequest(*m_mainFrame->coreFrame(), request, substituteData);
1636     frameLoadRequest.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicy);
1637     frameLoadRequest.setShouldTreatAsContinuingLoad(shouldTreatAsContinuingLoad);
1638     frameLoadRequest.setIsRequestFromClientOrUserInput();
1639     m_mainFrame->coreFrame()->loader().load(WTFMove(frameLoadRequest));
1640 }
1641
1642 void WebPage::loadData(LoadParameters&& loadParameters)
1643 {
1644     platformDidReceiveLoadParameters(loadParameters);
1645
1646     auto sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(loadParameters.data.data()), loadParameters.data.size());
1647     URL baseURL = loadParameters.baseURLString.isEmpty() ? aboutBlankURL() : URL(URL(), loadParameters.baseURLString);
1648     loadDataImpl(loadParameters.navigationID, loadParameters.shouldTreatAsContinuingLoad, WTFMove(loadParameters.websitePolicies), WTFMove(sharedBuffer), loadParameters.MIMEType, loadParameters.encodingName, baseURL, URL(), loadParameters.userData, loadParameters.isNavigatingToAppBoundDomain, loadParameters.shouldOpenExternalURLsPolicy);
1649 }
1650
1651 void WebPage::loadAlternateHTML(LoadParameters&& loadParameters)
1652 {
1653     platformDidReceiveLoadParameters(loadParameters);
1654
1655     URL baseURL = loadParameters.baseURLString.isEmpty() ? aboutBlankURL() : URL(URL(), loadParameters.baseURLString);
1656     URL unreachableURL = loadParameters.unreachableURLString.isEmpty() ? URL() : URL(URL(), loadParameters.unreachableURLString);
1657     URL provisionalLoadErrorURL = loadParameters.provisionalLoadErrorURLString.isEmpty() ? URL() : URL(URL(), loadParameters.provisionalLoadErrorURLString);
1658     auto sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(loadParameters.data.data()), loadParameters.data.size());
1659     m_mainFrame->coreFrame()->loader().setProvisionalLoadErrorBeingHandledURL(provisionalLoadErrorURL);    
1660     loadDataImpl(loadParameters.navigationID, loadParameters.shouldTreatAsContinuingLoad, WTFMove(loadParameters.websitePolicies), WTFMove(sharedBuffer), loadParameters.MIMEType, loadParameters.encodingName, baseURL, unreachableURL, loadParameters.userData, loadParameters.isNavigatingToAppBoundDomain);
1661     m_mainFrame->coreFrame()->loader().setProvisionalLoadErrorBeingHandledURL({ });
1662 }
1663
1664 void WebPage::navigateToPDFLinkWithSimulatedClick(const String& url, IntPoint documentPoint, IntPoint screenPoint)
1665 {
1666     Frame* mainFrame = m_mainFrame->coreFrame();
1667     Document* mainFrameDocument = mainFrame->document();
1668     if (!mainFrameDocument)
1669         return;
1670
1671     const int singleClick = 1;
1672     // FIXME: Set modifier keys.
1673     // FIXME: This should probably set IsSimulated::Yes.
1674     auto mouseEvent = MouseEvent::create(eventNames().clickEvent, Event::CanBubble::Yes, Event::IsCancelable::Yes, Event::IsComposed::Yes,
1675         MonotonicTime::now(), nullptr, singleClick, screenPoint, documentPoint, { }, { }, 0, 0, nullptr, 0, WebCore::NoTap);
1676
1677     mainFrame->loader().changeLocation(mainFrameDocument->completeURL(url), emptyString(), mouseEvent.ptr(), LockHistory::No, LockBackForwardList::No, ReferrerPolicy::NoReferrer, ShouldOpenExternalURLsPolicy::ShouldNotAllow);
1678 }
1679
1680 void WebPage::stopLoadingFrame(FrameIdentifier frameID)
1681 {
1682     WebFrame* frame = WebProcess::singleton().webFrame(frameID);
1683     if (!frame)
1684         return;
1685
1686     corePage()->userInputBridge().stopLoadingFrame(frame->coreFrame());
1687 }
1688
1689 void WebPage::stopLoading()
1690 {
1691     SendStopResponsivenessTimer stopper;
1692
1693     corePage()->userInputBridge().stopLoadingFrame(m_mainFrame->coreFrame());
1694 }
1695
1696 bool WebPage::defersLoading() const
1697 {
1698     return m_page->defersLoading();
1699 }
1700
1701 void WebPage::setDefersLoading(bool defersLoading)
1702 {
1703     m_page->setDefersLoading(defersLoading);
1704 }
1705
1706 void WebPage::reload(uint64_t navigationID, uint32_t reloadOptions, SandboxExtension::Handle&& sandboxExtensionHandle)
1707 {
1708     SendStopResponsivenessTimer stopper;
1709
1710     ASSERT(!m_mainFrame->coreFrame()->loader().frameHasLoaded() || !m_pendingNavigationID);
1711     m_pendingNavigationID = navigationID;
1712
1713     m_sandboxExtensionTracker.beginReload(m_mainFrame.ptr(), WTFMove(sandboxExtensionHandle));
1714     corePage()->userInputBridge().reloadFrame(m_mainFrame->coreFrame(), OptionSet<ReloadOption>::fromRaw(reloadOptions));
1715
1716     if (m_pendingNavigationID) {
1717         // This can happen if FrameLoader::reload() returns early because the document URL is empty.
1718         // The reload does nothing so we need to reset the pending navigation. See webkit.org/b/153210.
1719         m_pendingNavigationID = 0;
1720     }
1721 }
1722
1723 void WebPage::goToBackForwardItem(uint64_t navigationID, const BackForwardItemIdentifier& backForwardItemID, FrameLoadType backForwardType, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
1724 {
1725     SendStopResponsivenessTimer stopper;
1726
1727     ASSERT(isBackForwardLoadType(backForwardType));
1728
1729     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
1730     ASSERT(item);
1731     if (!item)
1732         return;
1733
1734     LOG(Loading, "In WebProcess pid %i, WebPage %" PRIu64 " is navigating to back/forward URL %s", getCurrentProcessID(), m_identifier.toUInt64(), item->url().string().utf8().data());
1735
1736     ASSERT(!m_pendingNavigationID);
1737     m_pendingNavigationID = navigationID;
1738     m_pendingWebsitePolicies = WTFMove(websitePolicies);
1739
1740     m_page->goToItem(*item, backForwardType, shouldTreatAsContinuingLoad);
1741 }
1742
1743 void WebPage::tryRestoreScrollPosition()
1744 {
1745     m_page->mainFrame().loader().history().restoreScrollPositionAndViewState();
1746 }
1747
1748 WebPage& WebPage::fromCorePage(Page& page)
1749 {
1750     return static_cast<WebChromeClient&>(page.chrome().client()).page();
1751 }
1752
1753 static Optional<FrameTreeNodeData> frameTreeNodeData(Frame& frame)
1754 {
1755     Optional<FrameTreeNodeData> info;
1756     if (auto* webFrame = WebFrame::fromCoreFrame(frame)) {
1757         Vector<FrameTreeNodeData> children;
1758         for (auto* childFrame = frame.tree().firstChild(); childFrame; childFrame = childFrame->tree().nextSibling()) {
1759             if (auto childInfo = frameTreeNodeData(*childFrame))
1760                 children.append(WTFMove(*childInfo));
1761         }
1762         info = FrameTreeNodeData {
1763             webFrame->info(),
1764             WTFMove(children)
1765         };
1766     }
1767     return info;
1768 }
1769
1770 void WebPage::getAllFrames(CompletionHandler<void(FrameTreeNodeData&&)>&& completionHandler)
1771 {
1772     completionHandler(*frameTreeNodeData(m_page->mainFrame()));
1773 }
1774
1775 void WebPage::setSize(const WebCore::IntSize& viewSize)
1776 {
1777     if (m_viewSize == viewSize)
1778         return;
1779
1780     m_viewSize = viewSize;
1781     FrameView* view = m_page->mainFrame().view();
1782     view->resize(viewSize);
1783     m_drawingArea->setNeedsDisplay();
1784
1785 #if USE(COORDINATED_GRAPHICS)
1786     if (view->useFixedLayout())
1787         sendViewportAttributesChanged(m_page->viewportArguments());
1788 #endif
1789 }
1790
1791 #if USE(COORDINATED_GRAPHICS)
1792 void WebPage::sendViewportAttributesChanged(const ViewportArguments& viewportArguments)
1793 {
1794     FrameView* view = m_page->mainFrame().view();
1795     ASSERT(view && view->useFixedLayout());
1796
1797     // Viewport properties have no impact on zero sized fixed viewports.
1798     if (m_viewSize.isEmpty())
1799         return;
1800
1801     // Recalculate the recommended layout size, when the available size (device pixel) changes.
1802     Settings& settings = m_page->settings();
1803
1804     int minimumLayoutFallbackWidth = std::max(settings.layoutFallbackWidth(), m_viewSize.width());
1805
1806     // If unset  we use the viewport dimensions. This fits with the behavior of desktop browsers.
1807     int deviceWidth = (settings.deviceWidth() > 0) ? settings.deviceWidth() : m_viewSize.width();
1808     int deviceHeight = (settings.deviceHeight() > 0) ? settings.deviceHeight() : m_viewSize.height();
1809
1810     ViewportAttributes attr = computeViewportAttributes(viewportArguments, minimumLayoutFallbackWidth, deviceWidth, deviceHeight, 1, m_viewSize);
1811
1812     // If no layout was done yet set contentFixedOrigin to (0,0).
1813     IntPoint contentFixedOrigin = view->didFirstLayout() ? view->fixedVisibleContentRect().location() : IntPoint();
1814
1815     // Put the width and height to the viewport width and height. In css units however.
1816     // Use FloatSize to avoid truncated values during scale.
1817     FloatSize contentFixedSize = m_viewSize;
1818
1819     contentFixedSize.scale(1 / attr.initialScale);
1820     view->setFixedVisibleContentRect(IntRect(contentFixedOrigin, roundedIntSize(contentFixedSize)));
1821
1822     attr.initialScale = m_page->viewportArguments().zoom; // Resets auto (-1) if no value was set by user.
1823
1824     // This also takes care of the relayout.
1825     setFixedLayoutSize(roundedIntSize(attr.layoutSize));
1826
1827 #if USE(COORDINATED_GRAPHICS)
1828     m_drawingArea->didChangeViewportAttributes(WTFMove(attr));
1829 #else
1830     send(Messages::WebPageProxy::DidChangeViewportProperties(attr));
1831 #endif
1832 }
1833 #endif
1834
1835 void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset)
1836 {
1837     FrameView* frameView = m_page->mainFrame().view();
1838
1839     ScrollPosition scrollPosition = frameView->scrollPosition();
1840     ScrollPosition maximumScrollPosition = frameView->maximumScrollPosition();
1841
1842     // If the current scroll position in a direction is the max scroll position 
1843     // we don't want to scroll at all.
1844     IntSize newScrollOffset;
1845     if (scrollPosition.x() < maximumScrollPosition.x())
1846         newScrollOffset.setWidth(scrollOffset.width());
1847     if (scrollPosition.y() < maximumScrollPosition.y())
1848         newScrollOffset.setHeight(scrollOffset.height());
1849
1850     if (newScrollOffset.isZero())
1851         return;
1852
1853     frameView->setScrollPosition(frameView->scrollPosition() + newScrollOffset);
1854 }
1855
1856 void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
1857 {
1858 #if PLATFORM(MAC)
1859     FrameView* mainFrameView = m_page->mainFrame().view();
1860     LocalDefaultSystemAppearance localAppearance(mainFrameView ? mainFrameView->useDarkAppearance() : false);
1861 #endif
1862
1863     GraphicsContextStateSaver stateSaver(graphicsContext);
1864     graphicsContext.clip(rect);
1865
1866     m_mainFrame->coreFrame()->view()->paint(graphicsContext, rect);
1867
1868 #if PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(PLAYSTATION)
1869     if (!m_page->settings().acceleratedCompositingEnabled() && m_page->inspectorController().enabled() && m_page->inspectorController().shouldShowOverlay()) {
1870         graphicsContext.beginTransparencyLayer(1);
1871         m_page->inspectorController().drawHighlight(graphicsContext);
1872         graphicsContext.endTransparencyLayer();
1873     }
1874 #endif
1875 }
1876
1877 double WebPage::textZoomFactor() const
1878 {
1879     PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
1880     if (pluginView && pluginView->requiresUnifiedScaleFactor()) {
1881         if (pluginView->handlesPageScaleFactor())
1882             return pluginView->pageScaleFactor();
1883         return pageScaleFactor();
1884     }
1885
1886     Frame* frame = m_mainFrame->coreFrame();
1887     if (!frame)
1888         return 1;
1889     return frame->textZoomFactor();
1890 }
1891
1892 void WebPage::setTextZoomFactor(double zoomFactor)
1893 {
1894     PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
1895     if (pluginView && pluginView->requiresUnifiedScaleFactor()) {
1896         if (pluginView->handlesPageScaleFactor())
1897             pluginView->setPageScaleFactor(zoomFactor, IntPoint());
1898         else
1899             scalePage(zoomFactor, IntPoint());
1900         return;
1901     }
1902
1903     Frame* frame = m_mainFrame->coreFrame();
1904     if (!frame)
1905         return;
1906     frame->setTextZoomFactor(static_cast<float>(zoomFactor));
1907 }
1908
1909 double WebPage::pageZoomFactor() const
1910 {
1911     PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
1912     if (pluginView && pluginView->requiresUnifiedScaleFactor()) {
1913         if (pluginView->handlesPageScaleFactor())
1914             return pluginView->pageScaleFactor();
1915         return pageScaleFactor();
1916     }
1917
1918     Frame* frame = m_mainFrame->coreFrame();
1919     if (!frame)
1920         return 1;
1921     return frame->pageZoomFactor();
1922 }
1923
1924 void WebPage::setPageZoomFactor(double zoomFactor)
1925 {
1926     PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
1927     if (pluginView && pluginView->requiresUnifiedScaleFactor()) {
1928         if (pluginView->handlesPageScaleFactor())
1929             pluginView->setPageScaleFactor(zoomFactor, IntPoint());
1930         else
1931             scalePage(zoomFactor, IntPoint());
1932         return;
1933     }
1934
1935     Frame* frame = m_mainFrame->coreFrame();
1936     if (!frame)
1937         return;
1938     frame->setPageZoomFactor(static_cast<float>(zoomFactor));
1939 }
1940
1941 static void dumpHistoryItem(HistoryItem& item, size_t indent, bool isCurrentItem, StringBuilder& stringBuilder, const String& directoryName)
1942 {
1943     if (isCurrentItem)
1944         stringBuilder.appendLiteral("curr->  ");
1945     else {
1946         for (size_t i = 0; i < indent; ++i)
1947             stringBuilder.append(' ');
1948     }
1949
1950     auto url = item.url();
1951     if (url.protocolIs("file")) {
1952         size_t start = url.string().find(directoryName);
1953         if (start == WTF::notFound)
1954             start = 0;
1955         else
1956             start += directoryName.length();
1957         stringBuilder.appendLiteral("(file test):");
1958         stringBuilder.append(url.string().substring(start));
1959     } else
1960         stringBuilder.append(url.string());
1961     
1962     auto& target = item.target();
1963     if (target.length()) {
1964         stringBuilder.appendLiteral(" (in frame \"");
1965         stringBuilder.append(target);
1966         stringBuilder.appendLiteral("\")");
1967     }
1968     
1969     if (item.isTargetItem())
1970         stringBuilder.appendLiteral("  **nav target**");
1971     
1972     stringBuilder.append('\n');
1973     
1974     Vector<Ref<HistoryItem>> children;
1975     children.reserveInitialCapacity(item.children().size());
1976     for (auto& child : item.children())
1977         children.uncheckedAppend(child.copyRef());
1978     std::stable_sort(children.begin(), children.end(), [] (auto& a, auto& b) {
1979         return codePointCompare(a->target(), b->target()) < 0;
1980     });
1981     for (auto& child : children)
1982         dumpHistoryItem(child, indent + 4, false, stringBuilder, directoryName);
1983 }
1984
1985 String WebPage::dumpHistoryForTesting(const String& directory)
1986 {
1987     if (!m_page)
1988         return { };
1989
1990     auto& list = m_page->backForward();
1991     
1992     StringBuilder builder;
1993     int begin = -list.backCount();
1994     if (list.itemAtIndex(begin)->url() == aboutBlankURL())
1995         ++begin;
1996     for (int i = begin; i <= static_cast<int>(list.forwardCount()); ++i)
1997         dumpHistoryItem(*list.itemAtIndex(i), 8, !i, builder, directory);
1998     return builder.toString();
1999 }
2000
2001 void WebPage::clearHistory()
2002 {
2003     if (!m_page)
2004         return;
2005
2006     static_cast<WebBackForwardListProxy&>(m_page->backForward().client()).clear();
2007 }
2008
2009 void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor)
2010 {
2011     PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
2012     if (pluginView && pluginView->requiresUnifiedScaleFactor()) {
2013         if (pluginView->handlesPageScaleFactor())
2014             pluginView->setPageScaleFactor(pageZoomFactor, IntPoint());
2015         else
2016             scalePage(pageZoomFactor, IntPoint());
2017         return;
2018     }
2019
2020     Frame* frame = m_mainFrame->coreFrame();
2021     if (!frame)
2022         return;
2023     return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor));
2024 }
2025
2026 void WebPage::windowScreenDidChange(PlatformDisplayID displayID, Optional<unsigned> nominalFramesPerSecond)
2027 {
2028     m_page->chrome().windowScreenDidChange(displayID, nominalFramesPerSecond);
2029
2030 #if PLATFORM(MAC)
2031     WebProcess::singleton().updatePageScreenProperties();
2032 #endif
2033 }
2034
2035 void WebPage::scalePage(double scale, const IntPoint& origin)
2036 {
2037     double totalScale = scale * viewScaleFactor();
2038     bool willChangeScaleFactor = totalScale != totalScaleFactor();
2039
2040 #if PLATFORM(IOS_FAMILY)
2041     if (willChangeScaleFactor) {
2042         if (!m_inDynamicSizeUpdate)
2043             m_dynamicSizeUpdateHistory.clear();
2044         m_scaleWasSetByUIProcess = false;
2045     }
2046 #endif
2047     PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
2048     if (pluginView && pluginView->handlesPageScaleFactor()) {
2049         // If the main-frame plugin wants to handle the page scale factor, make sure to reset WebCore's page scale.
2050         // Otherwise, we can end up with an immutable but non-1 page scale applied by WebCore on top of whatever the plugin does.
2051         if (m_page->pageScaleFactor() != 1) {
2052             m_page->setPageScaleFactor(1, origin);
2053             for (auto* pluginView : m_pluginViews)
2054                 pluginView->pageScaleFactorDidChange();
2055         }
2056
2057         pluginView->setPageScaleFactor(totalScale, origin);
2058         return;
2059     }
2060
2061     m_page->setPageScaleFactor(totalScale, origin);
2062
2063     // We can't early return before setPageScaleFactor because the origin might be different.
2064     if (!willChangeScaleFactor)
2065         return;
2066
2067     for (auto* pluginView : m_pluginViews)
2068         pluginView->pageScaleFactorDidChange();
2069
2070 #if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER)
2071     m_drawingArea->deviceOrPageScaleFactorChanged();
2072 #endif
2073
2074     send(Messages::WebPageProxy::PageScaleFactorDidChange(scale));
2075     platformDidScalePage();
2076 }
2077
2078 #if !PLATFORM(IOS_FAMILY)
2079
2080 void WebPage::platformDidScalePage()
2081 {
2082 }
2083
2084 #endif
2085
2086 void WebPage::scalePageInViewCoordinates(double scale, IntPoint centerInViewCoordinates)
2087 {
2088     double totalScale = scale * viewScaleFactor();
2089     if (totalScale == totalScaleFactor())
2090         return;
2091
2092     IntPoint scrollPositionAtNewScale = mainFrameView()->rootViewToContents(-centerInViewCoordinates);
2093     double scaleRatio = scale / pageScaleFactor();
2094     scrollPositionAtNewScale.scale(scaleRatio);
2095     scalePage(scale, scrollPositionAtNewScale);
2096 }
2097
2098 double WebPage::totalScaleFactor() const
2099 {
2100     PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame());
2101     if (pluginView && pluginView->handlesPageScaleFactor())
2102         return pluginView->pageScaleFactor();
2103
2104     return m_page->pageScaleFactor();
2105 }
2106
2107 double WebPage::pageScaleFactor() const
2108 {
2109     return totalScaleFactor() / viewScaleFactor();
2110 }
2111
2112 double WebPage::viewScaleFactor() const
2113 {
2114     return m_page->viewScaleFactor();
2115 }
2116
2117 void WebPage::scaleView(double scale)
2118 {
2119     if (viewScaleFactor() == scale)
2120         return;
2121
2122     float pageScale = pageScaleFactor();
2123
2124     IntPoint scrollPositionAtNewScale;
2125     if (FrameView* mainFrameView = m_page->mainFrame().view()) {
2126         double scaleRatio = scale / viewScaleFactor();
2127         scrollPositionAtNewScale = mainFrameView->scrollPosition();
2128         scrollPositionAtNewScale.scale(scaleRatio);
2129     }
2130
2131     m_page->setViewScaleFactor(scale);
2132     scalePage(pageScale, scrollPositionAtNewScale);
2133 }
2134
2135 void WebPage::setDeviceScaleFactor(float scaleFactor)
2136 {
2137     if (scaleFactor == m_page->deviceScaleFactor())
2138         return;
2139
2140     m_page->setDeviceScaleFactor(scaleFactor);
2141
2142     // Tell all our plug-in views that the device scale factor changed.
2143 #if PLATFORM(MAC)
2144     for (auto* pluginView : m_pluginViews)
2145         pluginView->setDeviceScaleFactor(scaleFactor);
2146
2147     updateHeaderAndFooterLayersForDeviceScaleChange(scaleFactor);
2148 #endif
2149
2150     if (findController().isShowingOverlay()) {
2151         // We must have updated layout to get the selection rects right.
2152         layoutIfNeeded();
2153         findController().deviceScaleFactorDidChange();
2154     }
2155
2156 #if USE(COORDINATED_GRAPHICS) || USE(TEXTURE_MAPPER)
2157     m_drawingArea->deviceOrPageScaleFactorChanged();
2158 #endif
2159 }
2160
2161 float WebPage::deviceScaleFactor() const
2162 {
2163     return m_page->deviceScaleFactor();
2164 }
2165
2166 void WebPage::accessibilitySettingsDidChange()
2167 {
2168     m_page->accessibilitySettingsDidChange();
2169 }
2170
2171 void WebPage::screenPropertiesDidChange()
2172 {
2173     m_page->screenPropertiesDidChange();
2174 }
2175
2176 void WebPage::setUseFixedLayout(bool fixed)
2177 {
2178     // Do not overwrite current settings if initially setting it to false.
2179     if (m_useFixedLayout == fixed)
2180         return;
2181     m_useFixedLayout = fixed;
2182
2183 #if !PLATFORM(IOS_FAMILY)
2184     m_page->settings().setFixedElementsLayoutRelativeToFrame(fixed);
2185 #endif
2186
2187     FrameView* view = mainFrameView();
2188     if (!view)
2189         return;
2190
2191     view->setUseFixedLayout(fixed);
2192     if (!fixed)
2193         setFixedLayoutSize(IntSize());
2194
2195     send(Messages::WebPageProxy::UseFixedLayoutDidChange(fixed));
2196 }
2197
2198 bool WebPage::setFixedLayoutSize(const IntSize& size)
2199 {
2200     FrameView* view = mainFrameView();
2201     if (!view || view->fixedLayoutSize() == size)
2202         return false;
2203
2204     LOG_WITH_STREAM(VisibleRects, stream << "WebPage " << m_identifier.toUInt64() << " setFixedLayoutSize " << size);
2205     view->setFixedLayoutSize(size);
2206
2207     send(Messages::WebPageProxy::FixedLayoutSizeDidChange(size));
2208     return true;
2209 }
2210
2211 IntSize WebPage::fixedLayoutSize() const
2212 {
2213     FrameView* view = mainFrameView();
2214     if (!view)
2215         return IntSize();
2216     return view->fixedLayoutSize();
2217 }
2218
2219 void WebPage::disabledAdaptationsDidChange(const OptionSet<DisabledAdaptations>& disabledAdaptations)
2220 {
2221 #if PLATFORM(IOS_FAMILY)
2222     if (m_viewportConfiguration.setDisabledAdaptations(disabledAdaptations))
2223         viewportConfigurationChanged();
2224 #else
2225     UNUSED_PARAM(disabledAdaptations);
2226 #endif
2227 }
2228
2229 void WebPage::viewportPropertiesDidChange(const ViewportArguments& viewportArguments)
2230 {
2231 #if PLATFORM(IOS_FAMILY)
2232     if (m_viewportConfiguration.setViewportArguments(viewportArguments))
2233         viewportConfigurationChanged();
2234 #endif
2235
2236 #if USE(COORDINATED_GRAPHICS)
2237     FrameView* view = m_page->mainFrame().view();
2238     if (view && view->useFixedLayout())
2239         sendViewportAttributesChanged(viewportArguments);
2240     else
2241         m_drawingArea->didChangeViewportAttributes(ViewportAttributes());
2242 #endif
2243
2244 #if !PLATFORM(IOS_FAMILY) && !USE(COORDINATED_GRAPHICS)
2245     UNUSED_PARAM(viewportArguments);
2246 #endif
2247 }
2248
2249 void WebPage::listenForLayoutMilestones(OptionSet<WebCore::LayoutMilestone> milestones)
2250 {
2251     if (!m_page)
2252         return;
2253     m_page->addLayoutMilestones(milestones);
2254 }
2255
2256 void WebPage::setSuppressScrollbarAnimations(bool suppressAnimations)
2257 {
2258     m_page->setShouldSuppressScrollbarAnimations(suppressAnimations);
2259 }
2260     
2261 void WebPage::setEnableVerticalRubberBanding(bool enableVerticalRubberBanding)
2262 {
2263     m_page->setVerticalScrollElasticity(enableVerticalRubberBanding ? ScrollElasticityAllowed : ScrollElasticityNone);
2264 }
2265     
2266 void WebPage::setEnableHorizontalRubberBanding(bool enableHorizontalRubberBanding)
2267 {
2268     m_page->setHorizontalScrollElasticity(enableHorizontalRubberBanding ? ScrollElasticityAllowed : ScrollElasticityNone);
2269 }
2270
2271 void WebPage::setBackgroundExtendsBeyondPage(bool backgroundExtendsBeyondPage)
2272 {
2273     if (m_page->settings().backgroundShouldExtendBeyondPage() != backgroundExtendsBeyondPage)
2274         m_page->settings().setBackgroundShouldExtendBeyondPage(backgroundExtendsBeyondPage);
2275 }
2276
2277 void WebPage::setPaginationMode(uint32_t mode)
2278 {
2279     Pagination pagination = m_page->pagination();
2280     pagination.mode = static_cast<Pagination::Mode>(mode);
2281     m_page->setPagination(pagination);
2282 }
2283
2284 void WebPage::setPaginationBehavesLikeColumns(bool behavesLikeColumns)
2285 {
2286     Pagination pagination = m_page->pagination();
2287     pagination.behavesLikeColumns = behavesLikeColumns;
2288     m_page->setPagination(pagination);
2289 }
2290
2291 void WebPage::setPageLength(double pageLength)
2292 {
2293     Pagination pagination = m_page->pagination();
2294     pagination.pageLength = pageLength;
2295     m_page->setPagination(pagination);
2296 }
2297
2298 void WebPage::setGapBetweenPages(double gap)
2299 {
2300     Pagination pagination = m_page->pagination();
2301     pagination.gap = gap;
2302     m_page->setPagination(pagination);
2303 }
2304
2305 void WebPage::setPaginationLineGridEnabled(bool lineGridEnabled)
2306 {
2307     m_page->setPaginationLineGridEnabled(lineGridEnabled);
2308 }
2309
2310 void WebPage::postInjectedBundleMessage(const String& messageName, const UserData& userData)
2311 {
2312     auto& webProcess = WebProcess::singleton();
2313     InjectedBundle* injectedBundle = webProcess.injectedBundle();
2314     if (!injectedBundle)
2315         return;
2316
2317     injectedBundle->didReceiveMessageToPage(this, messageName, webProcess.transformHandlesToObjects(userData.object()).get());
2318 }
2319
2320 #if !PLATFORM(IOS_FAMILY)
2321
2322 void WebPage::setHeaderPageBanner(PageBanner* pageBanner)
2323 {
2324     if (m_headerBanner)
2325         m_headerBanner->detachFromPage();
2326
2327     m_headerBanner = pageBanner;
2328
2329     if (m_headerBanner)
2330         m_headerBanner->addToPage(PageBanner::Header, this);
2331 }
2332
2333 PageBanner* WebPage::headerPageBanner()
2334 {
2335     return m_headerBanner.get();
2336 }
2337
2338 void WebPage::setFooterPageBanner(PageBanner* pageBanner)
2339 {
2340     if (m_footerBanner)
2341         m_footerBanner->detachFromPage();
2342
2343     m_footerBanner = pageBanner;
2344
2345     if (m_footerBanner)
2346         m_footerBanner->addToPage(PageBanner::Footer, this);
2347 }
2348
2349 PageBanner* WebPage::footerPageBanner()
2350 {
2351     return m_footerBanner.get();
2352 }
2353
2354 void WebPage::hidePageBanners()
2355 {
2356     if (m_headerBanner)
2357         m_headerBanner->hide();
2358     if (m_footerBanner)
2359         m_footerBanner->hide();
2360 }
2361
2362 void WebPage::showPageBanners()
2363 {
2364     if (m_headerBanner)
2365         m_headerBanner->showIfHidden();
2366     if (m_footerBanner)
2367         m_footerBanner->showIfHidden();
2368 }
2369
2370 void WebPage::setHeaderBannerHeightForTesting(int height)
2371 {
2372     corePage()->setHeaderHeight(height);
2373 }
2374
2375 void WebPage::setFooterBannerHeightForTesting(int height)
2376 {
2377     corePage()->setFooterHeight(height);
2378 }
2379
2380 #endif // !PLATFORM(IOS_FAMILY)
2381
2382 void WebPage::takeSnapshot(IntRect snapshotRect, IntSize bitmapSize, uint32_t options, CallbackID callbackID)
2383 {
2384     SnapshotOptions snapshotOptions = static_cast<SnapshotOptions>(options);
2385     snapshotOptions |= SnapshotOptionsShareable;
2386
2387     RefPtr<WebImage> image = snapshotAtSize(snapshotRect, bitmapSize, snapshotOptions);
2388
2389     ShareableBitmap::Handle handle;
2390     if (image)
2391         image->bitmap().createHandle(handle, SharedMemory::Protection::ReadOnly);
2392
2393     send(Messages::WebPageProxy::ImageCallback(handle, callbackID));
2394 }
2395
2396 RefPtr<WebImage> WebPage::scaledSnapshotWithOptions(const IntRect& rect, double additionalScaleFactor, SnapshotOptions options)
2397 {
2398     IntRect snapshotRect = rect;
2399     IntSize bitmapSize = snapshotRect.size();
2400     if (options & SnapshotOptionsPrinting) {
2401         ASSERT(additionalScaleFactor == 1);
2402         Frame* coreFrame = m_mainFrame->coreFrame();
2403         if (!coreFrame)
2404             return nullptr;
2405         bitmapSize.setHeight(PrintContext::numberOfPages(*coreFrame, bitmapSize) * (bitmapSize.height() + 1) - 1);
2406     } else {
2407         double scaleFactor = additionalScaleFactor;
2408         if (!(options & SnapshotOptionsExcludeDeviceScaleFactor))
2409             scaleFactor *= corePage()->deviceScaleFactor();
2410         bitmapSize.scale(scaleFactor);
2411     }
2412
2413     return snapshotAtSize(rect, bitmapSize, options);
2414 }
2415
2416 void WebPage::paintSnapshotAtSize(const IntRect& rect, const IntSize& bitmapSize, SnapshotOptions options, Frame& frame, FrameView& frameView, GraphicsContext& graphicsContext)
2417 {
2418     IntRect snapshotRect = rect;
2419     float horizontalScaleFactor = static_cast<float>(bitmapSize.width()) / rect.width();
2420     float verticalScaleFactor = static_cast<float>(bitmapSize.height()) / rect.height();
2421     float scaleFactor = std::max(horizontalScaleFactor, verticalScaleFactor);
2422
2423     if (options & SnapshotOptionsPrinting) {
2424         PrintContext::spoolAllPagesWithBoundaries(frame, graphicsContext, snapshotRect.size());
2425         return;
2426     }
2427
2428     Color documentBackgroundColor = frameView.documentBackgroundColor();
2429     Color backgroundColor = (frame.settings().backgroundShouldExtendBeyondPage() && documentBackgroundColor.isValid()) ? documentBackgroundColor : frameView.baseBackgroundColor();
2430     graphicsContext.fillRect(IntRect(IntPoint(), bitmapSize), backgroundColor);
2431
2432     if (!(options & SnapshotOptionsExcludeDeviceScaleFactor)) {
2433         double deviceScaleFactor = frame.page()->deviceScaleFactor();
2434         graphicsContext.applyDeviceScaleFactor(deviceScaleFactor);
2435         scaleFactor /= deviceScaleFactor;
2436     }
2437
2438     graphicsContext.scale(scaleFactor);
2439     graphicsContext.translate(-snapshotRect.location());
2440
2441     FrameView::SelectionInSnapshot shouldPaintSelection = FrameView::IncludeSelection;
2442     if (options & SnapshotOptionsExcludeSelectionHighlighting)
2443         shouldPaintSelection = FrameView::ExcludeSelection;
2444
2445     FrameView::CoordinateSpaceForSnapshot coordinateSpace = FrameView::DocumentCoordinates;
2446     if (options & SnapshotOptionsInViewCoordinates)
2447         coordinateSpace = FrameView::ViewCoordinates;
2448
2449     frameView.paintContentsForSnapshot(graphicsContext, snapshotRect, shouldPaintSelection, coordinateSpace);
2450
2451     if (options & SnapshotOptionsPaintSelectionRectangle) {
2452         FloatRect selectionRectangle = frame.selection().selectionBounds();
2453         graphicsContext.setStrokeColor(Color::red);
2454         graphicsContext.strokeRect(selectionRectangle, 1);
2455     }
2456 }
2457
2458 static ShareableBitmap::Configuration snapshotOptionsToBitmapConfiguration(SnapshotOptions options, WebPage& page)
2459 {
2460     ShareableBitmap::Configuration configuration;
2461 #if USE(CG)
2462     if (options & SnapshotOptionsUseScreenColorSpace)
2463         configuration.colorSpace.cgColorSpace = screenColorSpace(page.corePage()->mainFrame().view());
2464 #endif
2465     return configuration;
2466 }
2467
2468 RefPtr<WebImage> WebPage::snapshotAtSize(const IntRect& rect, const IntSize& bitmapSize, SnapshotOptions options)
2469 {
2470     Frame* coreFrame = m_mainFrame->coreFrame();
2471     if (!coreFrame)
2472         return nullptr;
2473
2474     FrameView* frameView = coreFrame->view();
2475     if (!frameView)
2476         return nullptr;
2477
2478     auto snapshot = WebImage::create(bitmapSize, snapshotOptionsToImageOptions(options), snapshotOptionsToBitmapConfiguration(options, *this));
2479     if (!snapshot)
2480         return nullptr;
2481     auto graphicsContext = snapshot->bitmap().createGraphicsContext();
2482     if (!graphicsContext)
2483         return nullptr;
2484
2485     paintSnapshotAtSize(rect, bitmapSize, options, *coreFrame, *frameView, *graphicsContext);
2486
2487     return snapshot;
2488 }
2489
2490 RefPtr<WebImage> WebPage::snapshotNode(WebCore::Node& node, SnapshotOptions options, unsigned maximumPixelCount)
2491 {
2492     Frame* coreFrame = m_mainFrame->coreFrame();
2493     if (!coreFrame)
2494         return nullptr;
2495
2496     FrameView* frameView = coreFrame->view();
2497     if (!frameView)
2498         return nullptr;
2499
2500     if (!node.renderer())
2501         return nullptr;
2502
2503     LayoutRect topLevelRect;
2504     IntRect snapshotRect = snappedIntRect(node.renderer()->paintingRootRect(topLevelRect));
2505     if (snapshotRect.isEmpty())
2506         return nullptr;
2507
2508     double scaleFactor = 1;
2509     IntSize snapshotSize = snapshotRect.size();
2510     unsigned maximumHeight = maximumPixelCount / snapshotSize.width();
2511     if (maximumHeight < static_cast<unsigned>(snapshotSize.height())) {
2512         scaleFactor = static_cast<double>(maximumHeight) / snapshotSize.height();
2513         snapshotSize = IntSize(snapshotSize.width() * scaleFactor, maximumHeight);
2514     }
2515
2516     auto snapshot = WebImage::create(snapshotSize, snapshotOptionsToImageOptions(options), snapshotOptionsToBitmapConfiguration(options, *this));
2517     if (!snapshot)
2518         return nullptr;
2519     auto graphicsContext = snapshot->bitmap().createGraphicsContext();
2520     if (!graphicsContext)
2521         return nullptr;
2522
2523     if (!(options & SnapshotOptionsExcludeDeviceScaleFactor)) {
2524         double deviceScaleFactor = corePage()->deviceScaleFactor();
2525         graphicsContext->applyDeviceScaleFactor(deviceScaleFactor);
2526         scaleFactor /= deviceScaleFactor;
2527     }
2528
2529     graphicsContext->scale(scaleFactor);
2530     graphicsContext->translate(-snapshotRect.location());
2531
2532     Color savedBackgroundColor = frameView->baseBackgroundColor();
2533     frameView->setBaseBackgroundColor(Color::transparentBlack);
2534     frameView->setNodeToDraw(&node);
2535
2536     frameView->paintContentsForSnapshot(*graphicsContext, snapshotRect, FrameView::ExcludeSelection, FrameView::DocumentCoordinates);
2537
2538     frameView->setBaseBackgroundColor(savedBackgroundColor);
2539     frameView->setNodeToDraw(nullptr);
2540
2541     return snapshot;
2542 }
2543
2544 void WebPage::pageDidScroll()
2545 {
2546 #if PLATFORM(IOS_FAMILY)
2547     if (!m_inDynamicSizeUpdate)
2548         m_dynamicSizeUpdateHistory.clear();
2549 #endif
2550     m_uiClient->pageDidScroll(this);
2551
2552     m_pageScrolledHysteresis.impulse();
2553
2554     send(Messages::WebPageProxy::PageDidScroll());
2555 }
2556
2557 void WebPage::pageStoppedScrolling()
2558 {
2559     // Maintain the current history item's scroll position up-to-date.
2560     if (Frame* frame = m_mainFrame->coreFrame())
2561         frame->loader().history().saveScrollPositionAndViewStateToItem(frame->loader().history().currentItem());
2562 }
2563
2564 #if ENABLE(CONTEXT_MENUS)
2565 WebContextMenu* WebPage::contextMenu()
2566 {
2567     if (!m_contextMenu)
2568         m_contextMenu = WebContextMenu::create(this);
2569     return m_contextMenu.get();
2570 }
2571
2572 WebContextMenu* WebPage::contextMenuAtPointInWindow(const IntPoint& point)
2573 {
2574     corePage()->contextMenuController().clearContextMenu();
2575
2576     // Simulate a mouse click to generate the correct menu.
2577     PlatformMouseEvent mousePressEvent(point, point, RightButton, PlatformEvent::MousePressed, 1, false, false, false, false, WallTime::now(), WebCore::ForceAtClick, WebCore::NoTap);
2578     corePage()->userInputBridge().handleMousePressEvent(mousePressEvent);
2579     bool handled = corePage()->userInputBridge().handleContextMenuEvent(mousePressEvent, corePage()->mainFrame());
2580     auto* menu = handled ? contextMenu() : nullptr;
2581     PlatformMouseEvent mouseReleaseEvent(point, point, RightButton, PlatformEvent::MouseReleased, 1, false, false, false, false, WallTime::now(), WebCore::ForceAtClick, WebCore::NoTap);
2582     corePage()->userInputBridge().handleMouseReleaseEvent(mouseReleaseEvent);
2583
2584     return menu;
2585 }
2586 #endif
2587
2588 // Events 
2589
2590 static const WebEvent* g_currentEvent = 0;
2591
2592 // FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to
2593 // WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct
2594 // platform events passed to the event handler code.
2595 const WebEvent* WebPage::currentEvent()
2596 {
2597     return g_currentEvent;
2598 }
2599
2600 void WebPage::freezeLayerTree(LayerTreeFreezeReason reason)
2601 {
2602     auto oldReasons = m_layerTreeFreezeReasons.toRaw();
2603     UNUSED_PARAM(oldReasons);
2604     m_layerTreeFreezeReasons.add(reason);
2605     RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "freezeLayerTree: Adding a reason to freeze layer tree (reason=%d, new=%d, old=%d)", static_cast<unsigned>(reason), m_layerTreeFreezeReasons.toRaw(), oldReasons);
2606     updateDrawingAreaLayerTreeFreezeState();
2607 }
2608
2609 void WebPage::unfreezeLayerTree(LayerTreeFreezeReason reason)
2610 {
2611     auto oldReasons = m_layerTreeFreezeReasons.toRaw();
2612     UNUSED_PARAM(oldReasons);
2613     m_layerTreeFreezeReasons.remove(reason);
2614     RELEASE_LOG_IF_ALLOWED(ProcessSuspension, "unfreezeLayerTree: Removing a reason to freeze layer tree (reason=%d, new=%d, old=%d)", static_cast<unsigned>(reason), m_layerTreeFreezeReasons.toRaw(), oldReasons);
2615     updateDrawingAreaLayerTreeFreezeState();
2616 }
2617
2618 void WebPage::updateDrawingAreaLayerTreeFreezeState()
2619 {
2620     if (!m_drawingArea)
2621         return;
2622     m_drawingArea->setLayerTreeStateIsFrozen(!!m_layerTreeFreezeReasons);
2623 }
2624
2625 void WebPage::callVolatilityCompletionHandlers(bool succeeded)
2626 {
2627     auto completionHandlers = std::exchange(m_markLayersAsVolatileCompletionHandlers, { });
2628     for (auto& completionHandler : completionHandlers)
2629         completionHandler(succeeded);
2630 }
2631
2632 void WebPage::layerVolatilityTimerFired()
2633 {
2634     Seconds newInterval = m_layerVolatilityTimer.repeatInterval() * 2.;
2635     bool didSucceed = markLayersVolatileImmediatelyIfPossible();
2636     if (didSucceed || newInterval > maximumLayerVolatilityTimerInterval) {
2637         m_layerVolatilityTimer.stop();
2638         if (didSucceed)
2639             RELEASE_LOG_IF_ALLOWED(Layers, "layerVolatilityTimerFired: Succeeded in marking layers as volatile");
2640         else
2641             RELEASE_LOG_IF_ALLOWED(Layers, "layerVolatilityTimerFired: Failed to mark layers as volatile within %gms", maximumLayerVolatilityTimerInterval.milliseconds());
2642         callVolatilityCompletionHandlers(didSucceed);
2643         return;
2644     }
2645
2646     RELEASE_LOG_ERROR_IF_ALLOWED(Layers, "layerVolatilityTimerFired: Failed to mark all layers as volatile, will retry in %g ms", newInterval.milliseconds());
2647     m_layerVolatilityTimer.startRepeating(newInterval);
2648 }
2649
2650 bool WebPage::markLayersVolatileImmediatelyIfPossible()
2651 {
2652     return !drawingArea() || drawingArea()->markLayersVolatileImmediatelyIfPossible();
2653 }
2654
2655 void WebPage::markLayersVolatile(CompletionHandler<void(bool)>&& completionHandler)
2656 {
2657     RELEASE_LOG_IF_ALLOWED(Layers, "markLayersVolatile:");
2658
2659     if (m_layerVolatilityTimer.isActive())
2660         m_layerVolatilityTimer.stop();
2661
2662     if (completionHandler)
2663         m_markLayersAsVolatileCompletionHandlers.append(WTFMove(completionHandler));
2664
2665     bool didSucceed = markLayersVolatileImmediatelyIfPossible();
2666     if (didSucceed || m_isSuspendedUnderLock) {
2667         if (didSucceed)
2668             RELEASE_LOG_IF_ALLOWED(Layers, "markLayersVolatile: Successfully marked layers as volatile");
2669         else {
2670             // If we get suspended when locking the screen, it is expected that some IOSurfaces cannot be marked as purgeable so we do not keep retrying.
2671             RELEASE_LOG_IF_ALLOWED(Layers, "markLayersVolatile: Did what we could to mark IOSurfaces as purgeable after locking the screen");
2672         }
2673         callVolatilityCompletionHandlers(didSucceed);
2674         return;
2675     }
2676
2677     RELEASE_LOG_IF_ALLOWED(Layers, "markLayersVolatile: Failed to mark all layers as volatile, will retry in %g ms", initialLayerVolatilityTimerInterval.milliseconds());
2678     m_layerVolatilityTimer.startRepeating(initialLayerVolatilityTimerInterval);
2679 }
2680
2681 void WebPage::cancelMarkLayersVolatile()
2682 {
2683     RELEASE_LOG_IF_ALLOWED(Layers, "cancelMarkLayersVolatile:");
2684     m_layerVolatilityTimer.stop();
2685     callVolatilityCompletionHandlers(false);
2686 }
2687
2688 class CurrentEvent {
2689 public:
2690     explicit CurrentEvent(const WebEvent& event)
2691         : m_previousCurrentEvent(g_currentEvent)
2692     {
2693         g_currentEvent = &event;
2694     }
2695
2696     ~CurrentEvent()
2697     {
2698         g_currentEvent = m_previousCurrentEvent;
2699     }
2700
2701 private:
2702     const WebEvent* m_previousCurrentEvent;
2703 };
2704
2705 #if ENABLE(CONTEXT_MENU_EVENT)
2706 static bool isContextClick(const PlatformMouseEvent& event)
2707 {
2708 #if USE(APPKIT)
2709     return WebEventFactory::shouldBeHandledAsContextClick(event);
2710 #else
2711     return event.button() == WebCore::RightButton;
2712 #endif
2713 }
2714
2715 static bool handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent, WebPage* page)
2716 {
2717     IntPoint point = page->corePage()->mainFrame().view()->windowToContents(platformMouseEvent.position());
2718     constexpr OptionSet<HitTestRequest::RequestType> hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::DisallowUserAgentShadowContent,  HitTestRequest::AllowChildFrameContent };
2719     HitTestResult result = page->corePage()->mainFrame().eventHandler().hitTestResultAtPoint(point, hitType);
2720
2721     Frame* frame = &page->corePage()->mainFrame();
2722     if (result.innerNonSharedNode())
2723         frame = result.innerNonSharedNode()->document().frame();
2724
2725     bool handled = page->corePage()->userInputBridge().handleContextMenuEvent(platformMouseEvent, *frame);
2726 #if ENABLE(CONTEXT_MENUS)
2727     if (handled)
2728         page->contextMenu()->show();
2729 #endif
2730     return handled;
2731 }
2732
2733 void WebPage::contextMenuForKeyEvent()
2734 {
2735 #if ENABLE(CONTEXT_MENUS)
2736     corePage()->contextMenuController().clearContextMenu();
2737 #endif
2738
2739     Frame& frame = m_page->focusController().focusedOrMainFrame();
2740     bool handled = frame.eventHandler().sendContextMenuEventForKey();
2741 #if ENABLE(CONTEXT_MENUS)
2742     if (handled)
2743         contextMenu()->show();
2744 #else
2745     UNUSED_PARAM(handled);
2746 #endif
2747 }
2748 #endif
2749
2750 static bool handleMouseEvent(const WebMouseEvent& mouseEvent, WebPage* page)
2751 {
2752     Frame& frame = page->corePage()->mainFrame();
2753     if (!frame.view())
2754         return false;
2755
2756     PlatformMouseEvent platformMouseEvent = platform(mouseEvent);
2757
2758     switch (platformMouseEvent.type()) {
2759         case PlatformEvent::MousePressed: {
2760 #if ENABLE(CONTEXT_MENUS)
2761             if (isContextClick(platformMouseEvent))
2762                 page->corePage()->contextMenuController().clearContextMenu();
2763 #endif
2764
2765             bool handled = page->corePage()->userInputBridge().handleMousePressEvent(platformMouseEvent);
2766 #if ENABLE(CONTEXT_MENU_EVENT)
2767             if (isContextClick(platformMouseEvent))
2768                 handled = handleContextMenuEvent(platformMouseEvent, page);
2769 #endif
2770             return handled;
2771         }
2772         case PlatformEvent::MouseReleased:
2773             return page->corePage()->userInputBridge().handleMouseReleaseEvent(platformMouseEvent);
2774
2775         case PlatformEvent::MouseMoved:
2776 #if PLATFORM(COCOA)
2777             // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse
2778             // button is currently pressed. It is possible that neither of those things will be true since on
2779             // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one
2780             // of those cases where the page is not active and the mouse is not pressed, then we can fire a more
2781             // efficient scrollbars-only version of the event.
2782             if (!(page->corePage()->focusController().isActive() || (mouseEvent.button() != WebMouseEvent::NoButton)))
2783                 return page->corePage()->userInputBridge().handleMouseMoveOnScrollbarEvent(platformMouseEvent);
2784 #endif
2785             return page->corePage()->userInputBridge().handleMouseMoveEvent(platformMouseEvent);
2786
2787         case PlatformEvent::MouseForceChanged:
2788         case PlatformEvent::MouseForceDown:
2789         case PlatformEvent::MouseForceUp:
2790             return page->corePage()->userInputBridge().handleMouseForceEvent(platformMouseEvent);
2791
2792         default:
2793             ASSERT_NOT_REACHED();
2794             return false;
2795     }
2796 }
2797
2798 void WebPage::mouseEvent(const WebMouseEvent& mouseEvent)
2799 {
2800     SetForScope<bool> userIsInteractingChange { m_userIsInteracting, true };
2801
2802     m_userActivity.impulse();
2803
2804     bool shouldHandleEvent = true;
2805
2806 #if ENABLE(CONTEXT_MENUS)
2807     // Don't try to handle any pending mouse events if a context menu is showing.
2808     if (m_isShowingContextMenu)
2809         shouldHandleEvent = false;
2810 #endif
2811 #if ENABLE(DRAG_SUPPORT)
2812     if (m_isStartingDrag)
2813         shouldHandleEvent = false;
2814 #endif
2815
2816     if (!shouldHandleEvent) {
2817         send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), false));
2818         return;
2819     }
2820
2821     bool handled = false;
2822
2823 #if !PLATFORM(IOS_FAMILY)
2824     if (!handled && m_headerBanner)
2825         handled = m_headerBanner->mouseEvent(mouseEvent);
2826     if (!handled && m_footerBanner)
2827         handled = m_footerBanner->mouseEvent(mouseEvent);
2828 #endif // !PLATFORM(IOS_FAMILY)
2829
2830     if (!handled) {
2831         CurrentEvent currentEvent(mouseEvent);
2832         handled = handleMouseEvent(mouseEvent, this);
2833     }
2834
2835     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled));
2836 }
2837
2838 static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page)
2839 {
2840     Frame& frame = page->mainFrame();
2841     if (!frame.view())
2842         return false;
2843
2844     PlatformWheelEvent platformWheelEvent = platform(wheelEvent);
2845     return page->userInputBridge().handleWheelEvent(platformWheelEvent);
2846 }
2847
2848 void WebPage::wheelEvent(const WebWheelEvent& wheelEvent)
2849 {
2850     m_userActivity.impulse();
2851
2852     CurrentEvent currentEvent(wheelEvent);
2853
2854     bool handled = handleWheelEvent(wheelEvent, m_page.get());
2855
2856     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled));
2857 }
2858
2859 static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page)
2860 {
2861     if (!page->mainFrame().view())
2862         return false;
2863
2864     if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey())
2865         return page->userInputBridge().handleAccessKeyEvent(platform(keyboardEvent));
2866     return page->userInputBridge().handleKeyEvent(platform(keyboardEvent));
2867 }
2868
2869 void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent)
2870 {
2871     SetForScope<bool> userIsInteractingChange { m_userIsInteracting, true };
2872
2873     m_userActivity.impulse();
2874
2875     PlatformKeyboardEvent::setCurrentModifierState(platform(keyboardEvent).modifiers());
2876
2877     CurrentEvent currentEvent(keyboardEvent);
2878
2879     bool handled = handleKeyEvent(keyboardEvent, m_page.get());
2880     // FIXME: Platform default behaviors should be performed during normal DOM event dispatch (in most cases, in default keydown event handler).
2881     if (!handled)
2882         handled = performDefaultBehaviorForKeyEvent(keyboardEvent);
2883
2884     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled));
2885 }
2886
2887 bool WebPage::handleKeyEventByRelinquishingFocusToChrome(const KeyboardEvent& event)
2888 {
2889     if (m_page->tabKeyCyclesThroughElements())
2890         return false;
2891
2892     if (event.charCode() != '\t')
2893         return false;
2894
2895     if (!event.shiftKey() || event.ctrlKey() || event.metaKey() || event.altGraphKey())
2896         return false;
2897
2898     ASSERT(event.type() == eventNames().keypressEvent);
2899     // Allow a shift-tab keypress event to relinquish focus even if we don't allow tab to cycle between
2900     // elements inside the view. We can only do this for shift-tab, not tab itself because
2901     // tabKeyCyclesThroughElements is used to make tab character insertion work in editable web views.
2902     return m_page->focusController().relinquishFocusToChrome(FocusDirectionBackward);
2903 }
2904
2905 void WebPage::validateCommand(const String& commandName, CallbackID callbackID)
2906 {
2907     bool isEnabled = false;
2908     int32_t state = 0;
2909     Frame& frame = m_page->focusController().focusedOrMainFrame();
2910     if (PluginView* pluginView = focusedPluginViewForFrame(frame))
2911         isEnabled = pluginView->isEditingCommandEnabled(commandName);
2912     else {
2913         Editor::Command command = frame.editor().command(commandName);
2914         state = (command.state() != TriState::False);
2915         isEnabled = command.isSupported() && command.isEnabled();
2916     }
2917
2918     send(Messages::WebPageProxy::ValidateCommandCallback(commandName, isEnabled, state, callbackID));
2919 }
2920
2921 void WebPage::executeEditCommand(const String& commandName, const String& argument)
2922 {
2923     executeEditingCommand(commandName, argument);
2924 }
2925
2926 void WebPage::setNeedsFontAttributes(bool needsFontAttributes)
2927 {
2928     if (m_needsFontAttributes == needsFontAttributes)
2929         return;
2930
2931     m_needsFontAttributes = needsFontAttributes;
2932
2933     if (m_needsFontAttributes)
2934         scheduleFullEditorStateUpdate();
2935 }
2936
2937 void WebPage::restoreSessionInternal(const Vector<BackForwardListItemState>& itemStates, WasRestoredByAPIRequest restoredByAPIRequest, WebBackForwardListProxy::OverwriteExistingItem overwrite)
2938 {
2939     // Since we're merely restoring HistoryItems from the UIProcess, there is no need to send HistoryItem update notifications back to the UIProcess.
2940     // Also, with process-swap on navigation, these updates may actually overwrite important state in the UIProcess such as the scroll position.
2941     SetForScope<void (*)(WebCore::HistoryItem&)> bypassHistoryItemUpdateNotifications(WebCore::notifyHistoryItemChanged, [](WebCore::HistoryItem&){});
2942     for (const auto& itemState : itemStates) {
2943         auto historyItem = toHistoryItem(itemState);
2944         historyItem->setWasRestoredFromSession(restoredByAPIRequest == WasRestoredByAPIRequest::Yes);
2945         static_cast<WebBackForwardListProxy&>(corePage()->backForward().client()).addItemFromUIProcess(itemState.identifier, WTFMove(historyItem), m_identifier, overwrite);
2946     }
2947 }
2948
2949 void WebPage::restoreSession(const Vector<BackForwardListItemState>& itemStates)
2950 {
2951     restoreSessionInternal(itemStates, WasRestoredByAPIRequest::Yes, WebBackForwardListProxy::OverwriteExistingItem::No);
2952 }
2953
2954 void WebPage::updateBackForwardListForReattach(const Vector<WebKit::BackForwardListItemState>& itemStates)
2955 {
2956     restoreSessionInternal(itemStates, WasRestoredByAPIRequest::No, WebBackForwardListProxy::OverwriteExistingItem::Yes);
2957 }
2958
2959 void WebPage::setCurrentHistoryItemForReattach(WebKit::BackForwardListItemState&& itemState)
2960 {
2961     auto historyItem = toHistoryItem(itemState);
2962     auto& historyItemRef = historyItem.get();
2963     static_cast<WebBackForwardListProxy&>(corePage()->backForward().client()).addItemFromUIProcess(itemState.identifier, WTFMove(historyItem), m_identifier, WebBackForwardListProxy::OverwriteExistingItem::Yes);
2964     corePage()->mainFrame().loader().history().setCurrentItem(historyItemRef);
2965 }
2966
2967 void WebPage::requestFontAttributesAtSelectionStart(CallbackID callbackID)
2968 {
2969     auto attributes = m_page->focusController().focusedOrMainFrame().editor().fontAttributesAtSelectionStart();
2970     send(Messages::WebPageProxy::FontAttributesCallback(attributes, callbackID));
2971 }
2972
2973 void WebPage::cancelGesturesBlockedOnSynchronousReplies()
2974 {
2975 #if ENABLE(IOS_TOUCH_EVENTS)
2976     if (auto reply = WTFMove(m_pendingSynchronousTouchEventReply))
2977         reply(true);
2978 #endif
2979
2980 #if PLATFORM(IOS_FAMILY)
2981     if (auto reply = WTFMove(m_pendingSynchronousPositionInformationReply))
2982         reply(InteractionInformationAtPosition::invalidInformation());
2983 #endif
2984 }
2985
2986 #if ENABLE(TOUCH_EVENTS)
2987 static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page)
2988 {
2989     if (!page->mainFrame().view())
2990         return false;
2991
2992     return page->mainFrame().eventHandler().handleTouchEvent(platform(touchEvent));
2993 }
2994 #endif
2995
2996 #if ENABLE(IOS_TOUCH_EVENTS)
2997 void WebPage::dispatchTouchEvent(const WebTouchEvent& touchEvent, bool& handled)
2998 {
2999     SetForScope<bool> userIsInteractingChange { m_userIsInteracting, true };
3000     m_lastInteractionLocation = touchEvent.position();
3001     CurrentEvent currentEvent(touchEvent);
3002     handled = handleTouchEvent(touchEvent, m_page.get());
3003     updatePotentialTapSecurityOrigin(touchEvent, handled);
3004 }
3005
3006 void WebPage::touchEventSync(const WebTouchEvent& touchEvent, CompletionHandler<void(bool)>&& reply)
3007 {
3008     // Avoid UIProcess hangs when the WebContent process is stuck on a sync IPC.
3009     if (IPC::UnboundedSynchronousIPCScope::hasOngoingUnboundedSyncIPC()) {
3010         RELEASE_LOG_ERROR_IF_ALLOWED(Process, "touchEventSync: Not processing because the process is stuck on unbounded sync IPC");
3011         return reply(true);
3012     }
3013
3014     m_pendingSynchronousTouchEventReply = WTFMove(reply);
3015
3016     EventDispatcher::TouchEventQueue queuedEvents;
3017     WebProcess::singleton().eventDispatcher().takeQueuedTouchEventsForPage(*this, queuedEvents);
3018     dispatchAsynchronousTouchEvents(queuedEvents);
3019
3020     bool handled = true;
3021     dispatchTouchEvent(touchEvent, handled);
3022
3023     if (auto reply = WTFMove(m_pendingSynchronousTouchEventReply))
3024         reply(handled);
3025 }
3026
3027 void WebPage::resetPotentialTapSecurityOrigin()
3028 {
3029     m_potentialTapSecurityOrigin = nullptr;
3030 }
3031
3032 void WebPage::updatePotentialTapSecurityOrigin(const WebTouchEvent& touchEvent, bool wasHandled)
3033 {
3034     if (wasHandled)
3035         return;
3036
3037     if (!touchEvent.isPotentialTap())
3038         return;
3039
3040     if (touchEvent.type() != WebEvent::TouchStart)
3041         return;
3042
3043     auto& mainFrame = m_page->mainFrame();
3044     auto document = mainFrame.document();
3045     if (!document)
3046         return;
3047
3048     if (!document->handlingTouchEvent())
3049         return;
3050
3051     Frame* touchEventTargetFrame = &mainFrame;
3052     while (auto subframe = touchEventTargetFrame->eventHandler().touchEventTargetSubframe())
3053         touchEventTargetFrame = subframe;
3054
3055     auto& touches = touchEventTargetFrame->eventHandler().touches();
3056     if (touches.isEmpty())
3057         return;
3058
3059     ASSERT(touches.size() == 1);
3060
3061     if (auto targetDocument = touchEventTargetFrame->document())
3062         m_potentialTapSecurityOrigin = &targetDocument->securityOrigin();
3063 }
3064 #elif ENABLE(TOUCH_EVENTS)
3065 void WebPage::touchEvent(const WebTouchEvent& touchEvent)
3066 {
3067     CurrentEvent currentEvent(touchEvent);
3068
3069     bool handled = handleTouchEvent(touchEvent, m_page.get());
3070
3071     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled));
3072 }
3073 #endif
3074
3075 void WebPage::cancelPointer(WebCore::PointerID pointerId, const WebCore::IntPoint& documentPoint)
3076 {
3077     m_page->pointerCaptureController().cancelPointer(pointerId, documentPoint);
3078 }
3079
3080 void WebPage::touchWithIdentifierWasRemoved(WebCore::PointerID pointerId)
3081 {
3082     m_page->pointerCaptureController().touchWithIdentifierWasRemoved(pointerId);
3083 }
3084
3085 #if ENABLE(MAC_GESTURE_EVENTS)
3086 static bool handleGestureEvent(const WebGestureEvent& event, Page* page)
3087 {
3088     if (!page->mainFrame().view())
3089         return false;
3090
3091     return page->mainFrame().eventHandler().handleGestureEvent(platform(event));
3092 }
3093
3094 void WebPage::gestureEvent(const WebGestureEvent& gestureEvent)
3095 {
3096     CurrentEvent currentEvent(gestureEvent);
3097     bool handled = handleGestureEvent(gestureEvent, m_page.get());
3098     send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled));
3099 }
3100 #endif
3101
3102 bool WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
3103 {
3104     return page->userInputBridge().scrollRecursively(direction, granularity);
3105 }
3106
3107 bool WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity)
3108 {
3109     return page->userInputBridge().logicalScrollRecursively(direction, granularity);
3110 }
3111
3112 bool WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity)
3113 {
3114     return scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity));
3115 }
3116
3117 void WebPage::centerSelectionInVisibleArea()
3118 {
3119     Frame& frame = m_page->focusController().focusedOrMainFrame();
3120     frame.selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignCenterAlways);
3121     findController().showFindIndicatorInSelection();
3122 }
3123
3124 bool WebPage::isControlledByAutomation() const
3125 {
3126     return m_page->isControlledByAutomation();
3127 }
3128
3129 void WebPage::setControlledByAutomation(bool controlled)
3130 {
3131     m_page->setControlledByAutomation(controlled);
3132 }
3133
3134 void WebPage::connectInspector(const String& targetId, Inspector::FrontendChannel::ConnectionType connectionType)
3135 {
3136     m_inspectorTargetController->connectInspector(targetId, connectionType);
3137 }
3138
3139 void WebPage::disconnectInspector(const String& targetId)
3140 {
3141     m_inspectorTargetController->disconnectInspector(targetId);
3142 }
3143
3144 void WebPage::sendMessageToTargetBackend(const String& targetId, const String& message)
3145 {
3146     m_inspectorTargetController->sendMessageToTargetBackend(targetId, message);
3147 }
3148
3149 void WebPage::insertNewlineInQuotedContent()
3150 {
3151     Frame& frame = m_page->focusController().focusedOrMainFrame();
3152     if (frame.selection().isNone())
3153         return;
3154     frame.editor().insertParagraphSeparatorInQuotedContent();
3155 }
3156
3157 #if ENABLE(REMOTE_INSPECTOR)
3158 void WebPage::setIndicating(bool indicating)
3159 {
3160     m_page->inspectorController().setIndicating(indicating);
3161 }
3162 #endif
3163
3164 void WebPage::setBackgroundColor(const Optional<WebCore::Color>& backgroundColor)
3165 {
3166     if (m_backgroundColor == backgroundColor)
3167         return;
3168
3169     m_backgroundColor = backgroundColor;
3170
3171     if (FrameView* frameView = mainFrameView())
3172         frameView->updateBackgroundRecursively(backgroundColor);
3173
3174     m_drawingArea->setNeedsDisplay();
3175 }
3176
3177 #if PLATFORM(COCOA)
3178 void WebPage::setTopContentInsetFenced(float contentInset, const WTF::MachSendRight& machSendRight)
3179 {
3180     m_drawingArea->addFence(machSendRight);
3181     setTopContentInset(contentInset);
3182 }
3183 #endif
3184
3185 void WebPage::setTopContentInset(float contentInset)
3186 {
3187     if (contentInset == m_page->topContentInset())
3188         return;
3189
3190     m_page->setTopContentInset(contentInset);
3191
3192     for (auto* pluginView : m_pluginViews)
3193         pluginView->topContentInsetDidChange();
3194 }
3195
3196 void WebPage::viewWillStartLiveResize()
3197 {
3198     if (!m_page)
3199         return;
3200
3201     // FIXME: This should propagate to all ScrollableAreas.
3202     Frame& frame = m_page->focusController().focusedOrMainFrame();
3203     if (FrameView* view = frame.view())
3204         view->willStartLiveResize();
3205 }
3206
3207 void WebPage::viewWillEndLiveResize()
3208 {
3209     if (!m_page)
3210         return;
3211
3212     // FIXME: This should propagate to all ScrollableAreas.
3213     Frame& frame = m_page->focusController().focusedOrMainFrame();
3214     if (FrameView* view = frame.view())
3215         view->willEndLiveResize();
3216 }
3217
3218 void WebPage::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& event, CompletionHandler<void()>&& completionHandler)
3219 {
3220     if (!m_page)
3221         return completionHandler();
3222
3223     SetForScope<bool> userIsInteractingChange { m_userIsInteracting, true };
3224
3225     Frame& frame = m_page->focusController().focusedOrMainFrame();
3226     frame.document()->setFocusedElement(0);
3227
3228     if (isKeyboardEventValid && event.type() == WebEvent::KeyDown) {
3229         PlatformKeyboardEvent platformEvent(platform(event));
3230         platformEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown);
3231         m_page->focusController().setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, &KeyboardEvent::create(platformEvent, &frame.windowProxy()).get());
3232         completionHandler();
3233         return;
3234     }
3235
3236     m_page->focusController().setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, nullptr);
3237     completionHandler();
3238 }
3239
3240 void WebPage::setCanStartMediaTimerFired()
3241 {
3242     if (m_page)
3243         m_page->setCanStartMedia(true);
3244 }
3245
3246 void WebPage::updateIsInWindow(bool isInitialState)
3247 {
3248     bool isInWindow = m_activityState.contains(WebCore::ActivityState::IsInWindow);
3249
3250     if (!isInWindow) {
3251         m_setCanStartMediaTimer.stop();
3252         m_page->setCanStartMedia(false);
3253         
3254         // The WebProcess does not yet know about this page; no need to tell it we're leaving the window.
3255         if (!isInitialState)
3256             WebProcess::singleton().pageWillLeaveWindow(m_identifier);
3257     } else {
3258         // Defer the call to Page::setCanStartMedia() since it ends up sending a synchronous message to the UI process
3259         // in order to get plug-in connections, and the UI process will be waiting for the Web process to update the backing
3260         // store after moving the view into a window, until it times out and paints white. See <rdar://problem/9242771>.
3261         if (m_mayStartMediaWhenInWindow)
3262             m_setCanStartMediaTimer.startOneShot(0_s);
3263
3264         WebProcess::singleton().pageDidEnterWindow(m_identifier);
3265     }
3266
3267     if (isInWindow)
3268         layoutIfNeeded();
3269 }
3270
3271 void WebPage::visibilityDidChange()
3272 {
3273     bool isVisible = m_activityState.contains(ActivityState::IsVisible);
3274     if (!isVisible) {
3275         // We save the document / scroll state when backgrounding a tab so that we are able to restore it
3276         // if it gets terminated while in the background.
3277         if (auto* frame = m_mainFrame->coreFrame())
3278             frame->loader().history().saveDocumentAndScrollState();
3279     }
3280 }
3281
3282 void WebPage::setActivityState(OptionSet<ActivityState::Flag> activityState, ActivityStateChangeID activityStateChangeID, const Vector<CallbackID>& callbackIDs)
3283 {
3284     LOG_WITH_STREAM(ActivityState, stream << "WebPage " << identifier().toUInt64() << " setActivityState to " << activityState);
3285
3286     auto changed = m_activityState ^ activityState;
3287     m_activityState = activityState;
3288
3289     if (changed)
3290         updateThrottleState();
3291
3292     ASSERT_WITH_MESSAGE(m_page, "setActivityState called on %" PRIu64 " but WebCore page was null", identifier().toUInt64());
3293     if (m_page) {
3294         SetForScope<OptionSet<ActivityState::Flag>> currentlyChangingActivityState { m_lastActivityStateChanges, changed };
3295         m_page->setActivityState(activityState);
3296     }
3297     
3298     for (auto* pluginView : m_pluginViews)
3299         pluginView->activityStateDidChange(changed);
3300
3301     m_drawingArea->activityStateDidChange(changed, activityStateChangeID, callbackIDs);
3302     WebProcess::singleton().pageActivityStateDidChange(m_identifier, changed);
3303
3304     if (changed & ActivityState::IsInWindow)
3305         updateIsInWindow();
3306
3307     if (changed & ActivityState::IsVisible)
3308         visibilityDidChange();
3309 }
3310
3311 void WebPage::setLayerHostingMode(LayerHostingMode layerHostingMode)
3312 {
3313     m_layerHostingMode = layerHostingMode;
3314
3315     m_drawingArea->setLayerHostingMode(m_layerHostingMode);
3316
3317     for (auto* pluginView : m_pluginViews)
3318         pluginView->setLayerHostingMode(m_layerHostingMode);
3319 }
3320
3321 void WebPage::didReceivePolicyDecision(FrameIdentifier frameID, uint64_t listenerID, PolicyDecision&& policyDecision)
3322 {
3323     WebFrame* frame = WebProcess::singleton().webFrame(frameID);
3324     RELEASE_LOG_IF_ALLOWED(Loading, "didReceivePolicyDecision: policyAction: %u - frameID: %llu - webFrame: %p - mainFrame: %d", (unsigned)policyDecision.policyAction, frameID.toUInt64(), frame, frame ? frame->isMainFrame() : 0);
3325
3326     if (!frame)
3327         return;
3328 #if ENABLE(APP_BOUND_DOMAINS)
3329     setIsNavigatingToAppBoundDomain(policyDecision.isNavigatingToAppBoundDomain, frame);
3330 #endif
3331     frame->didReceivePolicyDecision(listenerID, WTFMove(policyDecision));
3332 }
3333
3334 void WebPage::continueWillSubmitForm(FrameIdentifier frameID, uint64_t listenerID)
3335 {
3336     WebFrame* frame = WebProcess::singleton().webFrame(frameID);
3337     if (!frame)
3338         return;
3339     frame->continueWillSubmitForm(listenerID);
3340 }
3341
3342 void WebPage::didStartPageTransition()
3343 {
3344     freezeLayerTree(LayerTreeFreezeReason::PageTransition);
3345
3346 #if PLATFORM(MAC)
3347     bool hasPreviouslyFocusedDueToUserInteraction = m_hasEverFocusedElementDueToUserInteractionSincePageTransition;
3348 #endif
3349     m_hasEverFocusedElementDueToUserInteractionSincePageTransition = false;
3350     m_lastEditorStateWasContentEditable = EditorStateIsContentEditable::Unset;
3351
3352 #if PLATFORM(MAC)
3353     if (hasPreviouslyFocusedDueToUserInteraction)
3354         send(Messages::WebPageProxy::SetHasHadSelectionChangesFromUserInteraction(m_hasEverFocusedElementDueToUserInteractionSincePageTransition));
3355 #endif
3356
3357 #if HAVE(TOUCH_BAR)
3358     if (m_isTouchBarUpdateSupressedForHiddenContentEditable) {
3359         m_isTouchBarUpdateSupressedForHiddenContentEditable = false;
3360         send(Messages::WebPageProxy::SetIsTouchBarUpdateSupressedForHiddenContentEditable(m_isTouchBarUpdateSupressedForHiddenContentEditable));
3361     }
3362
3363     if (m_isNeverRichlyEditableForTouchBar) {
3364         m_isNeverRichlyEditableForTouchBar = false;
3365         send(Messages::WebPageProxy::SetIsNeverRichlyEditableForTouchBar(m_isNeverRichlyEditableForTouchBar));
3366     }
3367 #endif
3368
3369 #if PLATFORM(IOS_FAMILY)
3370     m_isShowingInputViewForFocusedElement = false;
3371     // This is used to enable a first-tap quirk.
3372     m_hasHandledSyntheticClick = false;
3373 #endif
3374 }
3375
3376 void WebPage::didCompletePageTransition()
3377 {
3378     unfreezeLayerTree(LayerTreeFreezeReason::PageTransition);
3379 }
3380
3381 void WebPage::show()
3382 {
3383     send(Messages::WebPageProxy::ShowPage());
3384 }
3385
3386 void WebPage::setIsTakingSnapshotsForApplicationSuspension(bool isTakingSnapshotsForApplicationSuspension)
3387 {
3388     RELEASE_LOG_IF_ALLOWED(Resize, "setIsTakingSnapshotsForApplicationSuspension(%d)", isTakingSnapshotsForApplicationSuspension);
3389
3390     if (m_page)
3391         m_page->setIsTakingSnapshotsForApplicationSuspension(isTakingSnapshotsForApplicationSuspension);
3392 }
3393
3394 void WebPage::setNeedsDOMWindowResizeEvent()
3395 {
3396     if (!m_page)
3397         return;
3398
3399     if (auto* document = m_page->mainFrame().document())
3400         document->setNeedsDOMWindowResizeEvent();
3401 }
3402
3403 String WebPage::userAgent(const URL& webCoreURL) const
3404 {
3405     String userAgent = platformUserAgent(webCoreURL);
3406     if (!userAgent.isEmpty())
3407         return userAgent;
3408     return m_userAgent;
3409 }
3410
3411 void WebPage::setUserAgent(const String& userAgent)
3412 {
3413     if (m_userAgent == userAgent)
3414         return;
3415
3416     m_userAgent = userAgent;
3417
3418     if (m_page)
3419         m_page->userAgentChanged();
3420 }
3421
3422 void WebPage::suspendActiveDOMObjectsAndAnimations()
3423 {
3424     m_page->suspendActiveDOMObjectsAndAnimations();
3425 }
3426
3427 void WebPage::resumeActiveDOMObjectsAndAnimations()
3428 {
3429     m_page->resumeActiveDOMObjectsAndAnimations();
3430 }
3431
3432 IntPoint WebPage::screenToRootView(const IntPoint& point)
3433 {
3434     IntPoint windowPoint;
3435     sendSync(Messages::WebPageProxy::ScreenToRootView(point), Messages::WebPageProxy::ScreenToRootView::Reply(windowPoint));
3436     return windowPoint;
3437 }
3438     
3439 IntRect WebPage::rootViewToScreen(const IntRect& rect)
3440 {
3441     IntRect screenRect;
3442     sendSync(Messages::WebPageProxy::RootViewToScreen(rect), Messages::WebPageProxy::RootViewToScreen::Reply(screenRect));
3443     return screenRect;
3444 }
3445     
3446 IntPoint WebPage::accessibilityScreenToRootView(const IntPoint& point)
3447 {
3448     IntPoint windowPoint;
3449     sendSync(Messages::WebPageProxy::AccessibilityScreenToRootView(point), Messages::WebPageProxy::AccessibilityScreenToRootView::Reply(windowPoint));
3450     return windowPoint;
3451 }
3452
3453 IntRect WebPage::rootViewToAccessibilityScreen(const IntRect& rect)
3454 {
3455     IntRect screenRect;
3456     sendSync(Messages::WebPageProxy::RootViewToAccessibilityScreen(rect), Messages::WebPageProxy::RootViewToAccessibilityScreen::Reply(screenRect));
3457     return screenRect;
3458 }
3459
3460 KeyboardUIMode WebPage::keyboardUIMode()
3461 {
3462     bool fullKeyboardAccessEnabled = WebProcess::singleton().fullKeyboardAccessEnabled();
3463     return static_cast<KeyboardUIMode>((fullKeyboardAccessEnabled ? KeyboardAccessFull : KeyboardAccessDefault) | (m_tabToLinks ? KeyboardAccessTabsToLinks : 0));
3464 }
3465
3466 void WebPage::runJavaScript(WebFrame* frame, RunJavaScriptParameters&& parameters, ContentWorldIdentifier worldIdentifier, CompletionHandler<void(const IPC::DataReference&, const Optional<WebCore::ExceptionDetails>&)>&& completionHandler)
3467 {
3468     // NOTE: We need to be careful when running scripts that the objects we depend on don't
3469     // disappear during script execution.
3470
3471     if (!frame || !frame->coreFrame()) {
3472         completionHandler({ }, ExceptionDetails { "Unable to execute JavaScript: Target frame could not be found in the page"_s, 0, 0, ExceptionDetails::Type::InvalidTargetFrame });
3473         return;
3474     }
3475
3476     auto* world = m_userContentController->worldForIdentifier(worldIdentifier);
3477     if (!world) {
3478         completionHandler({ }, ExceptionDetails { "Unable to execute JavaScript: Cannot find specified content world"_s });
3479         return;
3480     }
3481
3482 #if ENABLE(APP_BOUND_DOMAINS)
3483     if (frame->shouldEnableInAppBrowserPrivacyProtections()) {
3484         completionHandler({ }, ExceptionDetails { "Unable to execute JavaScript in a frame that is not in an app-bound domain"_s, 0, 0, ExceptionDetails::Type::AppBoundDomain });
3485         if (auto* document = m_page->mainFrame().document())
3486             document->addConsoleMessage(MessageSource::Security, MessageLevel::Warning, "Ignoring user script injection for non-app bound domain.");
3487         RELEASE_LOG_ERROR_IF_ALLOWED(Loading, "runJavaScript: Ignoring user script injection for non app-bound domain");
3488         return;
3489     }
3490 #endif
3491
3492     auto resolveFunction = [world = makeRef(*world), frame = makeRef(*frame), completionHandler = WTFMove(completionHandler)] (ValueOrException result) mutable {
3493         RefPtr<SerializedScriptValue> serializedResultValue;
3494         if (result) {
3495             serializedResultValue = SerializedScriptValue::create(frame->jsContextForWorld(world.ptr()),
3496                 toRef(frame->coreFrame()->script().globalObject(world->coreWorld()), result.value()), nullptr);
3497         }
3498
3499         IPC::DataReference dataReference;
3500         if (serializedResultValue)
3501             dataReference = serializedResultValue->data();
3502
3503         Optional<ExceptionDetails> details;
3504         if (!result)
3505             details = result.error();
3506
3507         completionHandler(dataReference, details);
3508     };
3509     JSLockHolder lock(commonVM());
3510     frame->coreFrame()->script().executeAsynchronousUserAgentScriptInWorld(world->coreWorld(), WTFMove(parameters), WTFMove(resolveFunction));
3511 }
3512
3513 void WebPage::runJavaScriptInFrameInScriptWorld(RunJavaScriptParameters&& parameters, Optional<WebCore::FrameIdentifier> frameID, const std::pair<ContentWorldIdentifier, String>& worldData, CompletionHandler<void(const IPC::DataReference&, const Optional<WebCore::ExceptionDetails>&)>&& completionHandler)
3514 {
3515     auto* webFrame = frameID ? WebProcess::singleton().webFrame(*frameID) : &mainWebFrame();
3516
3517     if (auto* newWorld = m_userContentController->addContentWorld(worldData)) {
3518         auto& coreWorld = newWorld->coreWorld();
3519         for (RefPtr<Frame> frame = mainFrame(); frame; frame = frame->tree().traverseNext())
3520             frame->loader().client().dispatchGlobalObjectAvailable(coreWorld);
3521     }
3522
3523     runJavaScript(webFrame, WTFMove(parameters), worldData.first, WTFMove(completionHandler));
3524 }
3525
3526 void WebPage::getContentsAsString(ContentAsStringIncludesChildFrames includeChildFrames, CallbackID callbackID)
3527 {
3528     switch (includeChildFrames) {
3529     case ContentAsStringIncludesChildFrames::No: {
3530         String resultString = m_mainFrame->contentsAsString();
3531         send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
3532         break;
3533     }
3534     case ContentAsStringIncludesChildFrames::Yes: {
3535         StringBuilder builder;
3536         for (RefPtr<Frame> frame = m_mainFrame->coreFrame(); frame; frame = frame->tree().traverseNextRendered()) {
3537             if (auto* webFrame = WebFrame::fromCoreFrame(*frame)) {
3538                 if (!builder.isEmpty())
3539                     builder.appendLiteral("\n\n");
3540
3541                 builder.append(webFrame->contentsAsString());
3542             }
3543         }
3544
3545         send(Messages::WebPageProxy::StringCallback(builder.toString(), callbackID));
3546         break;
3547     }
3548     }
3549 }
3550
3551 #if ENABLE(MHTML)
3552 void WebPage::getContentsAsMHTMLData(CallbackID callbackID)
3553 {
3554     send(Messages::WebPageProxy::DataCallback({ MHTMLArchive::generateMHTMLData(m_page.get()) }, callbackID));
3555 }
3556 #endif
3557
3558 void WebPage::getRenderTreeExternalRepresentation(CallbackID callbackID)
3559 {
3560     String resultString = renderTreeExternalRepresentation();
3561     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
3562 }
3563
3564 static Frame* frameWithSelection(Page* page)
3565 {
3566     for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
3567         if (frame->selection().isRange())
3568             return frame;
3569     }
3570
3571     return 0;
3572 }
3573
3574 void WebPage::getSelectionAsWebArchiveData(CallbackID callbackID)
3575 {
3576 #if PLATFORM(COCOA)
3577     RetainPtr<CFDataRef> data;
3578     if (Frame* frame = frameWithSelection(m_page.get()))
3579         data = LegacyWebArchive::createFromSelection(frame)->rawDataRepresentation();
3580 #endif
3581
3582     IPC::SharedBufferDataReference dataReference;
3583 #if PLATFORM(COCOA)
3584     if (data)
3585         dataReference = { CFDataGetBytePtr(data.get()), static_cast<size_t>(CFDataGetLength(data.get())) };
3586 #endif
3587     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
3588 }
3589
3590 void WebPage::getSelectionOrContentsAsString(CallbackID callbackID)
3591 {
3592     WebFrame* focusedOrMainFrame = WebFrame::fromCoreFrame(m_page->focusController().focusedOrMainFrame());
3593     String resultString = focusedOrMainFrame->selectionAsString();
3594     if (resultString.isEmpty())
3595         resultString = focusedOrMainFrame->contentsAsString();
3596     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
3597 }
3598
3599 void WebPage::getSourceForFrame(FrameIdentifier frameID, CallbackID callbackID)
3600 {
3601     String resultString;
3602     if (WebFrame* frame = WebProcess::singleton().webFrame(frameID))
3603        resultString = frame->source();
3604
3605     send(Messages::WebPageProxy::StringCallback(resultString, callbackID));
3606 }
3607
3608 void WebPage::getMainResourceDataOfFrame(FrameIdentifier frameID, CallbackID callbackID)
3609 {
3610     RefPtr<SharedBuffer> buffer;
3611     if (WebFrame* frame = WebProcess::singleton().webFrame(frameID)) {
3612         if (PluginView* pluginView = pluginViewForFrame(frame->coreFrame()))
3613             buffer = pluginView->liveResourceData();
3614         if (!buffer) {
3615             if (DocumentLoader* loader = frame->coreFrame()->loader().documentLoader())
3616                 buffer = loader->mainResourceData();
3617         }
3618     }
3619
3620     IPC::SharedBufferDataReference dataReference;
3621     if (buffer)
3622         dataReference = { *buffer };
3623     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
3624 }
3625
3626 static RefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const URL& resourceURL)
3627 {
3628     DocumentLoader* loader = frame->loader().documentLoader();
3629     if (!loader)
3630         return nullptr;
3631
3632     RefPtr<ArchiveResource> subresource = loader->subresource(resourceURL);
3633     if (!subresource)
3634         return nullptr;
3635
3636     return &subresource->data();
3637 }
3638
3639 void WebPage::getResourceDataFromFrame(FrameIdentifier frameID, const String& resourceURLString, CallbackID callbackID)
3640 {
3641     RefPtr<SharedBuffer> buffer;
3642     if (auto* frame = WebProcess::singleton().webFrame(frameID)) {
3643         URL resourceURL(URL(), resourceURLString);
3644         buffer = resourceDataForFrame(frame->coreFrame(), resourceURL);
3645     }
3646
3647     IPC::SharedBufferDataReference dataReference;
3648     if (buffer)
3649         dataReference = { *buffer };
3650     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
3651 }
3652
3653 void WebPage::getWebArchiveOfFrame(FrameIdentifier frameID, CallbackID callbackID)
3654 {
3655 #if PLATFORM(COCOA)
3656     RetainPtr<CFDataRef> data;
3657     if (WebFrame* frame = WebProcess::singleton().webFrame(frameID))
3658         data = frame->webArchiveData(nullptr, nullptr);
3659 #else
3660     UNUSED_PARAM(frameID);
3661 #endif
3662
3663     IPC::SharedBufferDataReference dataReference;
3664 #if PLATFORM(COCOA)
3665     if (data)
3666         dataReference = { CFDataGetBytePtr(data.get()), static_cast<size_t>(CFDataGetLength(data.get())) };
3667 #endif
3668     send(Messages::WebPageProxy::DataCallback(dataReference, callbackID));
3669 }
3670
3671 void WebPage::forceRepaintWithoutCallback()
3672 {
3673     m_drawingArea->forceRepaint();
3674 }
3675
3676 void WebPage::forceRepaint(CallbackID callbackID)
3677 {
3678     if (m_drawingArea->forceRepaintAsync(callbackID))
3679         return;
3680
3681     forceRepaintWithoutCallback();
3682     send(Messages::WebPageProxy::VoidCallback(callbackID));
3683 }
3684
3685 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
3686 {
3687     WebPreferencesStore::removeTestRunnerOverrides();
3688     updatePreferences(store);
3689 }
3690
3691 void WebPage::updatePreferences(const WebPreferencesStore& store)
3692 {
3693     updatePreferencesGenerated(store);
3694     updateSettingsGenerated(store);
3695
3696     Settings& settings = m_page->settings();
3697
3698 #if !PLATFORM(GTK) && !PLATFORM(WIN)
3699     if (!settings.acceleratedCompositingEnabled()) {
3700         RELEASE_LOG_IF_ALLOWED(Layers, "updatePreferences: acceleratedCompositingEnabled setting was false. WebKit cannot function in this mode; changing setting to true");
3701         settings.setAcceleratedCompositingEnabled(true);
3702     }
3703 #endif
3704
3705     bool requiresUserGestureForMedia = store.getBoolValueForKey(WebPreferencesKey::requiresUserGestureForMediaPlaybackKey());
3706     settings.setVideoPlaybackRequiresUserGesture(requiresUserGestureForMedia || store.getBoolValueForKey(WebPreferencesKey::requiresUserGestureForVideoPlaybackKey()));
3707     settings.setAudioPlaybackRequiresUserGesture(requiresUserGestureForMedia || store.getBoolValueForKey(WebPreferencesKey::requiresUserGestureForAudioPlaybackKey()));
3708     settings.setUserInterfaceDirectionPolicy(static_cast<WebCore::UserInterfaceDirectionPolicy>(store.getUInt32ValueForKey(WebPreferencesKey::userInterfaceDirectionPolicyKey())));
3709     settings.setSystemLayoutDirection(static_cast<TextDirection>(store.getUInt32ValueForKey(WebPreferencesKey::systemLayoutDirectionKey())));
3710     settings.setJavaScriptRuntimeFlags(static_cast<RuntimeFlags>(store.getUInt32ValueForKey(WebPreferencesKey::javaScriptRuntimeFlagsKey())));
3711     settings.setStorageBlockingPolicy(static_cast<SecurityOrigin::StorageBlockingPolicy>(store.getUInt32ValueForKey(WebPreferencesKey::storageBlockingPolicyKey())));
3712     settings.setFrameFlattening(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey()) ? WebCore::FrameFlattening::FullyEnabled : WebCore::FrameFlattening::Disabled);
3713     settings.setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey())));
3714 #if ENABLE(DATA_DETECTION)
3715     settings.setDataDetectorTypes(static_cast<DataDetectorTypes>(store.getUInt32ValueForKey(WebPreferencesKey::dataDetectorTypesKey())));
3716 #endif
3717
3718     DatabaseManager::singleton().setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey()));
3719
3720     m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey());
3721     m_asynchronousPluginInitializationEnabled = store.getBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledKey());
3722     m_asynchronousPluginInitializationEnabledForAllPlugins = store.getBoolValueForKey(WebPreferencesKey::asynchronousPluginInitializationEnabledForAllPluginsKey());
3723     m_artificialPluginInitializationDelayEnabled = store.getBoolValueForKey(WebPreferencesKey::artificialPluginInitializationDelayEnabledKey());
3724
3725     m_scrollingPerformanceLoggingEnabled = store.getBoolValueForKey(WebPreferencesKey::scrollingPerformanceLoggingEnabledKey());
3726     settings.setScrollingPerformanceLoggingEnabled(m_scrollingPerformanceLoggingEnabled);
3727
3728     bool isAppNapEnabled = store.getBoolValueForKey(WebPreferencesKey::pageVisibilityBasedProcessSuppressionEnabledKey());
3729     if (m_isAppNapEnabled != isAppNapEnabled) {
3730         m_isAppNapEnabled = isAppNapEnabled;
3731         updateThrottleState();
3732     }
3733
3734 #if PLATFORM(COCOA)
3735     m_pdfPluginEnabled = store.getBoolValueForKey(WebPreferencesKey::pdfPluginEnabledKey());
3736 #endif
3737 #if ENABLE(PAYMENT_REQUEST)
3738     settings.setPaymentRequestEnabled(store.getBoolValueForKey(WebPreferencesKey::applePayEnabledKey()));
3739 #endif
3740
3741 #if PLATFORM(IOS_FAMILY)
3742     setForceAlwaysUserScalable(m_forceAlwaysUserScalable || store.getBoolValueForKey(WebPreferencesKey::forceAlwaysUserScalableKey()));
3743
3744     settings.setUseImageDocumentForSubframePDF(true);
3745 #if HAVE(AVKIT)
3746     DeprecatedGlobalSettings::setAVKitEnabled(true);
3747 #endif
3748 #endif
3749
3750 #if ENABLE(SERVICE_WORKER)
3751     if (store.getBoolValueForKey(WebPreferencesKey::serviceWorkerEntitlementDisabledForTestingKey()))
3752         disableServiceWorkerEntitlement();
3753 #if ENABLE(APP_BOUND_DOMAINS)
3754     bool shouldAllowServiceWorkersForAppBoundViews = m_limitsNavigationsToAppBoundDomains;
3755 #else
3756     bool shouldAllowServiceWorkersForAppBoundViews = false;
3757 #endif
3758
3759     if (store.getBoolValueForKey(WebPreferencesKey::serviceWorkersEnabledKey())) {
3760         ASSERT(parentProcessHasServiceWorkerEntitlement() || shouldAllowServiceWorkersForAppBoundViews);
3761         if (!parentProcessHasServiceWorkerEntitlement() && !shouldAllowServiceWorkersForAppBoundViews)
3762             RuntimeEnabledFeatures::sharedFeatures().setServiceWorkerEnabled(false);
3763     }
3764 #endif
3765
3766     settings.setLayoutViewportHeightExpansionFactor(store.getDoubleValueForKey(WebPreferencesKey::layoutViewportHeightExpansionFactorKey()));
3767
3768 #if ENABLE(APP_BOUND_DOMAINS)
3769     m_needsInAppBrowserPrivacyQuirks = store.getBoolValueForKey(WebPreferencesKey::needsInAppBrowserPrivacyQuirksKey());
3770 #endif
3771
3772     if (m_drawingArea)
3773         m_drawingArea->updatePreferences(store);
3774
3775 #if USE(LIBWEBRTC)
3776     m_page->libWebRTCProvider().setH265Support(RuntimeEnabledFeatures::sharedFeatures().webRTCH265CodecEnabled());
3777     m_page->libWebRTCProvider().setVP9Support(RuntimeEnabledFeatures::sharedFeatures().webRTCVP9CodecEnabled());
3778     LibWebRTCProvider::setH264HardwareEncoderAllowed(store.getBoolValueForKey(WebPreferencesKey::webRTCH264HardwareEncoderEnabledKey()));
3779 #endif
3780
3781 #if ENABLE(GPU_PROCESS)
3782     // FIXME: useGPUProcessForMediaEnabled should be a RuntimeEnabledFeature since it's global.
3783     static_cast<WebMediaStrategy&>(platformStrategies()->mediaStrategy()).setUseGPUProcess(settings.useGPUProcessForMediaEnabled());
3784     WebProcess::singleton().supplement<RemoteMediaPlayerManager>()->updatePreferences(settings);
3785     WebProcess::singleton().setUseGPUProcessForMedia(settings.useGPUProcessForMediaEnabled());
3786 #endif
3787 }
3788
3789 #if ENABLE(DATA_DETECTION)
3790
3791 void WebPage::setDataDetectionResults(NSArray *detectionResults)
3792 {
3793     DataDetectionResult dataDetectionResult;
3794     dataDetectionResult.results = detectionResults;
3795     send(Messages::WebPageProxy::SetDataDetectionResult(dataDetectionResult));
3796 }
3797
3798 void WebPage::removeDataDetectedLinks(CompletionHandler<void(const DataDetectionResult&)>&& completionHandler)
3799 {
3800     for (auto frame = makeRefPtr(&m_page->mainFrame()); frame; frame = frame->tree().traverseNext()) {
3801         auto document = makeRefPtr(frame->document());
3802         if (!document)
3803             continue;
3804
3805         DataDetection::removeDataDetectedLinksInDocument(*document);
3806         frame->setDataDetectionResults(nullptr);
3807     }
3808     completionHandler({ m_page->mainFrame().dataDetectionResults() });
3809 }
3810
3811 void WebPage::detectDataInAllFrames(uint64_t types, CompletionHandler<void(const DataDetectionResult&)>&& completionHandler)
3812 {
3813     auto dataDetectorTypes = static_cast<WebCore::DataDetectorTypes>(types);
3814     for (auto frame = makeRefPtr(&m_page->mainFrame()); frame; frame = frame->tree().traverseNext()) {
3815         auto document = makeRefPtr(frame->document());
3816         if (!document)
3817             continue;
3818         frame->setDataDetectionResults(DataDetection::detectContentInRange(makeRangeSelectingNodeContents(*document), dataDetectorTypes, m_dataDetectionContext.get()));
3819     }
3820     completionHandler({ m_page->mainFrame().dataDetectionResults() });
3821 }
3822
3823 #endif // ENABLE(DATA_DETECTION)
3824
3825 #if PLATFORM(COCOA)
3826 void WebPage::willCommitLayerTree(RemoteLayerTreeTransaction& layerTransaction)
3827 {
3828     FrameView* frameView = corePage()->mainFrame().view();
3829     if (!frameView)
3830         return;
3831
3832     layerTransaction.setContentsSize(frameView->contentsSize());
3833     layerTransaction.setScrollOrigin(frameView->scrollOrigin());
3834     layerTransaction.setPageScaleFactor(corePage()->pageScaleFactor());
3835     layerTransaction.setRenderTreeSize(corePage()->renderTreeSize());
3836     layerTransaction.setPageExtendedBackgroundColor(corePage()->pageExtendedBackgroundColor());
3837
3838     layerTransaction.setBaseLayoutViewportSize(frameView->baseLayoutViewportSize());
3839     layerTransaction.setMinStableLayoutViewportOrigin(frameView->minStableLayoutViewportOrigin());
3840     layerTransaction.setMaxStableLayoutViewportOrigin(frameView->maxStableLayoutViewportOrigin());
3841
3842 #if PLATFORM(IOS_FAMILY)
3843     layerTransaction.setScaleWasSetByUIProcess(scaleWasSetByUIProcess());
3844     layerTransaction.setMinimumScaleFactor(m_viewportConfiguration.minimumScale());
3845     layerTransaction.setMaximumScaleFactor(m_viewportConfiguration.maximumScale());
3846     layerTransaction.setInitialScaleFactor(m_viewportConfiguration.initialScale());
3847     layerTransaction.setViewportMetaTagWidth(m_viewportConfiguration.viewportArguments().width);
3848     layerTransaction.setViewportMetaTagWidthWasExplicit(m_viewportConfiguration.viewportArguments().widthWasExplicit);
3849     layerTransaction.setViewportMetaTagCameFromImageDocument(m_viewportConfiguration.viewportArguments().type == ViewportArguments::ImageDocument);
3850     layerTransaction.setAvoidsUnsafeArea(m_viewportConfiguration.avoidsUnsafeArea());
3851     layerTransaction.setIsInStableState(m_isInStableState);
3852     layerTransaction.setAllowsUserScaling(allowsUserScaling());
3853     if (m_pendingDynamicViewportSizeUpdateID) {
3854         layerTransaction.setDynamicViewportSizeUpdateID(*m_pendingDynamicViewportSizeUpdateID);
3855         m_pendingDynamicViewportSizeUpdateID = WTF::nullopt;
3856     }
3857     if (m_lastTransactionPageScaleFactor != layerTransaction.pageScaleFactor()) {
3858         m_lastTransactionPageScaleFactor = layerTransaction.pageScaleFactor();
3859         m_lastTransactionIDWithScaleChange = layerTransaction.transactionID();
3860     }
3861 #endif
3862
3863     layerTransaction.setScrollPosition(frameView->scrollPosition());
3864
3865     if (m_hasPendingEditorStateUpdate) {
3866         layerTransaction.setEditorState(editorState());
3867         m_hasPendingEditorStateUpdate = false;
3868     }
3869 }
3870
3871 void WebPage::didFlushLayerTreeAtTime(MonotonicTime timestamp)
3872 {
3873 #if PLATFORM(IOS_FAMILY)
3874     if (m_oldestNonStableUpdateVisibleContentRectsTimestamp != MonotonicTime()) {
3875         Seconds elapsed = timestamp - m_oldestNonStableUpdateVisibleContentRectsTimestamp;
3876         m_oldestNonStableUpdateVisibleContentRectsTimestamp = MonotonicTime();
3877
3878         m_estimatedLatency = m_estimatedLatency * 0.80 + elapsed * 0.20;
3879     }
3880 #else
3881     UNUSED_PARAM(timestamp);
3882 #endif
3883 }
3884 #endif
3885
3886 void WebPage::layoutIfNeeded()
3887 {
3888     m_page->layoutIfNeeded();
3889 }
3890     
3891 void WebPage::updateRendering()
3892 {
3893     m_page->updateRendering();
3894 }
3895
3896 void WebPage::finalizeRenderingUpdate(OptionSet<FinalizeRenderingUpdateFlags> flags)
3897 {
3898     m_page->finalizeRenderingUpdate(flags);
3899 }
3900
3901 WebInspector* WebPage::inspector(LazyCreationPolicy behavior)
3902 {
3903     if (m_isClosed)
3904         return nullptr;
3905     if (!m_inspector && behavior == LazyCreationPolicy::CreateIfNeeded)
3906         m_inspector = WebInspector::create(this);
3907     return m_inspector.get();
3908 }
3909
3910 WebInspectorUI* WebPage::inspectorUI()
3911 {
3912     if (m_isClosed)
3913         return nullptr;
3914     if (!m_inspectorUI)
3915         m_inspectorUI = WebInspectorUI::create(*this);
3916     return m_inspectorUI.get();
3917 }
3918
3919 RemoteWebInspectorUI* WebPage::remoteInspectorUI()
3920 {
3921     if (m_isClosed)
3922         return nullptr;
3923     if (!m_remoteInspectorUI)
3924         m_remoteInspectorUI = RemoteWebInspectorUI::create(*this);
3925     return m_remoteInspectorUI.get();
3926 }
3927
3928 void WebPage::inspectorFrontendCountChanged(unsigned count)
3929 {
3930     send(Messages::WebPageProxy::DidChangeInspectorFrontendCount(count));
3931 }
3932
3933 #if ENABLE(VIDEO_PRESENTATION_MODE)
3934 PlaybackSessionManager& WebPage::playbackSessionManager()
3935 {
3936     if (!m_playbackSessionManager)
3937         m_playbackSessionManager = PlaybackSessionManager::create(*this);
3938     return *m_playbackSessionManager;
3939 }
3940
3941 VideoFullscreenManager& WebPage::videoFullscreenManager()
3942 {
3943     if (!m_videoFullscreenManager)
3944         m_videoFullscreenManager = VideoFullscreenManager::create(*this, playbackSessionManager());
3945     return *m_videoFullscreenManager;
3946 }
3947
3948 void WebPage::videoControlsManagerDidChange()
3949 {
3950 #if ENABLE(FULLSCREEN_API)
3951     if (auto* manager = fullScreenManager())
3952         manager->videoControlsManagerDidChange();
3953 #endif
3954 }
3955
3956 #endif
3957
3958 #if PLATFORM(IOS_FAMILY)
3959 void WebPage::setAllowsMediaDocumentInlinePlayback(bool allows)
3960 {
3961     m_page->setAllowsMediaDocumentInlinePlayback(allows);
3962 }
3963 #endif
3964
3965 #if ENABLE(FULLSCREEN_API)
3966 WebFullScreenManager* WebPage::fullScreenManager()
3967 {
3968     if (!m_fullScreenManager)
3969         m_fullScreenManager = WebFullScreenManager::create(this);
3970     return m_fullScreenManager.get();
3971 }
3972 #endif
3973
3974 void WebPage::addConsoleMessage(FrameIdentifier frameID, MessageSource messageSource, MessageLevel messageLevel, const String& message, uint64_t requestID)
3975 {
3976     if (auto* frame = WebProcess::singleton().webFrame(frameID))
3977         frame->addConsoleMessage(messageSource, messageLevel, message, requestID);
3978 }
3979
3980 void WebPage::sendCSPViolationReport(FrameIdentifier frameID, const URL& reportURL, IPC::FormDataReference&& reportData)
3981 {
3982     auto report = reportData.takeData();
3983     if (!report)
3984         return;
3985     if (auto* frame = WebProcess::singleton().webFrame(frameID))
3986         PingLoader::sendViolationReport(*frame->coreFrame(), reportURL, report.releaseNonNull(), ViolationReportType::ContentSecurityPolicy);
3987 }
3988
3989 void WebPage::enqueueSecurityPolicyViolationEvent(FrameIdentifier frameID, SecurityPolicyViolationEvent::Init&& eventInit)
3990 {
3991     auto* frame = WebProcess::singleton().webFrame(frameID);
3992     if (!frame)
3993         return;
3994     auto* coreFrame = frame->coreFrame();
3995     if (!coreFrame)
3996         return;
3997     if (auto* document = coreFrame->document())
3998         document->enqueueSecurityPolicyViolationEvent(WTFMove(eventInit));
3999 }
4000
4001 NotificationPermissionRequestManager* WebPage::notificationPermissionRequestManager()
4002 {
4003     if (m_notificationPermissionRequestManager)
4004         return m_notificationPermissionRequestManager.get();
4005
4006     m_notificationPermissionRequestManager = NotificationPermissionRequestManager::create(this);
4007     return m_notificationPermissionRequestManager.get();
4008 }
4009
4010 #if ENABLE(DRAG_SUPPORT)
4011
4012 #if PLATFORM(GTK)
4013 void WebPage::performDragControllerAction(DragControllerAction action, const IntPoint& clientPosition, const IntPoint& globalPosition, OptionSet<DragOperation> draggingSourceOperationMask, SelectionData&& selectionData, OptionSet<DragApplicationFlags> flags)
4014 {
4015     if (!m_page) {
4016         send(Messages::WebPageProxy::DidPerformDragControllerAction(WTF::nullopt, DragHandlingMethod::None, false, 0, { }, { }));
4017         return;
4018     }
4019
4020     DragData dragData(&selectionData, clientPosition, globalPosition, draggingSourceOperationMask, flags);
4021     switch (action) {
4022     case DragControllerAction::Entered: {
4023         auto resolvedDragOperation = m_page->dragController().dragEntered(dragData);
4024         send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().dragHandlingMethod(), m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted(), { }, { }));
4025         return;
4026     }
4027     case DragControllerAction::Updated: {
4028         auto resolvedDragOperation = m_page->dragController().dragUpdated(dragData);
4029         send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().dragHandlingMethod(), m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted(), { }, { }));
4030         return;
4031     }
4032     case DragControllerAction::Exited:
4033         m_page->dragController().dragExited(dragData);
4034         return;
4035
4036     case DragControllerAction::PerformDragOperation: {
4037         m_page->dragController().performDragOperation(dragData);
4038         return;
4039     }
4040     }
4041     ASSERT_NOT_REACHED();
4042 }
4043 #else
4044 void WebPage::performDragControllerAction(DragControllerAction action, const WebCore::DragData& dragData, SandboxExtension::Handle&& sandboxExtensionHandle, SandboxExtension::HandleArray&& sandboxExtensionsHandleArray)
4045 {
4046     if (!m_page) {
4047         send(Messages::WebPageProxy::DidPerformDragControllerAction(WTF::nullopt, DragHandlingMethod::None, false, 0, { }, { }));
4048         return;
4049     }
4050
4051     switch (action) {
4052     case DragControllerAction::Entered: {
4053         auto resolvedDragOperation = m_page->dragController().dragEntered(dragData);
4054         send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().dragHandlingMethod(), m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted(), m_page->dragCaretController().caretRectInRootViewCoordinates(), m_page->dragCaretController().editableElementRectInRootViewCoordinates()));
4055         return;
4056     }
4057     case DragControllerAction::Updated: {
4058         auto resolvedDragOperation = m_page->dragController().dragUpdated(dragData);
4059         send(Messages::WebPageProxy::DidPerformDragControllerAction(resolvedDragOperation, m_page->dragController().dragHandlingMethod(), m_page->dragController().mouseIsOverFileInput(), m_page->dragController().numberOfItemsToBeAccepted(), m_page->dragCaretController().caretRectInRootViewCoordinates(), m_page->dragCaretController().editableElementRectInRootViewCoordinates()));
4060         return;
4061     }
4062     case DragControllerAction::Exited:
4063         m_page->dragController().dragExited(dragData);
4064         send(Messages::WebPageProxy::DidPerformDragControllerAction(WTF::nullopt, DragHandlingMethod::None, false, 0, { }, { }));
4065         return;
4066         
4067     case DragControllerAction::PerformDragOperation: {
4068         ASSERT(!m_pendingDropSandboxExtension);
4069
4070         m_pendingDropSandboxExtension = SandboxExtension::create(WTFMove(sandboxExtensionHandle));
4071         for (size_t i = 0; i < sandboxExtensionsHandleArray.size(); i++) {
4072             if (auto extension = SandboxExtension::create(WTFMove(sandboxExtensionsHandleArray[i])))
4073                 m_pendingDropExtensionsForFileUpload.append(extension);
4074         }
4075
4076         bool handled = m_page->dragController().performDragOperation(dragData);
4077
4078         // If we started loading a local file, the sandbox extension tracker would have adopted this
4079         // pending drop sandbox extension. If not, we'll play it safe and clear it.
4080         m_pendingDropSandboxExtension = nullptr;
4081
4082         m_pendingDropExtensionsForFileUpload.clear();
4083         send(Messages::WebPageProxy::DidPerformDragOperation(handled));
4084         return;
4085     }
4086     }
4087     ASSERT_NOT_REACHED();
4088 }
4089 #endif
4090
4091 void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, OptionSet<WebCore::DragOperation> dragOperationMask)
4092 {
4093     IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController().dragOffset().x(), clientPosition.y() + m_page->dragController().dragOffset().y());
4094     IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController().dragOffset().x(), globalPosition.y() + m_page->dragController().dragOffset().y());
4095
4096     m_page->dragController().dragEnded();
4097     FrameView* view = m_page->mainFrame().view();
4098     if (!view)
4099         return;
4100     // FIXME: These are fake modifier keys here, but they should be real ones instead.
4101     PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, WallTime::now(), 0, WebCore::NoTap);
4102     m_page->mainFrame().eventHandler().dragSourceEndedAt(event, dragOperationMask);
4103
4104     send(Messages::WebPageProxy::DidEndDragging());
4105
4106     m_isStartingDrag = false;
4107 }
4108
4109 void WebPage::willPerformLoadDragDestinationAction()
4110 {
4111     m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(WTFMove(m_pendingDropSandboxExtension));
4112 }
4113
4114 void WebPage::mayPerformUploadDragDestinationAction()
4115 {
4116     for (size_t i = 0; i < m_pendingDropExtensionsForFileUpload.size(); i++)
4117         m_pendingDropExtensionsForFileUpload[i]->consumePermanently();
4118     m_pendingDropExtensionsForFileUpload.clear();
4119 }
4120
4121 void WebPage::didStartDrag()
4122 {
4123     m_isStartingDrag = false;
4124     m_page->mainFrame().eventHandler().didStartDrag();
4125 }
4126
4127 void WebPage::dragCancelled()
4128 {
4129     m_isStartingDrag = false;
4130     m_page->mainFrame().eventHandler().dragCancelled();
4131 }
4132     
4133 #endif // ENABLE(DRAG_SUPPORT)
4134
4135 WebUndoStep* WebPage::webUndoStep(WebUndoStepID stepID)
4136 {
4137     return m_undoStepMap.get(stepID);
4138 }
4139
4140 void WebPage::addWebUndoStep(WebUndoStepID stepID, Ref<WebUndoStep>&& entry)
4141 {
4142     auto addResult = m_undoStepMap.set(stepID, WTFMove(entry));
4143     ASSERT_UNUSED(addResult, addResult.isNewEntry);
4144 }
4145
4146 void WebPage::removeWebEditCommand(WebUndoStepID stepID)
4147 {
4148     if (auto undoStep = m_undoStepMap.take(stepID))
4149         undoStep->didRemoveFromUndoManager();
4150 }
4151
4152 bool WebPage::isAlwaysOnLoggingAllowed() const
4153 {
4154     return corePage() && corePage()->isAlwaysOnLoggingAllowed();
4155 }
4156
4157 void WebPage::unapplyEditCommand(WebUndoStepID stepID)
4158 {
4159     auto* step = webUndoStep(stepID);
4160     if (!step)
4161         return;
4162
4163     step->step().unapply();
4164 }
4165
4166 void WebPage::reapplyEditCommand(WebUndoStepID stepID)
4167 {
4168     auto* step = webUndoStep(stepID);
4169     if (!step)
4170         return;