summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/automation/automation_provider_observers.cc94
-rw-r--r--chrome/browser/automation/automation_provider_observers.h27
-rw-r--r--chrome/browser/automation/testing_automation_provider.cc36
-rw-r--r--chrome/browser/automation/testing_automation_provider.h4
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