summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_idle_api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/extension_idle_api.cc')
-rw-r--r--chrome/browser/extensions/extension_idle_api.cc160
1 files changed, 160 insertions, 0 deletions
diff --git a/chrome/browser/extensions/extension_idle_api.cc b/chrome/browser/extensions/extension_idle_api.cc
new file mode 100644
index 0000000..0a6a25f
--- /dev/null
+++ b/chrome/browser/extensions/extension_idle_api.cc
@@ -0,0 +1,160 @@
+// 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 <string>
+
+#include "base/json/json_writer.h"
+#include "base/message_loop.h"
+#include "base/stl_util-inl.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_idle_api_constants.h"
+#include "chrome/browser/extensions/extension_message_service.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_->GetInteger(0, &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(),
+ GURL());
+}