Index: chrome/browser/component_updater/recovery_component_installer.cc |
diff --git a/chrome/browser/component_updater/recovery_component_installer.cc b/chrome/browser/component_updater/recovery_component_installer.cc |
index 617cb8876a90c37293fe9f1e4238dd9597a2c3bb..f244ca46583fe0189d81724538f9cee05a536a35 100644 |
--- a/chrome/browser/component_updater/recovery_component_installer.cc |
+++ b/chrome/browser/component_updater/recovery_component_installer.cc |
@@ -1,176 +1,495 @@ |
-// Copyright (c) 2012 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/recovery_component_installer.h" |
- |
-#include <string> |
- |
-#include "base/base_paths.h" |
-#include "base/bind.h" |
-#include "base/command_line.h" |
-#include "base/compiler_specific.h" |
-#include "base/file_util.h" |
-#include "base/files/file_path.h" |
-#include "base/logging.h" |
-#include "base/path_service.h" |
-#include "base/prefs/pref_registry_simple.h" |
-#include "base/prefs/pref_service.h" |
-#include "base/process/launch.h" |
-#include "base/strings/string_util.h" |
-#include "base/values.h" |
-#include "chrome/browser/component_updater/component_updater_service.h" |
-#include "components/component_updater/component_updater_paths.h" |
-#include "components/component_updater/pref_names.h" |
-#include "content/public/browser/browser_thread.h" |
- |
-using content::BrowserThread; |
- |
-namespace component_updater { |
- |
-namespace { |
- |
-// CRX hash. The extension id is: npdjjkjlcidkjlamlmmdelcjbcpdjocm. |
-const uint8 kSha2Hash[] = {0xdf, 0x39, 0x9a, 0x9b, 0x28, 0x3a, 0x9b, 0x0c, |
- 0xbc, 0xc3, 0x4b, 0x29, 0x12, 0xf3, 0x9e, 0x2c, |
- 0x19, 0x7a, 0x71, 0x4b, 0x0a, 0x7c, 0x80, 0x1c, |
- 0xf6, 0x29, 0x7c, 0x0a, 0x5f, 0xea, 0x67, 0xb7}; |
- |
-// File name of the recovery binary on different platforms. |
-const base::FilePath::CharType kRecoveryFileName[] = |
-#if defined(OS_WIN) |
- FILE_PATH_LITERAL("ChromeRecovery.exe"); |
-#else // OS_LINUX, OS_MACOSX, etc. |
- FILE_PATH_LITERAL("ChromeRecovery"); |
-#endif |
- |
-const char kRecoveryManifestName[] = "ChromeRecovery"; |
- |
-} // namespace |
- |
-class RecoveryComponentInstaller : public ComponentInstaller { |
- public: |
- explicit RecoveryComponentInstaller(const Version& version, |
- PrefService* prefs); |
- |
- virtual ~RecoveryComponentInstaller() {} |
- |
- virtual void OnUpdateError(int error) OVERRIDE; |
- |
- virtual bool Install(const base::DictionaryValue& manifest, |
- const base::FilePath& unpack_path) OVERRIDE; |
- |
- virtual bool GetInstalledFile(const std::string& file, |
- base::FilePath* installed_file) OVERRIDE; |
- |
- private: |
- Version current_version_; |
- PrefService* prefs_; |
-}; |
- |
-void RecoveryRegisterHelper(ComponentUpdateService* cus, PrefService* prefs) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- Version version(prefs->GetString(prefs::kRecoveryComponentVersion)); |
- if (!version.IsValid()) { |
- NOTREACHED(); |
- return; |
- } |
- |
- CrxComponent recovery; |
- recovery.name = "recovery"; |
- recovery.installer = new RecoveryComponentInstaller(version, prefs); |
- recovery.version = version; |
- recovery.pk_hash.assign(kSha2Hash, &kSha2Hash[sizeof(kSha2Hash)]); |
- if (cus->RegisterComponent(recovery) != ComponentUpdateService::kOk) { |
- NOTREACHED() << "Recovery component registration failed."; |
- } |
-} |
- |
-void RecoveryUpdateVersionHelper(const Version& version, PrefService* prefs) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- prefs->SetString(prefs::kRecoveryComponentVersion, version.GetString()); |
-} |
- |
-RecoveryComponentInstaller::RecoveryComponentInstaller(const Version& version, |
- PrefService* prefs) |
- : current_version_(version), prefs_(prefs) { |
- DCHECK(version.IsValid()); |
-} |
- |
-void RecoveryComponentInstaller::OnUpdateError(int error) { |
- NOTREACHED() << "Recovery component update error: " << error; |
-} |
- |
-bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest, |
- const base::FilePath& unpack_path) { |
- std::string name; |
- manifest.GetStringASCII("name", &name); |
- if (name != kRecoveryManifestName) |
- return false; |
- std::string proposed_version; |
- manifest.GetStringASCII("version", &proposed_version); |
- Version version(proposed_version.c_str()); |
- if (!version.IsValid()) |
- return false; |
- if (current_version_.CompareTo(version) >= 0) |
- return false; |
- |
- // Passed the basic tests. Copy the installation to a permanent directory. |
- base::FilePath path; |
- if (!PathService::Get(DIR_RECOVERY_BASE, &path)) |
- return false; |
- path = path.AppendASCII(version.GetString()); |
- if (base::PathExists(path) && !base::DeleteFile(path, true)) |
- return false; |
- if (!base::Move(unpack_path, path)) { |
- DVLOG(1) << "Recovery component move failed."; |
- return false; |
- } |
- |
- base::FilePath main_file = path.Append(kRecoveryFileName); |
- if (!base::PathExists(main_file)) |
- return false; |
- // Run the recovery component. |
- CommandLine cmdline(main_file); |
- std::string arguments; |
- if (manifest.GetStringASCII("x-recovery-args", &arguments)) |
- cmdline.AppendArg(arguments); |
- std::string add_version; |
- if (manifest.GetStringASCII("x-recovery-add-version", &add_version)) { |
- if (add_version == "yes") |
- cmdline.AppendSwitchASCII("version", current_version_.GetString()); |
- } |
- current_version_ = version; |
- if (prefs_) { |
- BrowserThread::PostTask( |
- BrowserThread::UI, |
- FROM_HERE, |
- base::Bind(&RecoveryUpdateVersionHelper, version, prefs_)); |
- } |
- return base::LaunchProcess(cmdline, base::LaunchOptions(), NULL); |
-} |
- |
-bool RecoveryComponentInstaller::GetInstalledFile( |
- const std::string& file, |
- base::FilePath* installed_file) { |
- return false; |
-} |
- |
-void RegisterRecoveryComponent(ComponentUpdateService* cus, |
- PrefService* prefs) { |
-#if !defined(OS_CHROMEOS) |
- // We delay execute the registration because we are not required in |
- // the critical path during browser startup. |
- BrowserThread::PostDelayedTask( |
- BrowserThread::UI, |
- FROM_HERE, |
- base::Bind(&RecoveryRegisterHelper, cus, prefs), |
- base::TimeDelta::FromSeconds(6)); |
-#endif |
-} |
- |
-void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) { |
- registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0"); |
-} |
- |
-} // namespace component_updater |
+// Copyright (c) 2012 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/recovery_component_installer.h" |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "base/base_paths.h" |
+#include "base/bind.h" |
+#include "base/command_line.h" |
+#include "base/compiler_specific.h" |
+#include "base/file_util.h" |
+#include "base/files/file_path.h" |
+#include "base/logging.h" |
+#include "base/memory/singleton.h" |
+#include "base/path_service.h" |
+#include "base/prefs/pref_registry_simple.h" |
+#include "base/prefs/pref_service.h" |
+#include "base/process/kill.h" |
+#include "base/process/launch.h" |
+#include "base/strings/string_util.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "base/synchronization/waitable_event.h" |
+#include "base/values.h" |
+#include "chrome/browser/component_updater/component_unpacker.h" |
+#include "chrome/browser/component_updater/component_updater_service.h" |
+#include "chrome/common/chrome_paths.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "chrome/common/chrome_version_info.h" |
+#include "chrome/common/pref_names.h" |
+#include "components/component_updater/component_updater_paths.h" |
+#include "components/component_updater/pref_names.h" |
+#include "content/public/browser/browser_thread.h" |
+ |
+using content::BrowserThread; |
+ |
+namespace component_updater { |
+ |
+namespace { |
+ |
+// CRX hash. The extension id is: npdjjkjlcidkjlamlmmdelcjbcpdjocm. |
+const uint8 kSha2Hash[] = {0xdf, 0x39, 0x9a, 0x9b, 0x28, 0x3a, 0x9b, 0x0c, |
+ 0xbc, 0xc3, 0x4b, 0x29, 0x12, 0xf3, 0x9e, 0x2c, |
+ 0x19, 0x7a, 0x71, 0x4b, 0x0a, 0x7c, 0x80, 0x1c, |
+ 0xf6, 0x29, 0x7c, 0x0a, 0x5f, 0xea, 0x67, 0xb7}; |
+ |
+// File name of the recovery binary on different platforms. |
+const base::FilePath::CharType kRecoveryFileName[] = |
+#if defined(OS_WIN) |
+ FILE_PATH_LITERAL("ChromeRecovery.exe"); |
+#else // OS_LINUX, OS_MACOSX, etc. |
+ FILE_PATH_LITERAL("ChromeRecovery"); |
+#endif |
+ |
+const char kRecoveryManifestName[] = "ChromeRecovery"; |
+ |
+// This is a contract between ChromeRecovery and this installer for the |
+// meaning of ChromeRecovery process exit code. |
+enum ChromeRecvoeryExitCode { |
+ EXIT_CODE_RECOVERY_SUCCEEDED = 0, |
+ EXIT_CODE_RECOVERY_SKIPPED = 1, |
+ EXIT_CODE_ELEVATION_NEEDED = 2, |
+}; |
+ |
+// Place where CRX and other installer files will be saved for elevated install. |
+base::FilePath GetInstallerBackupPath(const std::string& version) { |
+ base::FilePath path; |
+ if (PathService::Get(DIR_RECOVERY_BASE, &path)) { |
+ path = path.Append(FILE_PATH_LITERAL("backup")); |
+ path = path.AppendASCII(version); |
+ } |
+ return path; |
+} |
+ |
+// Returns a secure location that only elevated process can write. |
+// The elevated installer stores files there to make sure files will not be |
+// tampered by unauthorized process in the installation process. |
+base::FilePath GetSecureRecoveryPath(const std::string& version) { |
+ base::FilePath path; |
+ if (PathService::Get(DIR_SECURE_RECOVERY_BASE, &path)) { |
+ path = path.AppendASCII(version); |
+ } |
+ return path; |
+} |
+ |
+} // namespace |
+ |
+// Recovery component installer tries to recover chrome with current process |
+// privilege first. If that fails, it then tries elevated install, if |
+// applicable applicable. The workflow of the elevated recovery is: |
+// 1) In the default recovery install, the recovery process returns an exit |
+// code that indicates elevation is needed. When that happens, the unpacker |
+// saves CRX to the backup path and then a preference flag will be set. |
+// 2) UpgradeDetector detects the flag, gets elevation permission from user. |
+// 3) ElevatedInstallLauncher starts an elevated process for recovery. |
+// 4) ElevatedRecoveryInstaller runs in the newly created elevated process, |
+// move the backed-up CRX to a secure location, verifies signature and |
+// unpacks CRX to a secure folder. |
+// 5) RecoveryComponentInstaller tries to do recovery again with elevated |
+// privilege. |
+class RecoveryComponentInstaller : public ComponentInstaller { |
+ public: |
+ RecoveryComponentInstaller( |
+ const Version& version, PrefService* prefs, bool elevated_install); |
+ |
+ virtual ~RecoveryComponentInstaller() {} |
+ |
+ virtual void OnUpdateError(int error) OVERRIDE; |
+ |
+ virtual bool Install(const base::DictionaryValue& manifest, |
+ const base::FilePath& unpack_path) OVERRIDE; |
+ |
+ virtual base::FilePath GetBackupPath() const OVERRIDE; |
+ |
+ virtual void InstallExternally() OVERRIDE; |
+ |
+ virtual bool GetInstalledFile(const std::string& file, |
+ base::FilePath* installed_file) OVERRIDE; |
+ |
+ private: |
+ bool IsElevatedInstallNeeded() const; |
+ |
+ Version current_version_; |
+ PrefService* prefs_; |
+ bool elevated_install_; |
+ int installer_exit_code_; |
+}; |
+ |
+// Creates an elevated process for recovery. |
+class ElevatedInstallLauncher { |
+ public: |
+ static ElevatedInstallLauncher* GetInstance(); |
+ void Launch(PrefService* prefs, bool elevation_allowed, |
+ const base::Closure& callback); |
+ |
+ private: |
+ friend struct DefaultSingletonTraits<ElevatedInstallLauncher>; |
+ |
+ ElevatedInstallLauncher(); |
+ |
+ static void RunInstaller( |
+ PrefService* prefs, const std::string& version, bool elevation_allowed); |
+ |
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ElevatedInstallLauncher); |
+}; |
+ |
+class ElevatedRecoveryInstaller { |
+ public: |
+ static ElevatedRecoveryInstaller* GetInstance(); |
+ void Install(const std::string& version); |
+ void WaitForInstallToComplete(); |
+ |
+ private: |
+ friend struct DefaultSingletonTraits<ElevatedRecoveryInstaller>; |
+ |
+ ElevatedRecoveryInstaller(); |
+ |
+ bool PrepareInstall(const std::string& version_str); |
+ void DoInstall(const std::string& version_str); |
+ void DoneInstall(ComponentUnpacker::Error error, int extended_error); |
+ void PostInstallCleanup(); |
+ |
+ Version version_; |
+ scoped_refptr<ComponentUnpacker> unpacker_; |
+ scoped_ptr<RecoveryComponentInstaller> rc_installer_; |
+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; |
+ base::WaitableEvent install_complete_event_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ElevatedRecoveryInstaller); |
+}; |
+ |
+void RecoveryRegisterHelper(ComponentUpdateService* cus, PrefService* prefs) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ Version version(prefs->GetString(prefs::kRecoveryComponentVersion)); |
+ if (!version.IsValid()) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ |
+ CrxComponent recovery; |
+ recovery.name = "recovery"; |
+ recovery.installer = new RecoveryComponentInstaller(version, prefs, false); |
+ recovery.version = version; |
+ recovery.pk_hash.assign(kSha2Hash, &kSha2Hash[sizeof(kSha2Hash)]); |
+ if (cus->RegisterComponent(recovery) != ComponentUpdateService::kOk) { |
+ NOTREACHED() << "Recovery component registration failed."; |
+ } |
+} |
+ |
+void RecoveryUpdateVersionHelper(const Version& version, PrefService* prefs) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ prefs->SetString(prefs::kRecoveryComponentVersion, version.GetString()); |
+} |
+ |
+void RecoveryUpdateElevationHelper(bool needs_elevation, PrefService* prefs) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ prefs->SetBoolean(prefs::kRecoveryComponentNeedsElevation, needs_elevation); |
+} |
+ |
+RecoveryComponentInstaller::RecoveryComponentInstaller( |
+ const Version& version, PrefService* prefs, bool elevated_install) |
+ : current_version_(version), |
+ prefs_(prefs), |
+ elevated_install_(elevated_install), |
+ installer_exit_code_(0) { |
+ DCHECK(version.IsValid()); |
+} |
+ |
+void RecoveryComponentInstaller::OnUpdateError(int error) { |
+ NOTREACHED() << "Recovery component update error: " << error; |
+} |
+ |
+bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest, |
+ const base::FilePath& unpack_path) { |
+ std::string name; |
+ manifest.GetStringASCII("name", &name); |
+ if (name != kRecoveryManifestName) |
+ return false; |
+ std::string proposed_version; |
+ manifest.GetStringASCII("version", &proposed_version); |
+ Version version(proposed_version.c_str()); |
+ if (!version.IsValid()) |
+ return false; |
+ if (current_version_.CompareTo(version) >= 0) |
+ return false; |
+ |
+ base::FilePath path; |
+ if (elevated_install_) { |
+ // For elevated install, |unpack_path| should be a secure path that is |
+ // accessible by elevated user only and should be available thoughout the |
+ // installation process. |
+ path = unpack_path; |
+ } else { |
+ // Passed the basic tests. Copy the installation to a permanent directory. |
+ if (!PathService::Get(DIR_RECOVERY_BASE, &path)) |
+ return false; |
+ path = path.AppendASCII(version.GetString()); |
+ if (base::PathExists(path) && !base::DeleteFile(path, true)) |
+ return false; |
+ if (!base::Move(unpack_path, path)) { |
+ DVLOG(1) << "Recovery component move failed."; |
+ return false; |
+ } |
+ } |
+ |
+ base::FilePath main_file = path.Append(kRecoveryFileName); |
+ if (!base::PathExists(main_file)) |
+ return false; |
+ // Run the recovery component. |
+ CommandLine cmdline(main_file); |
+ std::string arguments; |
+ if (manifest.GetStringASCII("x-recovery-args", &arguments)) |
+ cmdline.AppendArg(arguments); |
+ std::string add_version; |
+ if (manifest.GetStringASCII("x-recovery-add-version", &add_version)) { |
+ if (add_version == "yes") |
+ cmdline.AppendSwitchASCII("version", current_version_.GetString()); |
+ } |
+ current_version_ = version; |
+ if (prefs_) { |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&RecoveryUpdateVersionHelper, version, prefs_)); |
+ } |
+ |
+ base::ProcessHandle process_handle; |
+ base::LaunchOptions option; |
+ if (elevated_install_) { |
+#if defined(OS_WIN) |
+ if (!base::LaunchElevatedProcess(cmdline, option, &process_handle)) |
+ return false; |
+#else |
+ // At this moment, elevated install is supported on Windows platform only. |
+ return false; |
+#endif |
+ } else if (!base::LaunchProcess(cmdline, option, &process_handle)) { |
+ return false; |
+ } |
+ |
+ installer_exit_code_ = 0; |
+ const base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(300); |
+ if (!base::WaitForExitCodeWithTimeout(process_handle, |
+ &installer_exit_code_, |
+ kMaxWaitTime)) { |
+ // Ensure that the process terminates. |
+ base::KillProcess(process_handle, -1, true); |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+bool RecoveryComponentInstaller::IsElevatedInstallNeeded() const { |
+ return prefs_ && !elevated_install_ && |
+ installer_exit_code_ == EXIT_CODE_ELEVATION_NEEDED; |
+} |
+ |
+base::FilePath RecoveryComponentInstaller::GetBackupPath() const { |
+ if (!IsElevatedInstallNeeded()) |
+ return base::FilePath(); |
+ |
+ return GetInstallerBackupPath(current_version_.GetString()); |
+} |
+ |
+void RecoveryComponentInstaller::InstallExternally() { |
+ // Set a flag in the preference so UpgradeDetector can detect and notify user |
+ // about the elevation request. If user permits, elevated install will be |
+ // triggered by the UI. |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&RecoveryUpdateElevationHelper, true, prefs_)); |
+} |
+ |
+bool RecoveryComponentInstaller::GetInstalledFile( |
+ const std::string& file, |
+ base::FilePath* installed_file) { |
+ return false; |
+} |
+ |
+ElevatedInstallLauncher::ElevatedInstallLauncher() { |
+ blocking_task_runner_ = BrowserThread::GetBlockingPool()-> |
+ GetSequencedTaskRunnerWithShutdownBehavior( |
+ BrowserThread::GetBlockingPool()->GetSequenceToken(), |
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
+} |
+ |
+ElevatedInstallLauncher* ElevatedInstallLauncher::GetInstance() { |
+ return Singleton<ElevatedInstallLauncher>::get(); |
+} |
+ |
+void ElevatedInstallLauncher::Launch(PrefService* prefs, |
+ bool elevation_allowed, |
+ const base::Closure& callback) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ // Reset the flag regardless of the install result. If later we want to |
+ // retry failed install, we should postpone setting this flag until |
+ // install completes. |
+ BrowserThread::PostTaskAndReply(BrowserThread::UI, FROM_HERE, |
+ base::Bind(&RecoveryUpdateElevationHelper, false, prefs), |
+ callback); |
+ |
+ blocking_task_runner_->PostTask(FROM_HERE, |
+ base::Bind(&ElevatedInstallLauncher::RunInstaller, |
+ prefs, prefs->GetString(prefs::kRecoveryComponentVersion), |
+ elevation_allowed)); |
+} |
+ |
+void ElevatedInstallLauncher::RunInstaller(PrefService* prefs, |
+ const std::string& version, |
+ bool elevation_allowed) { |
+ if (!elevation_allowed) { |
+ base::DeleteFile(GetInstallerBackupPath(version), true); |
+ return; |
+ } |
+ |
+ base::FilePath chrome_exe; |
+ if (!PathService::Get(base::FILE_EXE, &chrome_exe)) |
+ return; |
+ |
+ CommandLine cmdline(chrome_exe); |
+ cmdline.AppendSwitchASCII(switches::kInstallRecoveryComponent, version); |
+#if defined(OS_WIN) |
+ base::LaunchOptions option; |
+ option.start_hidden = true; |
+ base::LaunchElevatedProcess(cmdline, option, NULL); |
+#else |
+ // Currently elevated install is supported only on Windows platform. |
+ return; |
+#endif |
+} |
+ |
+ElevatedRecoveryInstaller* ElevatedRecoveryInstaller::GetInstance() { |
+ return Singleton<ElevatedRecoveryInstaller>::get(); |
+} |
+ |
+ElevatedRecoveryInstaller::ElevatedRecoveryInstaller() |
+ : install_complete_event_(false, false) { |
+ blocking_task_runner_ = BrowserThread::GetBlockingPool()-> |
+ GetSequencedTaskRunnerWithShutdownBehavior( |
+ BrowserThread::GetBlockingPool()->GetSequenceToken(), |
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
+} |
+ |
+void ElevatedRecoveryInstaller::Install(const std::string& version) { |
+ blocking_task_runner_->PostTask(FROM_HERE, |
+ base::Bind(&ElevatedRecoveryInstaller::DoInstall, |
+ base::Unretained(this), |
+ version)); |
+} |
+ |
+bool ElevatedRecoveryInstaller::PrepareInstall(const std::string& version_str) { |
+ Version version(version_str); |
+ if (!version.IsValid()) |
+ return false; |
+ |
+ // Move CRX and related files to a secure location |
+ base::FilePath secure_path; |
+ secure_path = GetSecureRecoveryPath(version_str); |
+ if (secure_path.empty()) |
+ return false; |
+ if (base::PathExists(secure_path) && !base::DeleteFile(secure_path, true)) |
+ return false; |
+ if (!base::Move(GetInstallerBackupPath(version_str), secure_path)) { |
+ DVLOG(1) << "Failed to move recovery component CRX to secure location."; |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+void ElevatedRecoveryInstaller::DoInstall(const std::string& version_str) { |
+ if (!PrepareInstall(version_str)) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ |
+ version_ = Version(version_str); |
+ rc_installer_.reset(new RecoveryComponentInstaller(version_, NULL, true)); |
+ |
+ std::vector<uint8> pk_hash; |
+ pk_hash.assign(kSha2Hash, &kSha2Hash[sizeof(kSha2Hash)]); |
+ |
+ base::FilePath path(GetSecureRecoveryPath(version_.GetString())); |
+ unpacker_ = ComponentUnpacker::CreateFromBackup( |
+ path, pk_hash, rc_installer_.get(), |
+ blocking_task_runner_); |
+ |
+ if (unpacker_.get()) { |
+ unpacker_->set_unpack_base_dir(path); |
+ unpacker_->Unpack(base::Bind(&ElevatedRecoveryInstaller::DoneInstall, |
+ base::Unretained(this))); |
+ } else { |
+ // Unpacker creation failed, skip installation and go directly to cleanup. |
+ PostInstallCleanup(); |
+ } |
+} |
+ |
+void ElevatedRecoveryInstaller::DoneInstall(ComponentUnpacker::Error error, |
+ int extended_error) { |
+ PostInstallCleanup(); |
+} |
+ |
+void ElevatedRecoveryInstaller::PostInstallCleanup() { |
+ base::FilePath secure_path; |
+ secure_path = GetSecureRecoveryPath(version_.GetString()); |
+ if (!secure_path.empty() && base::PathExists(secure_path)) { |
+ base::DeleteFile(secure_path, true); |
+ } |
+ |
+ unpacker_ = NULL; |
+ rc_installer_.reset(); |
+ version_ = Version(); |
+ install_complete_event_.Signal(); |
+} |
+ |
+void ElevatedRecoveryInstaller::WaitForInstallToComplete() { |
+ install_complete_event_.Wait(); |
+} |
+ |
+void RegisterRecoveryComponent(ComponentUpdateService* cus, |
+ PrefService* prefs) { |
+#if !defined(OS_CHROMEOS) |
+ // We delay execute the registration because we are not required in |
+ // the critical path during browser startup. |
+ BrowserThread::PostDelayedTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&RecoveryRegisterHelper, cus, prefs), |
+ base::TimeDelta::FromSeconds(6)); |
+#endif |
+} |
+ |
+void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) { |
+ registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0"); |
+ registry->RegisterBooleanPref(prefs::kRecoveryComponentNeedsElevation, false); |
+} |
+ |
+void StartElevatedRecoveryProcess( |
+ PrefService* prefs, bool elevation_allowed, const base::Closure& callback) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ ElevatedInstallLauncher::GetInstance()->Launch( |
+ prefs, elevation_allowed, callback); |
+} |
+ |
+void InstallRecoveryComponentElevated(const std::string& version) { |
+ ElevatedRecoveryInstaller::GetInstance()->Install(version); |
+ |
+ // Return from this function cause the process to exit. So wait to make sure |
+ // recovery install completes before return. |
+ ElevatedRecoveryInstaller::GetInstance()->WaitForInstallToComplete(); |
+} |
+ |
+} // namespace component_updater |