summaryrefslogtreecommitdiff
path: root/Source/WebCore/page/Page.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/page/Page.cpp')
-rw-r--r--Source/WebCore/page/Page.cpp1395
1 files changed, 1035 insertions, 360 deletions
diff --git a/Source/WebCore/page/Page.cpp b/Source/WebCore/page/Page.cpp
index d5d994919..1fd0aad74 100644
--- a/Source/WebCore/page/Page.cpp
+++ b/Source/WebCore/page/Page.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2006-2015 Apple Inc. All Rights Reserved.
* Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
* This library is free software; you can redistribute it and/or
@@ -20,25 +20,29 @@
#include "config.h"
#include "Page.h"
+#include "ActivityStateChangeObserver.h"
#include "AlternativeTextClient.h"
-#include "AnimationController.h"
+#include "ApplicationCacheStorage.h"
#include "BackForwardClient.h"
#include "BackForwardController.h"
+#include "CSSAnimationController.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "ClientRectList.h"
#include "ContextMenuClient.h"
#include "ContextMenuController.h"
-#include "DOMWindow.h"
+#include "DatabaseProvider.h"
+#include "DiagnosticLoggingClient.h"
+#include "DiagnosticLoggingKeys.h"
+#include "DocumentLoader.h"
#include "DocumentMarkerController.h"
-#include "DocumentStyleSheetCollection.h"
#include "DragController.h"
#include "Editor.h"
#include "EditorClient.h"
+#include "EmptyClients.h"
#include "Event.h"
#include "EventNames.h"
-#include "ExceptionCode.h"
-#include "ExceptionCodePlaceholder.h"
+#include "ExtensionStyleSheets.h"
#include "FileSystem.h"
#include "FocusController.h"
#include "FrameLoader.h"
@@ -51,104 +55,159 @@
#include "HistoryItem.h"
#include "InspectorController.h"
#include "InspectorInstrumentation.h"
+#include "LibWebRTCProvider.h"
#include "Logging.h"
#include "MainFrame.h"
#include "MediaCanStartListener.h"
#include "Navigator.h"
#include "NetworkStateNotifier.h"
-#include "PageActivityAssertionToken.h"
#include "PageCache.h"
-#include "PageConsole.h"
+#include "PageConfiguration.h"
+#include "PageConsoleClient.h"
#include "PageDebuggable.h"
#include "PageGroup.h"
-#include "PageThrottler.h"
+#include "PageOverlayController.h"
+#include "PerformanceMonitor.h"
+#include "PlatformMediaSessionManager.h"
#include "PlugInClient.h"
#include "PluginData.h"
-#include "PluginView.h"
+#include "PluginInfoProvider.h"
+#include "PluginViewBase.h"
#include "PointerLockController.h"
#include "ProgressTracker.h"
#include "RenderLayerCompositor.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "RenderWidget.h"
+#include "ResourceUsageOverlay.h"
#include "RuntimeEnabledFeatures.h"
+#include "SVGDocumentExtensions.h"
#include "SchemeRegistry.h"
#include "ScriptController.h"
#include "ScrollingCoordinator.h"
#include "Settings.h"
#include "SharedBuffer.h"
+#include "SocketProvider.h"
#include "StorageArea.h"
#include "StorageNamespace.h"
+#include "StorageNamespaceProvider.h"
#include "StyleResolver.h"
+#include "StyleScope.h"
#include "SubframeLoader.h"
#include "TextResourceDecoder.h"
-#include "UserContentController.h"
+#include "UserContentProvider.h"
+#include "UserInputBridge.h"
+#include "ValidationMessageClient.h"
#include "VisitedLinkState.h"
+#include "VisitedLinkStore.h"
#include "VoidCallback.h"
+#include "WebGLStateTracker.h"
#include "Widget.h"
-#include <wtf/HashMap.h>
+#include <wtf/CurrentTime.h>
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/Base64.h>
#include <wtf/text/StringHash.h>
+#if ENABLE(WEB_REPLAY)
+#include "ReplayController.h"
+#include <replay/InputCursor.h>
+#endif
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+#include "HTMLVideoElement.h"
+#include "MediaPlaybackTarget.h"
+#endif
+
+#if ENABLE(MEDIA_SESSION)
+#include "MediaSessionManager.h"
+#endif
+
+#if ENABLE(INDEXED_DATABASE)
+#include "IDBConnectionToServer.h"
+#include "InProcessIDBServer.h"
+#endif
+
+#if ENABLE(DATA_INTERACTION)
+#include "SelectionRect.h"
+#endif
+
namespace WebCore {
static HashSet<Page*>* allPages;
+static unsigned nonUtilityPageCount { 0 };
+
+static inline bool isUtilityPageChromeClient(ChromeClient& chromeClient)
+{
+ return chromeClient.isEmptyChromeClient() || chromeClient.isSVGImageChromeClient();
+}
DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, pageCounter, ("Page"));
+void Page::forEachPage(std::function<void(Page&)> function)
+{
+ if (!allPages)
+ return;
+ for (Page* page : *allPages)
+ function(*page);
+}
+
+void Page::updateValidationBubbleStateIfNeeded()
+{
+ if (auto* client = validationMessageClient())
+ client->updateValidationBubbleStateIfNeeded();
+}
+
static void networkStateChanged(bool isOnLine)
{
Vector<Ref<Frame>> frames;
// Get all the frames of all the pages in all the page groups
- for (auto it = allPages->begin(), end = allPages->end(); it != end; ++it) {
- for (Frame* frame = &(*it)->mainFrame(); frame; frame = frame->tree().traverseNext())
+ for (auto& page : *allPages) {
+ for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext())
frames.append(*frame);
- InspectorInstrumentation::networkStateChanged(*it);
+ InspectorInstrumentation::networkStateChanged(*page);
}
AtomicString eventName = isOnLine ? eventNames().onlineEvent : eventNames().offlineEvent;
- for (unsigned i = 0; i < frames.size(); i++)
- frames[i]->document()->dispatchWindowEvent(Event::create(eventName, false, false));
+ for (auto& frame : frames) {
+ if (!frame->document())
+ continue;
+ frame->document()->dispatchWindowEvent(Event::create(eventName, false, false));
+ }
}
-float deviceScaleFactor(Frame* frame)
-{
- if (!frame)
- return 1;
- Page* page = frame->page();
- if (!page)
- return 1;
- return page->deviceScaleFactor();
-}
+static const ActivityState::Flags PageInitialActivityState = ActivityState::IsVisible | ActivityState::IsInWindow;
-Page::Page(PageClients& pageClients)
- : m_chrome(std::make_unique<Chrome>(*this, *pageClients.chromeClient))
+Page::Page(PageConfiguration&& pageConfiguration)
+ : m_chrome(std::make_unique<Chrome>(*this, *pageConfiguration.chromeClient))
, m_dragCaretController(std::make_unique<DragCaretController>())
#if ENABLE(DRAG_SUPPORT)
- , m_dragController(std::make_unique<DragController>(*this, *pageClients.dragClient))
+ , m_dragController(std::make_unique<DragController>(*this, *pageConfiguration.dragClient))
#endif
- , m_focusController(std::make_unique<FocusController>(*this))
+ , m_focusController(std::make_unique<FocusController>(*this, PageInitialActivityState))
#if ENABLE(CONTEXT_MENUS)
- , m_contextMenuController(std::make_unique<ContextMenuController>(*this, *pageClients.contextMenuClient))
+ , m_contextMenuController(std::make_unique<ContextMenuController>(*this, *pageConfiguration.contextMenuClient))
#endif
-#if ENABLE(INSPECTOR)
- , m_inspectorController(std::make_unique<InspectorController>(*this, pageClients.inspectorClient))
+ , m_userInputBridge(std::make_unique<UserInputBridge>(*this))
+#if ENABLE(WEB_REPLAY)
+ , m_replayController(std::make_unique<ReplayController>(*this))
#endif
+ , m_inspectorController(std::make_unique<InspectorController>(*this, pageConfiguration.inspectorClient))
#if ENABLE(POINTER_LOCK)
- , m_pointerLockController(PointerLockController::create(this))
+ , m_pointerLockController(std::make_unique<PointerLockController>(*this))
#endif
, m_settings(Settings::create(this))
- , m_progress(std::make_unique<ProgressTracker>(*pageClients.progressTrackerClient))
- , m_backForwardController(std::make_unique<BackForwardController>(*this, pageClients.backForwardClient))
- , m_mainFrame(MainFrame::create(*this, *pageClients.loaderClientForMainFrame))
+ , m_progress(std::make_unique<ProgressTracker>(*pageConfiguration.progressTrackerClient))
+ , m_backForwardController(std::make_unique<BackForwardController>(*this, *WTFMove(pageConfiguration.backForwardClient)))
+ , m_mainFrame(MainFrame::create(*this, pageConfiguration))
, m_theme(RenderTheme::themeForPage(this))
- , m_editorClient(pageClients.editorClient)
- , m_plugInClient(pageClients.plugInClient)
- , m_validationMessageClient(pageClients.validationMessageClient)
- , m_subframeCount(0)
+ , m_editorClient(WTFMove(pageConfiguration.editorClient))
+ , m_plugInClient(pageConfiguration.plugInClient)
+ , m_validationMessageClient(WTFMove(pageConfiguration.validationMessageClient))
+ , m_diagnosticLoggingClient(WTFMove(pageConfiguration.diagnosticLoggingClient))
+ , m_webGLStateTracker(WTFMove(pageConfiguration.webGLStateTracker))
+ , m_libWebRTCProvider(WTFMove(pageConfiguration.libWebRTCProvider))
, m_openedByDOM(false)
, m_tabKeyCyclesThroughElements(true)
, m_defersLoading(false)
@@ -157,24 +216,27 @@ Page::Page(PageClients& pageClients)
, m_areMemoryCacheClientCallsEnabled(true)
, m_mediaVolume(1)
, m_pageScaleFactor(1)
- , m_deviceScaleFactor(1)
+ , m_zoomedOutPageScaleFactor(0)
+ , m_topContentInset(0)
+#if ENABLE(TEXT_AUTOSIZING)
+ , m_textAutosizingWidth(0)
+#endif
, m_suppressScrollbarAnimations(false)
+ , m_verticalScrollElasticity(ScrollElasticityAllowed)
+ , m_horizontalScrollElasticity(ScrollElasticityAllowed)
, m_didLoadUserStyleSheet(false)
, m_userStyleSheetModificationTime(0)
- , m_group(0)
- , m_debugger(0)
- , m_customHTMLTokenizerTimeDelay(-1)
- , m_customHTMLTokenizerChunkSize(-1)
+ , m_group(nullptr)
+ , m_debugger(nullptr)
, m_canStartMedia(true)
#if ENABLE(VIEW_MODE_CSS_MEDIA)
, m_viewMode(ViewModeWindowed)
#endif // ENABLE(VIEW_MODE_CSS_MEDIA)
- , m_minimumTimerInterval(Settings::defaultMinDOMTimerInterval())
- , m_timerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval())
+ , m_timerAlignmentInterval(DOMTimer::defaultAlignmentInterval())
+ , m_timerAlignmentIntervalIncreaseTimer(*this, &Page::timerAlignmentIntervalIncreaseTimerFired)
, m_isEditable(false)
- , m_isInWindow(true)
- , m_isVisible(true)
, m_isPrerender(false)
+ , m_activityState(PageInitialActivityState)
, m_requestedLayoutMilestones(0)
, m_headerHeight(0)
, m_footerHeight(0)
@@ -182,17 +244,32 @@ Page::Page(PageClients& pageClients)
#ifndef NDEBUG
, m_isPainting(false)
#endif
- , m_alternativeTextClient(pageClients.alternativeTextClient)
+ , m_alternativeTextClient(pageConfiguration.alternativeTextClient)
, m_scriptedAnimationsSuspended(false)
- , m_pageThrottler(std::make_unique<PageThrottler>(*this))
- , m_console(std::make_unique<PageConsole>(*this))
+ , m_consoleClient(std::make_unique<PageConsoleClient>(*this))
#if ENABLE(REMOTE_INSPECTOR)
, m_inspectorDebuggable(std::make_unique<PageDebuggable>(*this))
#endif
, m_lastSpatialNavigationCandidatesCount(0) // NOTE: Only called from Internals for Spatial Navigation testing.
- , m_framesHandlingBeforeUnloadEvent(0)
-{
- ASSERT(m_editorClient);
+ , m_forbidPromptsDepth(0)
+ , m_socketProvider(WTFMove(pageConfiguration.socketProvider))
+ , m_applicationCacheStorage(*WTFMove(pageConfiguration.applicationCacheStorage))
+ , m_databaseProvider(*WTFMove(pageConfiguration.databaseProvider))
+ , m_pluginInfoProvider(*WTFMove(pageConfiguration.pluginInfoProvider))
+ , m_storageNamespaceProvider(*WTFMove(pageConfiguration.storageNamespaceProvider))
+ , m_userContentProvider(*WTFMove(pageConfiguration.userContentProvider))
+ , m_visitedLinkStore(*WTFMove(pageConfiguration.visitedLinkStore))
+ , m_sessionID(SessionID::defaultSessionID())
+ , m_isClosing(false)
+ , m_isUtilityPage(isUtilityPageChromeClient(chrome().client()))
+ , m_performanceMonitor(isUtilityPage() ? nullptr : std::make_unique<PerformanceMonitor>(*this))
+{
+ updateTimerThrottlingState();
+
+ m_pluginInfoProvider->addPage(*this);
+ m_storageNamespaceProvider->addPage(*this);
+ m_userContentProvider->addPage(*this);
+ m_visitedLinkStore->addPage(*this);
if (!allPages) {
allPages = new HashSet<Page*>;
@@ -202,6 +279,8 @@ Page::Page(PageClients& pageClients)
ASSERT(!allPages->contains(this));
allPages->add(this);
+ if (!isUtilityPage())
+ ++nonUtilityPageCount;
#ifndef NDEBUG
pageCounter.increment();
@@ -210,42 +289,67 @@ Page::Page(PageClients& pageClients)
#if ENABLE(REMOTE_INSPECTOR)
m_inspectorDebuggable->init();
#endif
+
+#if PLATFORM(COCOA)
+ platformInitialize();
+#endif
}
Page::~Page()
{
- m_mainFrame->setView(0);
+ ASSERT(!m_nestedRunLoopCount);
+ ASSERT(!m_unnestCallback);
+
+ m_validationMessageClient = nullptr;
+ m_diagnosticLoggingClient = nullptr;
+ m_mainFrame->setView(nullptr);
setGroupName(String());
allPages->remove(this);
+ if (!isUtilityPage())
+ --nonUtilityPageCount;
m_settings->pageDestroyed();
+ m_inspectorController->inspectedPageDestroyed();
+
for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
frame->willDetachPage();
frame->detachFromPage();
}
- m_editorClient->pageDestroyed();
if (m_plugInClient)
m_plugInClient->pageDestroyed();
if (m_alternativeTextClient)
m_alternativeTextClient->pageDestroyed();
-#if ENABLE(INSPECTOR)
- m_inspectorController->inspectedPageDestroyed();
-#endif
-
if (m_scrollingCoordinator)
m_scrollingCoordinator->pageDestroyed();
backForward().close();
+ PageCache::singleton().removeAllItemsForPage(*this);
#ifndef NDEBUG
pageCounter.decrement();
#endif
- if (m_userContentController)
- m_userContentController->removePage(*this);
+ m_pluginInfoProvider->removePage(*this);
+ m_storageNamespaceProvider->removePage(*this);
+ m_userContentProvider->removePage(*this);
+ m_visitedLinkStore->removePage(*this);
+}
+
+void Page::clearPreviousItemFromAllPages(HistoryItem* item)
+{
+ if (!allPages)
+ return;
+
+ for (auto& page : *allPages) {
+ HistoryController& controller = page->mainFrame().loader().history();
+ if (item == controller.previousItem()) {
+ controller.clearPreviousItem();
+ return;
+ }
+ }
}
uint64_t Page::renderTreeSize() const
@@ -267,7 +371,7 @@ ViewportArguments Page::viewportArguments() const
ScrollingCoordinator* Page::scrollingCoordinator()
{
if (!m_scrollingCoordinator && m_settings->scrollingCoordinatorEnabled()) {
- m_scrollingCoordinator = chrome().client().createScrollingCoordinator(this);
+ m_scrollingCoordinator = chrome().client().createScrollingCoordinator(*this);
if (!m_scrollingCoordinator)
m_scrollingCoordinator = ScrollingCoordinator::create(this);
}
@@ -297,18 +401,22 @@ String Page::synchronousScrollingReasonsAsText()
return String();
}
-PassRefPtr<ClientRectList> Page::nonFastScrollableRects(const Frame* frame)
+Ref<ClientRectList> Page::nonFastScrollableRects()
{
if (Document* document = m_mainFrame->document())
document->updateLayout();
Vector<IntRect> rects;
- if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
- rects = scrollingCoordinator->computeNonFastScrollableRegion(frame, IntPoint()).rects();
+ if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
+ const EventTrackingRegions& eventTrackingRegions = scrollingCoordinator->absoluteEventTrackingRegions();
+ for (const auto& synchronousEventRegion : eventTrackingRegions.eventSpecificSynchronousDispatchRegions)
+ rects.appendVector(synchronousEventRegion.value.rects());
+ }
Vector<FloatQuad> quads(rects.size());
for (size_t i = 0; i < rects.size(); ++i)
quads[i] = FloatRect(rects[i]);
+
return ClientRectList::create(quads);
}
@@ -318,7 +426,7 @@ struct ViewModeInfo {
Page::ViewMode type;
};
static const int viewModeMapSize = 5;
-static ViewModeInfo viewModeMap[viewModeMapSize] = {
+static const ViewModeInfo viewModeMap[viewModeMapSize] = {
{"windowed", Page::ViewModeWindowed},
{"floating", Page::ViewModeFloating},
{"fullscreen", Page::ViewModeFullscreen},
@@ -328,9 +436,9 @@ static ViewModeInfo viewModeMap[viewModeMapSize] = {
Page::ViewMode Page::stringToViewMode(const String& text)
{
- for (int i = 0; i < viewModeMapSize; ++i) {
- if (text == viewModeMap[i].name)
- return viewModeMap[i].type;
+ for (auto& mode : viewModeMap) {
+ if (text == mode.name)
+ return mode.type;
}
return Page::ViewModeInvalid;
}
@@ -342,14 +450,12 @@ void Page::setViewMode(ViewMode viewMode)
m_viewMode = viewMode;
- if (!m_mainFrame)
- return;
if (m_mainFrame->view())
m_mainFrame->view()->forceLayout();
if (m_mainFrame->document())
- m_mainFrame->document()->styleResolverChanged(RecalcStyleImmediately);
+ m_mainFrame->document()->styleScope().didChangeStyleSheetEnvironment();
}
#endif // ENABLE(VIEW_MODE_CSS_MEDIA)
@@ -363,11 +469,11 @@ void Page::setOpenedByDOM()
m_openedByDOM = true;
}
-void Page::goToItem(HistoryItem* item, FrameLoadType type)
+void Page::goToItem(HistoryItem& item, FrameLoadType type)
{
// stopAllLoaders may end up running onload handlers, which could cause further history traversals that may lead to the passed in HistoryItem
// being deref()-ed. Make sure we can still use it with HistoryController::goToItem later.
- RefPtr<HistoryItem> protector(item);
+ Ref<HistoryItem> protector(item);
if (m_mainFrame->loader().history().shouldStopLoadingForHistoryItem(item))
m_mainFrame->loader().stopAllLoaders();
@@ -409,37 +515,26 @@ void Page::updateStyleForAllPagesAfterGlobalChangeInEnvironment()
{
if (!allPages)
return;
- HashSet<Page*>::iterator end = allPages->end();
- for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it)
- for (Frame* frame = &(*it)->mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ for (auto& page : *allPages) {
+ for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
// If a change in the global environment has occurred, we need to
// make sure all the properties a recomputed, therefore we invalidate
// the properties cache.
- if (StyleResolver* styleResolver = frame->document()->styleResolverIfExists())
+ if (!frame->document())
+ continue;
+ if (StyleResolver* styleResolver = frame->document()->styleScope().resolverIfExists())
styleResolver->invalidateMatchedPropertiesCache();
frame->document()->scheduleForcedStyleRecalc();
}
+ }
}
void Page::setNeedsRecalcStyleInAllFrames()
{
+ // FIXME: Figure out what this function is actually trying to add in different call sites.
for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
if (Document* document = frame->document())
- document->styleResolverChanged(DeferRecalcStyle);
- }
-}
-
-void Page::jettisonStyleResolversInAllDocuments()
-{
- if (!allPages)
- return;
-
- for (auto it = allPages->begin(), end = allPages->end(); it != end; ++it) {
- Page& page = **it;
- for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
- if (Document* document = frame->document())
- document->clearStyleResolver();
- }
+ document->styleScope().didChangeStyleSheetEnvironment();
}
}
@@ -448,41 +543,47 @@ void Page::refreshPlugins(bool reload)
if (!allPages)
return;
- PluginData::refresh();
+ HashSet<PluginInfoProvider*> pluginInfoProviders;
- Vector<Ref<Frame>> framesNeedingReload;
+ for (auto& page : *allPages)
+ pluginInfoProviders.add(&page->pluginInfoProvider());
- for (auto it = allPages->begin(), end = allPages->end(); it != end; ++it) {
- Page& page = **it;
- page.m_pluginData.clear();
-
- if (!reload)
- continue;
-
- for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
- if (frame->loader().subframeLoader().containsPlugins())
- framesNeedingReload.append(*frame);
- }
- }
-
- for (size_t i = 0; i < framesNeedingReload.size(); ++i)
- framesNeedingReload[i]->loader().reload();
+ for (auto& pluginInfoProvider : pluginInfoProviders)
+ pluginInfoProvider->refresh(reload);
}
-PluginData& Page::pluginData() const
+PluginData& Page::pluginData()
{
if (!m_pluginData)
- m_pluginData = PluginData::create(this);
+ m_pluginData = PluginData::create(*this);
return *m_pluginData;
}
-inline MediaCanStartListener* Page::takeAnyMediaCanStartListener()
+void Page::clearPluginData()
+{
+ m_pluginData = nullptr;
+}
+
+bool Page::showAllPlugins() const
+{
+ if (m_showAllPlugins)
+ return true;
+
+ if (Document* document = mainFrame().document())
+ return document->securityOrigin().isLocal();
+
+ return false;
+}
+
+inline std::optional<std::pair<MediaCanStartListener&, Document&>> Page::takeAnyMediaCanStartListener()
{
for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
if (MediaCanStartListener* listener = frame->document()->takeAnyMediaCanStartListener())
- return listener;
+ return { { *listener, *frame->document() } };
}
- return 0;
+ return std::nullopt;
}
void Page::setCanStartMedia(bool canStartMedia)
@@ -493,10 +594,10 @@ void Page::setCanStartMedia(bool canStartMedia)
m_canStartMedia = canStartMedia;
while (m_canStartMedia) {
- MediaCanStartListener* listener = takeAnyMediaCanStartListener();
+ auto listener = takeAnyMediaCanStartListener();
if (!listener)
break;
- listener->mediaCanStart();
+ listener->first.mediaCanStart(listener->second);
}
}
@@ -536,35 +637,37 @@ bool Page::findString(const String& target, FindOptions options)
return false;
}
-void Page::findStringMatchingRanges(const String& target, FindOptions options, int limit, Vector<RefPtr<Range>>* matchRanges, int& indexForSelection)
+void Page::findStringMatchingRanges(const String& target, FindOptions options, int limit, Vector<RefPtr<Range>>& matchRanges, int& indexForSelection)
{
indexForSelection = 0;
Frame* frame = &mainFrame();
- Frame* frameWithSelection = 0;
+ Frame* frameWithSelection = nullptr;
do {
- frame->editor().countMatchesForText(target, 0, options, limit ? (limit - matchRanges->size()) : 0, true, matchRanges);
+ frame->editor().countMatchesForText(target, 0, options, limit ? (limit - matchRanges.size()) : 0, true, &matchRanges);
if (frame->selection().isRange())
frameWithSelection = frame;
frame = incrementFrame(frame, true, false);
} while (frame);
- if (matchRanges->isEmpty())
+ if (matchRanges.isEmpty())
return;
if (frameWithSelection) {
indexForSelection = NoMatchAfterUserSelection;
RefPtr<Range> selectedRange = frameWithSelection->selection().selection().firstRange();
if (options & Backwards) {
- for (size_t i = matchRanges->size(); i > 0; --i) {
- if (selectedRange->compareBoundaryPoints(Range::END_TO_START, matchRanges->at(i - 1).get(), IGNORE_EXCEPTION) > 0) {
+ for (size_t i = matchRanges.size(); i > 0; --i) {
+ auto result = selectedRange->compareBoundaryPoints(Range::END_TO_START, *matchRanges[i - 1]);
+ if (!result.hasException() && result.releaseReturnValue() > 0) {
indexForSelection = i - 1;
break;
}
}
} else {
- for (size_t i = 0; i < matchRanges->size(); ++i) {
- if (selectedRange->compareBoundaryPoints(Range::START_TO_END, matchRanges->at(i).get(), IGNORE_EXCEPTION) < 0) {
+ for (size_t i = 0, size = matchRanges.size(); i < size; ++i) {
+ auto result = selectedRange->compareBoundaryPoints(Range::START_TO_END, *matchRanges[i]);
+ if (!result.hasException() && result.releaseReturnValue() < 0) {
indexForSelection = i;
break;
}
@@ -572,26 +675,26 @@ void Page::findStringMatchingRanges(const String& target, FindOptions options, i
}
} else {
if (options & Backwards)
- indexForSelection = matchRanges->size() - 1;
+ indexForSelection = matchRanges.size() - 1;
else
indexForSelection = 0;
}
}
-PassRefPtr<Range> Page::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
+RefPtr<Range> Page::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
{
if (target.isEmpty())
- return 0;
+ return nullptr;
if (referenceRange && referenceRange->ownerDocument().page() != this)
- return 0;
+ return nullptr;
bool shouldWrap = options & WrapAround;
Frame* frame = referenceRange ? referenceRange->ownerDocument().frame() : &mainFrame();
Frame* startFrame = frame;
do {
if (RefPtr<Range> resultRange = frame->editor().rangeOfString(target, frame == startFrame ? referenceRange : 0, options & ~WrapAround))
- return resultRange.release();
+ return resultRange;
frame = incrementFrame(frame, !(options & Backwards), shouldWrap);
} while (frame && frame != startFrame);
@@ -600,10 +703,10 @@ PassRefPtr<Range> Page::rangeOfString(const String& target, Range* referenceRang
// We cheat a bit and just search again with wrap on.
if (shouldWrap && referenceRange) {
if (RefPtr<Range> resultRange = startFrame->editor().rangeOfString(target, referenceRange, options | WrapAround | StartInSelection))
- return resultRange.release();
+ return resultRange;
}
- return 0;
+ return nullptr;
}
unsigned Page::findMatchesForText(const String& target, FindOptions options, unsigned maxMatchCount, ShouldHighlightMatches shouldHighlightMatches, ShouldMarkMatches shouldMarkMatches)
@@ -685,6 +788,13 @@ void Page::setInLowQualityImageInterpolationMode(bool mode)
m_inLowQualityInterpolationMode = mode;
}
+DiagnosticLoggingClient& Page::diagnosticLoggingClient() const
+{
+ if (!settings().diagnosticLoggingEnabled() || !m_diagnosticLoggingClient)
+ return emptyDiagnosticLoggingClient();
+ return *m_diagnosticLoggingClient;
+}
+
void Page::setMediaVolume(float volume)
{
if (volume < 0 || volume > 1)
@@ -695,21 +805,47 @@ void Page::setMediaVolume(float volume)
m_mediaVolume = volume;
for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
frame->document()->mediaVolumeDidChange();
}
}
-void Page::setPageScaleFactor(float scale, const IntPoint& origin)
+void Page::setZoomedOutPageScaleFactor(float scale)
+{
+ if (m_zoomedOutPageScaleFactor == scale)
+ return;
+ m_zoomedOutPageScaleFactor = scale;
+
+ mainFrame().deviceOrPageScaleFactorChanged();
+}
+
+void Page::setPageScaleFactor(float scale, const IntPoint& origin, bool inStableState)
{
Document* document = mainFrame().document();
FrameView* view = document->view();
if (scale == m_pageScaleFactor) {
- if (view && (view->scrollPosition() != origin || view->delegatesScrolling())) {
+ if (view && view->scrollPosition() != origin) {
if (!m_settings->delegatesPageScaling())
document->updateLayoutIgnorePendingStylesheets();
- view->setScrollPosition(origin);
+
+ if (!view->delegatesScrolling())
+ view->setScrollPosition(origin);
+#if USE(COORDINATED_GRAPHICS)
+ else
+ view->requestScrollPositionUpdate(origin);
+#endif
}
+#if ENABLE(MEDIA_CONTROLS_SCRIPT)
+ if (inStableState) {
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+ frame->document()->pageScaleFactorChangedAndStable();
+ }
+ }
+#endif
return;
}
@@ -725,9 +861,7 @@ void Page::setPageScaleFactor(float scale, const IntPoint& origin)
mainFrame().view()->invalidateRect(IntRect(LayoutRect::infiniteRect()));
}
-#if USE(ACCELERATED_COMPOSITING)
mainFrame().deviceOrPageScaleFactorChanged();
-#endif
if (view && view->fixedElementsLayoutRelativeToFrame())
view->setViewportConstrainedObjectsNeedLayout();
@@ -735,29 +869,100 @@ void Page::setPageScaleFactor(float scale, const IntPoint& origin)
if (view && view->scrollPosition() != origin) {
if (!m_settings->delegatesPageScaling() && document->renderView() && document->renderView()->needsLayout() && view->didFirstLayout())
view->layout();
- view->setScrollPosition(origin);
+
+ if (!view->delegatesScrolling())
+ view->setScrollPosition(origin);
+#if USE(COORDINATED_GRAPHICS)
+ else
+ view->requestScrollPositionUpdate(origin);
+#endif
+ }
+
+#if ENABLE(MEDIA_CONTROLS_SCRIPT)
+ if (inStableState) {
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+ frame->document()->pageScaleFactorChangedAndStable();
+ }
}
+#else
+ UNUSED_PARAM(inStableState);
+#endif
}
+void Page::setViewScaleFactor(float scale)
+{
+ if (m_viewScaleFactor == scale)
+ return;
+
+ m_viewScaleFactor = scale;
+ PageCache::singleton().markPagesForDeviceOrPageScaleChanged(*this);
+}
void Page::setDeviceScaleFactor(float scaleFactor)
{
+ ASSERT(scaleFactor > 0);
+ if (scaleFactor <= 0)
+ return;
+
if (m_deviceScaleFactor == scaleFactor)
return;
m_deviceScaleFactor = scaleFactor;
setNeedsRecalcStyleInAllFrames();
-#if USE(ACCELERATED_COMPOSITING)
mainFrame().deviceOrPageScaleFactorChanged();
- pageCache()->markPagesForDeviceScaleChanged(this);
+ PageCache::singleton().markPagesForDeviceOrPageScaleChanged(*this);
+
+ GraphicsContext::updateDocumentMarkerResources();
+
+ mainFrame().pageOverlayController().didChangeDeviceScaleFactor();
+}
+
+void Page::setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection userInterfaceLayoutDirection)
+{
+ if (m_userInterfaceLayoutDirection == userInterfaceLayoutDirection)
+ return;
+
+ m_userInterfaceLayoutDirection = userInterfaceLayoutDirection;
+#if ENABLE(MEDIA_CONTROLS_SCRIPT)
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+ frame->document()->userInterfaceLayoutDirectionChanged();
+ }
#endif
+}
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
- frame->editor().deviceScaleFactorChanged();
+void Page::didStartProvisionalLoad()
+{
+ if (m_performanceMonitor)
+ m_performanceMonitor->didStartProvisionalLoad();
+}
- pageCache()->markPagesForFullStyleRecalc(this);
- GraphicsContext::updateDocumentMarkerResources();
+void Page::didFinishLoad()
+{
+ resetRelevantPaintedObjectCounter();
+
+ if (m_performanceMonitor)
+ m_performanceMonitor->didFinishLoad();
+}
+
+bool Page::isOnlyNonUtilityPage() const
+{
+ return !isUtilityPage() && nonUtilityPageCount == 1;
+}
+
+void Page::setTopContentInset(float contentInset)
+{
+ if (m_topContentInset == contentInset)
+ return;
+
+ m_topContentInset = contentInset;
+
+ if (FrameView* view = mainFrame().view())
+ view->topContentInsetDidChange(m_topContentInset);
}
void Page::setShouldSuppressScrollbarAnimations(bool suppressAnimations)
@@ -786,12 +991,32 @@ void Page::lockAllOverlayScrollbarsToHidden(bool lockOverlayScrollbars)
if (!scrollableAreas)
continue;
- for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
- ScrollableArea* scrollableArea = *it;
+ for (auto& scrollableArea : *scrollableAreas)
scrollableArea->lockOverlayScrollbarStateToHidden(lockOverlayScrollbars);
- }
}
}
+
+void Page::setVerticalScrollElasticity(ScrollElasticity elasticity)
+{
+ if (m_verticalScrollElasticity == elasticity)
+ return;
+
+ m_verticalScrollElasticity = elasticity;
+
+ if (FrameView* view = mainFrame().view())
+ view->setVerticalScrollElasticity(elasticity);
+}
+
+void Page::setHorizontalScrollElasticity(ScrollElasticity elasticity)
+{
+ if (m_horizontalScrollElasticity == elasticity)
+ return;
+
+ m_horizontalScrollElasticity = elasticity;
+
+ if (FrameView* view = mainFrame().view())
+ view->setHorizontalScrollElasticity(elasticity);
+}
void Page::setPagination(const Pagination& pagination)
{
@@ -801,7 +1026,16 @@ void Page::setPagination(const Pagination& pagination)
m_pagination = pagination;
setNeedsRecalcStyleInAllFrames();
- pageCache()->markPagesForFullStyleRecalc(this);
+}
+
+void Page::setPaginationLineGridEnabled(bool enabled)
+{
+ if (m_paginationLineGridEnabled == enabled)
+ return;
+
+ m_paginationLineGridEnabled = enabled;
+
+ setNeedsRecalcStyleInAllFrames();
}
unsigned Page::pageCount() const
@@ -813,16 +1047,16 @@ unsigned Page::pageCount() const
document->updateLayoutIgnorePendingStylesheets();
RenderView* contentRenderer = mainFrame().contentRenderer();
- return contentRenderer ? contentRenderer->columnCount(contentRenderer->columnInfo()) : 0;
+ return contentRenderer ? contentRenderer->pageCount() : 0;
}
void Page::setIsInWindow(bool isInWindow)
{
- if (m_isInWindow == isInWindow)
- return;
-
- m_isInWindow = isInWindow;
+ setActivityState(isInWindow ? m_activityState | ActivityState::IsInWindow : m_activityState & ~ActivityState::IsInWindow);
+}
+void Page::setIsInWindowInternal(bool isInWindow)
+{
for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
if (FrameView* frameView = frame->view())
frameView->setIsInWindow(isInWindow);
@@ -832,6 +1066,16 @@ void Page::setIsInWindow(bool isInWindow)
resumeAnimatingImages();
}
+void Page::addActivityStateChangeObserver(ActivityStateChangeObserver& observer)
+{
+ m_activityStateChangeObservers.add(&observer);
+}
+
+void Page::removeActivityStateChangeObserver(ActivityStateChangeObserver& observer)
+{
+ m_activityStateChangeObservers.remove(&observer);
+}
+
void Page::suspendScriptedAnimations()
{
m_scriptedAnimationsSuspended = true;
@@ -850,9 +1094,12 @@ void Page::resumeScriptedAnimations()
}
}
-void Page::setIsVisuallyIdle(bool isVisuallyIdle)
+void Page::setIsVisuallyIdleInternal(bool isVisuallyIdle)
{
- m_pageThrottler->setIsVisuallyIdle(isVisuallyIdle);
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (frame->document())
+ frame->document()->scriptedAnimationControllerSetThrottled(isVisuallyIdle);
+ }
}
void Page::userStyleSheetLocationChanged()
@@ -862,7 +1109,7 @@ void Page::userStyleSheetLocationChanged()
URL url = m_settings->userStyleSheetLocation();
// Allow any local file URL scheme to be loaded.
- if (SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol()))
+ if (SchemeRegistry::shouldTreatURLSchemeAsLocal(url.protocol().toStringWithoutCopying()))
m_userStyleSheetPath = url.fileSystemPath();
else
m_userStyleSheetPath = String();
@@ -877,13 +1124,13 @@ void Page::userStyleSheetLocationChanged()
m_didLoadUserStyleSheet = true;
Vector<char> styleSheetAsUTF8;
- if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, Base64IgnoreWhitespace))
+ if (base64Decode(decodeURLEscapeSequences(url.string().substring(35)), styleSheetAsUTF8, Base64IgnoreSpacesAndNewLines))
m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size());
}
for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
if (frame->document())
- frame->document()->styleSheetCollection().updatePageUserSheet();
+ frame->document()->extensionStyleSheets().updatePageUserSheet();
}
}
@@ -921,57 +1168,36 @@ const String& Page::userStyleSheet() const
if (!data)
return m_userStyleSheet;
- RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/css");
- m_userStyleSheet = decoder->decode(data->data(), data->size());
- m_userStyleSheet.append(decoder->flush());
+ m_userStyleSheet = TextResourceDecoder::create("text/css")->decodeAndFlush(data->data(), data->size());
return m_userStyleSheet;
}
-void Page::removeAllVisitedLinks()
+void Page::invalidateStylesForAllLinks()
{
- if (!allPages)
- return;
- HashSet<PageGroup*> groups;
- HashSet<Page*>::iterator pagesEnd = allPages->end();
- for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
- if (PageGroup* group = (*it)->groupPtr())
- groups.add(group);
+ for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+ frame->document()->visitedLinkState().invalidateStyleForAllLinks();
}
- HashSet<PageGroup*>::iterator groupsEnd = groups.end();
- for (HashSet<PageGroup*>::iterator it = groups.begin(); it != groupsEnd; ++it)
- (*it)->removeVisitedLinks();
}
-void Page::allVisitedStateChanged(PageGroup* group)
+void Page::invalidateStylesForLink(LinkHash linkHash)
{
- ASSERT(group);
- if (!allPages)
- return;
-
- HashSet<Page*>::iterator pagesEnd = allPages->end();
- for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
- Page* page = *it;
- if (page->m_group != group)
+ for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
continue;
- for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
- frame->document()->visitedLinkState().invalidateStyleForAllLinks();
+ frame->document()->visitedLinkState().invalidateStyleForLink(linkHash);
}
}
-void Page::visitedStateChanged(PageGroup* group, LinkHash linkHash)
+void Page::invalidateInjectedStyleSheetCacheInAllFrames()
{
- ASSERT(group);
- if (!allPages)
- return;
-
- HashSet<Page*>::iterator pagesEnd = allPages->end();
- for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) {
- Page* page = *it;
- if (page->m_group != group)
+ for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext()) {
+ Document* document = frame->document();
+ if (!document)
continue;
- for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
- frame->document()->visitedLinkState().invalidateStyleForLink(linkHash);
+ document->extensionStyleSheets().invalidateInjectedStyleSheetCache();
}
}
@@ -982,39 +1208,45 @@ void Page::setDebugger(JSC::Debugger* debugger)
m_debugger = debugger;
- for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
+ for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
frame->script().attachDebugger(m_debugger);
}
StorageNamespace* Page::sessionStorage(bool optionalCreate)
{
if (!m_sessionStorage && optionalCreate)
- m_sessionStorage = StorageNamespace::sessionStorageNamespace(this);
+ m_sessionStorage = m_storageNamespaceProvider->createSessionStorageNamespace(*this, m_settings->sessionStorageQuota());
return m_sessionStorage.get();
}
-void Page::setSessionStorage(PassRefPtr<StorageNamespace> newStorage)
+void Page::setSessionStorage(RefPtr<StorageNamespace>&& newStorage)
{
- m_sessionStorage = newStorage;
+ m_sessionStorage = WTFMove(newStorage);
}
-void Page::setCustomHTMLTokenizerTimeDelay(double customHTMLTokenizerTimeDelay)
+StorageNamespace* Page::ephemeralLocalStorage(bool optionalCreate)
{
- if (customHTMLTokenizerTimeDelay < 0) {
- m_customHTMLTokenizerTimeDelay = -1;
- return;
- }
- m_customHTMLTokenizerTimeDelay = customHTMLTokenizerTimeDelay;
+ if (!m_ephemeralLocalStorage && optionalCreate)
+ m_ephemeralLocalStorage = m_storageNamespaceProvider->createEphemeralLocalStorageNamespace(*this, m_settings->sessionStorageQuota());
+
+ return m_ephemeralLocalStorage.get();
}
-void Page::setCustomHTMLTokenizerChunkSize(int customHTMLTokenizerChunkSize)
+void Page::setEphemeralLocalStorage(RefPtr<StorageNamespace>&& newStorage)
{
- if (customHTMLTokenizerChunkSize < 0) {
- m_customHTMLTokenizerChunkSize = -1;
- return;
- }
- m_customHTMLTokenizerChunkSize = customHTMLTokenizerChunkSize;
+ m_ephemeralLocalStorage = WTFMove(newStorage);
+}
+
+bool Page::hasCustomHTMLTokenizerTimeDelay() const
+{
+ return m_settings->maxParseDuration() != -1;
+}
+
+double Page::customHTMLTokenizerTimeDelay() const
+{
+ ASSERT(m_settings->maxParseDuration() != -1);
+ return m_settings->maxParseDuration();
}
void Page::setMemoryCacheClientCallsEnabled(bool enabled)
@@ -1030,91 +1262,211 @@ void Page::setMemoryCacheClientCallsEnabled(bool enabled)
frame->loader().tellClientAboutPastMemoryCacheLoads();
}
-void Page::setMinimumTimerInterval(double minimumTimerInterval)
+void Page::hiddenPageDOMTimerThrottlingStateChanged()
{
- double oldTimerInterval = m_minimumTimerInterval;
- m_minimumTimerInterval = minimumTimerInterval;
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNextWithWrap(false)) {
- if (frame->document())
- frame->document()->adjustMinimumTimerInterval(oldTimerInterval);
- }
+ // Disable & reengage to ensure state is updated.
+ setTimerThrottlingState(TimerThrottlingState::Disabled);
+ updateTimerThrottlingState();
}
-double Page::minimumTimerInterval() const
+void Page::updateTimerThrottlingState()
{
- return m_minimumTimerInterval;
+ // Timer throttling disabled if page is visually active, or disabled by setting.
+ if (!m_settings->hiddenPageDOMTimerThrottlingEnabled() || !(m_activityState & ActivityState::IsVisuallyIdle)) {
+ setTimerThrottlingState(TimerThrottlingState::Disabled);
+ return;
+ }
+
+ // If the page is visible (but idle), there is any activity (loading, media playing, etc), or per setting,
+ // we allow timer throttling, but not increasing timer throttling.
+ if (!m_settings->hiddenPageDOMTimerThrottlingAutoIncreases()
+ || m_activityState & (ActivityState::IsVisible | ActivityState::IsAudible | ActivityState::IsLoading)) {
+ setTimerThrottlingState(TimerThrottlingState::Enabled);
+ return;
+ }
+
+ // If we get here increasing timer throttling is enabled.
+ setTimerThrottlingState(TimerThrottlingState::EnabledIncreasing);
}
-void Page::setTimerAlignmentInterval(double interval)
+void Page::setTimerThrottlingState(TimerThrottlingState state)
{
- if (interval == m_timerAlignmentInterval)
+ if (state == m_timerThrottlingState)
return;
- m_timerAlignmentInterval = interval;
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNextWithWrap(false)) {
- if (frame->document())
- frame->document()->didChangeTimerAlignmentInterval();
+ m_timerThrottlingState = state;
+ m_timerThrottlingStateLastChangedTime = std::chrono::steady_clock::now();
+
+ updateDOMTimerAlignmentInterval();
+
+ // When throttling is disabled, release all throttled timers.
+ if (state == TimerThrottlingState::Disabled) {
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (auto* document = frame->document())
+ document->didChangeTimerAlignmentInterval();
+ }
}
}
-double Page::timerAlignmentInterval() const
+void Page::setTimerAlignmentIntervalIncreaseLimit(std::chrono::milliseconds limit)
{
- return m_timerAlignmentInterval;
+ m_timerAlignmentIntervalIncreaseLimit = limit;
+
+ // If (m_timerAlignmentIntervalIncreaseLimit < m_timerAlignmentInterval) then we need
+ // to update m_timerAlignmentInterval, if greater then need to restart the increase timer.
+ if (m_timerThrottlingState == TimerThrottlingState::EnabledIncreasing)
+ updateDOMTimerAlignmentInterval();
+}
+
+void Page::updateDOMTimerAlignmentInterval()
+{
+ bool needsIncreaseTimer = false;
+
+ switch (m_timerThrottlingState) {
+ case TimerThrottlingState::Disabled:
+ m_timerAlignmentInterval = DOMTimer::defaultAlignmentInterval();
+ break;
+
+ case TimerThrottlingState::Enabled:
+ m_timerAlignmentInterval = DOMTimer::hiddenPageAlignmentInterval();
+ break;
+
+ case TimerThrottlingState::EnabledIncreasing:
+ // For pages in prerender state maximum throttling kicks in immediately.
+ if (m_isPrerender)
+ m_timerAlignmentInterval = m_timerAlignmentIntervalIncreaseLimit;
+ else {
+ ASSERT(m_timerThrottlingStateLastChangedTime.time_since_epoch() != std::chrono::steady_clock::duration::zero());
+ m_timerAlignmentInterval = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_timerThrottlingStateLastChangedTime);
+ // If we're below the limit, set the timer. If above, clamp to limit.
+ if (m_timerAlignmentInterval < m_timerAlignmentIntervalIncreaseLimit)
+ needsIncreaseTimer = true;
+ else
+ m_timerAlignmentInterval = m_timerAlignmentIntervalIncreaseLimit;
+ }
+ // Alignment interval should not be less than DOMTimer::hiddenPageAlignmentInterval().
+ m_timerAlignmentInterval = std::max(m_timerAlignmentInterval, DOMTimer::hiddenPageAlignmentInterval());
+ }
+
+ // If throttling is enabled, auto-increasing of throttling is enabled, and the auto-increase
+ // limit has not yet been reached, and then arm the timer to consider an increase. Time to wait
+ // between increases is equal to the current throttle time. Since alinment interval increases
+ // exponentially, time between steps is exponential too.
+ if (!needsIncreaseTimer)
+ m_timerAlignmentIntervalIncreaseTimer.stop();
+ else if (!m_timerAlignmentIntervalIncreaseTimer.isActive())
+ m_timerAlignmentIntervalIncreaseTimer.startOneShot(m_timerAlignmentInterval);
+}
+
+void Page::timerAlignmentIntervalIncreaseTimerFired()
+{
+ ASSERT(m_settings->hiddenPageDOMTimerThrottlingAutoIncreases());
+ ASSERT(m_timerThrottlingState == TimerThrottlingState::EnabledIncreasing);
+ ASSERT(m_timerAlignmentInterval < m_timerAlignmentIntervalIncreaseLimit);
+
+ // Alignment interval is increased to equal the time the page has been throttled, to a limit.
+ updateDOMTimerAlignmentInterval();
}
void Page::dnsPrefetchingStateChanged()
{
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
frame->document()->initDNSPrefetch();
+ }
}
Vector<Ref<PluginViewBase>> Page::pluginViews()
{
Vector<Ref<PluginViewBase>> views;
-
for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
- FrameView* view = frame->view();
+ auto* view = frame->view();
if (!view)
break;
-
- for (auto it = view->children().begin(), end = view->children().end(); it != end; ++it) {
- Widget* widget = (*it).get();
- if (widget->isPluginViewBase())
- views.append(*toPluginViewBase(widget));
+ for (auto& widget : view->children()) {
+ if (is<PluginViewBase>(widget.get()))
+ views.append(downcast<PluginViewBase>(widget.get()));
}
}
-
return views;
}
void Page::storageBlockingStateChanged()
{
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
frame->document()->storageBlockingStateDidChange();
+ }
// Collect the PluginViews in to a vector to ensure that action the plug-in takes
// from below storageBlockingStateChanged does not affect their lifetime.
- auto views = pluginViews();
+ for (auto& view : pluginViews())
+ view->storageBlockingStateChanged();
+}
+
+void Page::enableLegacyPrivateBrowsing(bool privateBrowsingEnabled)
+{
+ // Don't allow changing the legacy private browsing state if we have set a session ID.
+ ASSERT(m_sessionID == SessionID::defaultSessionID() || m_sessionID == SessionID::legacyPrivateSessionID());
- for (unsigned i = 0; i < views.size(); ++i)
- views[i]->storageBlockingStateChanged();
+ setSessionID(privateBrowsingEnabled ? SessionID::legacyPrivateSessionID() : SessionID::defaultSessionID());
}
-void Page::privateBrowsingStateChanged()
+void Page::updateIsPlayingMedia(uint64_t sourceElementID)
{
- bool privateBrowsingEnabled = m_settings->privateBrowsingEnabled();
+ MediaProducer::MediaStateFlags state = MediaProducer::IsNotPlaying;
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (Document* document = frame->document())
+ state |= document->mediaState();
+ }
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
- frame->document()->privateBrowsingStateDidChange();
+ if (state == m_mediaState)
+ return;
- // Collect the PluginViews in to a vector to ensure that action the plug-in takes
- // from below privateBrowsingStateChanged does not affect their lifetime.
- auto views = pluginViews();
+ m_mediaState = state;
- for (unsigned i = 0; i < views.size(); ++i)
- views[i]->privateBrowsingStateChanged(privateBrowsingEnabled);
+ chrome().client().isPlayingMediaDidChange(state, sourceElementID);
}
+void Page::setMuted(MediaProducer::MutedStateFlags muted)
+{
+ if (m_mutedState == muted)
+ return;
+
+ m_mutedState = muted;
+
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+ frame->document()->pageMutedStateDidChange();
+ }
+}
+
+#if ENABLE(MEDIA_SESSION)
+void Page::handleMediaEvent(MediaEventType eventType)
+{
+ switch (eventType) {
+ case MediaEventType::PlayPause:
+ MediaSessionManager::singleton().togglePlayback();
+ break;
+ case MediaEventType::TrackNext:
+ MediaSessionManager::singleton().skipToNextTrack();
+ break;
+ case MediaEventType::TrackPrevious:
+ MediaSessionManager::singleton().skipToPreviousTrack();
+ break;
+ }
+}
+
+void Page::setVolumeOfMediaElement(double volume, uint64_t elementID)
+{
+ if (HTMLMediaElement* element = HTMLMediaElement::elementWithID(elementID))
+ element->setVolume(volume, ASSERT_NO_EXCEPTION);
+}
+#endif
+
#if !ASSERT_DISABLED
void Page::checkSubframeCountConsistency() const
{
@@ -1128,86 +1480,127 @@ void Page::checkSubframeCountConsistency() const
}
#endif
-void Page::throttleTimers()
+void Page::resumeAnimatingImages()
{
-#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
- if (m_settings->hiddenPageDOMTimerThrottlingEnabled())
- setTimerAlignmentInterval(Settings::hiddenPageDOMTimerAlignmentInterval());
-#endif
+ // Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
+ // require that we repaint animated images to kickstart the animation loop.
+ if (FrameView* view = mainFrame().view())
+ view->resumeVisibleImageAnimationsIncludingSubframes();
}
-void Page::unthrottleTimers()
+void Page::setActivityState(ActivityState::Flags activityState)
{
-#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
- if (m_settings->hiddenPageDOMTimerThrottlingEnabled())
- setTimerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval());
-#endif
+ ActivityState::Flags changed = m_activityState ^ activityState;
+ if (!changed)
+ return;
+
+ ActivityState::Flags oldActivityState = m_activityState;
+
+ bool wasVisibleAndActive = isVisibleAndActive();
+ m_activityState = activityState;
+
+ m_focusController->setActivityState(activityState);
+
+ if (changed & ActivityState::IsVisible)
+ setIsVisibleInternal(activityState & ActivityState::IsVisible);
+ if (changed & ActivityState::IsInWindow)
+ setIsInWindowInternal(activityState & ActivityState::IsInWindow);
+ if (changed & ActivityState::IsVisuallyIdle)
+ setIsVisuallyIdleInternal(activityState & ActivityState::IsVisuallyIdle);
+ if (changed & ActivityState::WindowIsActive) {
+ if (auto* view = m_mainFrame->view())
+ view->updateTiledBackingAdaptiveSizing();
+ }
+
+ if (changed & (ActivityState::IsVisible | ActivityState::IsVisuallyIdle | ActivityState::IsAudible | ActivityState::IsLoading))
+ updateTimerThrottlingState();
+
+ for (auto* observer : m_activityStateChangeObservers)
+ observer->activityStateDidChange(oldActivityState, m_activityState);
+
+ if (wasVisibleAndActive != isVisibleAndActive())
+ PlatformMediaSessionManager::updateNowPlayingInfoIfNecessary();
+
+ if (m_performanceMonitor)
+ m_performanceMonitor->activityStateChanged(oldActivityState, activityState);
}
-void Page::resumeAnimatingImages()
+bool Page::isVisibleAndActive() const
{
- // Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
- // require that we repaint animated images to kickstart the animation loop.
+ return (m_activityState & ActivityState::IsVisible) && (m_activityState & ActivityState::WindowIsActive);
+}
+
+bool Page::isWindowActive() const
+{
+ return m_activityState & ActivityState::WindowIsActive;
+}
+
+void Page::setIsVisible(bool isVisible)
+{
+ if (isVisible)
+ setActivityState((m_activityState & ~ActivityState::IsVisuallyIdle) | ActivityState::IsVisible | ActivityState::IsVisibleOrOccluded);
+ else
+ setActivityState((m_activityState & ~(ActivityState::IsVisible | ActivityState::IsVisibleOrOccluded)) | ActivityState::IsVisuallyIdle);
+}
+
+enum class SVGAnimationsState { Paused, Resumed };
+static inline void setSVGAnimationsState(Page& page, SVGAnimationsState state)
+{
+ for (Frame* frame = &page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ auto* document = frame->document();
+ if (!document)
+ continue;
+
+ if (!document->svgExtensions())
+ continue;
- for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
- CachedImage::resumeAnimatingImagesForLoader(frame->document()->cachedResourceLoader());
+ if (state == SVGAnimationsState::Paused)
+ document->accessSVGExtensions().pauseAnimations();
+ else
+ document->accessSVGExtensions().unpauseAnimations();
+ }
}
-void Page::setIsVisible(bool isVisible, bool isInitialState)
+void Page::setIsVisibleInternal(bool isVisible)
{
// FIXME: The visibility state should be stored on the top-level document.
// https://bugs.webkit.org/show_bug.cgi?id=116769
- if (m_isVisible == isVisible)
- return;
- m_isVisible = isVisible;
-
if (isVisible) {
m_isPrerender = false;
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
- if (FrameView* frameView = frame->view())
- frameView->didMoveOnscreen();
- }
-
resumeScriptedAnimations();
+#if PLATFORM(IOS)
+ resumeDeviceMotionAndOrientationUpdates();
+#endif
if (FrameView* view = mainFrame().view())
view->show();
- unthrottleTimers();
-
if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
mainFrame().animation().resumeAnimations();
+ setSVGAnimationsState(*this, SVGAnimationsState::Resumed);
+
resumeAnimatingImages();
}
-#if ENABLE(PAGE_VISIBILITY_API)
- if (!isInitialState) {
- Vector<Ref<Document>> documents;
- for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
- documents.append(*frame->document());
+ Vector<Ref<Document>> documents;
+ for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
+ documents.append(*frame->document());
- for (size_t i = 0, size = documents.size(); i < size; ++i)
- documents[i]->visibilityStateChanged();
- }
-#else
- UNUSED_PARAM(isInitialState);
-#endif
+ for (auto& document : documents)
+ document->visibilityStateChanged();
if (!isVisible) {
- if (m_pageThrottler->shouldThrottleTimers())
- throttleTimers();
-
if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
mainFrame().animation().suspendAnimations();
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
- if (FrameView* frameView = frame->view())
- frameView->willMoveOffscreen();
- }
+ setSVGAnimationsState(*this, SVGAnimationsState::Paused);
+#if PLATFORM(IOS)
+ suspendDeviceMotionAndOrientationUpdates();
+#endif
suspendScriptedAnimations();
if (FrameView* view = mainFrame().view())
@@ -1218,18 +1611,17 @@ void Page::setIsVisible(bool isVisible, bool isInitialState)
void Page::setIsPrerender()
{
m_isPrerender = true;
+ updateDOMTimerAlignmentInterval();
}
-#if ENABLE(PAGE_VISIBILITY_API)
PageVisibilityState Page::visibilityState() const
{
- if (m_isVisible)
- return PageVisibilityStateVisible;
+ if (isVisible())
+ return PageVisibilityState::Visible;
if (m_isPrerender)
- return PageVisibilityStatePrerender;
- return PageVisibilityStateHidden;
+ return PageVisibilityState::Prerender;
+ return PageVisibilityState::Hidden;
}
-#endif
#if ENABLE(RUBBER_BANDING)
void Page::addHeaderWithHeight(int headerHeight)
@@ -1265,6 +1657,41 @@ void Page::addFooterWithHeight(int footerHeight)
}
#endif
+void Page::incrementNestedRunLoopCount()
+{
+ m_nestedRunLoopCount++;
+}
+
+void Page::decrementNestedRunLoopCount()
+{
+ ASSERT(m_nestedRunLoopCount);
+ if (m_nestedRunLoopCount <= 0)
+ return;
+
+ m_nestedRunLoopCount--;
+
+ if (!m_nestedRunLoopCount && m_unnestCallback) {
+ callOnMainThread([this] {
+ if (insideNestedRunLoop())
+ return;
+
+ // This callback may destruct the Page.
+ if (m_unnestCallback) {
+ auto callback = m_unnestCallback;
+ m_unnestCallback = nullptr;
+ callback();
+ }
+ });
+ }
+}
+
+void Page::whenUnnested(std::function<void()> callback)
+{
+ ASSERT(!m_unnestCallback);
+
+ m_unnestCallback = callback;
+}
+
#if ENABLE(REMOTE_INSPECTOR)
bool Page::remoteInspectionAllowed() const
{
@@ -1276,6 +1703,16 @@ void Page::setRemoteInspectionAllowed(bool allowed)
m_inspectorDebuggable->setRemoteDebuggingAllowed(allowed);
}
+String Page::remoteInspectionNameOverride() const
+{
+ return m_inspectorDebuggable->nameOverride();
+}
+
+void Page::setRemoteInspectionNameOverride(const String& name)
+{
+ m_inspectorDebuggable->setNameOverride(name);
+}
+
void Page::remoteInspectorInformationDidChange() const
{
m_inspectorDebuggable->update();
@@ -1293,9 +1730,22 @@ void Page::removeLayoutMilestones(LayoutMilestones milestones)
m_requestedLayoutMilestones &= ~milestones;
}
+Color Page::pageExtendedBackgroundColor() const
+{
+ FrameView* frameView = mainFrame().view();
+ if (!frameView)
+ return Color();
+
+ RenderView* renderView = frameView->renderView();
+ if (!renderView)
+ return Color();
+
+ return renderView->compositor().rootExtendedBackgroundColor();
+}
+
// These are magical constants that might be tweaked over time.
-static double gMinimumPaintedAreaRatio = 0.1;
-static double gMaximumUnpaintedAreaRatio = 0.04;
+static const double gMinimumPaintedAreaRatio = 0.1;
+static const double gMaximumUnpaintedAreaRatio = 0.04;
bool Page::isCountingRelevantRepaintedObjects() const
{
@@ -1348,10 +1798,10 @@ void Page::addRelevantRepaintedObject(RenderObject* object, const LayoutRect& ob
LayoutRect relevantRect = relevantViewRect(&object->view());
// The objects are only relevant if they are being painted within the viewRect().
- if (!objectPaintRect.intersects(pixelSnappedIntRect(relevantRect)))
+ if (!objectPaintRect.intersects(snappedIntRect(relevantRect)))
return;
- IntRect snappedPaintRect = pixelSnappedIntRect(objectPaintRect);
+ IntRect snappedPaintRect = snappedIntRect(objectPaintRect);
// If this object was previously counted as an unpainted object, remove it from that HashSet
// and corresponding Region. FIXME: This doesn't do the right thing if the objects overlap.
@@ -1369,11 +1819,11 @@ void Page::addRelevantRepaintedObject(RenderObject* object, const LayoutRect& ob
// If the rect straddles both Regions, split it appropriately.
if (topRelevantRect.intersects(snappedPaintRect) && bottomRelevantRect.intersects(snappedPaintRect)) {
IntRect topIntersection = snappedPaintRect;
- topIntersection.intersect(pixelSnappedIntRect(topRelevantRect));
+ topIntersection.intersect(snappedIntRect(topRelevantRect));
m_topRelevantPaintedRegion.unite(topIntersection);
IntRect bottomIntersection = snappedPaintRect;
- bottomIntersection.intersect(pixelSnappedIntRect(bottomRelevantRect));
+ bottomIntersection.intersect(snappedIntRect(bottomRelevantRect));
m_bottomRelevantPaintedRegion.unite(bottomIntersection);
} else if (topRelevantRect.intersects(snappedPaintRect))
m_topRelevantPaintedRegion.unite(snappedPaintRect);
@@ -1393,7 +1843,7 @@ void Page::addRelevantRepaintedObject(RenderObject* object, const LayoutRect& ob
m_isCountingRelevantRepaintedObjects = false;
resetRelevantPaintedObjectCounter();
if (Frame* frame = &mainFrame())
- frame->loader().didLayout(DidHitRelevantRepaintedObjectsAreaThreshold);
+ frame->loader().didReachLayoutMilestone(DidHitRelevantRepaintedObjectsAreaThreshold);
}
}
@@ -1403,11 +1853,27 @@ void Page::addRelevantUnpaintedObject(RenderObject* object, const LayoutRect& ob
return;
// The objects are only relevant if they are being painted within the relevantViewRect().
- if (!objectPaintRect.intersects(pixelSnappedIntRect(relevantViewRect(&object->view()))))
+ if (!objectPaintRect.intersects(snappedIntRect(relevantViewRect(&object->view()))))
return;
m_relevantUnpaintedRenderObjects.add(object);
- m_relevantUnpaintedRegion.unite(pixelSnappedIntRect(objectPaintRect));
+ m_relevantUnpaintedRegion.unite(snappedIntRect(objectPaintRect));
+}
+
+void Page::suspendDeviceMotionAndOrientationUpdates()
+{
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (Document* document = frame->document())
+ document->suspendDeviceMotionAndOrientationUpdates();
+ }
+}
+
+void Page::resumeDeviceMotionAndOrientationUpdates()
+{
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (Document* document = frame->document())
+ document->resumeDeviceMotionAndOrientationUpdates();
+ }
}
void Page::suspendActiveDOMObjectsAndAnimations()
@@ -1464,89 +1930,298 @@ void Page::resetSeenMediaEngines()
m_seenMediaEngines.clear();
}
-std::unique_ptr<PageActivityAssertionToken> Page::createActivityToken()
-{
- return m_pageThrottler->createActivityToken();
-}
-
-#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
-void Page::hiddenPageDOMTimerThrottlingStateChanged()
-{
- if (m_settings->hiddenPageDOMTimerThrottlingEnabled()) {
-#if ENABLE(PAGE_VISIBILITY_API)
- if (m_pageThrottler->shouldThrottleTimers())
- setTimerAlignmentInterval(Settings::hiddenPageDOMTimerAlignmentInterval());
-#endif
- } else
- setTimerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval());
-}
-#endif
-
-#if (ENABLE_PAGE_VISIBILITY_API)
void Page::hiddenPageCSSAnimationSuspensionStateChanged()
{
- if (!m_isVisible) {
+ if (!isVisible()) {
if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
mainFrame().animation().suspendAnimations();
else
mainFrame().animation().resumeAnimations();
}
}
-#endif
#if ENABLE(VIDEO_TRACK)
void Page::captionPreferencesChanged()
{
- for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
frame->document()->captionPreferencesChanged();
+ }
}
#endif
-void Page::incrementFrameHandlingBeforeUnloadEventCount()
+void Page::forbidPrompts()
{
- ++m_framesHandlingBeforeUnloadEvent;
+ ++m_forbidPromptsDepth;
}
-void Page::decrementFrameHandlingBeforeUnloadEventCount()
+void Page::allowPrompts()
{
- ASSERT(m_framesHandlingBeforeUnloadEvent);
- --m_framesHandlingBeforeUnloadEvent;
+ ASSERT(m_forbidPromptsDepth);
+ --m_forbidPromptsDepth;
}
-bool Page::isAnyFrameHandlingBeforeUnloadEvent()
+bool Page::arePromptsAllowed()
{
- return m_framesHandlingBeforeUnloadEvent;
+ return !m_forbidPromptsDepth;
}
-void Page::setUserContentController(UserContentController* userContentController)
+PluginInfoProvider& Page::pluginInfoProvider()
{
- if (m_userContentController)
- m_userContentController->removePage(*this);
+ return m_pluginInfoProvider;
+}
- m_userContentController = userContentController;
+UserContentProvider& Page::userContentProvider()
+{
+ return m_userContentProvider;
+}
- if (m_userContentController)
- m_userContentController->addPage(*this);
+void Page::setUserContentProvider(Ref<UserContentProvider>&& userContentProvider)
+{
+ m_userContentProvider->removePage(*this);
+ m_userContentProvider = WTFMove(userContentProvider);
+ m_userContentProvider->addPage(*this);
+
+ invalidateInjectedStyleSheetCacheInAllFrames();
}
-Page::PageClients::PageClients()
- : alternativeTextClient(nullptr)
- , chromeClient(nullptr)
-#if ENABLE(CONTEXT_MENUS)
- , contextMenuClient(nullptr)
+void Page::setStorageNamespaceProvider(Ref<StorageNamespaceProvider>&& storageNamespaceProvider)
+{
+ m_storageNamespaceProvider->removePage(*this);
+ m_storageNamespaceProvider = WTFMove(storageNamespaceProvider);
+ m_storageNamespaceProvider->addPage(*this);
+
+ // This needs to reset all the local storage namespaces of all the pages.
+}
+
+VisitedLinkStore& Page::visitedLinkStore()
+{
+ return m_visitedLinkStore;
+}
+
+void Page::setVisitedLinkStore(Ref<VisitedLinkStore>&& visitedLinkStore)
+{
+ m_visitedLinkStore->removePage(*this);
+ m_visitedLinkStore = WTFMove(visitedLinkStore);
+ m_visitedLinkStore->addPage(*this);
+
+ invalidateStylesForAllLinks();
+}
+
+SessionID Page::sessionID() const
+{
+ return m_sessionID;
+}
+
+void Page::setSessionID(SessionID sessionID)
+{
+ ASSERT(sessionID.isValid());
+
+#if ENABLE(INDEXED_DATABASE)
+ if (sessionID != m_sessionID)
+ m_idbIDBConnectionToServer = nullptr;
+#endif
+
+ bool privateBrowsingStateChanged = (sessionID.isEphemeral() != m_sessionID.isEphemeral());
+
+ m_sessionID = sessionID;
+
+ if (!privateBrowsingStateChanged)
+ return;
+
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+ frame->document()->privateBrowsingStateDidChange();
+ }
+
+ // Collect the PluginViews in to a vector to ensure that action the plug-in takes
+ // from below privateBrowsingStateChanged does not affect their lifetime.
+
+ for (auto& view : pluginViews())
+ view->privateBrowsingStateChanged(sessionID.isEphemeral());
+}
+
+#if ENABLE(WIRELESS_PLAYBACK_TARGET)
+void Page::addPlaybackTargetPickerClient(uint64_t contextId)
+{
+ chrome().client().addPlaybackTargetPickerClient(contextId);
+}
+
+void Page::removePlaybackTargetPickerClient(uint64_t contextId)
+{
+ chrome().client().removePlaybackTargetPickerClient(contextId);
+}
+
+void Page::showPlaybackTargetPicker(uint64_t contextId, const WebCore::IntPoint& location, bool isVideo)
+{
+#if PLATFORM(IOS)
+ // FIXME: refactor iOS implementation.
+ UNUSED_PARAM(contextId);
+ UNUSED_PARAM(location);
+ chrome().client().showPlaybackTargetPicker(isVideo);
+#else
+ chrome().client().showPlaybackTargetPicker(contextId, location, isVideo);
+#endif
+}
+
+void Page::playbackTargetPickerClientStateDidChange(uint64_t contextId, MediaProducer::MediaStateFlags state)
+{
+ chrome().client().playbackTargetPickerClientStateDidChange(contextId, state);
+}
+
+void Page::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
+{
+ chrome().client().setMockMediaPlaybackTargetPickerEnabled(enabled);
+}
+
+void Page::setMockMediaPlaybackTargetPickerState(const String& name, MediaPlaybackTargetContext::State state)
+{
+ chrome().client().setMockMediaPlaybackTargetPickerState(name, state);
+}
+
+void Page::setPlaybackTarget(uint64_t contextId, Ref<MediaPlaybackTarget>&& target)
+{
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+ frame->document()->setPlaybackTarget(contextId, target.copyRef());
+ }
+}
+
+void Page::playbackTargetAvailabilityDidChange(uint64_t contextId, bool available)
+{
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+ frame->document()->playbackTargetAvailabilityDidChange(contextId, available);
+ }
+}
+
+void Page::setShouldPlayToPlaybackTarget(uint64_t clientId, bool shouldPlay)
+{
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (!frame->document())
+ continue;
+ frame->document()->setShouldPlayToPlaybackTarget(clientId, shouldPlay);
+ }
+}
#endif
- , editorClient(nullptr)
- , dragClient(nullptr)
- , inspectorClient(nullptr)
- , plugInClient(nullptr)
- , progressTrackerClient(nullptr)
- , validationMessageClient(nullptr)
- , loaderClientForMainFrame(nullptr)
+
+WheelEventTestTrigger& Page::ensureTestTrigger()
{
+ if (!m_testTrigger) {
+ m_testTrigger = adoptRef(new WheelEventTestTrigger());
+ // We need to update the scrolling coordinator so that the mainframe scrolling node can expect wheel event test triggers.
+ if (auto* frameView = mainFrame().view()) {
+ if (m_scrollingCoordinator)
+ m_scrollingCoordinator->updateExpectsWheelEventTestTriggerWithFrameView(*frameView);
+ }
+ }
+
+ return *m_testTrigger;
}
-Page::PageClients::~PageClients()
+#if ENABLE(VIDEO)
+void Page::setAllowsMediaDocumentInlinePlayback(bool flag)
+{
+ if (m_allowsMediaDocumentInlinePlayback == flag)
+ return;
+ m_allowsMediaDocumentInlinePlayback = flag;
+
+ Vector<Ref<Document>> documents;
+ for (Frame* frame = &m_mainFrame.get(); frame; frame = frame->tree().traverseNext())
+ documents.append(*frame->document());
+
+ for (auto& document : documents)
+ document->allowsMediaDocumentInlinePlaybackChanged();
+}
+#endif
+
+#if ENABLE(INDEXED_DATABASE)
+IDBClient::IDBConnectionToServer& Page::idbConnection()
+{
+ if (!m_idbIDBConnectionToServer)
+ m_idbIDBConnectionToServer = &databaseProvider().idbConnectionToServerForSession(m_sessionID);
+
+ return *m_idbIDBConnectionToServer;
+}
+#endif
+
+#if ENABLE(RESOURCE_USAGE)
+void Page::setResourceUsageOverlayVisible(bool visible)
+{
+ if (!visible) {
+ m_resourceUsageOverlay = nullptr;
+ return;
+ }
+
+ if (!m_resourceUsageOverlay && m_settings->acceleratedCompositingEnabled())
+ m_resourceUsageOverlay = std::make_unique<ResourceUsageOverlay>(*this);
+}
+#endif
+
+bool Page::isAlwaysOnLoggingAllowed() const
{
+ return m_sessionID.isAlwaysOnLoggingAllowed();
}
+String Page::captionUserPreferencesStyleSheet()
+{
+ return m_captionUserPreferencesStyleSheet;
+}
+
+void Page::setCaptionUserPreferencesStyleSheet(const String& styleSheet)
+{
+ if (m_captionUserPreferencesStyleSheet == styleSheet)
+ return;
+
+ m_captionUserPreferencesStyleSheet = styleSheet;
+
+ invalidateInjectedStyleSheetCacheInAllFrames();
+}
+
+void Page::accessibilitySettingsDidChange()
+{
+ bool neededRecalc = false;
+
+ for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext()) {
+ if (Document* document = frame->document()) {
+ auto* styleResolver = document->styleScope().resolverIfExists();
+ if (styleResolver && styleResolver->hasMediaQueriesAffectedByAccessibilitySettingsChange()) {
+ document->styleScope().didChangeStyleSheetEnvironment();
+ neededRecalc = true;
+ // FIXME: This instrumentation event is not strictly accurate since cached media query results do not persist across StyleResolver rebuilds.
+ InspectorInstrumentation::mediaQueryResultChanged(*document);
+ }
+ }
+ }
+
+ if (neededRecalc)
+ LOG(Layout, "hasMediaQueriesAffectedByAccessibilitySettingsChange, enqueueing style recalc");
+}
+
+#if ENABLE(DATA_INTERACTION)
+
+bool Page::hasDataInteractionAtPosition(const FloatPoint& position) const
+{
+ auto currentSelection = m_mainFrame->selection().selection();
+ if (!currentSelection.isRange())
+ return false;
+
+ if (auto selectedRange = currentSelection.toNormalizedRange()) {
+ Vector<SelectionRect> selectionRects;
+ selectedRange->collectSelectionRects(selectionRects);
+ for (auto selectionRect : selectionRects) {
+ if (FloatRect(selectionRect.rect()).contains(position))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#endif
+
} // namespace WebCore