Add experimental.alarms API to allow lazy background pages to wake themselves up after a timeout.

BUG=81758
TEST=no

Review URL: https://chromiumcodereview.appspot.com/9791011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129495 0039d316-1c4b-4281-b951-d872f2087c98
parent 3b3e801c
// 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/alarms/alarms_api.h"
#include "base/bind.h"
#include "base/json/json_writer.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_event_router.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/extensions/api/experimental.alarms.h"
namespace Alarms = extensions::api::experimental_alarms;
namespace {
const char kOnAlarmEvent[] = "experimental.alarms.onAlarm";
const char kDefaultAlarmName[] = "";
void AlarmCallback(Profile* profile, const std::string& extension_id) {
// The profile could have gone away before this task was run.
if (!g_browser_process->profile_manager()->IsValidProfile(profile))
return;
ListValue args;
std::string json_args;
args.Append(base::Value::CreateStringValue(kDefaultAlarmName));
base::JSONWriter::Write(&args, &json_args);
profile->GetExtensionEventRouter()->DispatchEventToExtension(
extension_id, kOnAlarmEvent, json_args, NULL, GURL());
}
}
bool AlarmsCreateFunction::RunImpl() {
scoped_ptr<Alarms::Create::Params> params(
Alarms::Create::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
// TODO(mpcomplete): Better handling of granularity. Introduce an alarm
// manager that dispatches alarms in batches, and can also cancel previous
// alarms. Handle the "name" parameter.
// http://crbug.com/81758
MessageLoop::current()->PostDelayedTask(FROM_HERE,
base::Bind(&AlarmCallback, profile(), extension_id()),
params->alarm_info.delay_in_seconds * 1000);
return true;
}
bool AlarmsGetFunction::RunImpl() {
error_ = "Not implemented.";
return false;
}
bool AlarmsGetAllFunction::RunImpl() {
error_ = "Not implemented.";
return false;
}
bool AlarmsClearFunction::RunImpl() {
error_ = "Not implemented.";
return false;
}
bool AlarmsClearAllFunction::RunImpl() {
error_ = "Not implemented.";
return false;
}
// 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_ALARMS_ALARMS_API_H__
#define CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARMS_API_H__
#pragma once
#include "chrome/browser/extensions/extension_function.h"
class AlarmsCreateFunction : public SyncExtensionFunction {
protected:
virtual bool RunImpl() OVERRIDE;
DECLARE_EXTENSION_FUNCTION_NAME("experimental.alarms.create");
};
class AlarmsGetFunction : public SyncExtensionFunction {
protected:
virtual bool RunImpl() OVERRIDE;
DECLARE_EXTENSION_FUNCTION_NAME("experimental.alarms.get");
};
class AlarmsGetAllFunction : public SyncExtensionFunction {
protected:
virtual bool RunImpl() OVERRIDE;
DECLARE_EXTENSION_FUNCTION_NAME("experimental.alarms.getAll");
};
class AlarmsClearFunction : public SyncExtensionFunction {
protected:
virtual bool RunImpl() OVERRIDE;
DECLARE_EXTENSION_FUNCTION_NAME("experimental.alarms.clear");
};
class AlarmsClearAllFunction : public SyncExtensionFunction {
protected:
virtual bool RunImpl() OVERRIDE;
DECLARE_EXTENSION_FUNCTION_NAME("experimental.alarms.clearAll");
};
#endif // CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARMS_API_H__
......@@ -10,6 +10,7 @@
#include "chrome/browser/extensions/api/web_request/web_request_api.h"
#include "chrome/browser/extensions/extension_devtools_manager.h"
#include "chrome/browser/extensions/extension_host.h"
#include "chrome/browser/extensions/extension_module.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_processes_api.h"
#include "chrome/browser/extensions/extension_processes_api_constants.h"
......@@ -33,7 +34,6 @@ using extensions::ExtensionAPI;
namespace {
const char kDispatchEvent[] = "Event.dispatchJSON";
const char kOnInstalledEvent[] = "experimental.extension.onInstalled";
void NotifyEventListenerRemovedOnIOThread(
void* profile,
......@@ -495,9 +495,7 @@ void ExtensionEventRouter::Observe(
// Dispatch the onInstalled event.
const Extension* extension =
content::Details<const Extension>(details).ptr();
AddLazyEventListener(kOnInstalledEvent, extension->id());
DispatchEventToExtension(
extension->id(), kOnInstalledEvent, "[]", NULL, GURL());
ExtensionModuleEventRouter::DispatchOnInstalledEvent(profile_, extension);
break;
}
......
......@@ -8,6 +8,7 @@
#include "chrome/browser/bookmarks/bookmark_extension_api.h"
#include "chrome/browser/bookmarks/bookmark_manager_extension_api.h"
#include "chrome/browser/download/download_extension_api.h"
#include "chrome/browser/extensions/api/alarms/alarms_api.h"
#include "chrome/browser/extensions/api/app/app_api.h"
#include "chrome/browser/extensions/api/browsing_data/browsing_data_api.h"
#include "chrome/browser/extensions/api/declarative/declarative_api.h"
......@@ -85,6 +86,13 @@ ExtensionFunctionRegistry::~ExtensionFunctionRegistry() {
void ExtensionFunctionRegistry::ResetFunctions() {
// Register all functions here.
// Alarms
RegisterFunction<AlarmsCreateFunction>();
RegisterFunction<AlarmsGetFunction>();
RegisterFunction<AlarmsGetAllFunction>();
RegisterFunction<AlarmsClearFunction>();
RegisterFunction<AlarmsClearAllFunction>();
// Windows
RegisterFunction<GetWindowFunction>();
RegisterFunction<GetCurrentWindowFunction>();
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// 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.
......@@ -6,10 +6,32 @@
#include <string>
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_event_router.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
namespace {
const char kOnInstalledEvent[] = "experimental.extension.onInstalled";
}
// static
void ExtensionModuleEventRouter::DispatchOnInstalledEvent(
Profile* profile, const Extension* extension) {
// Special case: normally, extensions add their own lazy event listeners.
// However, since the extension has just been installed, it hasn't had a
// chance to register for events. So we register on its behalf. If the
// extension does not actually have a listener, the event will just be
// ignored.
ExtensionEventRouter* router = profile->GetExtensionEventRouter();
router->AddLazyEventListener(kOnInstalledEvent, extension->id());
router->DispatchEventToExtension(
extension->id(), kOnInstalledEvent, "[]", NULL, GURL());
}
ExtensionPrefs* SetUpdateUrlDataFunction::extension_prefs() {
return profile()->GetExtensionService()->extension_prefs();
}
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// 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.
......@@ -10,6 +10,13 @@
class ExtensionPrefs;
class ExtensionModuleEventRouter {
public:
// Dispatches the onInstalled event to the given extension.
static void DispatchOnInstalledEvent(Profile* profile,
const Extension* extension);
};
class SetUpdateUrlDataFunction : public SyncExtensionFunction {
protected:
virtual bool RunImpl() OVERRIDE;
......@@ -30,4 +37,5 @@ class IsAllowedFileSchemeAccessFunction : public SyncExtensionFunction {
virtual bool RunImpl() OVERRIDE;
DECLARE_EXTENSION_FUNCTION_NAME("extension.isAllowedFileSchemeAccess");
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MODULE_H__
......@@ -50,7 +50,7 @@ void LazyBackgroundTaskQueue::AddPendingTask(
const Extension* extension = profile->GetExtensionService()->
extensions()->GetByID(extension_id);
DCHECK(extension->has_lazy_background_page());
ExtensionProcessManager* pm = profile->GetExtensionProcessManager();
ExtensionProcessManager* pm = profile->GetExtensionProcessManager();
pm->IncrementLazyKeepaliveCount(extension);
pm->CreateBackgroundHost(extension, extension->GetBackgroundURL());
} else {
......@@ -60,8 +60,7 @@ void LazyBackgroundTaskQueue::AddPendingTask(
tasks_list->push_back(task);
}
void LazyBackgroundTaskQueue::ProcessPendingTasks(
ExtensionHost* host) {
void LazyBackgroundTaskQueue::ProcessPendingTasks(ExtensionHost* host) {
PendingTasksKey key(host->profile(), host->extension()->id());
PendingTasksMap::iterator map_it = pending_tasks_.find(key);
if (map_it == pending_tasks_.end()) {
......
......@@ -60,6 +60,8 @@
'browser/extensions/api/api_resource_controller.h',
'browser/extensions/api/api_resource_event_notifier.cc',
'browser/extensions/api/api_resource_event_notifier.h',
'browser/extensions/api/alarms/alarms_api.cc',
'browser/extensions/api/alarms/alarms_api.h',
'browser/extensions/api/app/app_api.cc',
'browser/extensions/api/app/app_api.h',
'browser/extensions/api/bluetooth/bluetooth_api.cc',
......
......@@ -25,6 +25,7 @@
<include name="IDR_EXTENSION_API_JSON_DEVTOOLS" file="extensions\api\devtools.json" type="BINDATA" />
<include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_ACCESSIBILITY" file="extensions\api\experimental.accessibility.json" type="BINDATA" />
<include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_APP" file="extensions\api\experimental.app.json" type="BINDATA" />
<include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_ALARMS" file="extensions\api\experimental.alarms.json" type="BINDATA" />
<include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_BOOKMARKMANAGER" file="extensions\api\experimental.bookmarkManager.json" type="BINDATA" />
<include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_DECLARATIVE" file="extensions\api\experimental.declarative.json" type="BINDATA" />
<include name="IDR_EXTENSION_API_JSON_EXPERIMENTAL_DOWNLOADS" file="extensions\api\experimental.downloads.json" type="BINDATA" />
......
......@@ -18,6 +18,7 @@
'variables': {
'chromium_code': 1,
'json_schema_files': [
'experimental.alarms.json',
'experimental.declarative.json',
'permissions.json',
'tabs.json',
......
// 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.
[
{
"namespace": "experimental.alarms",
"types": [
{
"id": "Alarm",
"type": "object",
"properties": {
"name": {"type": "string",
"description": "Name of this alarm."},
"delayInSeconds": {"type": "integer", "minimum": "0",
"description": "Original length of time in seconds after which the onAlarm event should fire."},
"repeating": {"type": "boolean",
"description": "True if the alarm repeatedly fires at regular intervals, false if it only fires once."}
}
}
],
"functions": [
{
"name": "create",
"type": "function",
"description": "Creates an alarm. After the delay is expired, the onAlarm event is fired. If there is another alarm with the same name (or no name if none is specified), it will be cancelled and replaced by this alarm.",
"parameters": [
{
"type": "string",
"name": "name",
"optional": true,
"description": "Optional name to identify this alarm. Defaults to the empty string."
},
{
"type": "object",
"name": "alarmInfo",
"properties": {
"delayInSeconds": {"type": "integer", "minimum": "0",
"description": "Length of time in seconds after which the onAlarm event should fire. Note that granularity is not guaranteed: this value is more of a hint to the browser. For performance reasons, alarms may be delayed an arbitrary amount of time before firing."},
"repeating": {"type": "boolean", "optional": true,
"description": "True if the alarm should repeatedly fire at regular intervals. Defaults to false."}
}
}
]
},
{
"name": "get",
"type": "function",
"description": "Retrieves details about the specified alarm.",
"parameters": [
{
"type": "string",
"name": "name",
"optional": true,
"description": "The name of the alarm to get. Defaults to the empty string."
},
{
"type": "function",
"name": "callback",
"parameters": [
{ "name": "alarm", "$ref": "Alarm" }
]
}
]
},
{
"name": "getAll",
"type": "function",
"description": "Gets an array of all the alarms.",
"parameters": [
{
"type": "function",
"name": "callback",
"parameters": [
{ "name": "alarms", "type": "array", "items": { "$ref": "Alarm" } }
]
}
]
},
{
"name": "clear",
"type": "function",
"description": "Clears the alarm with the given name.",
"parameters": [
{
"type": "string",
"name": "name",
"optional": true,
"description": "The name of the alarm to clear. Defaults to the empty string."
}
]
},
{
"name": "clearAll",
"type": "function",
"description": "Clears all alarms.",
"parameters": []
}
],
"events": [
{
"name": "onAlarm",
"type": "function",
"description": "Fired when an alarm has expired. Useful for transient background pages.",
"parameters": [
{
"type": "string",
"name": "name",
"optional": true,
"description": "The name of the alarm that has expired."
}
]
}
]
}
]
......@@ -9,11 +9,8 @@
{
"name": "onInstalled",
"type": "function",
"description": "Fired when the extension is first installed.",
"parameters": [
]
"description": "Fired when the extension is first installed."
}
]
}
]
......@@ -144,6 +144,8 @@ ExtensionAPI::ExtensionAPI() {
IDR_EXTENSION_API_JSON_DEVTOOLS);
unloaded_schemas_["experimental.accessibility"] = ReadFromResource(
IDR_EXTENSION_API_JSON_EXPERIMENTAL_ACCESSIBILITY);
unloaded_schemas_["experimental.alarms"] = ReadFromResource(
IDR_EXTENSION_API_JSON_EXPERIMENTAL_ALARMS);
unloaded_schemas_["experimental.app"] = ReadFromResource(
IDR_EXTENSION_API_JSON_EXPERIMENTAL_APP);
unloaded_schemas_["experimental.bookmarkManager"] = ReadFromResource(
......
......@@ -237,6 +237,7 @@ on the following experimental APIs:
</p>
<ul>
<li>
<a href="experimental.alarms.html">experimental.alarms</a></li><li>
<a href="experimental.app.html">experimental.app</a></li><li>
<a href="experimental.devtools.audits.html">experimental.devtools.audits</a></li><li>
<a href="experimental.devtools.console.html">experimental.devtools.console</a></li><li>
......
......@@ -31,6 +31,7 @@ var MODULE_SCHEMAS = [
'../api/debugger.json',
'../api/devtools.json',
'../api/experimental.accessibility.json',
'../api/experimental.alarms.json',
'../api/experimental.app.json',
'../api/experimental.bookmarkManager.json',
'../api/experimental.downloads.json',
......
......@@ -87,6 +87,12 @@
"chrome.devtools.panels.ExtensionSidebarPane.setPage": "devtools.panels.html#method-ExtensionSidebarPane-setPage",
"chrome.devtools.panels.create": "devtools.panels.html#method-create",
"chrome.devtools.panels.setOpenResourceHandler": "devtools.panels.html#method-setOpenResourceHandler",
"chrome.experimental.alarms.clear": "experimental.alarms.html#method-clear",
"chrome.experimental.alarms.clearAll": "experimental.alarms.html#method-clearAll",
"chrome.experimental.alarms.get": "experimental.alarms.html#method-get",
"chrome.experimental.alarms.getAll": "experimental.alarms.html#method-getAll",
"chrome.experimental.alarms.onAlarm": "experimental.alarms.html#event-onAlarm",
"chrome.experimental.alarms.set": "experimental.alarms.html#method-set",
"chrome.experimental.app.clearAllNotifications": "experimental.app.html#method-clearAllNotifications",
"chrome.experimental.app.notify": "experimental.app.html#method-notify",
"chrome.experimental.devtools.audits.AuditCategory.onAuditStarted": "experimental.devtools.audits.html#event-AuditCategory-onAuditStarted",
......@@ -2277,7 +2283,7 @@
"popup.html",
"popup.js"
],
"source_hash": "70d9c5f3e56fb17c0ee9f0582c9b817d95cdc772",
"source_hash": "5a16cf4c1a8b25e1c73d7056ad5af86df2bc2f1c",
"zip_path": "examples\/api\/storage\/stylizr.zip"
},
{
......
......@@ -143,7 +143,8 @@ class ExtensionImpl : public ChromeV8Extension {
const std::set<std::string>& function_names =
v8_extension->extension_dispatcher_->function_names();
if (function_names.find(name) == function_names.end()) {
NOTREACHED() << "Unexpected function " << name;
NOTREACHED() << "Unexpected function " << name <<
". Did you remember to register it with ExtensionFunctionRegistry?";
return v8::Undefined();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment