diff options
author | brg@chromium.com <brg@chromium.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-16 00:19:34 +0000 |
---|---|---|
committer | brg@chromium.com <brg@chromium.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-16 00:19:34 +0000 |
commit | f5205419c04244f460891b8ff8e30d3793ffa507 (patch) | |
tree | 4becb4662d36d92050001eb65e624cffeec95c10 /chrome/browser | |
parent | 5c7c98d536de7fb818b7f23ae52a92383072aa0d (diff) | |
download | chromium_src-f5205419c04244f460891b8ff8e30d3793ffa507.zip chromium_src-f5205419c04244f460891b8ff8e30d3793ffa507.tar.gz chromium_src-f5205419c04244f460891b8ff8e30d3793ffa507.tar.bz2 |
Idle API for the extension system
Tests=ExtensionApiTest.Idle
Bug=one
Review URL: http://codereview.chromium.org/845005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41661 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/extensions/extension_function_dispatcher.cc | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_idle_api.cc | 156 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_idle_api.h | 28 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_idle_api_constants.cc | 18 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_idle_api_constants.h | 24 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_idle_apitest.cc | 15 | ||||
-rw-r--r-- | chrome/browser/idle.h | 18 | ||||
-rw-r--r-- | chrome/browser/idle_linux.cc | 15 | ||||
-rw-r--r-- | chrome/browser/idle_mac.cc | 16 | ||||
-rw-r--r-- | chrome/browser/idle_win.cc | 54 |
10 files changed, 348 insertions, 0 deletions
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index 02facbd..6d47016 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -18,6 +18,7 @@ #include "chrome/browser/extensions/extension_dom_ui.h" #include "chrome/browser/extensions/extension_function.h" #include "chrome/browser/extensions/extension_history_api.h" +#include "chrome/browser/extensions/extension_idle_api.h" #include "chrome/browser/extensions/extension_i18n_api.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extension_metrics_module.h" @@ -157,6 +158,9 @@ void FactoryRegistry::ResetFunctions() { RegisterFunction<GetVisitsHistoryFunction>(); RegisterFunction<SearchHistoryFunction>(); + // Idle + RegisterFunction<ExtensionIdleQueryStateFunction>(); + // Toolstrips. RegisterFunction<ToolstripExpandFunction>(); RegisterFunction<ToolstripCollapseFunction>(); diff --git a/chrome/browser/extensions/extension_idle_api.cc b/chrome/browser/extensions/extension_idle_api.cc new file mode 100644 index 0000000..688e4be --- /dev/null +++ b/chrome/browser/extensions/extension_idle_api.cc @@ -0,0 +1,156 @@ +// Copyright (c) 2010 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. + +// This implementation supposes a single extension thread and synchronized +// method invokation. + +#include "chrome/browser/extensions/extension_idle_api.h" + +#include "base/stl_util-inl.h" +#include "base/json/json_writer.h" +#include "base/task.h" +#include "base/time.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/extensions/extension_host.h" +#include "chrome/browser/extensions/extension_message_service.h" +#include "chrome/browser/extensions/extension_idle_api_constants.h" +#include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/notification_service.h" + +namespace keys = extension_idle_api_constants; + +namespace { + +const int kIdlePollInterval = 15; // Number of seconds between status checks + // when polling for active. +const int kMinThreshold = 15; // In seconds. Set >1 sec for security concerns. +const int kMaxThreshold = 60*60; // One hours, in seconds. Not set arbitrarily + // high for security concerns. + +struct ExtensionIdlePollingData { + IdleState state; + double timestamp; +}; + +// Static variables shared between instances of polling. +static ExtensionIdlePollingData polling_data; + +// Forward declaration of utility methods. +static const wchar_t* IdleStateToDescription(IdleState state); +static StringValue* CreateIdleValue(IdleState idle_state); +static int CheckThresholdBounds(int timeout); +static IdleState CalculateIdleStateAndUpdateTimestamp(int threshold); +static void CreateNewPollTask(Profile* profile); +static IdleState ThrottledCalculateIdleState(int threshold, Profile* profile); + +// Internal object which watches for changes in the system idle state. +class ExtensionIdlePollingTask : public Task { + public: + explicit ExtensionIdlePollingTask(Profile* profile) : profile_(profile) {} + virtual ~ExtensionIdlePollingTask() {} + + // Overridden from Task. + virtual void Run(); + + private: + Profile* profile_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionIdlePollingTask); +}; + +const wchar_t* IdleStateToDescription(IdleState state) { + if (IDLE_STATE_ACTIVE == state) + return keys::kStateActive; + if (IDLE_STATE_IDLE == state) + return keys::kStateIdle; + return keys::kStateLocked; +}; + +// 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; +} + +IdleState CalculateIdleStateAndUpdateTimestamp(int threshold) { + polling_data.timestamp = base::Time::Now().ToDoubleT(); + return CalculateIdleState(threshold); +} + +void CreateNewPollTask(Profile* profile) { + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + new ExtensionIdlePollingTask(profile), + kIdlePollInterval * 1000); +} + +IdleState ThrottledCalculateIdleState(int threshold, Profile* profile) { + // If we are not active we should be polling. + if (IDLE_STATE_ACTIVE != polling_data.state) + return polling_data.state; + + // Only allow one check per threshold. + double time_now = base::Time::Now().ToDoubleT(); + double delta = time_now - polling_data.timestamp; + if (delta < threshold) + return polling_data.state; + + // Update the new state with a poll. Note this updates time of last check. + polling_data.state = CalculateIdleStateAndUpdateTimestamp(threshold); + + if (IDLE_STATE_ACTIVE != polling_data.state) + CreateNewPollTask(profile); + + return polling_data.state; +} + +void ExtensionIdlePollingTask::Run() { + IdleState state = CalculateIdleStateAndUpdateTimestamp( + kIdlePollInterval); + if (state != polling_data.state) { + polling_data.state = state; + + // Inform of change if the current state is IDLE_STATE_ACTIVE. + if (IDLE_STATE_ACTIVE == polling_data.state) + ExtensionIdleEventRouter::OnIdleStateChange(profile_, state); + } + + // Create a secondary polling task until an active state is reached. + if (IDLE_STATE_ACTIVE != polling_data.state) + CreateNewPollTask(profile_); +} + +}; // namespace + +bool ExtensionIdleQueryStateFunction::RunImpl() { + int threshold; + EXTENSION_FUNCTION_VALIDATE(args_->GetAsInteger(&threshold)); + threshold = CheckThresholdBounds(threshold); + IdleState state = ThrottledCalculateIdleState(threshold, profile()); + result_.reset(CreateIdleValue(state)); + return true; +} + +void ExtensionIdleEventRouter::OnIdleStateChange(Profile* profile, + IdleState state) { + // Prepare the single argument of the current state. + ListValue args; + args.Append(CreateIdleValue(state)); + std::string json_args; + base::JSONWriter::Write(&args, false, &json_args); + + profile->GetExtensionMessageService()->DispatchEventToRenderers( + keys::kOnStateChanged, + json_args, + profile->IsOffTheRecord()); +} diff --git a/chrome/browser/extensions/extension_idle_api.h b/chrome/browser/extensions/extension_idle_api.h new file mode 100644 index 0000000..641628a --- /dev/null +++ b/chrome/browser/extensions/extension_idle_api.h @@ -0,0 +1,28 @@ +// Copyright (c) 2010 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_EXTENSION_IDLE_API_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_IDLE_API_H_ + +#include "chrome/browser/idle.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/extensions/extension_function.h" + +// 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.experimental.idle.queryState API. +class ExtensionIdleQueryStateFunction : public SyncExtensionFunction { + public: + virtual bool RunImpl(); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.idle.queryState") +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_IDLE_API_H_ diff --git a/chrome/browser/extensions/extension_idle_api_constants.cc b/chrome/browser/extensions/extension_idle_api_constants.cc new file mode 100644 index 0000000..7cabe37 --- /dev/null +++ b/chrome/browser/extensions/extension_idle_api_constants.cc @@ -0,0 +1,18 @@ +// Copyright (c) 2010 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/extension_idle_api_constants.h" + +namespace extension_idle_api_constants { + +const wchar_t kSecondsKey[] = L"seconds"; +const wchar_t kStateKey[] = L"state"; + +const char kOnStateChanged[] = "experimental.idle.onStateChanged"; + +const wchar_t kStateActive[] = L"active"; +const wchar_t kStateIdle[] = L"idle"; +const wchar_t kStateLocked[] = L"locked"; + +} // namespace extension_idle_api_constants diff --git a/chrome/browser/extensions/extension_idle_api_constants.h b/chrome/browser/extensions/extension_idle_api_constants.h new file mode 100644 index 0000000..5bdf696 --- /dev/null +++ b/chrome/browser/extensions/extension_idle_api_constants.h @@ -0,0 +1,24 @@ +// Copyright (c) 2010 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_EXTENSION_IDLE_API_CONSTANTS_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_IDLE_API_CONSTANTS_H_ + +namespace extension_idle_api_constants { + +// Keys. +extern const wchar_t kSecondsKey[]; +extern const wchar_t kStateKey[]; + +// Events. +extern const char kOnStateChanged[]; + +// States +extern const wchar_t kStateActive[]; +extern const wchar_t kStateIdle[]; +extern const wchar_t kStateLocked[]; + +}; // namespace extension_idle_api_constants + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_IDLE_API_CONSTANTS_H_ diff --git a/chrome/browser/extensions/extension_idle_apitest.cc b/chrome/browser/extensions/extension_idle_apitest.cc new file mode 100644 index 0000000..89d7c3b --- /dev/null +++ b/chrome/browser/extensions/extension_idle_apitest.cc @@ -0,0 +1,15 @@ +// Copyright (c) 2010 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 "base/command_line.h" +#include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/common/chrome_switches.h" +#include "net/base/mock_host_resolver.h" + +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Idle) { + CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + + ASSERT_TRUE(RunExtensionTest("idle")) << message_; +} diff --git a/chrome/browser/idle.h b/chrome/browser/idle.h new file mode 100644 index 0000000..e850dbe --- /dev/null +++ b/chrome/browser/idle.h @@ -0,0 +1,18 @@ +// Copyright (c) 2010 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_IDLE_H_ +#define CHROME_BROWSER_IDLE_H_ + +#include "base/task.h" + +enum IdleState { + IDLE_STATE_ACTIVE = 0, + IDLE_STATE_IDLE = 1, // No activity within threshold. + IDLE_STATE_LOCKED = 2 // Only available on supported systems. +}; + +IdleState CalculateIdleState(unsigned int idle_threshold); + +#endif // CHROME_BROWSER_IDLE_H_ diff --git a/chrome/browser/idle_linux.cc b/chrome/browser/idle_linux.cc new file mode 100644 index 0000000..0da7f72 --- /dev/null +++ b/chrome/browser/idle_linux.cc @@ -0,0 +1,15 @@ +// Copyright (c) 2010 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 "chrome/browser/sync/engine/idle_query_linux.h" + +IdleState CalculateIdleState(unsigned int idle_threshold) { + browser_sync::IdleQueryLinux idle_query; + unsigned int idle_time = idle_query.IdleTime(); + if (idle_time >= idle_threshold) + return IDLE_STATE_IDLE; + return IDLE_STATE_ACTIVE; +} diff --git a/chrome/browser/idle_mac.cc b/chrome/browser/idle_mac.cc new file mode 100644 index 0000000..383e4c7 --- /dev/null +++ b/chrome/browser/idle_mac.cc @@ -0,0 +1,16 @@ +// Copyright (c) 2009 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 <CoreGraphics/CGEventSource.h> + +IdleState CalculateIdleState(unsigned int idle_threshold) { + unsigned int idle_time = CGEventSourceSecondsSinceLastEventType( + kCGEventSourceStateCombinedSessionState, + kCGAnyInputEventType); + if (idle_time >= idle_threshold) + return IDLE_STATE_IDLE; + return IDLE_STATE_ACTIVE; +} diff --git a/chrome/browser/idle_win.cc b/chrome/browser/idle_win.cc new file mode 100644 index 0000000..0b9ce72 --- /dev/null +++ b/chrome/browser/idle_win.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2010 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" + +static bool IsScreensaverRunning(); +static bool IsWorkstationLocked(); + +IdleState CalculateIdleState(unsigned int idle_threshold) { + if (IsScreensaverRunning() || IsWorkstationLocked()) + return IDLE_STATE_LOCKED; + + LASTINPUTINFO last_input_info = {0}; + last_input_info.cbSize = sizeof(LASTINPUTINFO); + DWORD current_idle_time = 0; + if (::GetLastInputInfo(&last_input_info)) { + current_idle_time = ::GetTickCount() - last_input_info.dwTime; + // Will go -ve if we have been idle for a long time (2gb seconds). + if (current_idle_time < 0) + current_idle_time = INT_MAX; + // Convert from ms to seconds. + current_idle_time /= 1000; + } + + if (current_idle_time >= idle_threshold) + return IDLE_STATE_IDLE; + return IDLE_STATE_ACTIVE; +} + +bool IsScreensaverRunning() { + DWORD result = 0; + if (::SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &result, 0)) + return result != FALSE; + return false; +} + +bool IsWorkstationLocked() { + bool is_locked = true; + HDESK input_desk = ::OpenInputDesktop(0, 0, GENERIC_READ); + if (input_desk) { + wchar_t name[256] = {0}; + DWORD needed = 0; + if (::GetUserObjectInformation(input_desk, + UOI_NAME, + name, + sizeof(name), + &needed)) { + is_locked = lstrcmpi(name, L"default") != 0; + } + ::CloseDesktop(input_desk); + } + return is_locked; +} |