recovery_component_installer.cc revision 116680a4aac90f2aa7413d9095a592090648e557
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/component_updater/recovery_component_installer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <string>
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
19bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/component_updater/component_updater_service.h"
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/component_updater/component_updater_paths.h"
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/component_updater/pref_names.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace component_updater {
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CRX hash. The extension id is: npdjjkjlcidkjlamlmmdelcjbcpdjocm.
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const uint8 kSha2Hash[] = {0xdf, 0x39, 0x9a, 0x9b, 0x28, 0x3a, 0x9b, 0x0c,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0xbc, 0xc3, 0x4b, 0x29, 0x12, 0xf3, 0x9e, 0x2c,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0x19, 0x7a, 0x71, 0x4b, 0x0a, 0x7c, 0x80, 0x1c,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0xf6, 0x29, 0x7c, 0x0a, 0x5f, 0xea, 0x67, 0xb7};
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// File name of the recovery binary on different platforms.
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kRecoveryFileName[] =
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE_PATH_LITERAL("ChromeRecovery.exe");
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // OS_LINUX, OS_MACOSX, etc.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE_PATH_LITERAL("ChromeRecovery");
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRecoveryManifestName[] = "ChromeRecovery";
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RecoveryComponentInstaller : public ComponentInstaller {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit RecoveryComponentInstaller(const Version& version,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      PrefService* prefs);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~RecoveryComponentInstaller() {}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnUpdateError(int error) OVERRIDE;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool Install(const base::DictionaryValue& manifest,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const base::FilePath& unpack_path) OVERRIDE;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual bool GetInstalledFile(const std::string& file,
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                base::FilePath* installed_file) OVERRIDE;
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Version current_version_;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* prefs_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void RecoveryRegisterHelper(ComponentUpdateService* cus, PrefService* prefs) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Version version(prefs->GetString(prefs::kRecoveryComponentVersion));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!version.IsValid()) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrxComponent recovery;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recovery.name = "recovery";
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recovery.installer = new RecoveryComponentInstaller(version, prefs);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recovery.version = version;
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  recovery.pk_hash.assign(kSha2Hash, &kSha2Hash[sizeof(kSha2Hash)]);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cus->RegisterComponent(recovery) != ComponentUpdateService::kOk) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED() << "Recovery component registration failed.";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecoveryUpdateVersionHelper(const Version& version, PrefService* prefs) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kRecoveryComponentVersion, version.GetString());
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)RecoveryComponentInstaller::RecoveryComponentInstaller(const Version& version,
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                       PrefService* prefs)
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : current_version_(version), prefs_(prefs) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(version.IsValid());
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecoveryComponentInstaller::OnUpdateError(int error) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Recovery component update error: " << error;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest,
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         const base::FilePath& unpack_path) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  manifest.GetStringASCII("name", &name);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (name != kRecoveryManifestName)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string proposed_version;
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  manifest.GetStringASCII("version", &proposed_version);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Version version(proposed_version.c_str());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!version.IsValid())
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_version_.CompareTo(version) >= 0)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Passed the basic tests. Copy the installation to a permanent directory.
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::FilePath path;
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!PathService::Get(DIR_RECOVERY_BASE, &path))
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  path = path.AppendASCII(version.GetString());
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (base::PathExists(path) && !base::DeleteFile(path, true))
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!base::Move(unpack_path, path)) {
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(1) << "Recovery component move failed.";
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::FilePath main_file = path.Append(kRecoveryFileName);
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::PathExists(main_file))
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Run the recovery component.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine cmdline(main_file);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string arguments;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (manifest.GetStringASCII("x-recovery-args", &arguments))
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cmdline.AppendArg(arguments);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string add_version;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (manifest.GetStringASCII("x-recovery-add-version", &add_version)) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (add_version == "yes")
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cmdline.AppendSwitchASCII("version", current_version_.GetString());
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_version_ = version;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prefs_) {
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    BrowserThread::PostTask(
146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        BrowserThread::UI,
147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        FROM_HERE,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&RecoveryUpdateVersionHelper, version, prefs_));
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::LaunchProcess(cmdline, base::LaunchOptions(), NULL);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool RecoveryComponentInstaller::GetInstalledFile(
154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const std::string& file,
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::FilePath* installed_file) {
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RegisterRecoveryComponent(ComponentUpdateService* cus,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               PrefService* prefs) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_CHROMEOS)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We delay execute the registration because we are not required in
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the critical path during browser startup.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostDelayedTask(
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::UI,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&RecoveryRegisterHelper, cus, prefs),
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::TimeDelta::FromSeconds(6));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0");
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace component_updater
177