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