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