Clean up PageThrottler interface
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Feb 2014 21:56:32 +0000 (21:56 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Feb 2014 21:56:32 +0000 (21:56 +0000)
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

Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/page/Page.cpp
Source/WebCore/page/Page.h
Source/WebCore/page/PageThrottler.cpp
Source/WebCore/page/PageThrottler.h
Source/WebCore/page/Settings.cpp
Source/WebCore/page/Settings.h

index f65db2a..04db420 100644 (file)
@@ -1,3 +1,66 @@
+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
index ac7a2a4..9f88db3 100644 (file)
@@ -1245,7 +1245,6 @@ __ZN7WebCore8Settings26defaultMinDOMTimerIntervalEv
 __ZN7WebCore8Settings26setSimpleLineLayoutEnabledEb
 __ZN7WebCore8Settings27setJavaEnabledForLocalFilesEb
 __ZN7WebCore8Settings27setLoadsImagesAutomaticallyEb
-__ZN7WebCore8Settings28setDOMTimerAlignmentIntervalEd
 __ZN7WebCore8Settings29setAuthorAndUserStylesEnabledEb
 __ZN7WebCore8Settings29setDefaultMinDOMTimerIntervalEd
 __ZN7WebCore8Settings30setShowTiledScrollingIndicatorEb
index e43ead0..1ba83f6 100644 (file)
@@ -63,6 +63,7 @@
 #include "MediaSessionManager.h"
 #include "PageActivityAssertionToken.h"
 #include "PageGroup.h"
+#include "PageThrottler.h"
 #include "ProgressTracker.h"
 #include "RenderLayerCompositor.h"
 #include "RenderVideo.h"
@@ -4286,7 +4287,7 @@ void HTMLMediaElement::updatePlayState()
         if (hasMediaControls())
             mediaControls()->playbackStarted();
         if (document().page())
-            m_activityToken = document().page()->createActivityToken();
+            m_activityToken = document().page()->pageThrottler().mediaActivityToken();
 
         startPlaybackProgressTimer();
         m_playing = true;
index 6e913ef..3a05b5a 100644 (file)
@@ -85,6 +85,7 @@
 #include "Page.h"
 #include "PageActivityAssertionToken.h"
 #include "PageCache.h"
+#include "PageThrottler.h"
 #include "PageTransitionEvent.h"
 #include "PlatformStrategies.h"
 #include "PluginData.h"
@@ -1142,7 +1143,7 @@ void FrameLoader::completed()
 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;
 }
index 0cafc5a..ed82495 100644 (file)
@@ -172,6 +172,7 @@ Page::Page(PageClients& pageClients)
     , 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)
@@ -185,7 +186,7 @@ Page::Page(PageClients& pageClients)
 #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))
@@ -847,7 +848,10 @@ void Page::resumeScriptedAnimations()
 
 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()
@@ -1040,23 +1044,25 @@ double Page::minimumTimerInterval() const
     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())
@@ -1123,22 +1129,6 @@ void Page::checkSubframeCountConsistency() const
 }
 #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.)
@@ -1158,6 +1148,7 @@ void Page::setViewState(ViewState::Flags viewState)
 
     m_viewState = viewState;
     m_focusController->setViewState(viewState);
+    m_pageThrottler.setViewState(viewState);
 
     if (changed & ViewState::IsVisible)
         setIsVisibleInternal(viewState & ViewState::IsVisible);
@@ -1190,8 +1181,6 @@ void Page::setIsVisibleInternal(bool isVisible)
         if (FrameView* view = mainFrame().view())
             view->show();
 
-        unthrottleTimers();
-
 #if ENABLE(PAGE_VISIBILITY_API)
         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
             mainFrame().animation().resumeAnimations();
@@ -1210,9 +1199,6 @@ void Page::setIsVisibleInternal(bool isVisible)
 #endif
 
     if (!isVisible) {
-        if (m_pageThrottler->shouldThrottleTimers())
-            throttleTimers();
-
 #if ENABLE(PAGE_VISIBILITY_API)
         if (m_settings->hiddenPageCSSAnimationSuspensionEnabled())
             mainFrame().animation().suspendAnimations();
@@ -1479,24 +1465,6 @@ 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()
 {
index 73ae9c9..6666e62 100644 (file)
@@ -26,6 +26,7 @@
 #include "FrameLoaderTypes.h"
 #include "LayoutMilestones.h"
 #include "LayoutRect.h"
+#include "PageThrottler.h"
 #include "PageVisibilityState.h"
 #include "Pagination.h"
 #include "PlatformScreen.h"
@@ -390,14 +391,10 @@ public:
     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
@@ -438,13 +435,11 @@ private:
     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;
@@ -522,6 +517,7 @@ private:
 
     double m_minimumTimerInterval;
 
+    bool m_timerThrottlingEnabled;
     double m_timerAlignmentInterval;
 
     bool m_isEditable;
@@ -544,7 +540,7 @@ private:
     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)
index e80a7a0..6ef5d5b 100644 (file)
@@ -37,19 +37,22 @@ namespace WebCore {
 
 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();
@@ -58,7 +61,17 @@ PageThrottler::~PageThrottler()
         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);
 }
@@ -69,12 +82,7 @@ void PageThrottler::throttlePage()
 
     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()
@@ -88,12 +96,26 @@ 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)
index 894bd08..cd71c09 100644 (file)
@@ -29,6 +29,7 @@
 #include "Timer.h"
 
 #include "UserActivity.h"
+#include "ViewState.h"
 #include <wtf/HashSet.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/PassOwnPtr.h>
@@ -40,18 +41,17 @@ class PageActivityAssertionToken;
 
 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 {
@@ -73,7 +73,11 @@ private:
     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;
index b45c251..3c59261 100644 (file)
@@ -499,11 +499,6 @@ double Settings::defaultDOMTimerAlignmentInterval()
     return gDefaultDOMTimerAlignmentInterval;
 }
 
-void Settings::setDOMTimerAlignmentInterval(double interval)
-{
-    m_page->setTimerAlignmentInterval(interval);
-}
-
 double Settings::domTimerAlignmentInterval() const
 {
     return m_page->timerAlignmentInterval();
@@ -693,7 +688,7 @@ void Settings::setHiddenPageDOMTimerThrottlingEnabled(bool flag)
     if (m_hiddenPageDOMTimerThrottlingEnabled == flag)
         return;
     m_hiddenPageDOMTimerThrottlingEnabled = flag;
-    m_page->hiddenPageDOMTimerThrottlingStateChanged();
+    m_page->pageThrottler().hiddenPageDOMTimerThrottlingStateChanged();
 }
 #endif
 
index 6f3c389..084ba69 100644 (file)
@@ -169,7 +169,6 @@ public:
     static void setDefaultDOMTimerAlignmentInterval(double);
     static double defaultDOMTimerAlignmentInterval();
 
-    void setDOMTimerAlignmentInterval(double);
     double domTimerAlignmentInterval() const;
 
     void setLayoutInterval(std::chrono::milliseconds);