Index: chrome/browser/component_updater/pnacl/pnacl_component_installer.cc |
diff --git a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc |
index a0d3250484685150e1544009c15096152b691c14..7b5efae3837fc9ee5978172b2f646bc7f3bc097c 100644 |
--- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc |
+++ b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc |
@@ -6,6 +6,7 @@ |
#include "base/base_paths.h" |
#include "base/bind.h" |
+#include "base/callback.h" |
#include "base/command_line.h" |
#include "base/compiler_specific.h" |
#include "base/file_util.h" |
@@ -33,11 +34,6 @@ using content::BrowserThread; |
namespace { |
-// If PNaCl isn't installed yet, but a user is running chrome with |
-// --enable-pnacl, this is the amount of time to wait before starting |
-// a background install. |
-const int kInitialDelaySeconds = 10; |
- |
// Name of the Pnacl component specified in the manifest. |
const char kPnaclManifestName[] = "PNaCl Translator"; |
@@ -194,10 +190,12 @@ bool CheckPnaclComponentManifest(const base::DictionaryValue& manifest, |
PnaclComponentInstaller::PnaclComponentInstaller() |
: per_user_(false), |
- cus_(NULL) { |
+ cus_(NULL), |
+ callback_nums_(0) { |
#if defined(OS_CHROMEOS) |
per_user_ = true; |
#endif |
+ updater_observer_.reset(new PnaclUpdaterObserver(this)); |
} |
PnaclComponentInstaller::~PnaclComponentInstaller() { |
@@ -241,42 +239,47 @@ void PnaclComponentInstaller::OnProfileChange() { |
bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest, |
const base::FilePath& unpack_path) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
scoped_ptr<base::DictionaryValue> pnacl_manifest( |
ReadPnaclManifest(unpack_path)); |
if (pnacl_manifest == NULL) { |
LOG(WARNING) << "Failed to read pnacl manifest."; |
+ NotifyInstallError(); |
return false; |
} |
Version version; |
if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) { |
LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; |
+ NotifyInstallError(); |
return false; |
} |
// Don't install if the current version is actually newer. |
- if (current_version().CompareTo(version) > 0) |
+ if (current_version().CompareTo(version) > 0) { |
+ NotifyInstallError(); |
return false; |
+ } |
// Passed the basic tests. Time to install it. |
base::FilePath path = GetPnaclBaseDirectory().AppendASCII( |
version.GetString()); |
if (file_util::PathExists(path)) { |
LOG(WARNING) << "Target path already exists, not installing."; |
+ NotifyInstallError(); |
return false; |
} |
if (!file_util::Move(unpack_path, path)) { |
LOG(WARNING) << "Move failed, not installing."; |
+ NotifyInstallError(); |
return false; |
} |
- // Installation is done. Now tell the rest of chrome (just the path service |
- // for now). TODO(jvoung): we need notifications if someone surfed to a |
- // Pnacl webpage and Pnacl was just installed at this time. They should |
- // then be able to reload the page and retry (or something). |
- // See: http://code.google.com/p/chromium/issues/detail?id=107438 |
+ // Installation is done. Now tell the rest of chrome. |
+ // - The path service. |
+ // - Callbacks that requested an update. |
set_current_version(version); |
- |
+ NotifyInstallSuccess(); |
OverrideDirPnaclComponent(path); |
return true; |
} |
@@ -286,16 +289,56 @@ bool PnaclComponentInstaller::GetInstalledFile( |
return false; |
} |
-namespace { |
+void PnaclComponentInstaller::AddInstallCallback( |
+ const InstallCallback& cb) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ int num = ++callback_nums_; |
+ install_callbacks_.push_back(std::make_pair(cb, num)); |
+} |
+ |
+void PnaclComponentInstaller::CancelCallback(int num) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ for (std::list<std::pair<InstallCallback, int> >::iterator |
+ i = install_callbacks_.begin(), |
+ e = install_callbacks_.end(); i != e; ++i) { |
+ if (i->second == num) { |
+ i->first.Run(false); |
+ install_callbacks_.erase(i); |
+ return; |
+ } |
+ } |
+} |
+ |
+void PnaclComponentInstaller::NotifyAllWithResult(bool status) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ while (!install_callbacks_.empty()) { |
+ install_callbacks_.front().first.Run(status); |
+ install_callbacks_.pop_front(); |
+ } |
+} |
+ |
+void PnaclComponentInstaller::NotifyInstallError() { |
+ if (!install_callbacks_.empty()) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&PnaclComponentInstaller::NotifyAllWithResult, |
+ // Unretained because installer lives until process shutdown. |
+ base::Unretained(this), false)); |
+ } |
+} |
-void DoCheckForUpdate(ComponentUpdateService* cus, |
- const CrxComponent& pnacl) { |
- if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) { |
- LOG(WARNING) << "Pnacl check for update failed."; |
+void PnaclComponentInstaller::NotifyInstallSuccess() { |
+ if (!install_callbacks_.empty()) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(&PnaclComponentInstaller::NotifyAllWithResult, |
+ // Unretained because installer lives until process shutdown. |
+ base::Unretained(this), true)); |
} |
} |
-// Finally, do the registration with the right version number. |
+namespace { |
+ |
void FinishPnaclUpdateRegistration(const Version& current_version, |
PnaclComponentInstaller* pci) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
@@ -312,17 +355,6 @@ void FinishPnaclUpdateRegistration(const Version& current_version, |
&& status != ComponentUpdateService::kReplaced) { |
NOTREACHED() << "Pnacl component registration failed."; |
} |
- |
- // If PNaCl is not yet installed but it is requested by --enable-pnacl, |
- // we want it to be available "soon", so kick off an update check |
- // earlier than usual. |
- Version null_version(kNullVersion); |
- if (pci->current_version().Equals(null_version)) { |
- BrowserThread::PostDelayedTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(DoCheckForUpdate, pci->cus(), pnacl_component), |
- base::TimeDelta::FromSeconds(kInitialDelaySeconds)); |
- } |
} |
// Check if there is an existing version on disk first to know when |
@@ -389,8 +421,7 @@ void GetProfileInformation(PnaclComponentInstaller* pci) { |
void PnaclComponentInstaller::RegisterPnaclComponent( |
ComponentUpdateService* cus, |
const CommandLine& command_line) { |
- // Only register when given the right flag. This is important since |
- // we do an early component updater check above (in DoCheckForUpdate). |
+ // Only register when given the right flag, for now. |
if (command_line.HasSwitch(switches::kEnablePnacl)) { |
cus_ = cus; |
// If per_user, create a profile observer to watch for logins. |
@@ -400,13 +431,11 @@ void PnaclComponentInstaller::RegisterPnaclComponent( |
} |
if (per_user_) { |
// Figure out profile information, before proceeding to look for files. |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&GetProfileInformation, this)); |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&GetProfileInformation, this)); |
} else { |
- BrowserThread::PostTask( |
- BrowserThread::FILE, FROM_HERE, |
- base::Bind(&StartPnaclUpdateRegistration, this)); |
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
+ base::Bind(&StartPnaclUpdateRegistration, this)); |
} |
} |
} |
@@ -422,3 +451,23 @@ void PnaclComponentInstaller::ReRegisterPnacl() { |
BrowserThread::UI, FROM_HERE, |
base::Bind(&GetProfileInformation, this)); |
} |
+ |
+void RequestFirstInstall(ComponentUpdateService* cus, |
+ PnaclComponentInstaller* pci, |
+ const base::Callback<void(bool)>& installed) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ Version null_version(kNullVersion); |
+ CrxComponent pnacl_component; |
+ pci->set_current_version(null_version); |
+ pnacl_component.version = null_version; |
+ pnacl_component.name = "pnacl"; |
+ pnacl_component.installer = pci; |
+ SetPnaclHash(&pnacl_component); |
+ ComponentUpdateService::Status status = cus->CheckForUpdateSoon( |
+ pnacl_component); |
+ if (status != ComponentUpdateService::kOk) { |
+ installed.Run(false); |
+ return; |
+ } |
+ pci->AddInstallCallback(installed); |
+} |