blob: 230a549532332846d03d34d76033549a4a754f5a [file] [log] [blame]
// Copyright (c) 2017 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_RECOVERY_IMPROVED_COMPONENT_INSTALLER_H_
#define CHROME_BROWSER_COMPONENT_UPDATER_RECOVERY_IMPROVED_COMPONENT_INSTALLER_H_
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/task/task_traits.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/component_updater/component_installer.h"
#include "components/crx_file/crx_verifier.h"
#include "components/update_client/component_unpacker.h"
#include "components/update_client/update_client.h"
namespace base {
class CommandLine;
class Process;
} // namespace base
class PrefService;
namespace component_updater {
// Handles the |run| action for the recovery component.
//
// The recovery component consists of a executable program (the name of the
// program is known at build time but it depends on the operating system),
// wrapped inside a CRX container, which CRX is itself contained inside a
// component updater CRX payload. In other words, looking from outside, the
// component updater installs and updates a CRX, containing a CRX, containing
// a program. When this program is run, it can restore the functionality of
// the Chrome updater.
// The |RecoveryComponentActionHandler| is responsible for unpacking the inner
// CRX described above, and running the executable program inside it.
//
// The |RecoveryComponentActionHandler::Handle| function is invoked as a result
// of an |action| element present in the update response for the recovery
// component. Note that the |action| element can be present in the update
// response even if there are no updates for the recovery component.
//
// When Chrome is installed per-system, the CRX is being handed over to
// a system elevator, which unpacks the CRX in a secure location of the
// file system, and runs the recovery program with system privileges.
//
// When Chrome is installed per-user, the CRX is unpacked in a temporary
// directory for the user, and the recovery program runs with normal user
// privileges.
class RecoveryComponentActionHandler : public update_client::ActionHandler {
public:
static scoped_refptr<update_client::ActionHandler> MakeActionHandler();
// Overrides for update_client::RecoveryComponentActionHandler. |action| is an
// absolute file path to a CRX to be unpacked. |session_id| contains the
// session id corresponding to the current update transaction. The session id
// is passed as a command line argument to the recovery program, and sent as
// part of the completion pings during the actual recovery.
void Handle(const base::FilePath& action,
const std::string& session_id,
Callback callback) override;
protected:
static constexpr base::TaskTraits kThreadPoolTaskTraits = {
base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
// This task joins a process, hence .WithBaseSyncPrimitives().
static constexpr base::TaskTraits kThreadPoolTaskTraitsRunCommand = {
base::MayBlock(), base::WithBaseSyncPrimitives(),
base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
// Accepts only the production key hash and the production proof by default.
RecoveryComponentActionHandler(
const std::vector<uint8_t>& key_hash = {std::begin(kKeyHash),
std::end(kKeyHash)},
crx_file::VerifierFormat verifier_format =
crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF);
~RecoveryComponentActionHandler() override;
base::FilePath crx_path() const { return crx_path_; }
std::string session_id() const { return session_id_; }
scoped_refptr<base::SequencedTaskRunner> main_task_runner() {
return main_task_runner_;
}
private:
// The production public key hash for the inner CRX.
static constexpr uint8_t kKeyHash[] = {
0x5f, 0x94, 0xe0, 0x3c, 0x64, 0x30, 0x9f, 0xbc, 0xfe, 0x00, 0x9a,
0x27, 0x3e, 0x52, 0xbf, 0xa5, 0x84, 0xb9, 0xb3, 0x75, 0x07, 0x29,
0xde, 0xfa, 0x32, 0x76, 0xd9, 0x93, 0xb5, 0xa3, 0xce, 0x02};
virtual base::CommandLine MakeCommandLine(
const base::FilePath& unpack_path) const = 0;
virtual void Elevate(Callback callback) = 0;
void Unpack();
void UnpackComplete(const update_client::ComponentUnpacker::Result& result);
void RunCommand(const base::CommandLine& cmdline);
void WaitForCommand(base::Process process);
SEQUENCE_CHECKER(sequence_checker_);
// Executes tasks in the context of the sequence which created this object.
scoped_refptr<base::SequencedTaskRunner> main_task_runner_ =
base::SequencedTaskRunnerHandle::Get();
// The key hash and its proof for the inner CRX to be unpacked and run.
const std::vector<uint8_t> key_hash_;
const crx_file::VerifierFormat verifier_format_;
// Contains the CRX specified as a run action.
base::FilePath crx_path_;
// The session id of the update transaction, as defined by |update_client|.
std::string session_id_;
// Called when the action is handled.
Callback callback_;
// Contains the path where the action CRX is unpacked in the per-user case.
base::FilePath unpack_path_;
RecoveryComponentActionHandler(const RecoveryComponentActionHandler&) =
delete;
RecoveryComponentActionHandler& operator=(
const RecoveryComponentActionHandler&) = delete;
};
class ComponentUpdateService;
class RecoveryImprovedInstallerPolicy : public ComponentInstallerPolicy {
public:
explicit RecoveryImprovedInstallerPolicy(PrefService* prefs)
: prefs_(prefs) {}
~RecoveryImprovedInstallerPolicy() override = default;
private:
friend class RecoveryImprovedInstallerTest;
// ComponentInstallerPolicy implementation.
bool SupportsGroupPolicyEnabledComponentUpdates() const override;
bool RequiresNetworkEncryption() const override;
update_client::CrxInstaller::Result OnCustomInstall(
const base::DictionaryValue& manifest,
const base::FilePath& install_dir) override;
void OnCustomUninstall() override;
bool VerifyInstallation(const base::DictionaryValue& manifest,
const base::FilePath& install_dir) const override;
void ComponentReady(const base::Version& version,
const base::FilePath& install_dir,
std::unique_ptr<base::DictionaryValue> manifest) override;
base::FilePath GetRelativeInstallDir() const override;
void GetHash(std::vector<uint8_t>* hash) const override;
std::string GetName() const override;
update_client::InstallerAttributes GetInstallerAttributes() const override;
PrefService* prefs_;
RecoveryImprovedInstallerPolicy(const RecoveryImprovedInstallerPolicy&) =
delete;
RecoveryImprovedInstallerPolicy& operator=(
const RecoveryImprovedInstallerPolicy&) = delete;
};
void RegisterRecoveryImprovedComponent(ComponentUpdateService* cus,
PrefService* prefs);
} // namespace component_updater
#endif // CHROME_BROWSER_COMPONENT_UPDATER_RECOVERY_IMPROVED_COMPONENT_INSTALLER_H_