Index: chrome/browser/extensions/extension_updater.cc |
diff --git a/chrome/browser/extensions/extension_updater.cc b/chrome/browser/extensions/extension_updater.cc |
index 9360bad51559ec5161b9a0c5d6b60a4e08caf30d..20f9849a4a93aa7241f8268c3b0b0c1f14ca4670 100644 |
--- a/chrome/browser/extensions/extension_updater.cc |
+++ b/chrome/browser/extensions/extension_updater.cc |
@@ -22,7 +22,9 @@ |
#include "base/version.h" |
#include "crypto/sha2.h" |
#include "content/common/notification_service.h" |
+#include "content/common/notification_source.h" |
#include "chrome/browser/browser_process.h" |
+#include "chrome/browser/extensions/crx_installer.h" |
#include "chrome/browser/extensions/extension_error_reporter.h" |
#include "chrome/browser/extensions/extension_service.h" |
#include "chrome/browser/prefs/pref_service.h" |
@@ -81,13 +83,13 @@ enum FileWriteResult { |
}; |
// Prototypes allow the functions to be defined in the order they run. |
-void CheckThatCrxIsReadable(const FilePath& crx_path); |
+void CheckThatCRXIsReadable(const FilePath& crx_path); |
void RecordFileUpdateHistogram(FileWriteResult file_write_result); |
// Record the result of writing a CRX file. Will be used to understand |
// high failure rates of CRX installs in the field. If |success| is |
// true, |crx_path| should be set to the path to the CRX file. |
-void RecordCrxWriteHistogram(bool success, const FilePath& crx_path) { |
+void RecordCRXWriteHistogram(bool success, const FilePath& crx_path) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
if (!success) { |
@@ -100,11 +102,11 @@ void RecordCrxWriteHistogram(bool success, const FilePath& crx_path) { |
// can not be read. Try reading. |
BrowserThread::PostTask( |
BrowserThread::FILE, FROM_HERE, |
- NewRunnableFunction(CheckThatCrxIsReadable, crx_path)); |
+ NewRunnableFunction(CheckThatCRXIsReadable, crx_path)); |
} |
} |
-void CheckThatCrxIsReadable(const FilePath& crx_path) { |
+void CheckThatCRXIsReadable(const FilePath& crx_path) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
FileWriteResult file_write_result = SUCCESS; |
@@ -444,6 +446,20 @@ ExtensionUpdater::ExtensionFetch::ExtensionFetch(const std::string& i, |
ExtensionUpdater::ExtensionFetch::~ExtensionFetch() {} |
+ExtensionUpdater::FetchedCRXFile::FetchedCRXFile(const std::string& i, |
+ const FilePath& p, |
+ const GURL& u) |
+ : id(i), |
+ path(p), |
+ download_url(u) {} |
+ |
+ExtensionUpdater::FetchedCRXFile::FetchedCRXFile() |
+ : id(""), |
+ path(), |
+ download_url() {} |
+ |
+ExtensionUpdater::FetchedCRXFile::~FetchedCRXFile() {} |
+ |
ExtensionUpdater::ExtensionUpdater(ExtensionServiceInterface* service, |
ExtensionPrefs* extension_prefs, |
PrefService* prefs, |
@@ -454,7 +470,8 @@ ExtensionUpdater::ExtensionUpdater(ExtensionServiceInterface* service, |
service_(service), frequency_seconds_(frequency_seconds), |
method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
will_check_soon_(false), extension_prefs_(extension_prefs), |
- prefs_(prefs), profile_(profile), blacklist_checks_enabled_(true) { |
+ prefs_(prefs), profile_(profile), blacklist_checks_enabled_(true), |
+ crx_install_is_running_(false) { |
Init(); |
} |
@@ -800,7 +817,7 @@ void ExtensionUpdater::OnCRXFetchComplete( |
<< current_extension_fetch_.id << ". " |
<< "Error code is "<< error_code; |
- RecordCrxWriteHistogram(false, FilePath()); |
+ RecordCRXWriteHistogram(false, FilePath()); |
OnCRXFileWriteError(current_extension_fetch_.id); |
} else if (status.status() == net::URLRequestStatus::SUCCESS && |
@@ -814,7 +831,7 @@ void ExtensionUpdater::OnCRXFetchComplete( |
FilePath crx_path; |
// Take ownership of the file at |crx_path|. |
CHECK(source->GetResponseAsFilePath(true, &crx_path)); |
- RecordCrxWriteHistogram(true, crx_path); |
+ RecordCRXWriteHistogram(true, crx_path); |
OnCRXFileWritten(current_extension_fetch_.id, crx_path, url); |
} |
} else { |
@@ -839,10 +856,55 @@ void ExtensionUpdater::OnCRXFileWritten(const std::string& id, |
const FilePath& path, |
const GURL& download_url) { |
DCHECK(alive_); |
- // The ExtensionService is now responsible for cleaning up the temp file |
- // at |path|. |
- service_->UpdateExtension(id, path, download_url); |
- in_progress_ids_.erase(id); |
+ |
+ FetchedCRXFile fetched(id, path, download_url); |
+ fetched_crx_files_.push(fetched); |
+ |
+ MaybeInstallCRXFile(); |
+} |
+ |
+bool ExtensionUpdater::MaybeInstallCRXFile() { |
+ if (crx_install_is_running_) |
+ return false; |
+ |
+ while (!fetched_crx_files_.empty() && !crx_install_is_running_) { |
+ const FetchedCRXFile& crx_file = fetched_crx_files_.top(); |
+ |
+ // The ExtensionService is now responsible for cleaning up the temp file |
+ // at |extension_file.path|. |
+ CrxInstaller* installer = NULL; |
+ if (service_->UpdateExtension(crx_file.id, |
+ crx_file.path, |
+ crx_file.download_url, |
+ &installer)) { |
+ crx_install_is_running_ = true; |
+ |
+ // Source parameter ensures that we only see the completion event for the |
+ // the installer we started. |
+ registrar_.Add(this, |
+ NotificationType::CRX_INSTALLER_DONE, |
+ Source<CrxInstaller>(installer)); |
+ } |
+ in_progress_ids_.erase(crx_file.id); |
+ fetched_crx_files_.pop(); |
+ } |
+ |
+ // If an updater is running, it was started above. |
+ return crx_install_is_running_; |
+} |
+ |
+void ExtensionUpdater::Observe(NotificationType type, |
+ const NotificationSource& source, |
+ const NotificationDetails& details) { |
+ DCHECK(type == NotificationType::CRX_INSTALLER_DONE); |
+ |
+ // No need to listen for CRX_INSTALLER_DONE anymore. |
+ registrar_.Remove(this, |
+ NotificationType::CRX_INSTALLER_DONE, |
+ source); |
+ crx_install_is_running_ = false; |
+ // If any files are available to update, start one. |
+ MaybeInstallCRXFile(); |
} |
void ExtensionUpdater::OnCRXFileWriteError(const std::string& id) { |