https://bugs.webkit.org/show_bug.cgi?id=128677
Reviewed by Benjamin Poulain.
Currently, responsibility for throttling DOM timers & suspending animations is split
between the Page & the PageThrottler. Clarify by making Page responsible for suspending
animations (PageThrottler is now purely related to aspects of timer throttling), and
move all timer throttling policy to the PageThrottler, with a single function on Page to
enable (Page::setTimerThrottlingEnabled).
Also, transmit the full ViewState to the PageThrottler (not just the IsVisuallyIdle flag),
and distinguish between media & page-load activity.
* WebCore.exp.in:
- removed setDOMTimerAlignmentInterval.
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::parseAttribute):
- createActivityToken -> mediaActivityToken
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::started):
- createActivityToken -> pageLoadActivityToken
* page/Page.cpp:
(WebCore::Page::Page):
- added m_timerThrottlingEnabled, made PageThrottler a member
(WebCore::Page::setIsVisuallyIdleInternal):
- update animiation suspension.
(WebCore::Page::setTimerThrottlingEnabled):
- setTimerAlignmentInterval -> setTimerThrottlingEnabled
(WebCore::Page::setViewState):
- pass viewState to PageThrottler.
(WebCore::Page::setIsVisibleInternal):
- don't update timer throttling.
* page/Page.h:
(WebCore::Page::pageThrottler):
- made PageThrottler a member.
(WebCore::Page::timerAlignmentInterval):
- inlined.
* page/PageThrottler.cpp:
(WebCore::PageThrottler::PageThrottler):
- initialize ViewState.
(WebCore::PageThrottler::~PageThrottler):
- clean up by calling setTimerThrottlingEnabled directly.
(WebCore::PageThrottler::hiddenPageDOMTimerThrottlingStateChanged):
- moved from Page.
(WebCore::PageThrottler::mediaActivityToken):
(WebCore::PageThrottler::pageLoadActivityToken):
- from Page::createActivityToken
(WebCore::PageThrottler::throttlePage):
(WebCore::PageThrottler::unthrottlePage):
- don't throttle animations here.
(WebCore::PageThrottler::setViewState):
(WebCore::PageThrottler::setIsVisible):
- added, throttle Dom timers.
* page/PageThrottler.h:
* page/Settings.cpp:
(WebCore::Settings::setHiddenPageDOMTimerThrottlingEnabled):
- removed setDOMTimerAlignmentInterval, hiddenPageDOMTimerThrottlingStateChanged moved to PageThrottler.
* page/Settings.h:
- removed setDOMTimerAlignmentInterval.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@163983
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2014-02-12 Gavin Barraclough <barraclough@apple.com>
+
+ Clean up PageThrottler interface
+ https://bugs.webkit.org/show_bug.cgi?id=128677
+
+ Reviewed by Benjamin Poulain.
+
+ Currently, responsibility for throttling DOM timers & suspending animations is split
+ between the Page & the PageThrottler. Clarify by making Page responsible for suspending
+ animations (PageThrottler is now purely related to aspects of timer throttling), and
+ move all timer throttling policy to the PageThrottler, with a single function on Page to
+ enable (Page::setTimerThrottlingEnabled).
+
+ Also, transmit the full ViewState to the PageThrottler (not just the IsVisuallyIdle flag),
+ and distinguish between media & page-load activity.
+
+ * WebCore.exp.in:
+ - removed setDOMTimerAlignmentInterval.
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::parseAttribute):
+ - createActivityToken -> mediaActivityToken
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::started):
+ - createActivityToken -> pageLoadActivityToken
+ * page/Page.cpp:
+ (WebCore::Page::Page):
+ - added m_timerThrottlingEnabled, made PageThrottler a member
+ (WebCore::Page::setIsVisuallyIdleInternal):
+ - update animiation suspension.
+ (WebCore::Page::setTimerThrottlingEnabled):
+ - setTimerAlignmentInterval -> setTimerThrottlingEnabled
+ (WebCore::Page::setViewState):
+ - pass viewState to PageThrottler.
+ (WebCore::Page::setIsVisibleInternal):
+ - don't update timer throttling.
+ * page/Page.h:
+ (WebCore::Page::pageThrottler):
+ - made PageThrottler a member.
+ (WebCore::Page::timerAlignmentInterval):
+ - inlined.
+ * page/PageThrottler.cpp:
+ (WebCore::PageThrottler::PageThrottler):
+ - initialize ViewState.
+ (WebCore::PageThrottler::~PageThrottler):
+ - clean up by calling setTimerThrottlingEnabled directly.
+ (WebCore::PageThrottler::hiddenPageDOMTimerThrottlingStateChanged):
+ - moved from Page.
+ (WebCore::PageThrottler::mediaActivityToken):
+ (WebCore::PageThrottler::pageLoadActivityToken):
+ - from Page::createActivityToken
+ (WebCore::PageThrottler::throttlePage):
+ (WebCore::PageThrottler::unthrottlePage):
+ - don't throttle animations here.
+ (WebCore::PageThrottler::setViewState):
+ (WebCore::PageThrottler::setIsVisible):
+ - added, throttle Dom timers.
+ * page/PageThrottler.h:
+ * page/Settings.cpp:
+ (WebCore::Settings::setHiddenPageDOMTimerThrottlingEnabled):
+ - removed setDOMTimerAlignmentInterval, hiddenPageDOMTimerThrottlingStateChanged moved to PageThrottler.
+ * page/Settings.h:
+ - removed setDOMTimerAlignmentInterval.
+
2014-02-12 Benjamin Poulain <bpoulain@apple.com>
[WK2][iOS] Add back the special viewport for the old xhtml mobile doctype
__ZN7WebCore8Settings26setSimpleLineLayoutEnabledEb
__ZN7WebCore8Settings27setJavaEnabledForLocalFilesEb
__ZN7WebCore8Settings27setLoadsImagesAutomaticallyEb
-__ZN7WebCore8Settings28setDOMTimerAlignmentIntervalEd
__ZN7WebCore8Settings29setAuthorAndUserStylesEnabledEb
__ZN7WebCore8Settings29setDefaultMinDOMTimerIntervalEd
__ZN7WebCore8Settings30setShowTiledScrollingIndicatorEb
#include "MediaSessionManager.h"
#include "PageActivityAssertionToken.h"
#include "PageGroup.h"
+#include "PageThrottler.h"
#include "ProgressTracker.h"
#include "RenderLayerCompositor.h"
#include "RenderVideo.h"
if (hasMediaControls())
mediaControls()->playbackStarted();
if (document().page())
- m_activityToken = document().page()->createActivityToken();
+ m_activityToken = document().page()->pageThrottler().mediaActivityToken();
startPlaybackProgressTimer();
m_playing = true;
#include "Page.h"
#include "PageActivityAssertionToken.h"
#include "PageCache.h"
+#include "PageThrottler.h"
#include "PageTransitionEvent.h"
#include "PlatformStrategies.h"
#include "PluginData.h"
void FrameLoader::started()
{
if (m_frame.page())
- m_activityAssertion = m_frame.page()->createActivityToken();
+ m_activityAssertion = m_frame.page()->pageThrottler().pageLoadActivityToken();
for (Frame* frame = &m_frame; frame; frame = frame->tree().parent())
frame->loader().m_isComplete = false;
}
, m_viewMode(ViewModeWindowed)
#endif // ENABLE(VIEW_MODE_CSS_MEDIA)
, m_minimumTimerInterval(Settings::defaultMinDOMTimerInterval())
+ , m_timerThrottlingEnabled(false)
, m_timerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval())
, m_isEditable(false)
, m_isPrerender(false)
#endif
, m_alternativeTextClient(pageClients.alternativeTextClient)
, m_scriptedAnimationsSuspended(false)
- , m_pageThrottler(std::make_unique<PageThrottler>(*this))
+ , m_pageThrottler(*this, PageInitialViewState)
, m_console(std::make_unique<PageConsole>(*this))
#if ENABLE(REMOTE_INSPECTOR)
, m_inspectorDebuggable(std::make_unique<PageDebuggable>(*this))
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()
return m_minimumTimerInterval;
}
-void Page::setTimerAlignmentInterval(double interval)
+void Page::setTimerThrottlingEnabled(bool enabled)
{
- if (interval == m_timerAlignmentInterval)
+#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
+ if (!m_settings->hiddenPageDOMTimerThrottlingEnabled())
+ enabled = false;
+#endif
+
+ if (enabled == m_timerThrottlingEnabled)
return;
- m_timerAlignmentInterval = interval;
+ m_timerThrottlingEnabled = enabled;
+ m_timerAlignmentInterval = enabled ? Settings::hiddenPageDOMTimerAlignmentInterval() : Settings::defaultDOMTimerAlignmentInterval();
+
for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNextWithWrap(false)) {
if (frame->document())
frame->document()->didChangeTimerAlignmentInterval();
}
}
-double Page::timerAlignmentInterval() const
-{
- return m_timerAlignmentInterval;
-}
-
void Page::dnsPrefetchingStateChanged()
{
for (Frame* frame = &mainFrame(); frame; frame = frame->tree().traverseNext())
}
#endif
-void Page::throttleTimers()
-{
-#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
- if (m_settings->hiddenPageDOMTimerThrottlingEnabled())
- setTimerAlignmentInterval(Settings::hiddenPageDOMTimerAlignmentInterval());
-#endif
-}
-
-void Page::unthrottleTimers()
-{
-#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
- if (m_settings->hiddenPageDOMTimerThrottlingEnabled())
- setTimerAlignmentInterval(Settings::defaultDOMTimerAlignmentInterval());
-#endif
-}
-
void Page::resumeAnimatingImages()
{
// Drawing models which cache painted content while out-of-window (WebKit2's composited drawing areas, etc.)
m_viewState = viewState;
m_focusController->setViewState(viewState);
+ m_pageThrottler.setViewState(viewState);
if (changed & ViewState::IsVisible)
setIsVisibleInternal(viewState & ViewState::IsVisible);
if (FrameView* view = mainFrame().view())
view->show();
- unthrottleTimers();
-
#if ENABLE(PAGE_VISIBILITY_API)
if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
mainFrame().animation().resumeAnimations();
#endif
if (!isVisible) {
- if (m_pageThrottler->shouldThrottleTimers())
- throttleTimers();
-
#if ENABLE(PAGE_VISIBILITY_API)
if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
mainFrame().animation().suspendAnimations();
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()
{
#include "FrameLoaderTypes.h"
#include "LayoutMilestones.h"
#include "LayoutRect.h"
+#include "PageThrottler.h"
#include "PageVisibilityState.h"
#include "Pagination.h"
#include "PlatformScreen.h"
void sawMediaEngine(const String& engineName);
void resetSeenMediaEngines();
- PageThrottler& pageThrottler() { return *m_pageThrottler; }
- std::unique_ptr<PageActivityAssertionToken> createActivityToken();
+ PageThrottler& pageThrottler() { return m_pageThrottler; }
PageConsole& console() { return *m_console; }
-#if ENABLE(HIDDEN_PAGE_DOM_TIMER_THROTTLING)
- void hiddenPageDOMTimerThrottlingStateChanged();
-#endif
#if ENABLE(PAGE_VISIBILITY_API)
void hiddenPageCSSAnimationSuspensionStateChanged();
#endif
void setMinimumTimerInterval(double);
double minimumTimerInterval() const;
- void setTimerAlignmentInterval(double);
- double timerAlignmentInterval() const;
+ double timerAlignmentInterval() const { return m_timerAlignmentInterval; }
Vector<Ref<PluginViewBase>> pluginViews();
- void throttleTimers();
- void unthrottleTimers();
+ void setTimerThrottlingEnabled(bool);
const std::unique_ptr<Chrome> m_chrome;
const std::unique_ptr<DragCaretController> m_dragCaretController;
double m_minimumTimerInterval;
+ bool m_timerThrottlingEnabled;
double m_timerAlignmentInterval;
bool m_isEditable;
AlternativeTextClient* m_alternativeTextClient;
bool m_scriptedAnimationsSuspended;
- const std::unique_ptr<PageThrottler> m_pageThrottler;
+ PageThrottler m_pageThrottler;
const std::unique_ptr<PageConsole> m_console;
#if ENABLE(REMOTE_INSPECTOR)
static const double kThrottleHysteresisSeconds = 2.0;
-PageThrottler::PageThrottler(Page& page)
+PageThrottler::PageThrottler(Page& page, ViewState::Flags viewState)
: m_page(page)
+ , m_viewState(viewState)
, m_throttleState(PageNotThrottledState)
, m_throttleHysteresisTimer(this, &PageThrottler::throttleHysteresisTimerFired)
, m_visuallyNonIdle("Page is not visually idle.")
, m_pageActivity("Page is active.")
{
m_pageActivity.beginActivity();
+
+ setIsVisuallyIdle(viewState & ViewState::IsVisuallyIdle);
}
PageThrottler::~PageThrottler()
{
- setIsVisuallyIdle(false);
+ m_page.setTimerThrottlingEnabled(false);
for (auto it = m_activityTokens.begin(), end = m_activityTokens.end(); it != end; ++it)
(*it)->invalidate();
m_pageActivity.endActivity();
}
-std::unique_ptr<PageActivityAssertionToken> PageThrottler::createActivityToken()
+void PageThrottler::hiddenPageDOMTimerThrottlingStateChanged()
+{
+ m_page.setTimerThrottlingEnabled(m_throttleState != PageNotThrottledState);
+}
+
+std::unique_ptr<PageActivityAssertionToken> PageThrottler::mediaActivityToken()
+{
+ return std::make_unique<PageActivityAssertionToken>(*this);
+}
+
+std::unique_ptr<PageActivityAssertionToken> PageThrottler::pageLoadActivityToken()
{
return std::make_unique<PageActivityAssertionToken>(*this);
}
m_pageActivity.endActivity();
- for (Frame* frame = &m_page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
- if (frame->document())
- frame->document()->scriptedAnimationControllerSetThrottled(true);
- }
-
- m_page.throttleTimers();
+ m_page.setTimerThrottlingEnabled(true);
}
void PageThrottler::unthrottlePage()
if (oldState == PageThrottledState)
m_pageActivity.beginActivity();
- for (Frame* frame = &m_page.mainFrame(); frame; frame = frame->tree().traverseNext()) {
- if (frame->document())
- frame->document()->scriptedAnimationControllerSetThrottled(false);
- }
+ m_page.setTimerThrottlingEnabled(false);
+}
+
+void PageThrottler::setViewState(ViewState::Flags viewState)
+{
+ ViewState::Flags changed = m_viewState ^ viewState;
+ m_viewState = viewState;
+
+ if (changed & ViewState::IsVisible)
+ setIsVisible(viewState & ViewState::IsVisible);
+ if (changed & ViewState::IsVisuallyIdle)
+ setIsVisuallyIdle(viewState & ViewState::IsVisuallyIdle);
+}
- m_page.unthrottleTimers();
+void PageThrottler::setIsVisible(bool isVisible)
+{
+ if (isVisible)
+ m_page.setTimerThrottlingEnabled(false);
+ else if (m_throttleState != PageNotThrottledState)
+ m_page.setTimerThrottlingEnabled(true);
}
void PageThrottler::setIsVisuallyIdle(bool isVisuallyIdle)
#include "Timer.h"
#include "UserActivity.h"
+#include "ViewState.h"
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
class PageThrottler {
public:
- PageThrottler(Page&);
+ PageThrottler(Page&, ViewState::Flags);
~PageThrottler();
- std::unique_ptr<PageActivityAssertionToken> createActivityToken();
-
- bool shouldThrottleAnimations() const { return m_throttleState != PageNotThrottledState; }
- bool shouldThrottleTimers() const { return m_throttleState != PageNotThrottledState; }
-
- void setIsVisuallyIdle(bool);
+ void setViewState(ViewState::Flags);
void didReceiveUserInput() { reportInterestingEvent(); }
void pluginDidEvaluate() { reportInterestingEvent(); }
+ std::unique_ptr<PageActivityAssertionToken> mediaActivityToken();
+ std::unique_ptr<PageActivityAssertionToken> pageLoadActivityToken();
+
+ void hiddenPageDOMTimerThrottlingStateChanged();
private:
enum PageThrottleState {
void throttlePage();
void unthrottlePage();
+ void setIsVisuallyIdle(bool);
+ void setIsVisible(bool);
+
Page& m_page;
+ ViewState::Flags m_viewState;
PageThrottleState m_throttleState;
Timer<PageThrottler> m_throttleHysteresisTimer;
HashSet<PageActivityAssertionToken*> m_activityTokens;
return gDefaultDOMTimerAlignmentInterval;
}
-void Settings::setDOMTimerAlignmentInterval(double interval)
-{
- m_page->setTimerAlignmentInterval(interval);
-}
-
double Settings::domTimerAlignmentInterval() const
{
return m_page->timerAlignmentInterval();
if (m_hiddenPageDOMTimerThrottlingEnabled == flag)
return;
m_hiddenPageDOMTimerThrottlingEnabled = flag;
- m_page->hiddenPageDOMTimerThrottlingStateChanged();
+ m_page->pageThrottler().hiddenPageDOMTimerThrottlingStateChanged();
}
#endif
static void setDefaultDOMTimerAlignmentInterval(double);
static double defaultDOMTimerAlignmentInterval();
- void setDOMTimerAlignmentInterval(double);
double domTimerAlignmentInterval() const;
void setLayoutInterval(std::chrono::milliseconds);