Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4788)

Unified Diff: chrome/browser/component_updater/pnacl/pnacl_component_installer.cc

Issue 12184029: Make pnacl install on demand when it is not already installed. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: forward decl Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 d6ab1a0b44046a8311c17b4642b30245f554da7f..32211f81a80d55aa03a88c4f60e4c106afb8d834 100644
--- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc
+++ b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc
@@ -4,8 +4,11 @@
#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
+#include <list>
+
#include "base/base_paths.h"
#include "base/bind.h"
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/file_path.h"
#include "base/file_util.h"
@@ -25,10 +28,9 @@ 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;
+// Time in seconds to wait for CheckUpdatesForPnacl to complete
+// before considering the update failed.
+int kPnaclInstallerTimeout = 45;
// One of the Pnacl component files, for checking that expected files exist.
// TODO(jvoung): perhaps replace this with a list of the expected files in the
@@ -72,7 +74,7 @@ std::string SanitizeForPath(const std::string& input) {
}
// Set the component's hash to the arch-specific PNaCl package.
-void SetPnaclHash(CrxComponent* component) {
+void SetPnaclHash(std::vector<uint8>* pk_hash) {
#if defined(ARCH_CPU_X86_FAMILY)
// Define both x86_32 and x86_64, and choose below.
static const uint8 x86_sha256_hash[][32] = {
@@ -87,23 +89,23 @@ void SetPnaclHash(CrxComponent* component) {
};
#if defined(ARCH_CPU_X86_64)
- component->pk_hash.assign(
+ pk_hash->assign(
x86_sha256_hash[1],
&x86_sha256_hash[1][sizeof(x86_sha256_hash[1])]);
#elif defined(OS_WIN)
bool x86_64 = (base::win::OSInfo::GetInstance()->wow64_status() ==
base::win::OSInfo::WOW64_ENABLED);
if (x86_64) {
- component->pk_hash.assign(
+ pk_hash->assign(
x86_sha256_hash[1],
&x86_sha256_hash[1][sizeof(x86_sha256_hash[1])]);
} else {
- component->pk_hash.assign(
+ pk_hash->assign(
x86_sha256_hash[0],
&x86_sha256_hash[0][sizeof(x86_sha256_hash[0])]);
}
#else
- component->pk_hash.assign(
+ pk_hash->assign(
x86_sha256_hash[0],
&x86_sha256_hash[0][sizeof(x86_sha256_hash[0])]);
#endif
@@ -114,8 +116,8 @@ void SetPnaclHash(CrxComponent* component) {
0x62, 0xde, 0x5a, 0x14, 0x14, 0x99, 0xd4, 0xd9, 0x01, 0x85, 0xc6,
0x9a, 0xd2, 0x51, 0x90, 0xa4, 0xb4, 0x94, 0xbd, 0xb8, 0x8b, 0xe8};
- component->pk_hash.assign(arm_sha256_hash,
- &arm_sha256_hash[sizeof(arm_sha256_hash)]);
+ pk_hash->assign(arm_sha256_hash,
+ &arm_sha256_hash[sizeof(arm_sha256_hash)]);
#elif defined(ARCH_CPU_MIPSEL)
// This is a dummy CRX hash for MIPS, so that it will at least compile.
static const uint8 mips32_sha256_hash[] = {
@@ -123,8 +125,8 @@ void SetPnaclHash(CrxComponent* component) {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- component->pk_hash.assign(mips32_sha256_hash,
- &mips32_sha256_hash[sizeof(mips32_sha256_hash)]);
+ pk_hash->assign(mips32_sha256_hash,
+ &mips32_sha256_hash[sizeof(mips32_sha256_hash)]);
#else
#error "Add support for your architecture to Pnacl Component Installer."
#endif
@@ -239,12 +241,28 @@ class PnaclComponentInstaller : public ComponentInstaller {
virtual bool Install(base::DictionaryValue* manifest,
const base::FilePath& unpack_path) OVERRIDE;
+ typedef base::Callback<void(bool)> InstallCallback;
+ void AddInstallCallback(const InstallCallback& cb);
+
private:
+ // Cancel a particular callback after a timeout.
+ void CancelCallback(int callback_num);
+
+ void NotifyInstallError();
+
+ void NotifyInstallSuccess();
+
Version current_version_;
+
+ // Counter for issue identifiers to each callback.
+ int callback_nums_;
+
+ // List of callbacks to issue when an install completes successfully.
+ std::list<std::pair<InstallCallback, int> > install_callbacks_;
};
PnaclComponentInstaller::PnaclComponentInstaller(
- const Version& version) : current_version_(version) {
+ const Version& version) : current_version_(version), callback_nums_(0) {
DCHECK(version.IsValid());
}
@@ -263,14 +281,32 @@ bool PathContainsPnacl(const base::FilePath& base_path) {
return file_util::PathExists(base_path.AppendASCII(expected_filename));
}
+CrxComponent GetPnaclComponentWithVersion(const Version& current_version) {
+ // Note: the source is the default of BANDAID, even though the
+ // crxes are hosted from CWS.
+ LOG(WARNING) << "GetPnaclComponentWithVersion!!\n";
+ CrxComponent pnacl;
+ pnacl.name = "pnacl";
+ // We need a singleton installer... or singleton component,
+ // so that the correct installer's Install() hook gets called.
+ // Or the component updater service needs to be able to look up
+ // the component by id instead.
+ pnacl.installer = new PnaclComponentInstaller(current_version);
+ pnacl.version = current_version;
+ SetPnaclHash(&pnacl.pk_hash);
+ return pnacl;
+}
+
} // namespace
bool PnaclComponentInstaller::Install(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;
}
@@ -279,15 +315,19 @@ bool PnaclComponentInstaller::Install(base::DictionaryValue* manifest,
pnacl_manifest.get(),
&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;
+ }
if (!PathContainsPnacl(unpack_path)) {
LOG(WARNING) << "PathContainsPnacl check failed, not installing.";
+ NotifyInstallError();
return false;
}
@@ -296,58 +336,88 @@ bool PnaclComponentInstaller::Install(base::DictionaryValue* manifest,
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.
current_version_ = version;
-
+ NotifyInstallSuccess();
PathService::Override(chrome::DIR_PNACL_COMPONENT, path);
return true;
}
-namespace {
+void PnaclComponentInstaller::AddInstallCallback(
+ const InstallCallback& cb) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ int num = ++callback_nums_;
+ install_callbacks_.push_back(std::make_pair(cb, num));
+
+ // Set a timeout. If the install doesn't complete within a minute,
+ // assume that the update failed and cancel the callback.
+ // Do this on the same thread that would have checked the callbacks.
+ BrowserThread::PostDelayedTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&PnaclComponentInstaller::CancelCallback,
+ // Why unretained? The installer should have
+ // the same lifetime as the component updater service,
+ // which lives until process shutdown.
+ base::Unretained(this),
+ num),
+ base::TimeDelta::FromSeconds(kPnaclInstallerTimeout));
+}
+
+void PnaclComponentInstaller::CancelCallback(int num) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ for (std::list<std::pair<InstallCallback, int> >::iterator
+ i = install_callbacks_.begin(),
+ e = install_callbacks_.end(); i != e; ++i) {
+ if (i->second == num) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(i->first, false));
+ install_callbacks_.erase(i);
+ return;
+ }
+ }
+}
+
+void PnaclComponentInstaller::NotifyInstallError() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ while (!install_callbacks_.empty()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(install_callbacks_.front().first, false));
+ install_callbacks_.pop_front();
+ }
+}
-void DoCheckForUpdate(ComponentUpdateService* cus,
- const CrxComponent& pnacl) {
- if (cus->CheckForUpdateSoon(pnacl) != ComponentUpdateService::kOk) {
- LOG(WARNING) << "Pnacl check for update failed.";
+void PnaclComponentInstaller::NotifyInstallSuccess() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ while (!install_callbacks_.empty()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(install_callbacks_.front().first, true));
+ install_callbacks_.pop_front();
}
}
+namespace {
+
// Finally, do the registration with the right version number.
void FinishPnaclUpdateRegistration(ComponentUpdateService* cus,
- const Version& current_version) {
+ const CrxComponent& pnacl) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // Note: the source is the default of BANDAID, even though the
- // crxes are hosted from CWS.
- CrxComponent pnacl;
- pnacl.name = "pnacl";
- pnacl.installer = new PnaclComponentInstaller(current_version);
- pnacl.version = current_version;
- SetPnaclHash(&pnacl);
if (cus->RegisterComponent(pnacl) != ComponentUpdateService::kOk) {
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 (current_version.Equals(null_version)) {
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(DoCheckForUpdate, cus, pnacl),
- base::TimeDelta::FromSeconds(kInitialDelaySeconds));
- }
}
// Check if there is an existing version on disk first to know when
@@ -374,7 +444,9 @@ void StartPnaclUpdateRegistration(ComponentUpdateService* cus) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&FinishPnaclUpdateRegistration, cus, version));
+ base::Bind(&FinishPnaclUpdateRegistration,
+ cus,
+ GetPnaclComponentWithVersion(version)));
// Remove older versions of PNaCl.
for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
@@ -390,3 +462,30 @@ void RegisterPnaclComponent(ComponentUpdateService* cus) {
BrowserThread::FILE, FROM_HERE,
base::Bind(&StartPnaclUpdateRegistration, cus));
}
+
+void CheckUpdatesForPnacl(ComponentUpdateService* cus,
+ const base::Callback<void(bool)>& installed) {
+ std::vector<uint8> pk_hash;
+ SetPnaclHash(&pk_hash);
+ CrxComponent pnacl;
+ if (!cus->FindRegisteredComponent(pk_hash, &pnacl)) {
+ installed.Run(false);
+ return;
+ }
+ ComponentUpdateService::Status status = cus->CheckForUpdateSoon(pnacl);
+ if (status != ComponentUpdateService::kOk) {
+ installed.Run(false);
+ return;
+ }
+ PnaclComponentInstaller* installer =
+ static_cast<PnaclComponentInstaller*>(pnacl.installer);
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(
+ &PnaclComponentInstaller::AddInstallCallback,
+ // Why unretained? The installer should have
+ // the same lifetime as the component updater service,
+ // which lives until process shutdown.
+ base::Unretained(installer),
+ installed));
+}
« no previous file with comments | « chrome/browser/component_updater/pnacl/pnacl_component_installer.h ('k') | chrome/browser/nacl_host/pnacl_file_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698