- Revision
- 164948
- Author
- [email protected]
- Date
- 2014-03-02 12:44:17 -0800 (Sun, 02 Mar 2014)
Log Message
Split UserActivity, simplify PageThrottler
https://bugs.webkit.org/show_bug.cgi?id=129551
Reviewed by Darin Adler.
The class UserActivity currently implements two things – a hysteresis mechanism, and
an abstraction of NSActivity controlled by that mechanism. PageThrottler implements
its own hysteresis mechanism, which directly controls DOM timer throttling and also
controls a couple of UserActivities, giving a total of 3 separate hysteresis mechanisms,
layered two deep.
Split UserActivity into three, with HysteresisActivity implementing an abstract hysteresis
mechanism, UserActivity::Impl controlling the NSActivity, and then UserActivity combining
these two back together. The interface to UserActivity is unchanged.
Remove PageThrottler's bespoke hysteresis, replacing it with a use of HysteresisActivity.
Replace the two UserActivities with a single UserActivity::Impl, so there are no longer
layered hysteresis mechanisms.
* WebCore.exp.in:
- exports changed.
* WebCore.xcodeproj/project.pbxproj:
- added HysteresisActivity.h.
* page/PageThrottler.cpp:
(WebCore::PageThrottler::PageThrottler):
- if the page starts visible, begin activity. If it starts hidden throttle DOM timers.
(WebCore::PageThrottler::hiddenPageDOMTimerThrottlingStateChanged):
- when the DOM timer throttling setting changes, make sure we update.
(WebCore::PageThrottler::incrementActivityCount):
(WebCore::PageThrottler::decrementActivityCount):
- when m_activityCount changes update the hysteresis state.
(WebCore::PageThrottler::updateHysteresis):
(WebCore::PageThrottler::setViewState):
- when IsVisuallyIdle changes update the hysteresis state.
(WebCore::PageThrottler::started):
(WebCore::PageThrottler::stopped):
- callbacks from HysteresisActivity, these control m_activity and DOM timer throttling.
* page/PageThrottler.h:
(WebCore::PageThrottler::didReceiveUserInput):
(WebCore::PageThrottler::pluginDidEvaluate):
- call impulse to temporarily enable the activity.
* platform/HysteresisActivity.h: Copied from Source/WebCore/platform/UserActivity.h.
(WebCore::HysteresisActivity::HysteresisActivity):
- constructor takes a delegate optionally a timeout.
(WebCore::HysteresisActivity::start):
- start activity immediately. If stopped, call started method on delegate. If in timeout period, cancel the timer.
(WebCore::HysteresisActivity::stop):
- stop activity after hysteresis. If started, initiate timeout period.
(WebCore::HysteresisActivity::impulse):
- ensure activity for at least the timeout period.
(WebCore::HysteresisActivity::hysteresisTimerFired):
- delayed stop - when the timer fires call stopped on the delegate.
* platform/UserActivity.cpp:
(WebCore::UserActivity::Impl::Impl):
(WebCore::UserActivity::Impl::beginActivity):
(WebCore::UserActivity::Impl::endActivity):
- nop implementation.
(WebCore::UserActivity::UserActivity):
- UserActivity maintains existing interface with hysteresis.
(WebCore::UserActivity::started):
(WebCore::UserActivity::stopped):
- callbacks from HysteresisTimer; forward to Impl.
* platform/UserActivity.h:
* platform/mac/UserActivityMac.mm:
(WebCore::UserActivity::Impl::Impl):
- UserActivity::Impl, abstraction for NSActivity without added hysteresis.
(WebCore::UserActivity::Impl::beginActivity):
- allocate NSActivity.
(WebCore::UserActivity::Impl::endActivity):
- release NSActivity.
Modified Paths
Added Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (164947 => 164948)
--- trunk/Source/WebCore/ChangeLog 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/ChangeLog 2014-03-02 20:44:17 UTC (rev 164948)
@@ -1,3 +1,76 @@
+2014-03-01 Gavin Barraclough <[email protected]>
+
+ Split UserActivity, simplify PageThrottler
+ https://bugs.webkit.org/show_bug.cgi?id=129551
+
+ Reviewed by Darin Adler.
+
+ The class UserActivity currently implements two things – a hysteresis mechanism, and
+ an abstraction of NSActivity controlled by that mechanism. PageThrottler implements
+ its own hysteresis mechanism, which directly controls DOM timer throttling and also
+ controls a couple of UserActivities, giving a total of 3 separate hysteresis mechanisms,
+ layered two deep.
+
+ Split UserActivity into three, with HysteresisActivity implementing an abstract hysteresis
+ mechanism, UserActivity::Impl controlling the NSActivity, and then UserActivity combining
+ these two back together. The interface to UserActivity is unchanged.
+
+ Remove PageThrottler's bespoke hysteresis, replacing it with a use of HysteresisActivity.
+ Replace the two UserActivities with a single UserActivity::Impl, so there are no longer
+ layered hysteresis mechanisms.
+
+ * WebCore.exp.in:
+ - exports changed.
+ * WebCore.xcodeproj/project.pbxproj:
+ - added HysteresisActivity.h.
+ * page/PageThrottler.cpp:
+ (WebCore::PageThrottler::PageThrottler):
+ - if the page starts visible, begin activity. If it starts hidden throttle DOM timers.
+ (WebCore::PageThrottler::hiddenPageDOMTimerThrottlingStateChanged):
+ - when the DOM timer throttling setting changes, make sure we update.
+ (WebCore::PageThrottler::incrementActivityCount):
+ (WebCore::PageThrottler::decrementActivityCount):
+ - when m_activityCount changes update the hysteresis state.
+ (WebCore::PageThrottler::updateHysteresis):
+ (WebCore::PageThrottler::setViewState):
+ - when IsVisuallyIdle changes update the hysteresis state.
+ (WebCore::PageThrottler::started):
+ (WebCore::PageThrottler::stopped):
+ - callbacks from HysteresisActivity, these control m_activity and DOM timer throttling.
+ * page/PageThrottler.h:
+ (WebCore::PageThrottler::didReceiveUserInput):
+ (WebCore::PageThrottler::pluginDidEvaluate):
+ - call impulse to temporarily enable the activity.
+ * platform/HysteresisActivity.h: Copied from Source/WebCore/platform/UserActivity.h.
+ (WebCore::HysteresisActivity::HysteresisActivity):
+ - constructor takes a delegate optionally a timeout.
+ (WebCore::HysteresisActivity::start):
+ - start activity immediately. If stopped, call started method on delegate. If in timeout period, cancel the timer.
+ (WebCore::HysteresisActivity::stop):
+ - stop activity after hysteresis. If started, initiate timeout period.
+ (WebCore::HysteresisActivity::impulse):
+ - ensure activity for at least the timeout period.
+ (WebCore::HysteresisActivity::hysteresisTimerFired):
+ - delayed stop - when the timer fires call stopped on the delegate.
+ * platform/UserActivity.cpp:
+ (WebCore::UserActivity::Impl::Impl):
+ (WebCore::UserActivity::Impl::beginActivity):
+ (WebCore::UserActivity::Impl::endActivity):
+ - nop implementation.
+ (WebCore::UserActivity::UserActivity):
+ - UserActivity maintains existing interface with hysteresis.
+ (WebCore::UserActivity::started):
+ (WebCore::UserActivity::stopped):
+ - callbacks from HysteresisTimer; forward to Impl.
+ * platform/UserActivity.h:
+ * platform/mac/UserActivityMac.mm:
+ (WebCore::UserActivity::Impl::Impl):
+ - UserActivity::Impl, abstraction for NSActivity without added hysteresis.
+ (WebCore::UserActivity::Impl::beginActivity):
+ - allocate NSActivity.
+ (WebCore::UserActivity::Impl::endActivity):
+ - release NSActivity.
+
2014-03-02 Brian Burg <[email protected]>
DocumentLoader should keep maps of ResourceLoaders instead of sets
Modified: trunk/Source/WebCore/GNUmakefile.list.am (164947 => 164948)
--- trunk/Source/WebCore/GNUmakefile.list.am 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/GNUmakefile.list.am 2014-03-02 20:44:17 UTC (rev 164948)
@@ -5491,7 +5491,8 @@
Source/WebCore/platform/ThreadGlobalData.cpp \
Source/WebCore/platform/ThreadGlobalData.h \
Source/WebCore/platform/UserActivity.cpp \
- Source/WebCore/platform/UserActivity.h
+ Source/WebCore/platform/UserActivity.h \
+ Source/WebCore/platform/HysteresisActivity.h
platform_sources += \
Source/WebCore/platform/animation/AnimationUtilities.h \
Modified: trunk/Source/WebCore/WebCore.exp.in (164947 => 164948)
--- trunk/Source/WebCore/WebCore.exp.in 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/WebCore.exp.in 2014-03-02 20:44:17 UTC (rev 164948)
@@ -240,8 +240,7 @@
__ZN7WebCore12TextIterator8subrangeEPNS_5RangeEii
__ZN7WebCore12TextIteratorC1EPKNS_5RangeENS_20TextIteratorBehaviorE
__ZN7WebCore12TextIteratorD1Ev
-__ZN7WebCore12UserActivity4stopEv
-__ZN7WebCore12UserActivity5startEv
+__ZN7WebCore12UserActivity7startedEv
__ZN7WebCore12UserActivityC1EPKc
__ZN7WebCore12UTF8EncodingEv
__ZN7WebCore12WorkerThread17workerThreadCountEv
@@ -318,8 +317,7 @@
__ZN7WebCore13NodeTraversal13deepLastChildEPNS_4NodeE
__ZN7WebCore13NodeTraversal19nextAncestorSiblingEPKNS_4NodeE
__ZN7WebCore13NodeTraversal19nextAncestorSiblingEPKNS_4NodeES3_
-__ZN7WebCore13PageThrottler22reportInterestingEventEv
-__ZN7WebCore13PageThrottlerD1Ev
+__ZN7WebCore13PageThrottler7startedEv
__ZN7WebCore13QualifiedNameD1Ev
__ZN7WebCore13ResourceErrorC1EP7NSError
__ZN7WebCore13ResourceErrorC1EP9__CFError
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (164947 => 164948)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2014-03-02 20:44:17 UTC (rev 164948)
@@ -19002,6 +19002,7 @@
<ClInclude Include="..\platform\Timer.h" />
<ClInclude Include="..\platform\TreeShared.h" />
<ClInclude Include="..\platform\UserActivity.h" />
+ <ClInclude Include="..\platform\HysteresisActivity.h" />
<ClInclude Include="..\platform\UUID.h" />
<ClInclude Include="..\platform\Widget.h" />
<ClInclude Include="..\platform\win\BitmapInfo.h" />
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters (164947 => 164948)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters 2014-03-02 20:44:17 UTC (rev 164948)
@@ -8120,6 +8120,9 @@
<ClInclude Include="..\platform\UserActivity.h">
<Filter>platform</Filter>
</ClInclude>
+ <ClInclude Include="..\platform\HysteresisActivity.h">
+ <Filter>platform</Filter>
+ </ClInclude>
<ClInclude Include="..\platform\UUID.h">
<Filter>platform</Filter>
</ClInclude>
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (164947 => 164948)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2014-03-02 20:44:17 UTC (rev 164948)
@@ -2937,6 +2937,7 @@
861C2EA413FB4FDD00062ABB /* DocumentLoadTiming.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 861C2EA313FB4FDD00062ABB /* DocumentLoadTiming.cpp */; };
861C2EA613FB4FFF00062ABB /* ResourceLoadTiming.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 861C2EA513FB4FFF00062ABB /* ResourceLoadTiming.cpp */; };
862F129E18C1576F005C54AF /* CountedUserActivity.h in Headers */ = {isa = PBXBuildFile; fileRef = 862F129D18C1572C005C54AF /* CountedUserActivity.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 862F12A018C1DD02005C54AF /* HysteresisActivity.h in Headers */ = {isa = PBXBuildFile; fileRef = 862F129F18C1DCE4005C54AF /* HysteresisActivity.h */; settings = {ATTRIBUTES = (Private, ); }; };
86512EDE154A2AEF00A90426 /* PerformanceResourceTiming.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86512EDB154A2AEE00A90426 /* PerformanceResourceTiming.cpp */; };
86512EDF154A2AEF00A90426 /* PerformanceResourceTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 86512EDC154A2AEF00A90426 /* PerformanceResourceTiming.h */; };
8678D0BB1878E891003ABDE6 /* ViewState.h in Headers */ = {isa = PBXBuildFile; fileRef = 8678D0BA1878E810003ABDE6 /* ViewState.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -9840,6 +9841,7 @@
861C2EA313FB4FDD00062ABB /* DocumentLoadTiming.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentLoadTiming.cpp; sourceTree = "<group>"; };
861C2EA513FB4FFF00062ABB /* ResourceLoadTiming.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadTiming.cpp; sourceTree = "<group>"; };
862F129D18C1572C005C54AF /* CountedUserActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountedUserActivity.h; sourceTree = "<group>"; };
+ 862F129F18C1DCE4005C54AF /* HysteresisActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HysteresisActivity.h; sourceTree = "<group>"; };
86512EDB154A2AEE00A90426 /* PerformanceResourceTiming.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PerformanceResourceTiming.cpp; sourceTree = "<group>"; };
86512EDC154A2AEF00A90426 /* PerformanceResourceTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PerformanceResourceTiming.h; sourceTree = "<group>"; };
86512EDD154A2AEF00A90426 /* PerformanceResourceTiming.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PerformanceResourceTiming.idl; sourceTree = "<group>"; };
@@ -20730,6 +20732,7 @@
D6FDAEF2149C06190037B1E1 /* HistogramSupport.cpp */,
D630E2AB149BF344005B2F93 /* HistogramSupport.h */,
BC3BC29B0E91AB0F00835588 /* HostWindow.h */,
+ 862F129F18C1DCE4005C54AF /* HysteresisActivity.h */,
1AE00D57182DAC8D00087DD7 /* KeyedCoding.h */,
521D46F711AEC9B100514613 /* KillRing.h */,
4306E4E514955543007F17AC /* KillRingNone.cpp */,
@@ -23771,6 +23774,7 @@
4415292E0E1AE8A000C4A2D0 /* HTMLPlugInImageElement.h in Headers */,
A8EA7CB00A192B9C00A8EF5F /* HTMLPreElement.h in Headers */,
977B3873122883E900B81FF8 /* HTMLPreloadScanner.h in Headers */,
+ 862F12A018C1DD02005C54AF /* HysteresisActivity.h in Headers */,
A43BF5991149290A00C643CA /* HTMLProgressElement.h in Headers */,
A8CFF7A30A156978000A4234 /* HTMLQuoteElement.h in Headers */,
A8D223FE16B52E4E00157288 /* HTMLResourcePreloader.h in Headers */,
Modified: trunk/Source/WebCore/page/PageThrottler.cpp (164947 => 164948)
--- trunk/Source/WebCore/page/PageThrottler.cpp 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/page/PageThrottler.cpp 2014-03-02 20:44:17 UTC (rev 164948)
@@ -35,34 +35,25 @@
namespace WebCore {
-static const double kThrottleHysteresisSeconds = 2.0;
-
PageThrottler::PageThrottler(Page& page, ViewState::Flags viewState)
: m_page(page)
, m_viewState(viewState)
- , m_throttleState(PageNotThrottledState)
- , m_throttleHysteresisTimer(this, &PageThrottler::throttleHysteresisTimerFired)
, m_weakPtrFactory(this)
+ , m_hysteresis(*this)
+ , m_activity("Page is active.")
, m_activityCount(0)
- , m_visuallyNonIdle("Page is not visually idle.")
- , m_pageActivity("Page is active.")
{
- m_pageActivity.increment();
-
- setIsVisuallyIdle(viewState & ViewState::IsVisuallyIdle);
+ if (m_viewState & ViewState::IsVisuallyIdle)
+ m_page.setTimerThrottlingEnabled(true);
+ else
+ m_hysteresis.start();
}
-PageThrottler::~PageThrottler()
-{
- m_page.setTimerThrottlingEnabled(false);
-
- if (m_throttleState != PageThrottledState)
- m_pageActivity.decrement();
-}
-
void PageThrottler::hiddenPageDOMTimerThrottlingStateChanged()
{
- m_page.setTimerThrottlingEnabled(m_throttleState != PageNotThrottledState);
+ // If timer throttling is enabled, this will temporarily disable it.
+ // After a timeout it will be reenabled, rereading the setting.
+ m_hysteresis.impulse();
}
std::unique_ptr<PageActivityAssertionToken> PageThrottler::mediaActivityToken()
@@ -75,27 +66,24 @@
return std::make_unique<PageActivityAssertionToken>(*this);
}
-void PageThrottler::throttlePage()
+void PageThrottler::incrementActivityCount()
{
- m_throttleState = PageThrottledState;
-
- m_pageActivity.decrement();
-
- m_page.setTimerThrottlingEnabled(true);
+ ++m_activityCount;
+ updateHysteresis();
}
-void PageThrottler::unthrottlePage()
+void PageThrottler::decrementActivityCount()
{
- PageThrottleState oldState = m_throttleState;
- m_throttleState = PageNotThrottledState;
+ --m_activityCount;
+ updateHysteresis();
+}
- if (oldState == PageNotThrottledState)
- return;
-
- if (oldState == PageThrottledState)
- m_pageActivity.increment();
-
- m_page.setTimerThrottlingEnabled(false);
+void PageThrottler::updateHysteresis()
+{
+ if (m_activityCount || !(m_viewState & ViewState::IsVisuallyIdle))
+ m_hysteresis.start();
+ else
+ m_hysteresis.stop();
}
void PageThrottler::setViewState(ViewState::Flags viewState)
@@ -103,88 +91,20 @@
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);
+ updateHysteresis();
}
-void PageThrottler::setIsVisible(bool isVisible)
+void PageThrottler::started()
{
- if (isVisible)
- m_page.setTimerThrottlingEnabled(false);
- else if (m_throttleState != PageNotThrottledState)
- m_page.setTimerThrottlingEnabled(true);
+ m_page.setTimerThrottlingEnabled(false);
+ m_activity.beginActivity();
}
-void PageThrottler::setIsVisuallyIdle(bool isVisuallyIdle)
+void PageThrottler::stopped()
{
- if (isVisuallyIdle) {
- m_throttleState = PageWaitingToThrottleState;
- startThrottleHysteresisTimer();
- m_visuallyNonIdle.stop();
- } else {
- unthrottlePage();
- stopThrottleHysteresisTimer();
- m_visuallyNonIdle.start();
- }
+ m_page.setTimerThrottlingEnabled(true);
+ m_activity.endActivity();
}
-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_activityCount)
- m_throttleHysteresisTimer.startOneShot(kThrottleHysteresisSeconds);
-}
-
-void PageThrottler::throttleHysteresisTimerFired(Timer<PageThrottler>&)
-{
- ASSERT(!m_activityCount);
- throttlePage();
-}
-
-void PageThrottler::incrementActivityCount()
-{
- // If we've already got events that block throttling we can return early
- if (m_activityCount++)
- return;
-
- if (m_throttleState == PageNotThrottledState)
- return;
-
- if (m_throttleState == PageThrottledState)
- unthrottlePage();
-
- m_throttleState = PageWaitingToThrottleState;
- stopThrottleHysteresisTimer();
-}
-
-void PageThrottler::decrementActivityCount()
-{
- if (--m_activityCount)
- return;
-
- if (m_throttleState == PageNotThrottledState)
- return;
-
- ASSERT(m_throttleState == PageWaitingToThrottleState);
- startThrottleHysteresisTimer();
-}
-
-}
Modified: trunk/Source/WebCore/page/PageThrottler.h (164947 => 164948)
--- trunk/Source/WebCore/page/PageThrottler.h 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/page/PageThrottler.h 2014-03-02 20:44:17 UTC (rev 164948)
@@ -28,7 +28,7 @@
#include "Timer.h"
-#include "CountedUserActivity.h"
+#include "UserActivity.h"
#include "ViewState.h"
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
@@ -43,49 +43,34 @@
class PageThrottler {
public:
PageThrottler(Page&, ViewState::Flags);
- ~PageThrottler();
void setViewState(ViewState::Flags);
- void didReceiveUserInput() { reportInterestingEvent(); }
- void pluginDidEvaluate() { reportInterestingEvent(); }
+ void didReceiveUserInput() { m_hysteresis.impulse(); }
+ void pluginDidEvaluate() { m_hysteresis.impulse(); }
std::unique_ptr<PageActivityAssertionToken> mediaActivityToken();
std::unique_ptr<PageActivityAssertionToken> pageLoadActivityToken();
void hiddenPageDOMTimerThrottlingStateChanged();
private:
- enum PageThrottleState {
- PageNotThrottledState,
- PageWaitingToThrottleState,
- PageThrottledState
- };
-
friend class PageActivityAssertionToken;
WeakPtr<PageThrottler> weakPtr() { return m_weakPtrFactory.createWeakPtr(); }
void incrementActivityCount();
void decrementActivityCount();
- void reportInterestingEvent();
+ void updateHysteresis();
- void startThrottleHysteresisTimer();
- void stopThrottleHysteresisTimer();
- void throttleHysteresisTimerFired(Timer<PageThrottler>&);
+ friend class HysteresisActivity<PageThrottler>;
+ void started();
+ void stopped();
- void throttlePage();
- void unthrottlePage();
-
- void setIsVisuallyIdle(bool);
- void setIsVisible(bool);
-
Page& m_page;
ViewState::Flags m_viewState;
- PageThrottleState m_throttleState;
- Timer<PageThrottler> m_throttleHysteresisTimer;
WeakPtrFactory<PageThrottler> m_weakPtrFactory;
+ HysteresisActivity<PageThrottler> m_hysteresis;
+ UserActivity::Impl m_activity;
size_t m_activityCount;
- UserActivity m_visuallyNonIdle;
- CountedUserActivity m_pageActivity;
};
}
Copied: trunk/Source/WebCore/platform/HysteresisActivity.h (from rev 164913, trunk/Source/WebCore/platform/UserActivity.h) (0 => 164948)
--- trunk/Source/WebCore/platform/HysteresisActivity.h (rev 0)
+++ trunk/Source/WebCore/platform/HysteresisActivity.h 2014-03-02 20:44:17 UTC (rev 164948)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HysteresisActivity_h
+#define HysteresisActivity_h
+
+#include <wtf/RunLoop.h>
+
+namespace WebCore {
+
+static const double DefaultHysteresisSeconds = 5.0;
+
+template<typename Delegate>
+class HysteresisActivity {
+public:
+ explicit HysteresisActivity(Delegate& delegate, double hysteresisSeconds = DefaultHysteresisSeconds)
+ : m_delegate(delegate)
+ , m_hysteresisSeconds(hysteresisSeconds)
+ , m_active(false)
+ , m_timer(RunLoop::main(), this, &HysteresisActivity<Delegate>::hysteresisTimerFired)
+ {
+ }
+
+ void start()
+ {
+ if (m_active)
+ return;
+ m_active = true;
+
+ if (m_timer.isActive())
+ m_timer.stop();
+ else
+ m_delegate.started();
+ }
+
+ void stop()
+ {
+ if (!m_active)
+ return;
+ m_active = false;
+
+ m_timer.startOneShot(m_hysteresisSeconds);
+ }
+
+ void impulse()
+ {
+ if (!m_active) {
+ start();
+ stop();
+ }
+ }
+
+private:
+ void hysteresisTimerFired()
+ {
+ m_delegate.stopped();
+ m_timer.stop();
+ }
+
+ Delegate& m_delegate;
+ double m_hysteresisSeconds;
+ bool m_active;
+ RunLoop::Timer<HysteresisActivity> m_timer;
+};
+
+} // namespace WebCore
+
+#endif // HysteresisActivity_h
Modified: trunk/Source/WebCore/platform/UserActivity.cpp (164947 => 164948)
--- trunk/Source/WebCore/platform/UserActivity.cpp 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/platform/UserActivity.cpp 2014-03-02 20:44:17 UTC (rev 164948)
@@ -30,18 +30,34 @@
#if !HAVE(NS_ACTIVITY)
-UserActivity::UserActivity(const char*)
+UserActivity::Impl::Impl(const char*)
{
}
-void UserActivity::start()
+void UserActivity::Impl::beginActivity()
{
}
-void UserActivity::stop()
+void UserActivity::Impl::endActivity()
{
}
#endif
+UserActivity::UserActivity(const char* description)
+ : HysteresisActivity<UserActivity>(*this)
+ , m_impl(description)
+{
+}
+
+void UserActivity::started()
+{
+ m_impl.beginActivity();
+}
+
+void UserActivity::stopped()
+{
+ m_impl.endActivity();
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/UserActivity.h (164947 => 164948)
--- trunk/Source/WebCore/platform/UserActivity.h 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/platform/UserActivity.h 2014-03-02 20:44:17 UTC (rev 164948)
@@ -26,9 +26,10 @@
#ifndef UserActivity_h
#define UserActivity_h
+#include "HysteresisActivity.h"
+
#if HAVE(NS_ACTIVITY)
#include <wtf/RetainPtr.h>
-#include <wtf/RunLoop.h>
OBJC_CLASS NSString;
#endif
@@ -37,23 +38,31 @@
// The UserActivity type is used to indicate to the operating system that
// a user initiated or visible action is taking place, and as such that
// resources should be allocated to the process accordingly.
-class UserActivity {
+class UserActivity : public HysteresisActivity<UserActivity> {
public:
- UserActivity(const char* description);
+ class Impl {
+ public:
+ explicit Impl(const char* description);
- void start();
- void stop();
+ void beginActivity();
+ void endActivity();
-private:
#if HAVE(NS_ACTIVITY)
- void hysteresisTimerFired();
- bool isValid();
+ private:
+ RetainPtr<id> m_activity;
+ RetainPtr<NSString> m_description;
+#endif
+ };
- bool m_active;
- RetainPtr<NSString> m_description;
- RunLoop::Timer<UserActivity> m_timer;
- RetainPtr<id> m_activity;
-#endif
+ explicit UserActivity(const char* description);
+
+private:
+ friend class HysteresisActivity<UserActivity>;
+
+ void started();
+ void stopped();
+
+ Impl m_impl;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/mac/UserActivityMac.mm (164947 => 164948)
--- trunk/Source/WebCore/platform/mac/UserActivityMac.mm 2014-03-02 20:34:51 UTC (rev 164947)
+++ trunk/Source/WebCore/platform/mac/UserActivityMac.mm 2014-03-02 20:44:17 UTC (rev 164948)
@@ -30,65 +30,23 @@
#if HAVE(NS_ACTIVITY)
-static const double kHysteresisSeconds = 5.0;
-
-UserActivity::UserActivity(const char* description)
- : m_active(false)
- , m_description([NSString stringWithUTF8String:description])
- , m_timer(RunLoop::main(), this, &UserActivity::hysteresisTimerFired)
+UserActivity::Impl::Impl(const char* description)
+ : m_description([NSString stringWithUTF8String:description])
{
- ASSERT(isValid());
}
-bool UserActivity::isValid()
+void UserActivity::Impl::beginActivity()
{
- // If count is non-zero then we should be holding an activity, and the hysteresis timer should not be running.
- // Else if count is zero then:
- // (a) if we're holding an activity there should be an active timer to clear this,
- // (b) if we're not holding an activity there should be no active timer.
- return m_active ? m_activity && !m_timer.isActive() : !!m_activity == m_timer.isActive();
-}
-
-void UserActivity::start()
-{
- ASSERT(isValid());
-
- if (m_active)
- return;
- m_active = true;
-
- if (m_timer.isActive())
- m_timer.stop();
if (!m_activity) {
NSActivityOptions options = (NSActivityUserInitiatedAllowingIdleSystemSleep | NSActivityLatencyCritical) & ~(NSActivitySuddenTerminationDisabled | NSActivityAutomaticTerminationDisabled);
m_activity = [[NSProcessInfo processInfo] beginActivityWithOptions:options reason:m_description.get()];
}
-
- ASSERT(isValid());
}
-void UserActivity::stop()
+void UserActivity::Impl::endActivity()
{
- ASSERT(isValid());
-
- if (!m_active)
- return;
- m_active = false;
-
- m_timer.startOneShot(kHysteresisSeconds);
-
- ASSERT(isValid());
-}
-
-void UserActivity::hysteresisTimerFired()
-{
- ASSERT(isValid());
-
[[NSProcessInfo processInfo] endActivity:m_activity.get()];
m_activity.clear();
- m_timer.stop();
-
- ASSERT(isValid());
}
#endif