diff options
| author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
|---|---|---|
| committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
| commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
| tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/WebCore/page/PageThrottler.cpp | |
| parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
| download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz | |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/WebCore/page/PageThrottler.cpp')
| -rw-r--r-- | Source/WebCore/page/PageThrottler.cpp | 145 |
1 files changed, 128 insertions, 17 deletions
diff --git a/Source/WebCore/page/PageThrottler.cpp b/Source/WebCore/page/PageThrottler.cpp index 824cfd129..28c63f1e1 100644 --- a/Source/WebCore/page/PageThrottler.cpp +++ b/Source/WebCore/page/PageThrottler.cpp @@ -26,42 +26,153 @@ #include "config.h" #include "PageThrottler.h" +#include "Chrome.h" +#include "ChromeClient.h" +#include "MainFrame.h" #include "Page.h" +#include "PageActivityAssertionToken.h" +#include <wtf/StdLibExtras.h> namespace WebCore { +static const double kThrottleHysteresisSeconds = 2.0; + PageThrottler::PageThrottler(Page& page) : m_page(page) - , m_userInputHysteresis([this](HysteresisState state) { setActivityFlag(PageActivityState::UserInputActivity, state == HysteresisState::Started); }) - , m_audiblePluginHysteresis([this](HysteresisState state) { setActivityFlag(PageActivityState::AudiblePlugin, state == HysteresisState::Started); }) - , m_mediaActivityCounter([this](bool value) { setActivityFlag(PageActivityState::MediaActivity, value); }) - , m_pageLoadActivityCounter([this](bool value) { setActivityFlag(PageActivityState::PageLoadActivity, value); }) + , m_throttleState(PageNotThrottledState) + , m_throttleHysteresisTimer(this, &PageThrottler::throttleHysteresisTimerFired) + , m_visuallyNonIdle("Page is not visually idle.") +{ + m_page.chrome().client().incrementActivePageCount(); +} + +PageThrottler::~PageThrottler() { + setIsVisuallyIdle(false); + + for (auto it = m_activityTokens.begin(), end = m_activityTokens.end(); it != end; ++it) + (*it)->invalidate(); + + if (m_throttleState != PageThrottledState) + m_page.chrome().client().decrementActivePageCount(); } -PageActivityAssertionToken PageThrottler::mediaActivityToken() +std::unique_ptr<PageActivityAssertionToken> PageThrottler::createActivityToken() { - return m_mediaActivityCounter.token<PageActivityAssertionTokenType>(); + return std::make_unique<PageActivityAssertionToken>(*this); } -PageActivityAssertionToken PageThrottler::pageLoadActivityToken() +void PageThrottler::throttlePage() { - return m_pageLoadActivityCounter.token<PageActivityAssertionTokenType>(); + m_throttleState = PageThrottledState; + + m_page.chrome().client().decrementActivePageCount(); + + for (Frame* frame = &m_page.mainFrame(); frame; frame = frame->tree().traverseNext()) { + if (frame->document()) + frame->document()->scriptedAnimationControllerSetThrottled(true); + } + + m_page.throttleTimers(); } -void PageThrottler::setActivityFlag(PageActivityState::Flags flag, bool value) +void PageThrottler::unthrottlePage() { - PageActivityState::Flags activityState = m_activityState; - if (value) - activityState |= flag; - else - activityState &= ~flag; + PageThrottleState oldState = m_throttleState; + m_throttleState = PageNotThrottledState; + + if (oldState == PageNotThrottledState) + return; + + if (oldState == PageThrottledState) + m_page.chrome().client().incrementActivePageCount(); + + for (Frame* frame = &m_page.mainFrame(); frame; frame = frame->tree().traverseNext()) { + if (frame->document()) + frame->document()->scriptedAnimationControllerSetThrottled(false); + } + + m_page.unthrottleTimers(); +} + +void PageThrottler::setIsVisuallyIdle(bool isVisuallyIdle) +{ + if (isVisuallyIdle) { + m_throttleState = PageWaitingToThrottleState; + startThrottleHysteresisTimer(); + if (m_visuallyNonIdle.isActive()) + m_visuallyNonIdle.endActivity(); + } else { + unthrottlePage(); + stopThrottleHysteresisTimer(); + if (!m_visuallyNonIdle.isActive()) + m_visuallyNonIdle.beginActivity(); + } +} + +void PageThrottler::stopThrottleHysteresisTimer() +{ + m_throttleHysteresisTimer.stop(); +} + +void PageThrottler::reportInterestingEvent() +{ + if (m_throttleState == PageNotThrottledState) + return; + if (m_throttleState == PageThrottledState) + unthrottlePage(); + m_throttleState = PageWaitingToThrottleState; + startThrottleHysteresisTimer(); +} + +void PageThrottler::startThrottleHysteresisTimer() +{ + if (m_throttleHysteresisTimer.isActive()) + m_throttleHysteresisTimer.stop(); + if (!m_activityTokens.size()) + m_throttleHysteresisTimer.startOneShot(kThrottleHysteresisSeconds); +} + +void PageThrottler::throttleHysteresisTimerFired(Timer<PageThrottler>&) +{ + ASSERT(!m_activityTokens.size()); + throttlePage(); +} + +void PageThrottler::addActivityToken(PageActivityAssertionToken& token) +{ + ASSERT(!m_activityTokens.contains(&token)); + + m_activityTokens.add(&token); + + // If we've already got events that block throttling we can return early + if (m_activityTokens.size() > 1) + return; + + if (m_throttleState == PageNotThrottledState) + return; + + if (m_throttleState == PageThrottledState) + unthrottlePage(); + + m_throttleState = PageWaitingToThrottleState; + stopThrottleHysteresisTimer(); +} + +void PageThrottler::removeActivityToken(PageActivityAssertionToken& token) +{ + ASSERT(m_activityTokens.contains(&token)); + + m_activityTokens.remove(&token); + + if (m_activityTokens.size()) + return; - if (m_activityState == activityState) + if (m_throttleState == PageNotThrottledState) return; - m_activityState = activityState; - m_page.setPageActivityState(m_activityState); + ASSERT(m_throttleState == PageWaitingToThrottleState); + startThrottleHysteresisTimer(); } } |
