diff options
Diffstat (limited to 'chrome')
15 files changed, 222 insertions, 41 deletions
diff --git a/chrome/browser/extensions/extension_event_names.cc b/chrome/browser/extensions/extension_event_names.cc index 421bab8..a70f293 100644 --- a/chrome/browser/extensions/extension_event_names.cc +++ b/chrome/browser/extensions/extension_event_names.cc @@ -13,9 +13,14 @@ const char kOnTabMoved[] = "tabs.onMoved"; const char kOnTabRemoved[] = "tabs.onRemoved"; const char kOnTabSelectionChanged[] = "tabs.onSelectionChanged"; const char kOnTabUpdated[] = "tabs.onUpdated"; + const char kOnWindowCreated[] = "windows.onCreated"; const char kOnWindowFocusedChanged[] = "windows.onFocusChanged"; const char kOnWindowRemoved[] = "windows.onRemoved"; -} // namespace extension_event_names +const char kOnExtensionInstalled[] = "experimental.management.onInstalled"; +const char kOnExtensionUninstalled[] = "experimental.management.onUninstalled"; +const char kOnExtensionEnabled[] = "experimental.management.onEnabled"; +const char kOnExtensionDisabled[] = "experimental.management.onDisabled"; +} // namespace extension_event_names diff --git a/chrome/browser/extensions/extension_event_names.h b/chrome/browser/extensions/extension_event_names.h index 4cbadfc..3c63f90 100644 --- a/chrome/browser/extensions/extension_event_names.h +++ b/chrome/browser/extensions/extension_event_names.h @@ -10,6 +10,7 @@ namespace extension_event_names { +// Tabs. extern const char kOnTabAttached[]; extern const char kOnTabCreated[]; extern const char kOnTabDetached[]; @@ -17,11 +18,19 @@ extern const char kOnTabMoved[]; extern const char kOnTabRemoved[]; extern const char kOnTabSelectionChanged[]; extern const char kOnTabUpdated[]; + +// Windows. extern const char kOnWindowCreated[]; extern const char kOnWindowFocusedChanged[]; extern const char kOnWindowRemoved[]; +// Management. +extern const char kOnExtensionInstalled[]; +extern const char kOnExtensionUninstalled[]; +extern const char kOnExtensionEnabled[]; +extern const char kOnExtensionDisabled[]; + + }; // namespace extension_event_names #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_EVENT_NAMES_H_ - diff --git a/chrome/browser/extensions/extension_management_api.cc b/chrome/browser/extensions/extension_management_api.cc index 6be0476..4b581b2 100644 --- a/chrome/browser/extensions/extension_management_api.cc +++ b/chrome/browser/extensions/extension_management_api.cc @@ -7,12 +7,19 @@ #include <map> #include <string> +#include "base/basictypes.h" +#include "base/json/json_writer.h" #include "base/string_number_conversions.h" #include "chrome/browser/browser.h" +#include "chrome/browser/extensions/extension_event_names.h" +#include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/common/extensions/extension_error_utils.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" using base::IntToString; +namespace events = extension_event_names; const char kAppLaunchUrlKey[] = "appLaunchUrl"; const char kEnabledKey[] = "enabled"; @@ -26,7 +33,6 @@ const char kUrlKey[] = "url"; const char kNoExtensionError[] = "No extension with id *"; - ExtensionsService* ExtensionManagementFunction::service() { return profile()->GetExtensionsService(); } @@ -128,3 +134,72 @@ bool UninstallFunction::RunImpl() { service()->UninstallExtension(extension_id, false /* external_uninstall */); return true; } + + +// static +ExtensionManagementEventRouter* ExtensionManagementEventRouter::GetInstance() { + return Singleton<ExtensionManagementEventRouter>::get(); +} + +ExtensionManagementEventRouter::ExtensionManagementEventRouter() {} + +ExtensionManagementEventRouter::~ExtensionManagementEventRouter() {} + +void ExtensionManagementEventRouter::Init() { + NotificationType::Type types[] = { + NotificationType::EXTENSION_INSTALLED, + NotificationType::EXTENSION_UNINSTALLED, + NotificationType::EXTENSION_LOADED, + NotificationType::EXTENSION_UNLOADED + }; + + for (size_t i = 0; i < arraysize(types); i++) { + registrar_.Add(this, + types[i], + NotificationService::AllSources()); + } +} + +void ExtensionManagementEventRouter::Observe( + NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + const char* event_name = NULL; + switch (type.value) { + case NotificationType::EXTENSION_INSTALLED: + event_name = events::kOnExtensionInstalled; + break; + case NotificationType::EXTENSION_UNINSTALLED: + event_name = events::kOnExtensionUninstalled; + break; + case NotificationType::EXTENSION_LOADED: + event_name = events::kOnExtensionEnabled; + break; + case NotificationType::EXTENSION_UNLOADED: + event_name = events::kOnExtensionDisabled; + break; + default: + NOTREACHED(); + return; + } + + Profile* profile = Source<Profile>(source).ptr(); + Extension* extension = Details<Extension>(details).ptr(); + CHECK(profile); + CHECK(extension); + + ExtensionsService* service = profile->GetExtensionsService(); + bool enabled = service->GetExtensionById(extension->id(), false) != NULL; + ListValue args; + args.Append(CreateExtensionInfo(*extension, enabled)); + + std::string args_json; + base::JSONWriter::Write(&args, false /* pretty_print */, &args_json); + + ExtensionMessageService* message_service = + profile->GetExtensionMessageService(); + message_service->DispatchEventToRenderers(event_name, + args_json, + profile->IsOffTheRecord(), + GURL()); +} diff --git a/chrome/browser/extensions/extension_management_api.h b/chrome/browser/extensions/extension_management_api.h index c32c833..9d3108d 100644 --- a/chrome/browser/extensions/extension_management_api.h +++ b/chrome/browser/extensions/extension_management_api.h @@ -6,7 +6,10 @@ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_API_H__ #pragma once +#include "base/singleton.h" #include "chrome/browser/extensions/extension_function.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" class ExtensionsService; @@ -39,4 +42,28 @@ class UninstallFunction : public ExtensionManagementFunction { DECLARE_EXTENSION_FUNCTION_NAME("experimental.management.uninstall"); }; +class ExtensionManagementEventRouter : public NotificationObserver { + public: + // Get the singleton instance of the event router. + static ExtensionManagementEventRouter* GetInstance(); + + // Performs one-time initialization of our singleton. + void Init(); + + private: + friend struct DefaultSingletonTraits<ExtensionManagementEventRouter>; + + ExtensionManagementEventRouter(); + virtual ~ExtensionManagementEventRouter(); + + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionManagementEventRouter); +}; + #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MANAGEMENT_API_H__ diff --git a/chrome/browser/extensions/extension_management_api_browsertest.cc b/chrome/browser/extensions/extension_management_api_browsertest.cc new file mode 100644 index 0000000..63fdfcf --- /dev/null +++ b/chrome/browser/extensions/extension_management_api_browsertest.cc @@ -0,0 +1,30 @@ +// 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_browsertest.h" +#include "chrome/browser/extensions/extension_test_message_listener.h" +#include "chrome/common/chrome_switches.h" + + +class ExtensionManagementApiBrowserTest : public ExtensionBrowserTest { + virtual void SetUpCommandLine(CommandLine* command_line) { + ExtensionBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitch( + switches::kEnableExperimentalExtensionApis); + } +}; + +// We test this here instead of in an ExtensionApiTest because normal extensions +// are not allowed to call the install function. +IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest, InstallEvent) { + ExtensionTestMessageListener listener1("ready"); + ASSERT_TRUE(LoadExtension( + test_data_dir_.AppendASCII("management/install_event"))); + ASSERT_TRUE(listener1.WaitUntilSatisfied()); + + ExtensionTestMessageListener listener2("got_event"); + ASSERT_TRUE(LoadExtension( + test_data_dir_.AppendASCII("api_test/management/enabled_extension"))); + ASSERT_TRUE(listener2.WaitUntilSatisfied()); +} diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 3fb4a91..5ea1ede 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -29,6 +29,7 @@ #include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_history_api.h" #include "chrome/browser/extensions/extension_host.h" +#include "chrome/browser/extensions/extension_management_api.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_updater.h" #include "chrome/browser/extensions/external_extension_provider.h" @@ -238,6 +239,7 @@ void ExtensionsService::InitEventRouters() { ExtensionBookmarkEventRouter::GetSingleton()->Observe( profile_->GetBookmarkModel()); ExtensionCookiesEventRouter::GetInstance()->Init(); + ExtensionManagementEventRouter::GetInstance()->Init(); } void ExtensionsService::Init() { @@ -533,7 +535,7 @@ void ExtensionsService::LoadComponentExtensions() { // In order for the --apps-gallery-url switch to work with the gallery // process isolation, we must insert any provided value into the component // app's launch url and web extent. - if (extension->id() == extension_misc::kWebStoreAppId ) { + if (extension->id() == extension_misc::kWebStoreAppId) { GURL gallery_url(CommandLine::ForCurrentProcess() ->GetSwitchValueASCII(switches::kAppsGalleryURL)); if (gallery_url.is_valid()) { diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index cff0ea7..1a61269 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1718,6 +1718,7 @@ 'browser/extensions/extension_input_apitest.cc', 'browser/extensions/extension_install_ui_browsertest.cc', 'browser/extensions/extension_javascript_url_apitest.cc', + 'browser/extensions/extension_management_api_browsertest.cc', 'browser/extensions/extension_management_apitest.cc', 'browser/extensions/extension_management_browsertest.cc', 'browser/extensions/extension_messages_apitest.cc', diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json index d8b3c02..1014714 100644 --- a/chrome/common/extensions/api/extension_api.json +++ b/chrome/common/extensions/api/extension_api.json @@ -3998,6 +3998,7 @@ { "name": "callback", "type": "function", + "optional": "true", "parameters": [] } ] @@ -4046,25 +4047,25 @@ "events": [ { "name": "onInstalled", - "description": "(NOT YET IMPLEMENTED)", + "description": "Fired when an app or extension has been installed.", "type": "function", "parameters": [{"name": "info", "$ref":"ExtensionInfo"}] }, { "name": "onUninstalled", - "description": "(NOT YET IMPLEMENTED)", + "description": "Fired when an app or extension has been uninstalled.", "type": "function", - "parameters": [{"name": "id", "type": "string", "description": "The id of the extension that was uninstalled."}] + "parameters": [{"name": "info", "$ref":"ExtensionInfo"}] }, { "name": "onEnabled", - "description": "(NOT YET IMPLEMENTED)", + "description": "Fired when an app or extension has been enabled.", "type": "function", "parameters": [{"name": "info", "$ref":"ExtensionInfo"}] }, { "name": "onDisabled", - "description": "(NOT YET IMPLEMENTED)", + "description": "Fired when an app or extension has been disabled", "type": "function", "parameters": [{"name": "info", "$ref":"ExtensionInfo"}] } diff --git a/chrome/common/extensions/docs/experimental.management.html b/chrome/common/extensions/docs/experimental.management.html index 4f3ac8d..479cd35 100644 --- a/chrome/common/extensions/docs/experimental.management.html +++ b/chrome/common/extensions/docs/experimental.management.html @@ -597,7 +597,7 @@ <!-- Note: intentionally longer 80 columns --> <span>chrome.experimental.management.setEnabled</span>(<span class="null"><span style="display: none; ">, </span><span>string</span> <var><span>id</span></var></span><span class="null"><span>, </span><span>boolean</span> - <var><span>enabled</span></var></span><span class="null"><span>, </span><span>function</span> + <var><span>enabled</span></var></span><span class="optional"><span>, </span><span>function</span> <var><span>callback</span></var></span>)</div> <div class="description"> @@ -732,7 +732,7 @@ <!-- TYPE --> <div style="display:inline"> ( - <span class="optional" style="display: none; ">optional</span> + <span class="optional">optional</span> <span class="enum" style="display: none; ">enumerated</span> <span id="typeTemplate"> <span style="display: none; "> @@ -799,11 +799,11 @@ <div> <div> <h4>Callback function</h4> - <p> + <p style="display: none; "> The callback <em>parameter</em> should specify a function that looks like this: </p> - <p style="display: none; "> + <p> If you specify the <em>callback</em> parameter, it should specify a function that looks like this: </p> @@ -1267,7 +1267,7 @@ <div class="summary"> <!-- Note: intentionally longer 80 columns --> - <span class="subdued">chrome.experimental.management.</span><span>onUninstalled</span><span class="subdued">.addListener</span>(function(<span>string id</span>) <span class="subdued">{...}</span>); + <span class="subdued">chrome.experimental.management.</span><span>onUninstalled</span><span class="subdued">.addListener</span>(function(<span>ExtensionInfo info</span>) <span class="subdued">{...}</span>); </div> <div class="description"> @@ -1280,7 +1280,7 @@ <div> <div> <dt> - <var>id</var> + <var>info</var> <em> <!-- TYPE --> @@ -1289,15 +1289,15 @@ <span class="optional" style="display: none; ">optional</span> <span class="enum" style="display: none; ">enumerated</span> <span id="typeTemplate"> - <span style="display: none; "> - <a> Type</a> - </span> <span> - <span style="display: none; "> + <a href="experimental.management.html#type-ExtensionInfo">ExtensionInfo</a> + </span> + <span style="display: none; "> + <span> array of <span><span></span></span> </span> - <span>string</span> - <span style="display: none; "></span> + <span>paramType</span> + <span></span> </span> </span> ) @@ -1305,10 +1305,12 @@ </em> </dt> - <dd class="todo" style="display: none; "> + <dd class="todo"> Undocumented. </dd> - <dd>The id of the extension that was uninstalled.</dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> <dd style="display: none; "> This parameter was added in version <b><span></span></b>. diff --git a/chrome/test/data/extensions/api_test/management/test/basics.js b/chrome/test/data/extensions/api_test/management/test/basics.js index ea5fc23..c998ca3d 100644 --- a/chrome/test/data/extensions/api_test/management/test/basics.js +++ b/chrome/test/data/extensions/api_test/management/test/basics.js @@ -17,8 +17,7 @@ function checkIcon(item, size, path) { var tests = [ function simple() { - chrome.management.getAll(function(items) { - assertNoLastError(); + chrome.management.getAll(callback(function(items) { chrome.test.assertEq(5, items.length); checkItem(items, "Extension Management API Test", true, false); @@ -36,33 +35,35 @@ var tests = [ checkIcon(extension, 128, "icon_128.png"); checkIcon(extension, 48, "icon_48.png"); checkIcon(extension, 16, "icon_16.png"); - - succeed(); - }); + })); }, // Disables an enabled app. function disable() { - chrome.management.getAll(function(items) { - assertNoLastError(); + listenOnce(chrome.management.onDisabled, function(info) { + assertEq(info.name, "enabled_app"); + }); + + chrome.management.getAll(callback(function(items) { checkItem(items, "enabled_app", true, true); var enabled_app = getItemNamed(items, "enabled_app"); chrome.management.setEnabled(enabled_app.id, false, function() { assertNoLastError(); chrome.management.getAll(function(items2) { assertNoLastError(); - chrome.test.log("re-checking enabled_app"); checkItem(items2, "enabled_app", false, true); - succeed(); + assertTrue(event_fired); }); }); - }); + })); }, // Enables a disabled extension. function enable() { - chrome.management.getAll(function(items) { - assertNoLastError(); + listenOnce(chrome.management.onEnabled, function(info) { + assertEq(info.name, "disabled_extension"); + }); + chrome.management.getAll(callback(function(items) { checkItem(items, "disabled_extension", false, false); var disabled = getItemNamed(items, "disabled_extension"); chrome.management.setEnabled(disabled.id, true, function() { @@ -70,10 +71,10 @@ var tests = [ chrome.management.getAll(function(items2) { assertNoLastError(); checkItem(items2, "disabled_extension", true, false); - succeed(); + assertTrue(event_fired); }); }); - }); + })); } ]; diff --git a/chrome/test/data/extensions/api_test/management/test/common.js b/chrome/test/data/extensions/api_test/management/test/common.js index 6385599..744ced4 100644 --- a/chrome/test/data/extensions/api_test/management/test/common.js +++ b/chrome/test/data/extensions/api_test/management/test/common.js @@ -12,6 +12,8 @@ var assertNoLastError = chrome.test.assertNoLastError; var assertTrue = chrome.test.assertTrue; var fail = chrome.test.fail; var succeed = chrome.test.succeed; +var listenOnce = chrome.test.listenOnce; +var callback = chrome.test.callback; function getItemNamed(list, name) { for (var i = 0; i < list.length; i++) { diff --git a/chrome/test/data/extensions/api_test/management/test/uninstall.js b/chrome/test/data/extensions/api_test/management/test/uninstall.js index e4a120b..f425c8e 100644 --- a/chrome/test/data/extensions/api_test/management/test/uninstall.js +++ b/chrome/test/data/extensions/api_test/management/test/uninstall.js @@ -3,8 +3,11 @@ // found in the LICENSE file. function uninstall(name) { - chrome.management.getAll(function(items) { - assertNoLastError(); + listenOnce(chrome.management.onUninstalled, function(info) { + assertEq(info.name, name); + }); + + chrome.management.getAll(callback(function(items) { var old_count = items.length; var item = getItemNamed(items, name); chrome.management.uninstall(item.id, function() { @@ -15,10 +18,10 @@ function uninstall(name) { for (var i = 0; i < items2.length; i++) { assertFalse(items2[i].name == name); } - succeed(); + assertTrue(event_fired); }); }); - }); + })); } var tests = [ diff --git a/chrome/test/data/extensions/management/install_event/background.html b/chrome/test/data/extensions/management/install_event/background.html new file mode 100644 index 0000000..46f4d74 --- /dev/null +++ b/chrome/test/data/extensions/management/install_event/background.html @@ -0,0 +1 @@ +<script src="test.js"></script> diff --git a/chrome/test/data/extensions/management/install_event/manifest.json b/chrome/test/data/extensions/management/install_event/manifest.json new file mode 100644 index 0000000..79a5831 --- /dev/null +++ b/chrome/test/data/extensions/management/install_event/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "Install event test", + "version": "0.1", + "permissions": ["experimental"], + "background_page": "background.html" +} + diff --git a/chrome/test/data/extensions/management/install_event/test.js b/chrome/test/data/extensions/management/install_event/test.js new file mode 100644 index 0000000..09ef1c4 --- /dev/null +++ b/chrome/test/data/extensions/management/install_event/test.js @@ -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. + +if (!chrome.management) { + chrome.management = chrome.experimental.management; +} + +chrome.management.onInstalled.addListener(function(info) { + if (info.name == "enabled_extension") { + chrome.test.sendMessage("got_event"); + } +}); + +chrome.test.sendMessage("ready"); |