diff options
author | dennisjeffrey@google.com <dennisjeffrey@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-11 19:45:48 +0000 |
---|---|---|
committer | dennisjeffrey@google.com <dennisjeffrey@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-11 19:45:48 +0000 |
commit | 6a0322f58d1e9cf7efa6c3e56ef2075496108cc9 (patch) | |
tree | 23503bbec2cc50ace17e0e8b520a062e7e7d069b /chrome/browser | |
parent | e5132ff7aa2c1e65de5996627be329798ce1c825 (diff) | |
download | chromium_src-6a0322f58d1e9cf7efa6c3e56ef2075496108cc9.zip chromium_src-6a0322f58d1e9cf7efa6c3e56ef2075496108cc9.tar.gz chromium_src-6a0322f58d1e9cf7efa6c3e56ef2075496108cc9.tar.bz2 |
New automation hook to update the extensions, with sample pyauto test.
Executing this hook has the same effect as clicking on the "Update
extensions now" button under "Developer tools" on Chrome's extensions
page. This hook is especially useful for testing the promo apps, because
the promo apps won't be installed until after the extensions are
updated.
BUG=75202
TEST=None
Review URL: http://codereview.chromium.org/6713104
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81140 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
4 files changed, 161 insertions, 0 deletions
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc index 07be91d..ba64791 100644 --- a/chrome/browser/automation/automation_provider_observers.cc +++ b/chrome/browser/automation/automation_provider_observers.cc @@ -26,6 +26,7 @@ #include "chrome/browser/dom_operation_notification_details.h" #include "chrome/browser/download/download_item.h" #include "chrome/browser/download/save_package.h" +#include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_updater.h" @@ -648,6 +649,99 @@ void ExtensionUnloadNotificationObserver::Observe( } } +ExtensionsUpdatedObserver::ExtensionsUpdatedObserver( + ExtensionProcessManager* manager, AutomationProvider* automation, + IPC::Message* reply_message) + : manager_(manager), automation_(automation->AsWeakPtr()), + reply_message_(reply_message), updater_finished_(false) { + registrar_.Add(this, NotificationType::EXTENSION_HOST_DID_STOP_LOADING, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::EXTENSION_INSTALL_ERROR, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::EXTENSION_INSTALL_NOT_ALLOWED, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::EXTENSION_LOADED, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::EXTENSION_UPDATE_DISABLED, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::EXTENSION_UPDATE_FOUND, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::EXTENSION_UPDATING_FINISHED, + NotificationService::AllSources()); +} + +ExtensionsUpdatedObserver::~ExtensionsUpdatedObserver() { +} + +void ExtensionsUpdatedObserver::Observe( + NotificationType type, const NotificationSource& source, + const NotificationDetails& details) { + if (!automation_) { + delete this; + return; + } + + // We expect the following sequence of events. First, the ExtensionUpdater + // service notifies of each extension that needs to be updated. Once the + // ExtensionUpdater has finished searching for extensions to update, it + // notifies that it is finished. Meanwhile, the extensions are updated + // asynchronously: either they will be updated and loaded, or else they will + // not load due to (1) not being allowed; (2) having updating disabled; or + // (3) encountering an error. Finally, notifications are also sent whenever + // an extension host stops loading. Updating is not considered complete if + // any extension hosts are still loading. + switch (type.value) { + case NotificationType::EXTENSION_UPDATE_FOUND: + // Extension updater has identified an extension that needs to be updated. + in_progress_updates_.insert(*(Details<const std::string>(details).ptr())); + break; + + case NotificationType::EXTENSION_UPDATING_FINISHED: + // Extension updater has completed notifying all extensions to update + // themselves. + updater_finished_ = true; + break; + + case NotificationType::EXTENSION_LOADED: + case NotificationType::EXTENSION_INSTALL_NOT_ALLOWED: + case NotificationType::EXTENSION_UPDATE_DISABLED: { + // An extension has either completed update installation and is now + // loaded, or else the install has been skipped because it is + // either not allowed or else has been disabled. + const Extension* extension = Details<Extension>(details).ptr(); + in_progress_updates_.erase(extension->id()); + break; + } + + case NotificationType::EXTENSION_INSTALL_ERROR: { + // An extension had an error on update installation. + CrxInstaller* installer = Source<CrxInstaller>(source).ptr(); + in_progress_updates_.erase(installer->expected_id()); + break; + } + + case NotificationType::EXTENSION_HOST_DID_STOP_LOADING: + // Break out to the conditional check below to see if all extension hosts + // have stopped loading. + break; + + default: + NOTREACHED(); + break; + } + + // Send the reply if (1) the extension updater has finished notifying all + // extensions to update themselves; (2) all extensions that need to be updated + // have completed installation and are now loaded; and (3) all extension hosts + // have stopped loading. + if (updater_finished_ && in_progress_updates_.empty() && + DidExtensionHostsStopLoading(manager_)) { + AutomationJSONReply reply(automation_, reply_message_.release()); + reply.SendSuccess(NULL); + delete this; + } +} + ExtensionTestResultNotificationObserver:: ExtensionTestResultNotificationObserver(AutomationProvider* automation) : automation_(automation->AsWeakPtr()) { diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index 4fa7679..0925d95e 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -360,6 +360,33 @@ class ExtensionUnloadNotificationObserver : public NotificationObserver { DISALLOW_COPY_AND_ASSIGN(ExtensionUnloadNotificationObserver); }; +// Observes when the extensions have been fully updated. The ExtensionUpdater +// service provides notifications for each extension that gets updated, but +// it does not wait for the updated extensions to be installed or loaded. This +// observer waits until all updated extensions have actually been loaded. +class ExtensionsUpdatedObserver : public NotificationObserver { + public: + ExtensionsUpdatedObserver(ExtensionProcessManager* manager, + AutomationProvider* automation, + IPC::Message* reply_message); + virtual ~ExtensionsUpdatedObserver(); + + // Implementation of NotificationObserver. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + NotificationRegistrar registrar_; + ExtensionProcessManager* manager_; + base::WeakPtr<AutomationProvider> automation_; + scoped_ptr<IPC::Message> reply_message_; + std::set<std::string> in_progress_updates_; + bool updater_finished_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionsUpdatedObserver); +}; + class ExtensionTestResultNotificationObserver : public NotificationObserver { public: explicit ExtensionTestResultNotificationObserver( diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc index 3de6a9b..99f5778 100644 --- a/chrome/browser/automation/testing_automation_provider.cc +++ b/chrome/browser/automation/testing_automation_provider.cc @@ -47,6 +47,7 @@ #include "chrome/browser/download/save_package.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_updater.h" #include "chrome/browser/history/top_sites.h" #include "chrome/browser/importer/importer_host.h" #include "chrome/browser/instant/instant_controller.h" @@ -2093,6 +2094,8 @@ void TestingAutomationProvider::SendJSONRequest(int handle, &TestingAutomationProvider::SendOSLevelKeyEventToTab; handler_map["ActivateTab"] = &TestingAutomationProvider::ActivateTabJSON; + handler_map["UpdateExtensionsNow"] = + &TestingAutomationProvider::UpdateExtensionsNow; handler_map["GetChromeDriverAutomationVersion"] = &TestingAutomationProvider::GetChromeDriverAutomationVersion; #if defined(OS_CHROMEOS) @@ -5210,6 +5213,39 @@ void TestingAutomationProvider::ActivateTabJSON( reply.SendSuccess(NULL); } +// Sample json input: { "command": "UpdateExtensionsNow" } +// Sample json output: {} +void TestingAutomationProvider::UpdateExtensionsNow( + DictionaryValue* args, + IPC::Message* reply_message) { + ExtensionService* service = profile()->GetExtensionService(); + if (!service) { + AutomationJSONReply(this, reply_message).SendError( + "No extensions service."); + return; + } + + ExtensionUpdater* updater = service->updater(); + if (!updater) { + AutomationJSONReply(this, reply_message).SendError( + "No updater for extensions service."); + return; + } + + ExtensionProcessManager* manager = profile()->GetExtensionProcessManager(); + if (!manager) { + AutomationJSONReply(this, reply_message).SendError( + "No extension process manager."); + return; + } + + // Create a new observer that waits until the extensions have been fully + // updated (we should not send the reply until after all extensions have + // been updated). This observer will delete itself. + new ExtensionsUpdatedObserver(manager, this, reply_message); + updater->CheckNow(); +} + void TestingAutomationProvider::GetChromeDriverAutomationVersion( DictionaryValue* args, IPC::Message* reply_message) { diff --git a/chrome/browser/automation/testing_automation_provider.h b/chrome/browser/automation/testing_automation_provider.h index 357bf60..9e9bbec 100644 --- a/chrome/browser/automation/testing_automation_provider.h +++ b/chrome/browser/automation/testing_automation_provider.h @@ -1015,6 +1015,10 @@ class TestingAutomationProvider : public AutomationProvider, // output: none void ActivateTabJSON(DictionaryValue* args, IPC::Message* message); + // Auto-updates installed extensions. + // Uses the JSON interface for input/output. + void UpdateExtensionsNow(DictionaryValue* args, IPC::Message* reply_message); + // Gets the version of ChromeDriver automation supported by this server. // Example: // input: none |