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) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <stdint.h> 8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <string> 9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 20bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/component_updater/component_updater_paths.h" 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/component_updater/component_updater_service.h" 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/component_updater/pref_names.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace component_updater { 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CRX hash. The extension id is: npdjjkjlcidkjlamlmmdelcjbcpdjocm. 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst uint8_t kSha2Hash[] = {0xdf, 0x39, 0x9a, 0x9b, 0x28, 0x3a, 0x9b, 0x0c, 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0xbc, 0xc3, 0x4b, 0x29, 0x12, 0xf3, 0x9e, 0x2c, 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0x19, 0x7a, 0x71, 0x4b, 0x0a, 0x7c, 0x80, 0x1c, 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0xf6, 0x29, 0x7c, 0x0a, 0x5f, 0xea, 0x67, 0xb7}; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// File name of the recovery binary on different platforms. 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kRecoveryFileName[] = 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_PATH_LITERAL("ChromeRecovery.exe"); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // OS_LINUX, OS_MACOSX, etc. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_PATH_LITERAL("ChromeRecovery"); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRecoveryManifestName[] = "ChromeRecovery"; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RecoveryComponentInstaller : public ComponentInstaller { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit RecoveryComponentInstaller(const Version& version, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* prefs); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~RecoveryComponentInstaller() {} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnUpdateError(int error) OVERRIDE; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual bool Install(const base::DictionaryValue& manifest, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& unpack_path) OVERRIDE; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual bool GetInstalledFile(const std::string& file, 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath* installed_file) OVERRIDE; 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version current_version_; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* prefs_; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void RecoveryRegisterHelper(ComponentUpdateService* cus, PrefService* prefs) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version version(prefs->GetString(prefs::kRecoveryComponentVersion)); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!version.IsValid()) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CrxComponent recovery; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recovery.name = "recovery"; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recovery.installer = new RecoveryComponentInstaller(version, prefs); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recovery.version = version; 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) recovery.pk_hash.assign(kSha2Hash, &kSha2Hash[sizeof(kSha2Hash)]); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cus->RegisterComponent(recovery) != ComponentUpdateService::kOk) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Recovery component registration failed."; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecoveryUpdateVersionHelper(const Version& version, PrefService* prefs) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->SetString(prefs::kRecoveryComponentVersion, version.GetString()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)RecoveryComponentInstaller::RecoveryComponentInstaller(const Version& version, 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) PrefService* prefs) 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : current_version_(version), prefs_(prefs) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(version.IsValid()); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecoveryComponentInstaller::OnUpdateError(int error) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Recovery component update error: " << error; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool RecoveryComponentInstaller::Install(const base::DictionaryValue& manifest, 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& unpack_path) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name; 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) manifest.GetStringASCII("name", &name); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name != kRecoveryManifestName) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string proposed_version; 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) manifest.GetStringASCII("version", &proposed_version); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version version(proposed_version.c_str()); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!version.IsValid()) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_version_.CompareTo(version) >= 0) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Passed the basic tests. Copy the installation to a permanent directory. 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath path; 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!PathService::Get(DIR_RECOVERY_BASE, &path)) 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 123e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch if (!base::PathExists(path)) { 124e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch if (!base::CreateDirectory(path)) { 125e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch return false; 126e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch } 127e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch } 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) path = path.AppendASCII(version.GetString()); 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (base::PathExists(path) && !base::DeleteFile(path, true)) 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!base::Move(unpack_path, path)) { 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DVLOG(1) << "Recovery component move failed."; 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath main_file = path.Append(kRecoveryFileName); 1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(main_file)) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Run the recovery component. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine cmdline(main_file); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string arguments; 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (manifest.GetStringASCII("x-recovery-args", &arguments)) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmdline.AppendArg(arguments); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string add_version; 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (manifest.GetStringASCII("x-recovery-add-version", &add_version)) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (add_version == "yes") 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmdline.AppendSwitchASCII("version", current_version_.GetString()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_version_ = version; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prefs_) { 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) BrowserThread::PostTask( 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) BrowserThread::UI, 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) FROM_HERE, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&RecoveryUpdateVersionHelper, version, prefs_)); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::LaunchProcess(cmdline, base::LaunchOptions(), NULL); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool RecoveryComponentInstaller::GetInstalledFile( 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const std::string& file, 161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::FilePath* installed_file) { 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return false; 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RegisterRecoveryComponent(ComponentUpdateService* cus, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* prefs) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_CHROMEOS) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We delay execute the registration because we are not required in 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the critical path during browser startup. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostDelayedTask( 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&RecoveryRegisterHelper, cus, prefs), 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(6)); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RegisterPrefsForRecoveryComponent(PrefRegistrySimple* registry) { 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterStringPref(prefs::kRecoveryComponentVersion, "0.0.0.0"); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace component_updater 183