summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjvoung@google.com <jvoung@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-09 00:39:56 +0000
committerjvoung@google.com <jvoung@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-09 00:39:56 +0000
commit9f108f2f375b79f33bdd0d75ba111530f91da586 (patch)
treedfca12b4c764f9aa413de82cbb5f07a47150a3df
parent41ca8c491a579da650020d435ce1137de8eee17a (diff)
downloadchromium_src-9f108f2f375b79f33bdd0d75ba111530f91da586.zip
chromium_src-9f108f2f375b79f33bdd0d75ba111530f91da586.tar.gz
chromium_src-9f108f2f375b79f33bdd0d75ba111530f91da586.tar.bz2
Turn on component updater on chromeos, only for the pnacl component.
Make the pnacl component place files in a profile-specific directory for chromeos. We don't want to share data between users on chromeos because of questions about integrity of these files. This adds a notification watcher and will re-register pnacl with a different version whenever the user logs into a different account. Files are installed to a stateful partition, which should be okay. The stateful partition is mounted no-exec, but the pnacl files are not typical executables. This is a temporary solution to help with testing out PNaCl on chromeos. We will need to find a different solution later that does not involve multiple copies, one for each user. BUG=221381 TEST= manual with: 1) export GYP_DEFINES="chromeos=1" 2) build 3) out/Release/chrome --enable-pnacl --enable-nacl --user-data-dir=/tmp/temp_profile_chromeos --login-profile=user --login-manager 4) wait 20 seconds and see /tmp/temp_profile_chromeos/test-user/pnacl/0.0.0.5 show up Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=192415 Review URL: https://codereview.chromium.org/13071002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192969 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/browser_process.h3
-rw-r--r--chrome/browser/browser_process_impl.cc17
-rw-r--r--chrome/browser/browser_process_impl.h9
-rw-r--r--chrome/browser/chrome_browser_main.cc10
-rw-r--r--chrome/browser/component_updater/pnacl/pnacl_component_installer.cc166
-rw-r--r--chrome/browser/component_updater/pnacl/pnacl_component_installer.h53
-rw-r--r--chrome/browser/component_updater/pnacl/pnacl_profile_observer.cc36
-rw-r--r--chrome/browser/component_updater/pnacl/pnacl_profile_observer.h31
-rw-r--r--chrome/browser/component_updater/test/component_updater_service_unittest.cc120
-rw-r--r--chrome/browser/profiles/profile_manager.h3
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/test/base/testing_browser_process.cc4
-rw-r--r--chrome/test/base/testing_browser_process.h1
13 files changed, 376 insertions, 79 deletions
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index a8be8f3..8087f73 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -31,6 +31,7 @@ class IntranetRedirectDetector;
class IOThread;
class MetricsService;
class NotificationUIManager;
+class PnaclComponentInstaller;
class PrefRegistrySimple;
class PrefService;
class Profile;
@@ -218,6 +219,8 @@ class BrowserProcess {
virtual CRLSetFetcher* crl_set_fetcher() = 0;
+ virtual PnaclComponentInstaller* pnacl_component_installer() = 0;
+
virtual BookmarkPromptController* bookmark_prompt_controller() = 0;
virtual chrome::MediaFileSystemRegistry* media_file_system_registry() = 0;
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index fa976f5..f23eced 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -27,6 +27,7 @@
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/component_updater/component_updater_configurator.h"
#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/devtools/remote_debugging_server.h"
#include "chrome/browser/download/download_request_limiter.h"
@@ -746,9 +747,6 @@ prerender::PrerenderTracker* BrowserProcessImpl::prerender_tracker() {
}
ComponentUpdateService* BrowserProcessImpl::component_updater() {
-#if defined(OS_CHROMEOS)
- return NULL;
-#else
if (!component_updater_.get()) {
ComponentUpdateService::Configurator* configurator =
MakeChromeComponentUpdaterConfigurator(
@@ -759,19 +757,18 @@ ComponentUpdateService* BrowserProcessImpl::component_updater() {
component_updater_.reset(ComponentUpdateServiceFactory(configurator));
}
return component_updater_.get();
-#endif
}
CRLSetFetcher* BrowserProcessImpl::crl_set_fetcher() {
-#if defined(OS_CHROMEOS)
- // There's no component updater on ChromeOS so there can't be a CRLSetFetcher
- // either.
- return NULL;
-#else
if (!crl_set_fetcher_.get())
crl_set_fetcher_ = new CRLSetFetcher();
return crl_set_fetcher_.get();
-#endif
+}
+
+PnaclComponentInstaller* BrowserProcessImpl::pnacl_component_installer() {
+ if (!pnacl_component_installer_.get())
+ pnacl_component_installer_.reset(new PnaclComponentInstaller());
+ return pnacl_component_installer_.get();
}
void BrowserProcessImpl::ResourceDispatcherHostCreated() {
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index 0d2199f..93d1901 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -132,6 +132,7 @@ class BrowserProcessImpl : public BrowserProcess,
virtual prerender::PrerenderTracker* prerender_tracker() OVERRIDE;
virtual ComponentUpdateService* component_updater() OVERRIDE;
virtual CRLSetFetcher* crl_set_fetcher() OVERRIDE;
+ virtual PnaclComponentInstaller* pnacl_component_installer() OVERRIDE;
virtual BookmarkPromptController* bookmark_prompt_controller() OVERRIDE;
virtual chrome::MediaFileSystemRegistry*
media_file_system_registry() OVERRIDE;
@@ -286,11 +287,13 @@ class BrowserProcessImpl : public BrowserProcess,
#if defined(OS_CHROMEOS)
scoped_ptr<chromeos::OomPriorityManager> oom_priority_manager_;
-#else
+#endif
+ // component updater is normally not used under ChromeOS due
+ // to concerns over integrity of data shared between profiles,
+ // but some users of component updater only install per-user.
scoped_ptr<ComponentUpdateService> component_updater_;
-
scoped_refptr<CRLSetFetcher> crl_set_fetcher_;
-#endif
+ scoped_ptr<PnaclComponentInstaller> pnacl_component_installer_;
#if defined(ENABLE_PLUGIN_INSTALLATION)
scoped_refptr<PluginsResourceService> plugins_resource_service_;
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index a8abe15..ddf00ea 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -448,11 +448,11 @@ void RecordTouchEventState(const CommandLine& command_line) {
void RegisterComponentsForUpdate(const CommandLine& command_line) {
ComponentUpdateService* cus = g_browser_process->component_updater();
- if (!cus)
- return;
- // Registration can be before of after cus->Start() so it is ok to post
+
+ // Registration can be before or after cus->Start() so it is ok to post
// a task to the UI thread to do registration once you done the necessary
// file IO to know you existing component version.
+#if !defined(OS_CHROMEOS)
RegisterRecoveryComponent(cus, g_browser_process->local_state());
RegisterPepperFlashComponent(cus);
RegisterSwiftShaderComponent(cus);
@@ -461,8 +461,10 @@ void RegisterComponentsForUpdate(const CommandLine& command_line) {
// network.
if (!command_line.HasSwitch(switches::kDisableCRLSets))
g_browser_process->crl_set_fetcher()->StartInitialLoad(cus);
+#endif
- RegisterPnaclComponent(cus, command_line);
+ g_browser_process->pnacl_component_installer()->RegisterPnaclComponent(
+ cus, command_line);
cus->Start();
}
diff --git a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc
index f26ef1a..5f59d17 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"
@@ -116,21 +119,12 @@ void SetPnaclHash(CrxComponent* component) {
// If we don't have Pnacl installed, this is the version we claim.
const char kNullVersion[] = "0.0.0.0";
-// Pnacl components have the version encoded in the path itself:
-// <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;
-}
-
-bool GetLatestPnaclDirectory(base::FilePath* latest_dir,
+bool GetLatestPnaclDirectory(PnaclComponentInstaller* pci,
+ 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 = pci->GetPnaclBaseDirectory();
bool found = false;
file_util::FileEnumerator
file_enumerator(base_dir, false, file_util::FileEnumerator::DIRECTORIES);
@@ -210,30 +204,53 @@ 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;
+#endif
+}
-PnaclComponentInstaller::PnaclComponentInstaller(
- const Version& version) : current_version_(version) {
- DCHECK(version.IsValid());
+PnaclComponentInstaller::~PnaclComponentInstaller() {
}
void PnaclComponentInstaller::OnUpdateError(int error) {
NOTREACHED() << "Pnacl update error: " << error;
}
+// Pnacl components have the version encoded in the path itself:
+// <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 PnaclComponentInstaller::GetPnaclBaseDirectory() {
+ // 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_) {
+ DCHECK(!current_profile_path_.empty());
+ base::FilePath path = current_profile_path_.Append(
+ FILE_PATH_LITERAL("pnacl"));
+ return path;
+ } else {
+ base::FilePath result;
+ CHECK(PathService::Get(chrome::DIR_PNACL_BASE, &result));
+ return result;
+ }
+}
+
+void PnaclComponentInstaller::OnProfileChange() {
+ // On chromeos, we want to find the --login-profile=<foo> dir.
+ // Even though the path does vary between users, the content
+ // changes when logging out and logging in.
+ ProfileManager* pm = g_browser_process->profile_manager();
+ current_profile_path_ = pm->user_data_dir().Append(
+ pm->GetInitialProfileDir());
+}
+
namespace {
bool PathContainsPnacl(const base::FilePath& base_path) {
@@ -265,7 +282,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)) {
@@ -274,8 +291,8 @@ bool PnaclComponentInstaller::Install(base::DictionaryValue* manifest,
}
// Passed the basic tests. Time to install it.
- base::FilePath path =
- GetPnaclBaseDirectory().AppendASCII(version.GetString());
+ base::FilePath path = GetPnaclBaseDirectory().AppendASCII(
+ version.GetString());
if (file_util::PathExists(path)) {
LOG(WARNING) << "Target path already exists, not installing.";
return false;
@@ -290,7 +307,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;
@@ -306,17 +323,20 @@ void DoCheckForUpdate(ComponentUpdateService* cus,
}
// Finally, do the registration with the right version number.
-void FinishPnaclUpdateRegistration(ComponentUpdateService* cus,
- const Version& current_version) {
+void FinishPnaclUpdateRegistration(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 =
+ pci->cus()->RegisterComponent(pnacl_component);
+ if (status != ComponentUpdateService::kOk
+ && status != ComponentUpdateService::kReplaced) {
NOTREACHED() << "Pnacl component registration failed.";
}
@@ -324,19 +344,19 @@ 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, pci->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(PnaclComponentInstaller* pci) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- base::FilePath path = GetPnaclBaseDirectory();
+ base::FilePath path = pci->GetPnaclBaseDirectory();
if (!file_util::PathExists(path)) {
if (!file_util::CreateDirectory(path)) {
NOTREACHED() << "Could not create base Pnacl directory.";
@@ -346,7 +366,7 @@ void StartPnaclUpdateRegistration(ComponentUpdateService* cus) {
Version version(kNullVersion);
std::vector<base::FilePath> older_dirs;
- if (GetLatestPnaclDirectory(&path, &version, &older_dirs)) {
+ if (GetLatestPnaclDirectory(pci, &path, &version, &older_dirs)) {
if (!PathContainsPnacl(path)) {
version = Version(kNullVersion);
} else {
@@ -356,7 +376,7 @@ void StartPnaclUpdateRegistration(ComponentUpdateService* cus) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&FinishPnaclUpdateRegistration, cus, version));
+ base::Bind(&FinishPnaclUpdateRegistration, version, pci));
// Remove older versions of PNaCl.
for (std::vector<base::FilePath>::iterator iter = older_dirs.begin();
@@ -365,15 +385,55 @@ void StartPnaclUpdateRegistration(ComponentUpdateService* cus) {
}
}
+void GetProfileInformation(PnaclComponentInstaller* pci) {
+ // Bail if not logged in yet.
+ if (!g_browser_process->profile_manager()->IsLoggedIn()) {
+ return;
+ }
+
+ pci->OnProfileChange();
+
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&StartPnaclUpdateRegistration, pci));
+}
+
+
} // 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)) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&StartPnaclUpdateRegistration, cus));
+ cus_ = cus;
+ // If per_user, create a profile observer to watch for logins.
+ // Only do so after cus_ is set to something non-null.
+ if (per_user_ && !profile_observer_) {
+ profile_observer_.reset(new PnaclProfileObserver(this));
+ }
+ if (per_user_) {
+ // Figure out profile information, before proceeding to look for files.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&GetProfileInformation, this));
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&StartPnaclUpdateRegistration, this));
+ }
}
}
+
+void PnaclComponentInstaller::ReRegisterPnacl() {
+ // No need to check the commandline flags again here.
+ // We could only have gotten here after RegisterPnaclComponent
+ // found --enable-pnacl, since that is where we create the profile_observer_,
+ // which in turn calls ReRegisterPnacl.
+ DCHECK(per_user_);
+ // Figure out profile information, before proceeding to look for files.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&GetProfileInformation, this));
+}
diff --git a/chrome/browser/component_updater/pnacl/pnacl_component_installer.h b/chrome/browser/component_updater/pnacl/pnacl_component_installer.h
index 765b860..5d58402 100644
--- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.h
+++ b/chrome/browser/component_updater/pnacl/pnacl_component_installer.h
@@ -5,17 +5,62 @@
#ifndef CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_COMPONENT_INSTALLER_H_
#define CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_COMPONENT_INSTALLER_H_
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/browser/component_updater/pnacl/pnacl_profile_observer.h"
+
class CommandLine;
-class ComponentUpdateService;
class Version;
namespace base {
class DictionaryValue;
}
-// Component update registration for Portable Native Client.
-void RegisterPnaclComponent(ComponentUpdateService* cus,
- const CommandLine& command_line);
+// Component installer responsible for Portable Native Client files.
+// Files can be installed to a shared location, or be installed to
+// a per-user location.
+class PnaclComponentInstaller : public ComponentInstaller {
+ public:
+ PnaclComponentInstaller();
+
+ virtual ~PnaclComponentInstaller();
+
+ virtual void OnUpdateError(int error) OVERRIDE;
+
+ virtual bool Install(base::DictionaryValue* manifest,
+ const base::FilePath& unpack_path) OVERRIDE;
+
+ // Register a PNaCl component for the first time.
+ void RegisterPnaclComponent(ComponentUpdateService* cus,
+ const CommandLine& command_line);
+
+ // Check the PNaCl version again and re-register with the component
+ // updater service.
+ void ReRegisterPnacl();
+
+ bool per_user() const { return per_user_; }
+
+ // If per_user, function to call when profile is changed.
+ void OnProfileChange();
+
+ // Determine the base directory for storing each version of PNaCl.
+ base::FilePath GetPnaclBaseDirectory();
+
+ Version current_version() const { return current_version_; }
+
+ void set_current_version(const Version& v) { current_version_ = v; }
+
+ ComponentUpdateService* cus() const { return cus_; }
+
+ private:
+ bool per_user_;
+ scoped_ptr<PnaclProfileObserver> profile_observer_;
+ base::FilePath current_profile_path_;
+ Version current_version_;
+ ComponentUpdateService* cus_;
+ DISALLOW_COPY_AND_ASSIGN(PnaclComponentInstaller);
+};
// Returns true if this browser is compatible with the given Pnacl component
// manifest, with the version specified in the manifest in |version_out|.
diff --git a/chrome/browser/component_updater/pnacl/pnacl_profile_observer.cc b/chrome/browser/component_updater/pnacl/pnacl_profile_observer.cc
new file mode 100644
index 0000000..a3f9e34
--- /dev/null
+++ b/chrome/browser/component_updater/pnacl/pnacl_profile_observer.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/component_updater/pnacl/pnacl_profile_observer.h"
+
+#include "base/logging.h"
+#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_service.h"
+
+PnaclProfileObserver::PnaclProfileObserver(
+ PnaclComponentInstaller* installer) : pnacl_installer_(installer) {
+ // We only need to observe NOTIFICATION_LOGIN_USER_CHANGED for ChromeOS
+ // (and it's only defined for ChromeOS).
+#if defined(OS_CHROMEOS)
+ registrar_.Add(this,
+ chrome::NOTIFICATION_LOGIN_USER_CHANGED,
+ content::NotificationService::AllSources());
+#endif
+}
+
+PnaclProfileObserver::~PnaclProfileObserver() { }
+
+void PnaclProfileObserver::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+#if defined(OS_CHROMEOS)
+ if (type == chrome::NOTIFICATION_LOGIN_USER_CHANGED) {
+ pnacl_installer_->ReRegisterPnacl();
+ return;
+ }
+ NOTREACHED() << "Unexpected notification observed";
+#endif
+}
diff --git a/chrome/browser/component_updater/pnacl/pnacl_profile_observer.h b/chrome/browser/component_updater/pnacl/pnacl_profile_observer.h
new file mode 100644
index 0000000..52ab984
--- /dev/null
+++ b/chrome/browser/component_updater/pnacl/pnacl_profile_observer.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_PROFILE_OBSERVER_H_
+#define CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_PROFILE_OBSERVER_H_
+
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class PnaclComponentInstaller;
+
+// Monitors profile switching for ChromeOS to check the per-user
+// version of PNaCl.
+class PnaclProfileObserver : public content::NotificationObserver {
+ public:
+ explicit PnaclProfileObserver(PnaclComponentInstaller* installer);
+ virtual ~PnaclProfileObserver();
+
+ virtual void Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ content::NotificationRegistrar registrar_;
+ PnaclComponentInstaller* pnacl_installer_;
+ DISALLOW_COPY_AND_ASSIGN(PnaclProfileObserver);
+};
+
+#endif // CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_PROFILE_OBSERVER_H_
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.cc b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
index 471c90a..6689e49 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.cc
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
@@ -235,9 +235,9 @@ class ComponentUpdaterTest : public testing::Test {
return test_config_;
}
- void RegisterComponent(CrxComponent* com,
- TestComponents component,
- const Version& version) {
+ ComponentUpdateService::Status RegisterComponent(CrxComponent* com,
+ TestComponents component,
+ const Version& version) {
if (component == kTestComponent_abag) {
com->name = "test_abag";
com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash));
@@ -249,7 +249,7 @@ class ComponentUpdaterTest : public testing::Test {
TestInstaller* installer = new TestInstaller;
com->installer = installer;
test_installers_.push_back(installer);
- component_updater_->RegisterComponent(*com);
+ return component_updater_->RegisterComponent(*com);
}
private:
@@ -297,7 +297,8 @@ TEST_F(ComponentUpdaterTest, CheckCrxSleep) {
content::URLRequestPrepackagedInterceptor interceptor;
CrxComponent com;
- RegisterComponent(&com, kTestComponent_abag, Version("1.1"));
+ EXPECT_EQ(ComponentUpdateService::kOk,
+ RegisterComponent(&com, kTestComponent_abag, Version("1.1")));
const GURL expected_update_url(
"http://localhost/upd?extra=foo&x=id%3D"
@@ -653,3 +654,112 @@ TEST_F(ComponentUpdaterTest, CheckForUpdateSoon) {
EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
component_updater()->Stop();
}
+
+// Verify that a previously registered component can get re-registered
+// with a different version.
+TEST_F(ComponentUpdaterTest, CheckReRegistration) {
+ MessageLoop message_loop;
+ content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop);
+ content::TestBrowserThread file_thread(BrowserThread::FILE);
+ content::TestBrowserThread io_thread(BrowserThread::IO);
+
+ io_thread.StartIOThread();
+ file_thread.Start();
+
+ content::URLRequestPrepackagedInterceptor interceptor;
+
+ CrxComponent com1;
+ RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"));
+ CrxComponent com2;
+ RegisterComponent(&com2, kTestComponent_abag, Version("2.2"));
+
+ // Start with 0.9, and update to 1.0
+ const GURL expected_update_url_1(
+ "http://localhost/upd?extra=foo&x=id%3D"
+ "jebgalgnebhfojomionfpkfelancnnkf%26v%3D0.9%26uc&x=id%3D"
+ "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+
+ const GURL expected_update_url_2(
+ "http://localhost/upd?extra=foo&x=id%3D"
+ "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc&x=id%3D"
+ "jebgalgnebhfojomionfpkfelancnnkf%26v%3D1.0%26uc");
+
+ interceptor.SetResponse(expected_update_url_1,
+ test_file("updatecheck_reply_1.xml"));
+ interceptor.SetResponse(expected_update_url_2,
+ test_file("updatecheck_reply_1.xml"));
+ interceptor.SetResponse(GURL(expected_crx_url),
+ test_file("jebgalgnebhfojomionfpkfelancnnkf.crx"));
+
+ // Loop twice to issue two checks: (1) with original 0.9 version
+ // and (2) with the updated 1.0 version.
+ test_configurator()->SetLoopCount(2);
+
+ component_updater()->Start();
+ message_loop.Run();
+
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
+ EXPECT_EQ(1, static_cast<TestInstaller*>(com1.installer)->install_count());
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
+
+ EXPECT_EQ(3, interceptor.GetHitCount());
+
+ ASSERT_EQ(5ul, notification_tracker().size());
+
+ TestNotificationTracker::Event ev0 = notification_tracker().at(0);
+ EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
+
+ TestNotificationTracker::Event ev1 = notification_tracker().at(1);
+ EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, ev1.type);
+
+ TestNotificationTracker::Event ev2 = notification_tracker().at(2);
+ EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATE_READY, ev2.type);
+
+ TestNotificationTracker::Event ev3 = notification_tracker().at(3);
+ EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev3.type);
+
+ TestNotificationTracker::Event ev4 = notification_tracker().at(4);
+ EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev4.type);
+
+ // Now re-register, pretending to be an even newer version (2.2)
+ component_updater()->Stop();
+ EXPECT_EQ(ComponentUpdateService::kReplaced,
+ RegisterComponent(&com1, kTestComponent_jebg, Version("2.2")));
+
+ // Check that we send out 2.2 as our version.
+ // Interceptor's hit count should go up by 1.
+ const GURL expected_update_url_3(
+ "http://localhost/upd?extra=foo&x=id%3D"
+ "jebgalgnebhfojomionfpkfelancnnkf%26v%3D2.2%26uc&x=id%3D"
+ "abagagagagagagagagagagagagagagag%26v%3D2.2%26uc");
+
+ interceptor.SetResponse(expected_update_url_3,
+ test_file("updatecheck_reply_1.xml"));
+
+ notification_tracker().Reset();
+
+ // Loop once just to notice the check happening with the re-register version.
+ test_configurator()->SetLoopCount(1);
+ component_updater()->Start();
+ message_loop.Run();
+
+ ASSERT_EQ(2ul, notification_tracker().size());
+
+ ev0 = notification_tracker().at(0);
+ EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_STARTED, ev0.type);
+
+ ev1 = notification_tracker().at(1);
+ EXPECT_EQ(chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, ev1.type);
+
+ EXPECT_EQ(4, interceptor.GetHitCount());
+
+ // The test harness's Register() function creates a new installer,
+ // so the counts go back to 0.
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->error());
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com1.installer)->install_count());
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->error());
+ EXPECT_EQ(0, static_cast<TestInstaller*>(com2.installer)->install_count());
+
+ component_updater()->Stop();
+}
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h
index 71139bc..a0d1262d 100644
--- a/chrome/browser/profiles/profile_manager.h
+++ b/chrome/browser/profiles/profile_manager.h
@@ -216,6 +216,9 @@ class ProfileManager : public base::NonThreadSafe,
const base::FilePath& user_data_dir() const { return user_data_dir_; }
+ // For ChromeOS, determines if the user has logged in to a real profile.
+ bool IsLoggedIn() const { return logged_in_; }
+
protected:
// Does final initial actions.
virtual void DoFinalInit(Profile* profile, bool go_off_the_record);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index a0c3a893..264c0bc 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -368,6 +368,8 @@
'browser/component_updater/pepper_flash_component_installer.cc',
'browser/component_updater/pnacl/pnacl_component_installer.cc',
'browser/component_updater/pnacl/pnacl_component_installer.h',
+ 'browser/component_updater/pnacl/pnacl_profile_observer.cc',
+ 'browser/component_updater/pnacl/pnacl_profile_observer.h',
'browser/component_updater/recovery_component_installer.cc',
'browser/component_updater/recovery_component_installer.h',
'browser/component_updater/swiftshader_component_installer.cc',
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc
index a14834d..d3d21f0 100644
--- a/chrome/test/base/testing_browser_process.cc
+++ b/chrome/test/base/testing_browser_process.cc
@@ -305,6 +305,10 @@ CRLSetFetcher* TestingBrowserProcess::crl_set_fetcher() {
return NULL;
}
+PnaclComponentInstaller* TestingBrowserProcess::pnacl_component_installer() {
+ return NULL;
+}
+
BookmarkPromptController* TestingBrowserProcess::bookmark_prompt_controller() {
#if defined(OS_IOS)
NOTIMPLEMENTED();
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h
index 0d40a9c..3b02f35 100644
--- a/chrome/test/base/testing_browser_process.h
+++ b/chrome/test/base/testing_browser_process.h
@@ -106,6 +106,7 @@ class TestingBrowserProcess : public BrowserProcess {
virtual prerender::PrerenderTracker* prerender_tracker() OVERRIDE;
virtual ComponentUpdateService* component_updater() OVERRIDE;
virtual CRLSetFetcher* crl_set_fetcher() OVERRIDE;
+ virtual PnaclComponentInstaller* pnacl_component_installer() OVERRIDE;
virtual BookmarkPromptController* bookmark_prompt_controller() OVERRIDE;
virtual chrome::MediaFileSystemRegistry*
media_file_system_registry() OVERRIDE;