diff options
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 |