diff options
author | jvoung@google.com <jvoung@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-09 00:39:56 +0000 |
---|---|---|
committer | jvoung@google.com <jvoung@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-09 00:39:56 +0000 |
commit | 9f108f2f375b79f33bdd0d75ba111530f91da586 (patch) | |
tree | dfca12b4c764f9aa413de82cbb5f07a47150a3df | |
parent | 41ca8c491a579da650020d435ce1137de8eee17a (diff) | |
download | chromium_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.h | 3 | ||||
-rw-r--r-- | chrome/browser/browser_process_impl.cc | 17 | ||||
-rw-r--r-- | chrome/browser/browser_process_impl.h | 9 | ||||
-rw-r--r-- | chrome/browser/chrome_browser_main.cc | 10 | ||||
-rw-r--r-- | chrome/browser/component_updater/pnacl/pnacl_component_installer.cc | 166 | ||||
-rw-r--r-- | chrome/browser/component_updater/pnacl/pnacl_component_installer.h | 53 | ||||
-rw-r--r-- | chrome/browser/component_updater/pnacl/pnacl_profile_observer.cc | 36 | ||||
-rw-r--r-- | chrome/browser/component_updater/pnacl/pnacl_profile_observer.h | 31 | ||||
-rw-r--r-- | chrome/browser/component_updater/test/component_updater_service_unittest.cc | 120 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_manager.h | 3 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/test/base/testing_browser_process.cc | 4 | ||||
-rw-r--r-- | chrome/test/base/testing_browser_process.h | 1 |
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; |