| 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 f26ef1a3a0853d0df632a32b0545174a074591e4..431cf61ba43d9a23abc03a2691bebc958c468561 100644
|
| --- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc
|
| +++ b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc
|
| @@ -18,7 +18,10 @@
|
| #include "base/version.h"
|
| #include "base/win/windows_version.h"
|
| #include "build/build_config.h"
|
| +#include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/component_updater/component_updater_service.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/profiles/profile_manager.h"
|
| #include "chrome/common/chrome_paths.h"
|
| #include "chrome/common/chrome_switches.h"
|
| #include "chrome/common/omaha_query_params.h"
|
| @@ -120,17 +123,31 @@ const char kNullVersion[] = "0.0.0.0";
|
| // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\0.1.2.3\.
|
| // and the base directory will be:
|
| // <profile>\AppData\Local\Google\Chrome\User Data\Pnacl\.
|
| -base::FilePath GetPnaclBaseDirectory() {
|
| - base::FilePath result;
|
| - CHECK(PathService::Get(chrome::DIR_PNACL_BASE, &result));
|
| - return result;
|
| +base::FilePath GetPnaclBaseDirectory(bool per_user) {
|
| + // For ChromeOS, temporarily make this user-dependent (for integrity) until
|
| + // we find a better solution.
|
| + // This is not ideal because of the following:
|
| + // (a) We end up with per-user copies instead of a single copy
|
| + // (b) The profile can change as users log in to different accounts
|
| + // so we need to watch for user-login-events (see pnacl_profile_observer.h).
|
| + if (per_user) {
|
| + Profile* profile = ProfileManager::GetLastUsedProfile();
|
| + base::FilePath path = profile->GetPath().Append(
|
| + FILE_PATH_LITERAL("pnacl"));
|
| + return path;
|
| + } else {
|
| + base::FilePath result;
|
| + CHECK(PathService::Get(chrome::DIR_PNACL_BASE, &result));
|
| + return result;
|
| + }
|
| }
|
|
|
| -bool GetLatestPnaclDirectory(base::FilePath* latest_dir,
|
| +bool GetLatestPnaclDirectory(bool per_user,
|
| + base::FilePath* latest_dir,
|
| Version* latest_version,
|
| std::vector<base::FilePath>* older_dirs) {
|
| // Enumerate all versions starting from the base directory.
|
| - base::FilePath base_dir = GetPnaclBaseDirectory();
|
| + base::FilePath base_dir = GetPnaclBaseDirectory(per_user);
|
| bool found = false;
|
| file_util::FileEnumerator
|
| file_enumerator(base_dir, false, file_util::FileEnumerator::DIRECTORIES);
|
| @@ -210,24 +227,16 @@ bool CheckPnaclComponentManifest(base::DictionaryValue* manifest,
|
| return true;
|
| }
|
|
|
| -class PnaclComponentInstaller : public ComponentInstaller {
|
| - public:
|
| - explicit PnaclComponentInstaller(const Version& version);
|
| -
|
| - virtual ~PnaclComponentInstaller() {}
|
| -
|
| - virtual void OnUpdateError(int error) OVERRIDE;
|
| -
|
| - virtual bool Install(base::DictionaryValue* manifest,
|
| - const base::FilePath& unpack_path) OVERRIDE;
|
| -
|
| - private:
|
| - Version current_version_;
|
| -};
|
| +PnaclComponentInstaller::PnaclComponentInstaller()
|
| + : per_user_(false),
|
| + cus_(NULL) {
|
| +#if defined(OS_CHROMEOS)
|
| + per_user_ = true;
|
| + profile_observer_.reset(new PnaclProfileObserver(this));
|
| +#endif
|
| +}
|
|
|
| -PnaclComponentInstaller::PnaclComponentInstaller(
|
| - const Version& version) : current_version_(version) {
|
| - DCHECK(version.IsValid());
|
| +PnaclComponentInstaller::~PnaclComponentInstaller() {
|
| }
|
|
|
| void PnaclComponentInstaller::OnUpdateError(int error) {
|
| @@ -265,7 +274,7 @@ bool PnaclComponentInstaller::Install(base::DictionaryValue* manifest,
|
| }
|
|
|
| // Don't install if the current version is actually newer.
|
| - if (current_version_.CompareTo(version) > 0)
|
| + if (current_version().CompareTo(version) > 0)
|
| return false;
|
|
|
| if (!PathContainsPnacl(unpack_path)) {
|
| @@ -275,7 +284,7 @@ bool PnaclComponentInstaller::Install(base::DictionaryValue* manifest,
|
|
|
| // Passed the basic tests. Time to install it.
|
| base::FilePath path =
|
| - GetPnaclBaseDirectory().AppendASCII(version.GetString());
|
| + GetPnaclBaseDirectory(per_user()).AppendASCII(version.GetString());
|
| if (file_util::PathExists(path)) {
|
| LOG(WARNING) << "Target path already exists, not installing.";
|
| return false;
|
| @@ -290,7 +299,7 @@ bool PnaclComponentInstaller::Install(base::DictionaryValue* manifest,
|
| // 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
|
| - current_version_ = version;
|
| + set_current_version(version);
|
|
|
| PathService::Override(chrome::DIR_PNACL_COMPONENT, path);
|
| return true;
|
| @@ -307,16 +316,20 @@ void DoCheckForUpdate(ComponentUpdateService* cus,
|
|
|
| // Finally, do the registration with the right version number.
|
| void FinishPnaclUpdateRegistration(ComponentUpdateService* cus,
|
| - const Version& current_version) {
|
| + const Version& current_version,
|
| + PnaclComponentInstaller* pci) {
|
| 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) {
|
| + CrxComponent pnacl_component;
|
| + pnacl_component.version = current_version;
|
| + pnacl_component.name = "pnacl";
|
| + pnacl_component.installer = pci;
|
| + pci->set_current_version(current_version);
|
| + SetPnaclHash(&pnacl_component);
|
| +
|
| + ComponentUpdateService::Status status =
|
| + cus->RegisterComponent(pnacl_component);
|
| + if (status != ComponentUpdateService::kOk
|
| + && status != ComponentUpdateService::kReplaced) {
|
| NOTREACHED() << "Pnacl component registration failed.";
|
| }
|
|
|
| @@ -324,19 +337,24 @@ void FinishPnaclUpdateRegistration(ComponentUpdateService* cus,
|
| // 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)) {
|
| + if (pci->current_version().Equals(null_version)) {
|
| BrowserThread::PostDelayedTask(
|
| BrowserThread::UI, FROM_HERE,
|
| - base::Bind(DoCheckForUpdate, cus, pnacl),
|
| + base::Bind(DoCheckForUpdate, cus, pnacl_component),
|
| base::TimeDelta::FromSeconds(kInitialDelaySeconds));
|
| }
|
| }
|
|
|
| // Check if there is an existing version on disk first to know when
|
| // a hosted version is actually newer.
|
| -void StartPnaclUpdateRegistration(ComponentUpdateService* cus) {
|
| +void StartPnaclUpdateRegistration(ComponentUpdateService* cus,
|
| + PnaclComponentInstaller* pci) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| - base::FilePath path = GetPnaclBaseDirectory();
|
| + // If installation is per-user, do not start until logged in.
|
| + bool per_user = pci->per_user();
|
| + if (per_user && !g_browser_process->profile_manager()->IsLoggedIn())
|
| + return;
|
| + base::FilePath path = GetPnaclBaseDirectory(per_user);
|
| if (!file_util::PathExists(path)) {
|
| if (!file_util::CreateDirectory(path)) {
|
| NOTREACHED() << "Could not create base Pnacl directory.";
|
| @@ -346,7 +364,7 @@ void StartPnaclUpdateRegistration(ComponentUpdateService* cus) {
|
|
|
| Version version(kNullVersion);
|
| std::vector<base::FilePath> older_dirs;
|
| - if (GetLatestPnaclDirectory(&path, &version, &older_dirs)) {
|
| + if (GetLatestPnaclDirectory(per_user, &path, &version, &older_dirs)) {
|
| if (!PathContainsPnacl(path)) {
|
| version = Version(kNullVersion);
|
| } else {
|
| @@ -356,7 +374,7 @@ void StartPnaclUpdateRegistration(ComponentUpdateService* cus) {
|
|
|
| BrowserThread::PostTask(
|
| BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&FinishPnaclUpdateRegistration, cus, version));
|
| + base::Bind(&FinishPnaclUpdateRegistration, cus, version, pci));
|
|
|
| // Remove older versions of PNaCl.
|
| for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
|
| @@ -367,13 +385,24 @@ void StartPnaclUpdateRegistration(ComponentUpdateService* cus) {
|
|
|
| } // namespace
|
|
|
| -void RegisterPnaclComponent(ComponentUpdateService* cus,
|
| +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).
|
| if (command_line.HasSwitch(switches::kEnablePnacl)) {
|
| + cus_ = cus;
|
| BrowserThread::PostTask(
|
| BrowserThread::FILE, FROM_HERE,
|
| - base::Bind(&StartPnaclUpdateRegistration, cus));
|
| + base::Bind(&StartPnaclUpdateRegistration, cus_, this));
|
| }
|
| }
|
| +
|
| +void PnaclComponentInstaller::ReRegisterPnacl() {
|
| + // We only create the profile observer, which can trigger a
|
| + // call to ReRegisterPnacl, if kEnablePnacl is given on the commandline.
|
| + // Thus, we don't check the commandline flags again here.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::FILE, FROM_HERE,
|
| + base::Bind(&StartPnaclUpdateRegistration, cus_, this));
|
| +}
|
|
|