diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-16 02:40:09 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-16 02:40:09 +0000 |
commit | 6405a9a2c316766d3fbda622fbf8bfe33e402c28 (patch) | |
tree | f5282e1e7e1e2cac053f9f4f4dc6d2436900e5a4 /chrome/browser | |
parent | b6b9b4ec85ba5dee24bf190adec3338a67f54e0e (diff) | |
download | chromium_src-6405a9a2c316766d3fbda622fbf8bfe33e402c28.zip chromium_src-6405a9a2c316766d3fbda622fbf8bfe33e402c28.tar.gz chromium_src-6405a9a2c316766d3fbda622fbf8bfe33e402c28.tar.bz2 |
Revert 168104 because it broke interactive_ui_tests and browser_tests on debug builds.
===
1) added "idle" and "locked" transitions to idle.onStateChanged
2) Per-app/extension idle threshold, settable via idle.setDetectionInterval
3) Bug fixes
BUG=143275
Review URL: https://chromiumcodereview.appspot.com/10985056
TBR=courage@chromium.org
Review URL: https://codereview.chromium.org/11418024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@168118 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/extensions/api/idle/idle_api.cc | 264 | ||||
-rw-r--r-- | chrome/browser/extensions/api/idle/idle_api.h | 70 | ||||
-rw-r--r-- | chrome/browser/extensions/api/idle/idle_api_unittest.cc | 675 | ||||
-rw-r--r-- | chrome/browser/extensions/api/idle/idle_manager.cc | 271 | ||||
-rw-r--r-- | chrome/browser/extensions/api/idle/idle_manager.h | 136 | ||||
-rw-r--r-- | chrome/browser/extensions/api/idle/idle_manager_factory.cc | 53 | ||||
-rw-r--r-- | chrome/browser/extensions/api/idle/idle_manager_factory.h | 36 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function_registry.cc | 3 | ||||
-rw-r--r-- | chrome/browser/idle.cc | 31 | ||||
-rw-r--r-- | chrome/browser/idle.h | 6 | ||||
-rw-r--r-- | chrome/browser/idle_android.cc | 9 | ||||
-rw-r--r-- | chrome/browser/idle_chromeos.cc | 22 | ||||
-rw-r--r-- | chrome/browser/idle_linux.cc | 12 | ||||
-rw-r--r-- | chrome/browser/idle_mac.mm | 14 | ||||
-rw-r--r-- | chrome/browser/idle_win.cc | 21 | ||||
-rw-r--r-- | chrome/browser/notifications/notification_ui_manager_impl.cc | 2 | ||||
-rw-r--r-- | chrome/browser/policy/device_status_collector.cc | 2 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_dependency_manager.cc | 2 |
18 files changed, 464 insertions, 1165 deletions
diff --git a/chrome/browser/extensions/api/idle/idle_api.cc b/chrome/browser/extensions/api/idle/idle_api.cc index 1cd1fe4..178afb4 100644 --- a/chrome/browser/extensions/api/idle/idle_api.cc +++ b/chrome/browser/extensions/api/idle/idle_api.cc @@ -4,59 +4,273 @@ #include "chrome/browser/extensions/api/idle/idle_api.h" +#include <algorithm> +#include <map> +#include <string> + #include "base/bind.h" #include "base/callback.h" +#include "base/json/json_writer.h" +#include "base/message_loop.h" +#include "base/stl_util.h" +#include "base/time.h" +#include "chrome/browser/extensions/event_router.h" +#include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/api/idle/idle_api_constants.h" -#include "chrome/browser/extensions/api/idle/idle_manager.h" -#include "chrome/browser/extensions/api/idle/idle_manager_factory.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/extensions/extension.h" +#include "content/public/browser/render_view_host.h" + +using extensions::ExtensionIdleCache; +using extensions::ExtensionIdleEventRouter; +using extensions::ExtensionIdleQueryStateFunction; + +namespace keys = extensions::idle_api_constants; namespace { +const int kIdlePollInterval = 1; // Number of seconds between status checks + // when polling for active. +const int kThrottleInterval = 1; // Number of seconds to throttle idle checks + // for. Return the previously checked idle + // state if the next check is faster than this const int kMinThreshold = 15; // In seconds. Set >1 sec for security concerns. const int kMaxThreshold = 4*60*60; // Four hours, in seconds. Not set // arbitrarily high for security concerns. +const unsigned int kMaxCacheSize = 100; // Number of state queries to cache. -int ClampThreshold(int threshold) { - if (threshold < kMinThreshold) { - threshold = kMinThreshold; - } else if (threshold > kMaxThreshold) { - threshold = kMaxThreshold; - } +// Calculates the error query interval has in respect to idle interval. +// The error is defined as amount of the query interval that is not part of the +// idle interval. +double QueryErrorFromIdle(double idle_start, + double idle_end, + double query_start, + double query_end) { + return query_end - idle_end + std::max(0., idle_start - query_start); +} + +// Internal class which is used to poll for changes in the system idle state. +class ExtensionIdlePollingTask { + public: + explicit ExtensionIdlePollingTask(int threshold, IdleState last_state, + Profile* profile) : threshold_(threshold), last_state_(last_state), + profile_(profile) {} + + // Check if we're active; then restart the polling task. Do this till we are + // are in active state. + void CheckIdleState(); + void IdleStateCallback(IdleState state); + + // Create a poll task to check for Idle state + static void CreateNewPollTask(int threshold, IdleState state, + Profile* profile); + + private: + int threshold_; + IdleState last_state_; + Profile* profile_; + + static bool poll_task_running_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionIdlePollingTask); +}; + +// Implementation of ExtensionIdlePollingTask. +bool ExtensionIdlePollingTask::poll_task_running_ = false; + +void ExtensionIdlePollingTask::IdleStateCallback(IdleState current_state) { + // If we just came into an active state, notify the extension. + if (IDLE_STATE_ACTIVE == current_state && last_state_ != current_state) + ExtensionIdleEventRouter::OnIdleStateChange(profile_, + current_state); + + ExtensionIdlePollingTask::poll_task_running_ = false; + + ExtensionIdleCache::UpdateCache(threshold_, current_state); + + // Startup another polling task as we exit. + if (current_state != IDLE_STATE_ACTIVE) + ExtensionIdlePollingTask::CreateNewPollTask(threshold_, current_state, + profile_); + + // This instance won't be needed anymore. + delete this; +} + +void ExtensionIdlePollingTask::CheckIdleState() { + CalculateIdleState(threshold_, + base::Bind(&ExtensionIdlePollingTask::IdleStateCallback, + base::Unretained(this))); +} + +// static +void ExtensionIdlePollingTask::CreateNewPollTask(int threshold, IdleState state, + Profile* profile) { + if (ExtensionIdlePollingTask::poll_task_running_) return; + + ExtensionIdlePollingTask::poll_task_running_ = true; + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&ExtensionIdlePollingTask::CheckIdleState, base::Unretained( + new ExtensionIdlePollingTask(threshold, state, profile))), + base::TimeDelta::FromSeconds(kIdlePollInterval)); +} + + +const char* IdleStateToDescription(IdleState state) { + if (IDLE_STATE_ACTIVE == state) + return keys::kStateActive; + if (IDLE_STATE_IDLE == state) + return keys::kStateIdle; + return keys::kStateLocked; +}; - return threshold; +// Helper function for reporting the idle state. The lifetime of the object +// returned is controlled by the caller. +StringValue* CreateIdleValue(IdleState idle_state) { + StringValue* result = new StringValue(IdleStateToDescription(idle_state)); + return result; +} + +int CheckThresholdBounds(int timeout) { + if (timeout < kMinThreshold) return kMinThreshold; + if (timeout > kMaxThreshold) return kMaxThreshold; + return timeout; } } // namespace -namespace extensions { +void ExtensionIdleEventRouter::OnIdleStateChange(Profile* profile, + IdleState state) { + // Prepare the single argument of the current state. + scoped_ptr<ListValue> args(new ListValue()); + args->Append(CreateIdleValue(state)); + + extensions::ExtensionSystem::Get(profile)->event_router()-> + DispatchEventToRenderers(keys::kOnStateChanged, args.Pass(), profile, + GURL(), extensions::EventFilteringInfo()); +} -bool IdleQueryStateFunction::RunImpl() { +bool ExtensionIdleQueryStateFunction::RunImpl() { int threshold; EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &threshold)); - threshold = ClampThreshold(threshold); + threshold = CheckThresholdBounds(threshold); - IdleManagerFactory::GetForProfile(profile())->QueryState( - threshold, - base::Bind(&IdleQueryStateFunction::IdleStateCallback, this)); + IdleState state = ExtensionIdleCache::CalculateIdleState(threshold); + if (state != IDLE_STATE_UNKNOWN) { + SetResult(CreateIdleValue(state)); + SendResponse(true); + return true; + } + CalculateIdleState(threshold, + base::Bind(&ExtensionIdleQueryStateFunction::IdleStateCallback, + this, threshold)); // Don't send the response, it'll be sent by our callback return true; } -void IdleQueryStateFunction::IdleStateCallback(IdleState state) { - SetResult(IdleManager::CreateIdleValue(state)); +void ExtensionIdleQueryStateFunction::IdleStateCallback(int threshold, + IdleState state) { + // If our state is not active, make sure we're running a polling task to check + // for active state and report it when it changes to active. + if (state != IDLE_STATE_ACTIVE) { + ExtensionIdlePollingTask::CreateNewPollTask(threshold, state, profile_); + } + + SetResult(CreateIdleValue(state)); + + ExtensionIdleCache::UpdateCache(threshold, state); + SendResponse(true); } -bool IdleSetDetectionIntervalFunction::RunImpl() { - int threshold; - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &threshold)); - threshold = ClampThreshold(threshold); +ExtensionIdleCache::CacheData ExtensionIdleCache::cached_data = + {-1, -1, -1, -1}; - IdleManagerFactory::GetForProfile(profile())->SetThreshold(extension_id(), - threshold); +IdleState ExtensionIdleCache::CalculateIdleState(int threshold) { + return CalculateState(threshold, base::Time::Now().ToDoubleT()); +} - return true; +void ExtensionIdleCache::UpdateCache(int threshold, IdleState state) { + Update(threshold, state, base::Time::Now().ToDoubleT()); } -} // namespace extensions +IdleState ExtensionIdleCache::CalculateState(int threshold, double now) { + if (threshold < kMinThreshold) + return IDLE_STATE_UNKNOWN; + double threshold_moment = now - static_cast<double>(threshold); + double throttle_interval = static_cast<double>(kThrottleInterval); + + // We test for IDEL_STATE_LOCKED first, because the result should be + // independent of the data for idle and active state. If last state was + // LOCKED and test for LOCKED is satisfied we should always return LOCKED. + if (cached_data.latest_locked > 0 && + now - cached_data.latest_locked < throttle_interval) + return IDLE_STATE_LOCKED; + + // If thershold moment is beyond the moment after whih we are certain we have + // been active, return active state. We allow kThrottleInterval error. + if (cached_data.latest_known_active > 0 && + threshold_moment - cached_data.latest_known_active < throttle_interval) + return IDLE_STATE_ACTIVE; + + // If total error that query interval has in respect to last recorded idle + // interval is less than kThrottleInterval, return IDLE state. + // query interval is the interval [now, now - threshold] and the error is + // defined as amount of query interval that is outside of idle interval. + double error_from_idle = + QueryErrorFromIdle(cached_data.idle_interval_start, + cached_data.idle_interval_end, threshold_moment, now); + if (cached_data.idle_interval_end > 0 && + error_from_idle < throttle_interval) + return IDLE_STATE_IDLE; + + return IDLE_STATE_UNKNOWN; +} + +void ExtensionIdleCache::Update(int threshold, IdleState state, double now) { + if (threshold < kMinThreshold) + return; + double threshold_moment = now - static_cast<double>(threshold); + switch (state) { + case IDLE_STATE_IDLE: + if (threshold_moment > cached_data.idle_interval_end) { + // Cached and new interval don't overlap. We disregard the cached one. + cached_data.idle_interval_start = threshold_moment; + } else { + // Cached and new interval overlap, so we can combine them. We set + // the cached interval begining to less recent one. + cached_data.idle_interval_start = + std::min(cached_data.idle_interval_start, threshold_moment); + } + cached_data.idle_interval_end = now; + // Reset data for LOCKED state, since the last query result is not + // LOCKED. + cached_data.latest_locked = -1; + break; + case IDLE_STATE_ACTIVE: + if (threshold_moment > cached_data.latest_known_active) + cached_data.latest_known_active = threshold_moment; + // Reset data for LOCKED state, since the last query result is not + // LOCKED. + cached_data.latest_locked = -1; + break; + case IDLE_STATE_LOCKED: + if (threshold_moment > cached_data.latest_locked) + cached_data.latest_locked = now; + break; + default: + return; + } +} + +int ExtensionIdleCache::get_min_threshold() { + return kMinThreshold; +} + +double ExtensionIdleCache::get_throttle_interval() { + return static_cast<double>(kThrottleInterval); +} diff --git a/chrome/browser/extensions/api/idle/idle_api.h b/chrome/browser/extensions/api/idle/idle_api.h index a2310fa..fd1f0e4 100644 --- a/chrome/browser/extensions/api/idle/idle_api.h +++ b/chrome/browser/extensions/api/idle/idle_api.h @@ -5,36 +5,84 @@ #ifndef CHROME_BROWSER_EXTENSIONS_API_IDLE_IDLE_API_H_ #define CHROME_BROWSER_EXTENSIONS_API_IDLE_IDLE_API_H_ -#include "chrome/browser/extensions/extension_function.h" +#include "base/gtest_prod_util.h" #include "chrome/browser/idle.h" +#include "chrome/browser/extensions/extension_function.h" + +class Profile; + +FORWARD_DECLARE_TEST(ExtensionIdleApiTest, CacheTest); namespace extensions { +// Event router class for events related to the idle API. +class ExtensionIdleEventRouter { + public: + static void OnIdleStateChange(Profile* profile, + IdleState idleState); + private: + DISALLOW_COPY_AND_ASSIGN(ExtensionIdleEventRouter); +}; + // Implementation of the chrome.idle.queryState API. -class IdleQueryStateFunction : public AsyncExtensionFunction { +class ExtensionIdleQueryStateFunction : public AsyncExtensionFunction { public: DECLARE_EXTENSION_FUNCTION_NAME("idle.queryState") protected: - virtual ~IdleQueryStateFunction() {} + virtual ~ExtensionIdleQueryStateFunction() {} // ExtensionFunction: virtual bool RunImpl() OVERRIDE; private: - void IdleStateCallback(IdleState state); + void IdleStateCallback(int threshold, IdleState state); }; -// Implementation of the chrome.idle.setDetectionInterval API. -class IdleSetDetectionIntervalFunction : public SyncExtensionFunction { +// Class used for caching answers from CalculateIdleState. +class ExtensionIdleCache { public: - DECLARE_EXTENSION_FUNCTION_NAME("idle.setDetectionInterval"); + static IdleState CalculateIdleState(int threshold); + static void UpdateCache(int threshold, IdleState state); - protected: - virtual ~IdleSetDetectionIntervalFunction() {} + private: + FRIEND_TEST_ALL_PREFIXES(::ExtensionIdleApiTest, CacheTest); - // ExtensionFunction: - virtual bool RunImpl() OVERRIDE; + struct CacheData { + // Latest moment in history after which we are certain that there was some + // activity. If we are querying for a threshold beyond this moment, we know + // the result will be active. + double latest_known_active; + // [idle_interval_start, idle_interval_end] is the latest interval in + // history for which we are certain there was no activity. + double idle_interval_start; + double idle_interval_end; + // Set iff the last recored query result was IDLE_STATE_LOCKED. Equals the + // moment the result was recorded in cache. + double latest_locked; + }; + + // We assume moment is increasing with every call to one of these two methods. + + // Tries to determine the idle state based on results of previous queries. + // |threshold| is time span in seconds from now we consider in calculating + // state. + // |moment| is the moment in time this method was called (should be equal to + // now, except in tests). + // Returns calculated state, or IDLE_STATE_UNKNOWN if the state could not be + // determined. + static IdleState CalculateState(int threshold, double moment); + + // Updates cached data with the latest query result. + // |threshold| is threshold parameter of the query. + // |state| is result of the query. + // |moment| is moment in time this method is called. + static void Update(int threshold, IdleState state, double moment); + + static int get_min_threshold(); + static double get_throttle_interval(); + + static CacheData cached_data; }; } // namespace extensions diff --git a/chrome/browser/extensions/api/idle/idle_api_unittest.cc b/chrome/browser/extensions/api/idle/idle_api_unittest.cc index 82209c6..893596b 100644 --- a/chrome/browser/extensions/api/idle/idle_api_unittest.cc +++ b/chrome/browser/extensions/api/idle/idle_api_unittest.cc @@ -2,565 +2,122 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/extensions/api/idle/idle_api.h" - -#include <limits.h> -#include <string> - -#include "base/string_number_conversions.h" -#include "chrome/browser/extensions/api/idle/idle_api_constants.h" -#include "chrome/browser/extensions/api/idle/idle_manager.h" -#include "chrome/browser/extensions/api/idle/idle_manager_factory.h" -#include "chrome/browser/extensions/event_router.h" -#include "chrome/browser/extensions/extension_function_test_utils.h" -#include "chrome/common/chrome_notification_types.h" -#include "chrome/common/extensions/extension.h" -#include "chrome/common/extensions/extension_constants.h" -#include "chrome/test/base/browser_with_test_window_test.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::_; - -namespace utils = extension_function_test_utils; - -namespace extensions { - -namespace { - -class MockEventDelegate : public IdleManager::EventDelegate { - public: - MockEventDelegate() {} - virtual ~MockEventDelegate() {} - MOCK_METHOD2(OnStateChanged, void(const std::string&, IdleState)); - virtual void RegisterObserver(EventRouter::Observer* observer) {} - virtual void UnregisterObserver(EventRouter::Observer* observer) {} -}; - -class TestIdleProvider : public IdleManager::IdleTimeProvider { - public: - TestIdleProvider(); - virtual ~TestIdleProvider(); - virtual void CalculateIdleState(int idle_threshold, - IdleCallback notify) OVERRIDE; - virtual void CalculateIdleTime(IdleTimeCallback notify) OVERRIDE; - virtual bool CheckIdleStateIsLocked() OVERRIDE; - - void set_idle_time(int idle_time); - void set_locked(bool locked); - - private: - int idle_time_; - bool locked_; -}; - -TestIdleProvider::TestIdleProvider() - : idle_time_(0), - locked_(false) { -} - -TestIdleProvider::~TestIdleProvider() { -} - -void TestIdleProvider::CalculateIdleState(int idle_threshold, - IdleCallback notify) { - if (locked_) { - notify.Run(IDLE_STATE_LOCKED); - } else { - if (idle_time_ >= idle_threshold) { - notify.Run(IDLE_STATE_IDLE); - } else { - notify.Run(IDLE_STATE_ACTIVE); - } - } -} - -void TestIdleProvider::CalculateIdleTime(IdleTimeCallback notify) { - notify.Run(idle_time_); -} - -bool TestIdleProvider::CheckIdleStateIsLocked() { - return locked_; -} - -void TestIdleProvider::set_idle_time(int idle_time) { - idle_time_ = idle_time; -} - -void TestIdleProvider::set_locked(bool locked) { - locked_ = locked; -} - -class ScopedListen { - public: - ScopedListen(IdleManager* idle_manager, const std::string& extension_id); - ~ScopedListen(); - - private: - IdleManager* idle_manager_; - const std::string extension_id_; -}; - -ScopedListen::ScopedListen(IdleManager* idle_manager, - const std::string& extension_id) - : idle_manager_(idle_manager), - extension_id_(extension_id) { - const EventListenerInfo details(idle_api_constants::kOnStateChanged, - extension_id_); - idle_manager_->OnListenerAdded(details); -} - -ScopedListen::~ScopedListen() { - const EventListenerInfo details(idle_api_constants::kOnStateChanged, - extension_id_); - idle_manager_->OnListenerRemoved(details); -} - -ProfileKeyedService* IdleManagerTestFactory(Profile* profile) { - return new IdleManager(profile); -} - -} // namespace - -class IdleTest : public BrowserWithTestWindowTest { - public: - virtual void SetUp() OVERRIDE; - - protected: - base::Value* RunFunctionWithExtension( - UIThreadExtensionFunction* function, const std::string& args); - - void AddListener(const std::string& extension_id); - void RemoveListener(const std::string& extension_id); - - IdleManager* idle_manager_; - TestIdleProvider* idle_provider_; - testing::StrictMock<MockEventDelegate>* event_delegate_; - scoped_refptr<extensions::Extension> extension_; -}; - -void IdleTest::SetUp() { - BrowserWithTestWindowTest::SetUp(); - - IdleManagerFactory::GetInstance()->SetTestingFactory(browser()->profile(), - &IdleManagerTestFactory); - idle_manager_ = IdleManagerFactory::GetForProfile(browser()->profile()); - - extension_ = utils::CreateEmptyExtensionWithLocation( - extensions::Extension::LOAD); - - idle_provider_ = new TestIdleProvider(); - idle_manager_->SetIdleTimeProviderForTest( - scoped_ptr<IdleManager::IdleTimeProvider>(idle_provider_).Pass()); - event_delegate_ = new testing::StrictMock<MockEventDelegate>(); - idle_manager_->SetEventDelegateForTest( - scoped_ptr<IdleManager::EventDelegate>(event_delegate_).Pass()); - idle_manager_->Init(); -} - -base::Value* IdleTest::RunFunctionWithExtension( - UIThreadExtensionFunction* function, const std::string& args) { - function->set_extension(extension_.get()); - return utils::RunFunctionAndReturnSingleResult(function, args, browser()); -} - -// Verifies that "locked" takes priority over "active". -TEST_F(IdleTest, QueryLockedActive) { - idle_provider_->set_locked(true); - idle_provider_->set_idle_time(0); - - scoped_ptr<base::Value> result(RunFunctionWithExtension( - new IdleQueryStateFunction(), - "[60]")); - - std::string idle_state; - ASSERT_TRUE(result->GetAsString(&idle_state)); - EXPECT_EQ("locked", idle_state); -} - -// Verifies that "locked" takes priority over "idle". -TEST_F(IdleTest, QueryLockedIdle) { - idle_provider_->set_locked(true); - idle_provider_->set_idle_time(INT_MAX); - - scoped_ptr<base::Value> result(RunFunctionWithExtension( - new IdleQueryStateFunction(), - "[60]")); - - std::string idle_state; - ASSERT_TRUE(result->GetAsString(&idle_state)); - EXPECT_EQ("locked", idle_state); -} - -// Verifies that any amount of idle time less than the detection interval -// translates to a state of "active". -TEST_F(IdleTest, QueryActive) { - idle_provider_->set_locked(false); - - for (int time = 0; time < 60; ++time) { - SCOPED_TRACE(time); - idle_provider_->set_idle_time(time); - - scoped_ptr<base::Value> result(RunFunctionWithExtension( - new IdleQueryStateFunction(), - "[60]")); - - std::string idle_state; - ASSERT_TRUE(result->GetAsString(&idle_state)); - EXPECT_EQ("active", idle_state); - } -} - -// Verifies that an idle time >= the detection interval returns the "idle" -// state. -TEST_F(IdleTest, QueryIdle) { - idle_provider_->set_locked(false); - - for (int time = 80; time >= 60; --time) { - SCOPED_TRACE(time); - idle_provider_->set_idle_time(time); - - scoped_ptr<base::Value> result(RunFunctionWithExtension( - new IdleQueryStateFunction(), - "[60]")); - - std::string idle_state; - ASSERT_TRUE(result->GetAsString(&idle_state)); - EXPECT_EQ("idle", idle_state); - } -} - -// Verifies that requesting a detection interval < 15 has the same effect as -// passing in 15. -TEST_F(IdleTest, QueryMinThreshold) { - idle_provider_->set_locked(false); - - for (int threshold = 0; threshold < 20; ++threshold) { - for (int time = 10; time < 60; ++time) { - SCOPED_TRACE(threshold); - SCOPED_TRACE(time); - idle_provider_->set_idle_time(time); - - std::string args = "[" + base::IntToString(threshold) + "]"; - scoped_ptr<base::Value> result(RunFunctionWithExtension( - new IdleQueryStateFunction(), args)); - - std::string idle_state; - ASSERT_TRUE(result->GetAsString(&idle_state)); - - int real_threshold = (threshold < 15) ? 15 : threshold; - const char* expected = (time < real_threshold) ? "active" : "idle"; - EXPECT_EQ(expected, idle_state); - } - } -} - -// Verifies that passing in a detection interval > 4 hours has the same effect -// as passing in 4 hours. -TEST_F(IdleTest, QueryMaxThreshold) { - idle_provider_->set_locked(false); - - const int kFourHoursInSeconds = 4*60*60; - - for (int threshold = kFourHoursInSeconds - 20; - threshold < (kFourHoursInSeconds + 20); ++threshold) { - for (int time = kFourHoursInSeconds - 30; time < kFourHoursInSeconds + 30; - ++time) { - SCOPED_TRACE(threshold); - SCOPED_TRACE(time); - idle_provider_->set_idle_time(time); +#include <gtest/gtest.h> - std::string args = "[" + base::IntToString(threshold) + "]"; - scoped_ptr<base::Value> result(RunFunctionWithExtension( - new IdleQueryStateFunction(), args)); - - std::string idle_state; - ASSERT_TRUE(result->GetAsString(&idle_state)); - - int real_threshold = (threshold > kFourHoursInSeconds) ? - kFourHoursInSeconds : threshold; - const char* expected = (time < real_threshold) ? "active" : "idle"; - EXPECT_EQ(expected, idle_state); - } - } -} - -// Verifies that transitioning from an active to idle state fires an "idle" -// OnStateChanged event. -TEST_F(IdleTest, ActiveToIdle) { - ScopedListen listen_test(idle_manager_, "test"); - - idle_provider_->set_locked(false); - - for (int time = 0; time < 60; ++time) { - SCOPED_TRACE(time); - idle_provider_->set_idle_time(time); - - idle_manager_->UpdateIdleState(); - } - - idle_provider_->set_idle_time(60); - - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); - testing::Mock::VerifyAndClearExpectations(event_delegate_); - - for (int time = 61; time < 75; ++time) { - SCOPED_TRACE(time); - idle_provider_->set_idle_time(time); - idle_manager_->UpdateIdleState(); - } -} - -// Verifies that locking an active system generates a "locked" event. -TEST_F(IdleTest, ActiveToLocked) { - ScopedListen listen_test(idle_manager_, "test"); - - idle_provider_->set_locked(true); - idle_provider_->set_idle_time(5); - - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that transitioning from an idle to active state generates an -// "active" event. -TEST_F(IdleTest, IdleToActive) { - ScopedListen listen_test(idle_manager_, "test"); - - idle_provider_->set_locked(false); - idle_provider_->set_idle_time(75); - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); - testing::Mock::VerifyAndClearExpectations(event_delegate_); - - idle_provider_->set_idle_time(0); - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_ACTIVE)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that locking an idle system generates a "locked" event. -TEST_F(IdleTest, IdleToLocked) { - ScopedListen listen_test(idle_manager_, "test"); - - idle_provider_->set_locked(false); - idle_provider_->set_idle_time(75); - - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); - testing::Mock::VerifyAndClearExpectations(event_delegate_); - - idle_provider_->set_locked(true); - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that unlocking an active system generates an "active" event. -TEST_F(IdleTest, LockedToActive) { - ScopedListen listen_test(idle_manager_, "test"); - - idle_provider_->set_locked(true); - idle_provider_->set_idle_time(0); - - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED)); - idle_manager_->UpdateIdleState(); - - idle_provider_->set_locked(false); - idle_provider_->set_idle_time(5); - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_ACTIVE)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that unlocking an inactive system generates an "idle" event. -TEST_F(IdleTest, LockedToIdle) { - ScopedListen listen_test(idle_manager_, "test"); - - idle_provider_->set_locked(true); - idle_provider_->set_idle_time(75); - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_LOCKED)); - idle_manager_->UpdateIdleState(); - testing::Mock::VerifyAndClearExpectations(event_delegate_); - - idle_provider_->set_locked(false); - EXPECT_CALL(*event_delegate_, OnStateChanged("test", IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that events are routed to extensions that have one or more listeners -// in scope. -TEST_F(IdleTest, MultipleExtensions) { - ScopedListen listen_1(idle_manager_, "1"); - ScopedListen listen_2(idle_manager_, "2"); - - idle_provider_->set_locked(true); - EXPECT_CALL(*event_delegate_, OnStateChanged("1", IDLE_STATE_LOCKED)); - EXPECT_CALL(*event_delegate_, OnStateChanged("2", IDLE_STATE_LOCKED)); - idle_manager_->UpdateIdleState(); - testing::Mock::VerifyAndClearExpectations(event_delegate_); - - { - ScopedListen listen_2prime(idle_manager_, "2"); - ScopedListen listen_3(idle_manager_, "3"); - idle_provider_->set_locked(false); - EXPECT_CALL(*event_delegate_, OnStateChanged("1", IDLE_STATE_ACTIVE)); - EXPECT_CALL(*event_delegate_, OnStateChanged("2", IDLE_STATE_ACTIVE)); - EXPECT_CALL(*event_delegate_, OnStateChanged("3", IDLE_STATE_ACTIVE)); - idle_manager_->UpdateIdleState(); - testing::Mock::VerifyAndClearExpectations(event_delegate_); - } - - idle_provider_->set_locked(true); - EXPECT_CALL(*event_delegate_, OnStateChanged("1", IDLE_STATE_LOCKED)); - EXPECT_CALL(*event_delegate_, OnStateChanged("2", IDLE_STATE_LOCKED)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that setDetectionInterval changes the detection interval from the -// default of 60 seconds, and that the call only affects a single extension's -// IdleMonitor. -TEST_F(IdleTest, SetDetectionInterval) { - ScopedListen listen_default(idle_manager_, "default"); - ScopedListen listen_extension(idle_manager_, extension_->id()); - - scoped_ptr<base::Value> result45(RunFunctionWithExtension( - new IdleSetDetectionIntervalFunction(), - "[45]")); - - idle_provider_->set_locked(false); - idle_provider_->set_idle_time(44); - idle_manager_->UpdateIdleState(); - - idle_provider_->set_idle_time(45); - EXPECT_CALL(*event_delegate_, - OnStateChanged(extension_->id(), IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); - // Verify that the expectation has been fulfilled before incrementing the - // time again. - testing::Mock::VerifyAndClearExpectations(event_delegate_); - - idle_provider_->set_idle_time(60); - EXPECT_CALL(*event_delegate_, OnStateChanged("default", IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that setting the detection interval before creating the listener -// works correctly. -TEST_F(IdleTest, SetDetectionIntervalBeforeListener) { - scoped_ptr<base::Value> result45(RunFunctionWithExtension( - new IdleSetDetectionIntervalFunction(), - "[45]")); - - ScopedListen listen_extension(idle_manager_, extension_->id()); - - idle_provider_->set_locked(false); - idle_provider_->set_idle_time(44); - idle_manager_->UpdateIdleState(); - - idle_provider_->set_idle_time(45); - EXPECT_CALL(*event_delegate_, - OnStateChanged(extension_->id(), IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that setting a detection interval above the maximum value results -// in an interval of 4 hours. -TEST_F(IdleTest, SetDetectionIntervalMaximum) { - ScopedListen listen_extension(idle_manager_, extension_->id()); - - scoped_ptr<base::Value> result(RunFunctionWithExtension( - new IdleSetDetectionIntervalFunction(), - "[18000]")); // five hours in seconds - - idle_provider_->set_locked(false); - idle_provider_->set_idle_time(4*60*60 - 1); - idle_manager_->UpdateIdleState(); - - idle_provider_->set_idle_time(4*60*60); - EXPECT_CALL(*event_delegate_, - OnStateChanged(extension_->id(), IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that setting a detection interval below the minimum value results -// in an interval of 15 seconds. -TEST_F(IdleTest, SetDetectionIntervalMinimum) { - ScopedListen listen_extension(idle_manager_, extension_->id()); - - scoped_ptr<base::Value> result(RunFunctionWithExtension( - new IdleSetDetectionIntervalFunction(), - "[10]")); - - idle_provider_->set_locked(false); - idle_provider_->set_idle_time(14); - idle_manager_->UpdateIdleState(); - - idle_provider_->set_idle_time(15); - EXPECT_CALL(*event_delegate_, - OnStateChanged(extension_->id(), IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); -} - -// Verifies that an extension's detection interval is discarded when it unloads. -TEST_F(IdleTest, UnloadCleanup) { - { - ScopedListen listen(idle_manager_, extension_->id()); - - scoped_ptr<base::Value> result45(RunFunctionWithExtension( - new IdleSetDetectionIntervalFunction(), - "[15]")); - } - - // Listener count dropping to zero does not reset threshold. - - { - ScopedListen listen(idle_manager_, extension_->id()); - idle_provider_->set_idle_time(16); - EXPECT_CALL(*event_delegate_, - OnStateChanged(extension_->id(), IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); - testing::Mock::VerifyAndClearExpectations(event_delegate_); - } - - // Threshold will reset after unload (and listen count == 0) - UnloadedExtensionInfo details(extension_, - extension_misc::UNLOAD_REASON_UNINSTALL); - idle_manager_->Observe( - chrome::NOTIFICATION_EXTENSION_UNLOADED, - content::Source<Profile>(browser()->profile()), - content::Details<UnloadedExtensionInfo>(&details)); - - { - ScopedListen listen(idle_manager_, extension_->id()); - idle_manager_->UpdateIdleState(); - testing::Mock::VerifyAndClearExpectations(event_delegate_); - - idle_provider_->set_idle_time(61); - EXPECT_CALL(*event_delegate_, - OnStateChanged(extension_->id(), IDLE_STATE_IDLE)); - idle_manager_->UpdateIdleState(); - } -} - -// Verifies that unloading an extension with no listeners or threshold works. -TEST_F(IdleTest, UnloadOnly) { - UnloadedExtensionInfo details(extension_, - extension_misc::UNLOAD_REASON_UNINSTALL); - idle_manager_->Observe( - chrome::NOTIFICATION_EXTENSION_UNLOADED, - content::Source<Profile>(browser()->profile()), - content::Details<UnloadedExtensionInfo>(&details)); -} +#include "chrome/browser/extensions/api/idle/idle_api.h" -// Verifies that its ok for the unload notification to happen before all the -// listener removals. -TEST_F(IdleTest, UnloadWhileListening) { - ScopedListen listen(idle_manager_, extension_->id()); - UnloadedExtensionInfo details(extension_, - extension_misc::UNLOAD_REASON_UNINSTALL); - idle_manager_->Observe( - chrome::NOTIFICATION_EXTENSION_UNLOADED, - content::Source<Profile>(browser()->profile()), - content::Details<UnloadedExtensionInfo>(&details)); +using extensions::ExtensionIdleCache; + +TEST(ExtensionIdleApiTest, CacheTest) { + double throttle_interval = ExtensionIdleCache::get_throttle_interval(); + int min_threshold = ExtensionIdleCache::get_min_threshold(); + double now = 10 * min_threshold; + + EXPECT_EQ(IDLE_STATE_UNKNOWN, + ExtensionIdleCache::CalculateState(min_threshold, now)); + + ExtensionIdleCache::Update(2 * min_threshold, IDLE_STATE_IDLE, now); + + EXPECT_EQ(IDLE_STATE_IDLE, + ExtensionIdleCache::CalculateState(2 * min_threshold, now)); + EXPECT_EQ(IDLE_STATE_IDLE, + ExtensionIdleCache::CalculateState(2 * min_threshold, + now + 0.9 * throttle_interval)); + EXPECT_EQ(IDLE_STATE_IDLE, + ExtensionIdleCache::CalculateState(min_threshold, + now + 0.1 * throttle_interval)); + // Threshold exeeds idle interval boundries. + EXPECT_EQ(IDLE_STATE_UNKNOWN, + ExtensionIdleCache::CalculateState(2 * min_threshold + 1, + now + 0.1 * throttle_interval)); + // It has been more than throttle interval since last query. + EXPECT_EQ(IDLE_STATE_UNKNOWN, + ExtensionIdleCache::CalculateState(min_threshold, + now + 1.1 * throttle_interval)); + + now += 10 * min_threshold; + // Idle interval does not overlap with previous one. + ExtensionIdleCache::Update(5 * min_threshold, IDLE_STATE_IDLE, now); + EXPECT_EQ(IDLE_STATE_UNKNOWN, + ExtensionIdleCache::CalculateState(7 * min_threshold, now)); + + now += min_threshold; + // Idle interval overlaps with previous one. + ExtensionIdleCache::Update(2 * min_threshold, IDLE_STATE_IDLE, now); + // Threshold exeeds last idle interval boundaries, but does not exeed union of + // two last (overlaping) idle intervals. + EXPECT_EQ(IDLE_STATE_IDLE, + ExtensionIdleCache::CalculateState(4 * min_threshold, now)); + + now += 0.2 * throttle_interval; + ExtensionIdleCache::Update(8 * min_threshold, IDLE_STATE_ACTIVE, now); + EXPECT_EQ(IDLE_STATE_IDLE, + ExtensionIdleCache::CalculateState(4 * min_threshold, + now + 0.3 * throttle_interval)); + + // If both idle and active conditions are satisfied, return ACTIVE (because + // obviously ACTIVE was reported after last idle interval). + ExtensionIdleCache::Update(3 * min_threshold, IDLE_STATE_ACTIVE, now); + EXPECT_EQ(IDLE_STATE_ACTIVE, + ExtensionIdleCache::CalculateState(4 * min_threshold, + now + 0.3 * throttle_interval)); + + now += 10 * min_threshold; + ExtensionIdleCache::Update(8 * min_threshold, IDLE_STATE_ACTIVE, now); + // Threshold does not exeed last active state, but the error is within + // throttle interval. + EXPECT_EQ(IDLE_STATE_ACTIVE, + ExtensionIdleCache::CalculateState(8 * min_threshold, + now + 0.3 * throttle_interval)); + // The error is not within throttle interval. + EXPECT_EQ(IDLE_STATE_UNKNOWN, + ExtensionIdleCache::CalculateState(8 * min_threshold, + now + 1.1 * throttle_interval)); + + // We report LOCKED iff it was last reported state was LOCKED and it has + // been less than throttle_interval since last query. + now += 10 * min_threshold; + ExtensionIdleCache::Update(4 * min_threshold, IDLE_STATE_LOCKED, now); + EXPECT_EQ(IDLE_STATE_LOCKED, + ExtensionIdleCache::CalculateState(2 * min_threshold, + now + 0.3 * throttle_interval)); + // More than throttle_interval since last query. + EXPECT_EQ(IDLE_STATE_UNKNOWN, + ExtensionIdleCache::CalculateState(2 * min_threshold, + now + 1.1 * throttle_interval)); + + now += 0.2 * throttle_interval; + ExtensionIdleCache::Update(4 * min_threshold, IDLE_STATE_ACTIVE, now); + // Last reported query was ACTIVE. + EXPECT_EQ(IDLE_STATE_UNKNOWN, + ExtensionIdleCache::CalculateState(2 * min_threshold, + now + 0.3 * throttle_interval)); + + now += 0.2 * throttle_interval; + ExtensionIdleCache::Update(2 * min_threshold, IDLE_STATE_LOCKED, now); + EXPECT_EQ(IDLE_STATE_LOCKED, + ExtensionIdleCache::CalculateState(5 * min_threshold, + now + 0.3 * throttle_interval)); + + now += 10 * min_threshold; + ExtensionIdleCache::Update(4 * min_threshold, IDLE_STATE_LOCKED, now); + + now += 0.2 * throttle_interval; + ExtensionIdleCache::Update(2 * min_threshold, IDLE_STATE_IDLE, now); + + // Last reported state was IDLE. + EXPECT_EQ(IDLE_STATE_UNKNOWN, + ExtensionIdleCache::CalculateState(3 * min_threshold, + now + 0.3 * throttle_interval)); + + now += min_threshold; + ExtensionIdleCache::Update(2 * min_threshold, IDLE_STATE_LOCKED, now); + + now += 0.2 * throttle_interval; + ExtensionIdleCache::Update(4 * min_threshold, IDLE_STATE_ACTIVE, now); + + // Last reported state was ACTIVE. + EXPECT_EQ(IDLE_STATE_ACTIVE, + ExtensionIdleCache::CalculateState(6 * min_threshold, + now + 0.3 * throttle_interval)); } - -} // extensions diff --git a/chrome/browser/extensions/api/idle/idle_manager.cc b/chrome/browser/extensions/api/idle/idle_manager.cc deleted file mode 100644 index 5931348..0000000 --- a/chrome/browser/extensions/api/idle/idle_manager.cc +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/extensions/api/idle/idle_manager.h" - -#include <utility> - -#include "base/stl_util.h" -#include "chrome/browser/extensions/api/idle/idle_api_constants.h" -#include "chrome/browser/extensions/event_router.h" -#include "chrome/browser/extensions/extension_system.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/chrome_notification_types.h" -#include "chrome/common/extensions/extension.h" -#include "chrome/common/extensions/extension_constants.h" - -namespace keys = extensions::idle_api_constants; - -namespace extensions { - -namespace { - -const int kDefaultIdleThreshold = 60; -const int kPollInterval = 1; - -class DefaultEventDelegate : public IdleManager::EventDelegate { - public: - explicit DefaultEventDelegate(Profile* profile); - virtual ~DefaultEventDelegate(); - - virtual void OnStateChanged(const std::string& extension_id, - IdleState new_state) OVERRIDE; - virtual void RegisterObserver(EventRouter::Observer* observer) OVERRIDE; - virtual void UnregisterObserver(EventRouter::Observer* observer) OVERRIDE; - - private: - Profile* profile_; -}; - -DefaultEventDelegate::DefaultEventDelegate(Profile* profile) - : profile_(profile) { -} - -DefaultEventDelegate::~DefaultEventDelegate() { -} - -void DefaultEventDelegate::OnStateChanged(const std::string& extension_id, - IdleState new_state) { - scoped_ptr<ListValue> args(new ListValue()); - args->Append(IdleManager::CreateIdleValue(new_state)); - ExtensionSystem::Get(profile_)->event_router()->DispatchEventToExtension( - extension_id, keys::kOnStateChanged, args.Pass(), profile_, GURL()); -} - -void DefaultEventDelegate::RegisterObserver( - EventRouter::Observer* observer) { - ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( - observer, idle_api_constants::kOnStateChanged); -} - -void DefaultEventDelegate::UnregisterObserver(EventRouter::Observer* observer) { - ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(observer); -} - - -class DefaultIdleProvider : public IdleManager::IdleTimeProvider { - public: - DefaultIdleProvider(); - virtual ~DefaultIdleProvider(); - - virtual void CalculateIdleState(int idle_threshold, - IdleCallback notify) OVERRIDE; - virtual void CalculateIdleTime(IdleTimeCallback notify) OVERRIDE; - virtual bool CheckIdleStateIsLocked() OVERRIDE; -}; - -DefaultIdleProvider::DefaultIdleProvider() { -} - -DefaultIdleProvider::~DefaultIdleProvider() { -} - -void DefaultIdleProvider::CalculateIdleState(int idle_threshold, - IdleCallback notify) { - ::CalculateIdleState(idle_threshold, notify); -} - -void DefaultIdleProvider::CalculateIdleTime(IdleTimeCallback notify) { - ::CalculateIdleTime(notify); -} - -bool DefaultIdleProvider::CheckIdleStateIsLocked() { - return ::CheckIdleStateIsLocked(); -} - -IdleState IdleTimeToIdleState(bool locked, int idle_time, int idle_threshold) { - IdleState state; - - if (locked) { - state = IDLE_STATE_LOCKED; - } else if (idle_time >= idle_threshold) { - state = IDLE_STATE_IDLE; - } else { - state = IDLE_STATE_ACTIVE; - } - return state; -} - -} // namespace - -IdleMonitor::IdleMonitor(IdleState initial_state) - : last_state(initial_state), - listeners(0), - threshold(kDefaultIdleThreshold) { -} - -IdleManager::IdleManager(Profile* profile) - : profile_(profile), - last_state_(IDLE_STATE_ACTIVE), - weak_factory_(this), - idle_time_provider_(new DefaultIdleProvider()), - event_delegate_(new DefaultEventDelegate(profile)) { -} - -IdleManager::~IdleManager() { - DCHECK(thread_checker_.CalledOnValidThread()); - event_delegate_->UnregisterObserver(this); -} - -void IdleManager::Init() { - registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, - content::Source<Profile>(profile_->GetOriginalProfile())); - event_delegate_->RegisterObserver(this); -} - -void IdleManager::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(type == chrome::NOTIFICATION_EXTENSION_UNLOADED); - - const Extension* extension = - content::Details<extensions::UnloadedExtensionInfo>(details)->extension; - monitors_.erase(extension->id()); -} - -void IdleManager::OnListenerAdded(const EventListenerInfo& details) { - DCHECK(thread_checker_.CalledOnValidThread()); - - ++GetMonitor(details.extension_id)->listeners; - StartPolling(); -} - -void IdleManager::OnListenerRemoved(const EventListenerInfo& details) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // During unload the monitor could already have been deleted. No need to do - // anything in that case. - MonitorMap::iterator it = monitors_.find(details.extension_id); - if (it != monitors_.end()) { - DCHECK_GT(it->second.listeners, 0); - --it->second.listeners; - } -} - -void IdleManager::QueryState(int threshold, QueryStateCallback notify) { - DCHECK(thread_checker_.CalledOnValidThread()); - idle_time_provider_->CalculateIdleState(threshold, notify); -} - -void IdleManager::SetThreshold(const std::string& extension_id, - int threshold) { - DCHECK(thread_checker_.CalledOnValidThread()); - GetMonitor(extension_id)->threshold = threshold; -} - -// static -StringValue* IdleManager::CreateIdleValue(IdleState idle_state) { - const char* description; - - if (idle_state == IDLE_STATE_ACTIVE) { - description = keys::kStateActive; - } else if (idle_state == IDLE_STATE_IDLE) { - description = keys::kStateIdle; - } else { - description = keys::kStateLocked; - } - - return new StringValue(description); -} - -void IdleManager::SetEventDelegateForTest( - scoped_ptr<EventDelegate> event_delegate) { - DCHECK(thread_checker_.CalledOnValidThread()); - event_delegate_ = event_delegate.Pass(); -} - -void IdleManager::SetIdleTimeProviderForTest( - scoped_ptr<IdleTimeProvider> idle_time_provider) { - DCHECK(thread_checker_.CalledOnValidThread()); - idle_time_provider_ = idle_time_provider.Pass(); -} - -IdleMonitor* IdleManager::GetMonitor(const std::string& extension_id) { - DCHECK(thread_checker_.CalledOnValidThread()); - MonitorMap::iterator it = monitors_.find(extension_id); - - if (it == monitors_.end()) { - it = monitors_.insert(std::make_pair(extension_id, - IdleMonitor(last_state_))).first; - } - return &it->second; -} - -void IdleManager::StartPolling() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!poll_timer_.IsRunning()) { - poll_timer_.Start(FROM_HERE, - base::TimeDelta::FromSeconds(kPollInterval), - this, - &IdleManager::UpdateIdleState); - } -} - -void IdleManager::StopPolling() { - DCHECK(thread_checker_.CalledOnValidThread()); - poll_timer_.Stop(); -} - -void IdleManager::UpdateIdleState() { - DCHECK(thread_checker_.CalledOnValidThread()); - idle_time_provider_->CalculateIdleTime( - base::Bind( - &IdleManager::UpdateIdleStateCallback, - weak_factory_.GetWeakPtr())); -} - -void IdleManager::UpdateIdleStateCallback(int idle_time) { - DCHECK(thread_checker_.CalledOnValidThread()); - bool locked = idle_time_provider_->CheckIdleStateIsLocked(); - int listener_count = 0; - - // Remember this state for initializing new event listeners. - last_state_ = IdleTimeToIdleState(locked, - idle_time, - kDefaultIdleThreshold); - - for (MonitorMap::iterator it = monitors_.begin(); - it != monitors_.end(); ++it) { - if (it->second.listeners < 1) - continue; - - ++listener_count; - - IdleState new_state = IdleTimeToIdleState(locked, - idle_time, - it->second.threshold); - - if (new_state != it->second.last_state) { - it->second.last_state = new_state; - event_delegate_->OnStateChanged(it->first, new_state); - } - } - - if (listener_count == 0) { - StopPolling(); - } -} - -} // namespace extensions diff --git a/chrome/browser/extensions/api/idle/idle_manager.h b/chrome/browser/extensions/api/idle/idle_manager.h deleted file mode 100644 index e54df77..0000000 --- a/chrome/browser/extensions/api/idle/idle_manager.h +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_EXTENSIONS_API_IDLE_IDLE_MANAGER_H_ -#define CHROME_BROWSER_EXTENSIONS_API_IDLE_IDLE_MANAGER_H_ - -#include <map> -#include <string> - -#include "base/callback_forward.h" -#include "base/gtest_prod_util.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" -#include "base/timer.h" -#include "chrome/browser/extensions/event_router.h" -#include "chrome/browser/idle.h" -#include "chrome/browser/profiles/profile_keyed_service.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" - -namespace base { -class StringValue; -} // namespace base - -class Profile; - -namespace extensions { - -typedef base::Callback<void(IdleState)> QueryStateCallback; - -struct IdleMonitor { - explicit IdleMonitor(IdleState initial_state); - - IdleState last_state; - int listeners; - int threshold; -}; - -class IdleManager : public content::NotificationObserver, - public EventRouter::Observer, - public ProfileKeyedService { - public: - class IdleTimeProvider { - public: - IdleTimeProvider() {} - virtual ~IdleTimeProvider() {} - virtual void CalculateIdleState(int idle_threshold, - IdleCallback notify) = 0; - virtual void CalculateIdleTime(IdleTimeCallback notify) = 0; - virtual bool CheckIdleStateIsLocked() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(IdleTimeProvider); - }; - - class EventDelegate { - public: - EventDelegate() {} - virtual ~EventDelegate() {} - virtual void OnStateChanged(const std::string& extension_id, - IdleState new_state) = 0; - virtual void RegisterObserver(EventRouter::Observer* observer) = 0; - virtual void UnregisterObserver(EventRouter::Observer* observer) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(EventDelegate); - }; - - explicit IdleManager(Profile* profile); - virtual ~IdleManager(); - - void Init(); - - // content::NotificationDelegate implementation. - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; - - // EventRouter::Observer implementation. - virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE; - virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE; - - void QueryState(int threshold, QueryStateCallback notify); - void SetThreshold(const std::string& extension_id, int threshold); - static base::StringValue* CreateIdleValue(IdleState idle_state); - - // Override default event class. Callee assumes ownership. Used for testing. - void SetEventDelegateForTest(scoped_ptr<EventDelegate> event_delegate); - - // Override default idle time calculations. Callee assumes ownership. Used - // for testing. - void SetIdleTimeProviderForTest(scoped_ptr<IdleTimeProvider> idle_provider); - - private: - FRIEND_TEST_ALL_PREFIXES(IdleTest, ActiveToIdle); - FRIEND_TEST_ALL_PREFIXES(IdleTest, ActiveToLocked); - FRIEND_TEST_ALL_PREFIXES(IdleTest, IdleToActive); - FRIEND_TEST_ALL_PREFIXES(IdleTest, IdleToLocked); - FRIEND_TEST_ALL_PREFIXES(IdleTest, LockedToActive); - FRIEND_TEST_ALL_PREFIXES(IdleTest, LockedToIdle); - FRIEND_TEST_ALL_PREFIXES(IdleTest, MultipleExtensions); - FRIEND_TEST_ALL_PREFIXES(IdleTest, SetDetectionInterval); - FRIEND_TEST_ALL_PREFIXES(IdleTest, SetDetectionIntervalBeforeListener); - FRIEND_TEST_ALL_PREFIXES(IdleTest, SetDetectionIntervalMaximum); - FRIEND_TEST_ALL_PREFIXES(IdleTest, SetDetectionIntervalMinimum); - FRIEND_TEST_ALL_PREFIXES(IdleTest, UnloadCleanup); - - typedef std::map<const std::string, IdleMonitor> MonitorMap; - - IdleMonitor* GetMonitor(const std::string& extension_id); - void StartPolling(); - void StopPolling(); - void UpdateIdleState(); - void UpdateIdleStateCallback(int idle_time); - - Profile* profile_; - - IdleState last_state_; - MonitorMap monitors_; - - base::RepeatingTimer<IdleManager> poll_timer_; - base::WeakPtrFactory<IdleManager> weak_factory_; - content::NotificationRegistrar registrar_; - - scoped_ptr<IdleTimeProvider> idle_time_provider_; - scoped_ptr<EventDelegate> event_delegate_; - - base::ThreadChecker thread_checker_; - - DISALLOW_COPY_AND_ASSIGN(IdleManager); -}; - -} // namespace extensions - -#endif // CHROME_BROWSER_EXTENSIONS_API_IDLE_IDLE_MANAGER_H_ diff --git a/chrome/browser/extensions/api/idle/idle_manager_factory.cc b/chrome/browser/extensions/api/idle/idle_manager_factory.cc deleted file mode 100644 index 84df8cb..0000000 --- a/chrome/browser/extensions/api/idle/idle_manager_factory.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/extensions/api/idle/idle_manager_factory.h" - -#include "chrome/browser/extensions/api/idle/idle_manager.h" -#include "chrome/browser/extensions/extension_system_factory.h" -#include "chrome/browser/profiles/profile_dependency_manager.h" - -namespace extensions { - -// static -IdleManager* IdleManagerFactory::GetForProfile( - Profile* profile) { - return static_cast<IdleManager*>( - GetInstance()->GetServiceForProfile(profile, true)); -} - -// static -IdleManagerFactory* IdleManagerFactory::GetInstance() { - return Singleton<IdleManagerFactory>::get(); -} - -IdleManagerFactory::IdleManagerFactory() - : ProfileKeyedServiceFactory("IdleManager", - ProfileDependencyManager::GetInstance()) { - DependsOn(ExtensionSystemFactory::GetInstance()); -} - -IdleManagerFactory::~IdleManagerFactory() { -} - -ProfileKeyedService* IdleManagerFactory::BuildServiceInstanceFor( - Profile* profile) const { - IdleManager* idle_manager = new IdleManager(profile); - idle_manager->Init(); - return idle_manager; -} - -bool IdleManagerFactory::ServiceRedirectedInIncognito() const { - return true; -} - -bool IdleManagerFactory::ServiceIsCreatedWithProfile() const { - return true; -} - -bool IdleManagerFactory::ServiceIsNULLWhileTesting() const { - return true; -} - -} // namespace extensions diff --git a/chrome/browser/extensions/api/idle/idle_manager_factory.h b/chrome/browser/extensions/api/idle/idle_manager_factory.h deleted file mode 100644 index 8f902dc..0000000 --- a/chrome/browser/extensions/api/idle/idle_manager_factory.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_EXTENSIONS_API_IDLE_IDLE_MANAGER_FACTORY_H__ -#define CHROME_BROWSER_EXTENSIONS_API_IDLE_IDLE_MANAGER_FACTORY_H__ - -#include "base/memory/singleton.h" -#include "chrome/browser/profiles/profile_keyed_service_factory.h" - -namespace extensions { -class IdleManager; - -class IdleManagerFactory : public ProfileKeyedServiceFactory { - public: - static IdleManager* GetForProfile(Profile* profile); - - static IdleManagerFactory* GetInstance(); - - private: - friend struct DefaultSingletonTraits<IdleManagerFactory>; - - IdleManagerFactory(); - virtual ~IdleManagerFactory(); - - // ProfileKeyedBaseFactory implementation. - virtual ProfileKeyedService* BuildServiceInstanceFor( - Profile* profile) const OVERRIDE; - virtual bool ServiceRedirectedInIncognito() const OVERRIDE; - virtual bool ServiceIsCreatedWithProfile() const OVERRIDE; - virtual bool ServiceIsNULLWhileTesting() const OVERRIDE; -}; - -} // namespace extensions - -#endif // CHROME_BROWSER_EXTENSIONS_API_IDLE_IDLE_MANAGER_FACTORY_H__ diff --git a/chrome/browser/extensions/extension_function_registry.cc b/chrome/browser/extensions/extension_function_registry.cc index 53aedc8..21b9030 100644 --- a/chrome/browser/extensions/extension_function_registry.cc +++ b/chrome/browser/extensions/extension_function_registry.cc @@ -201,8 +201,7 @@ void ExtensionFunctionRegistry::ResetFunctions() { RegisterFunction<SearchHistoryFunction>(); // Idle - RegisterFunction<extensions::IdleQueryStateFunction>(); - RegisterFunction<extensions::IdleSetDetectionIntervalFunction>(); + RegisterFunction<extensions::ExtensionIdleQueryStateFunction>(); // I18N. RegisterFunction<GetAcceptLanguagesFunction>(); diff --git a/chrome/browser/idle.cc b/chrome/browser/idle.cc deleted file mode 100644 index 7a19943..0000000 --- a/chrome/browser/idle.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/idle.h" - -#include "base/bind.h" - -namespace { - -void CalculateIdleStateCallback(int idle_threshold, - IdleCallback notify, - int idle_time) { - if (idle_time >= idle_threshold) - notify.Run(IDLE_STATE_IDLE); - else - notify.Run(IDLE_STATE_ACTIVE); -} - -} // namespace - -void CalculateIdleState(int idle_threshold, IdleCallback notify) { - if (CheckIdleStateIsLocked()) { - notify.Run(IDLE_STATE_LOCKED); - return; - } - - CalculateIdleTime(base::Bind(&CalculateIdleStateCallback, - idle_threshold, - notify)); -} diff --git a/chrome/browser/idle.h b/chrome/browser/idle.h index 7b78cd9..df6abd7 100644 --- a/chrome/browser/idle.h +++ b/chrome/browser/idle.h @@ -23,13 +23,9 @@ void StopIdleMonitor(); #endif typedef base::Callback<void(IdleState)> IdleCallback; -typedef base::Callback<void(int)> IdleTimeCallback; // Calculate the Idle state and notify the callback. -void CalculateIdleState(int idle_threshold, IdleCallback notify); - -// Calculate Idle time in seconds and notify the callback -void CalculateIdleTime(IdleTimeCallback notify); +void CalculateIdleState(unsigned int idle_threshold, IdleCallback notify); // Checks synchronously if Idle state is IDLE_STATE_LOCKED. bool CheckIdleStateIsLocked(); diff --git a/chrome/browser/idle_android.cc b/chrome/browser/idle_android.cc index 9d4fa2c..7cf1969 100644 --- a/chrome/browser/idle_android.cc +++ b/chrome/browser/idle_android.cc @@ -10,12 +10,7 @@ // constrained devices such as Android we'll often get completely killed if // Chrome isn't active anyway. // TODO(yfriedman): Tracking in bug: 114481 -void CalculateIdleTime(IdleTimeCallback notify) { +void CalculateIdleState(unsigned int idle_threshold, IdleCallback notify) { NOTIMPLEMENTED(); - notify.Run(0); -} - -bool CheckIdleStateIsLocked() { - NOTIMPLEMENTED(); - return false; + notify.Run(IDLE_STATE_ACTIVE); } diff --git a/chrome/browser/idle_chromeos.cc b/chrome/browser/idle_chromeos.cc index 32b7fdd..d8f2f08 100644 --- a/chrome/browser/idle_chromeos.cc +++ b/chrome/browser/idle_chromeos.cc @@ -4,25 +4,27 @@ #include "chrome/browser/idle.h" -#include <limits.h> - #include "base/bind.h" #include "base/callback.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/power_manager_client.h" -void CalculateIdleTimeNotifier(IdleTimeCallback notify, - int64_t idle_time_s) { - if (idle_time_s > INT_MAX) { - // Just in case you are idle for > 100 years. - idle_time_s = INT_MAX; +void CalculateIdleStateNotifier(unsigned int idle_treshold, + IdleCallback notify, + int64_t idle_time_s) { + if (idle_time_s >= (int64_t)idle_treshold) { + notify.Run(IDLE_STATE_IDLE); + } else if (idle_time_s < 0) { + notify.Run(IDLE_STATE_UNKNOWN); + } else { + notify.Run(IDLE_STATE_ACTIVE); } - notify.Run(static_cast<int>(idle_time_s)); } -void CalculateIdleTime(IdleTimeCallback notify) { +void CalculateIdleState(unsigned int idle_threshold, IdleCallback notify) { chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> - CalculateIdleTime(base::Bind(&CalculateIdleTimeNotifier, notify)); + CalculateIdleTime(base::Bind(&CalculateIdleStateNotifier, idle_threshold, + notify)); } bool CheckIdleStateIsLocked() { diff --git a/chrome/browser/idle_linux.cc b/chrome/browser/idle_linux.cc index 023a1b2..045a47d 100644 --- a/chrome/browser/idle_linux.cc +++ b/chrome/browser/idle_linux.cc @@ -11,9 +11,17 @@ #include "chrome/browser/screensaver_window_finder_gtk.h" #endif -void CalculateIdleTime(IdleTimeCallback notify) { +void CalculateIdleState(unsigned int idle_threshold, IdleCallback notify) { + if (CheckIdleStateIsLocked()) { + notify.Run(IDLE_STATE_LOCKED); + return; + } chrome::IdleQueryLinux idle_query; - notify.Run(idle_query.IdleTime()); + unsigned int idle_time = idle_query.IdleTime(); + if (idle_time >= idle_threshold) + notify.Run(IDLE_STATE_IDLE); + else + notify.Run(IDLE_STATE_ACTIVE); } bool CheckIdleStateIsLocked() { diff --git a/chrome/browser/idle_mac.mm b/chrome/browser/idle_mac.mm index d13da03..8547ff5 100644 --- a/chrome/browser/idle_mac.mm +++ b/chrome/browser/idle_mac.mm @@ -50,7 +50,7 @@ } - (void)dealloc { - [[NSDistributedNotificationCenter defaultCenter] removeObserver:self]; + [[NSDistributedNotificationCenter defaultCenter] removeObject:self]; [super dealloc]; } @@ -84,11 +84,19 @@ void StopIdleMonitor() { g_screenMonitor = nil; } -void CalculateIdleTime(IdleTimeCallback notify) { +void CalculateIdleState(unsigned int idle_threshold, IdleCallback notify) { + if (CheckIdleStateIsLocked()) { + notify.Run(IDLE_STATE_LOCKED); + return; + } + CFTimeInterval idle_time = CGEventSourceSecondsSinceLastEventType( kCGEventSourceStateCombinedSessionState, kCGAnyInputEventType); - notify.Run(static_cast<int>(idle_time)); + if (idle_time >= idle_threshold) + notify.Run(IDLE_STATE_IDLE); + else + notify.Run(IDLE_STATE_ACTIVE); } bool CheckIdleStateIsLocked() { diff --git a/chrome/browser/idle_win.cc b/chrome/browser/idle_win.cc index 3c6c7d5..784bee7 100644 --- a/chrome/browser/idle_win.cc +++ b/chrome/browser/idle_win.cc @@ -7,9 +7,15 @@ #include <limits.h> #include <windows.h> -namespace { +static bool IsScreensaverRunning(); +static bool IsWorkstationLocked(); + +void CalculateIdleState(unsigned int idle_threshold, IdleCallback notify) { + if (CheckIdleStateIsLocked()) { + notify.Run(IDLE_STATE_LOCKED); + return; + } -DWORD CalculateIdleTimeInternal() { LASTINPUTINFO last_input_info = {0}; last_input_info.cbSize = sizeof(LASTINPUTINFO); DWORD current_idle_time = 0; @@ -31,7 +37,10 @@ DWORD CalculateIdleTimeInternal() { current_idle_time /= 1000; } - return current_idle_time; + if (current_idle_time >= idle_threshold) + notify.Run(IDLE_STATE_IDLE); + else + notify.Run(IDLE_STATE_ACTIVE); } bool IsScreensaverRunning() { @@ -59,12 +68,6 @@ bool IsWorkstationLocked() { return is_locked; } -} // namespace - -void CalculateIdleTime(IdleTimeCallback notify) { - notify.Run(static_cast<int>(CalculateIdleTimeInternal())); -} - bool CheckIdleStateIsLocked() { return IsWorkstationLocked() || IsScreensaverRunning(); } diff --git a/chrome/browser/notifications/notification_ui_manager_impl.cc b/chrome/browser/notifications/notification_ui_manager_impl.cc index 21b4b01..587efda5 100644 --- a/chrome/browser/notifications/notification_ui_manager_impl.cc +++ b/chrome/browser/notifications/notification_ui_manager_impl.cc @@ -54,14 +54,12 @@ NotificationUIManagerImpl::NotificationUIManagerImpl(PrefService* local_state) position_pref_.Init(prefs::kDesktopNotificationPosition, local_state, this); #if defined(OS_MACOSX) InitFullScreenMonitor(); - InitIdleMonitor(); #endif } NotificationUIManagerImpl::~NotificationUIManagerImpl() { STLDeleteElements(&show_queue_); #if defined(OS_MACOSX) - StopIdleMonitor(); StopFullScreenMonitor(); #endif } diff --git a/chrome/browser/policy/device_status_collector.cc b/chrome/browser/policy/device_status_collector.cc index 82d5a61..4505c554 100644 --- a/chrome/browser/policy/device_status_collector.cc +++ b/chrome/browser/policy/device_status_collector.cc @@ -31,7 +31,7 @@ namespace em = enterprise_management; namespace { // How many seconds of inactivity triggers the idle state. -const int kIdleStateThresholdSeconds = 300; +const unsigned int kIdleStateThresholdSeconds = 300; // How many days in the past to store active periods for. const unsigned int kMaxStoredPastActivityDays = 30; diff --git a/chrome/browser/profiles/profile_dependency_manager.cc b/chrome/browser/profiles/profile_dependency_manager.cc index 40cc47a..6674498 100644 --- a/chrome/browser/profiles/profile_dependency_manager.cc +++ b/chrome/browser/profiles/profile_dependency_manager.cc @@ -17,7 +17,6 @@ #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_factory.h" #include "chrome/browser/extensions/api/commands/command_service_factory.h" #include "chrome/browser/extensions/api/discovery/suggested_links_registry_factory.h" -#include "chrome/browser/extensions/api/idle/idle_manager_factory.h" #include "chrome/browser/extensions/api/processes/processes_api_factory.h" #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry_factory.h" #include "chrome/browser/extensions/app_restore_service_factory.h" @@ -225,7 +224,6 @@ void ProfileDependencyManager::AssertFactoriesBuilt() { extensions::AppRestoreServiceFactory::GetInstance(); extensions::BluetoothAPIFactory::GetInstance(); extensions::CommandServiceFactory::GetInstance(); - extensions::IdleManagerFactory::GetInstance(); extensions::SuggestedLinksRegistryFactory::GetInstance(); extensions::ExtensionSystemFactory::GetInstance(); extensions::ProcessesAPIFactory::GetInstance(); |