1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "build/branding_buildflags.h"
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
#include <windows.h>
#include <wrl/client.h>
#include <tuple>
#include <utility>
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/process/process.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/component_updater/component_updater_utils.h"
#include "chrome/browser/component_updater/recovery_improved_component_installer.h"
#include "chrome/elevation_service/elevation_service_idl.h"
#include "chrome/install_static/install_util.h"
#include "components/version_info/version_info.h"
namespace component_updater {
namespace {
const base::FilePath::CharType kRecoveryFileName[] =
FILE_PATH_LITERAL("ChromeRecovery.exe");
// Returns the Chrome's appid registered with Google Update for updates.
std::string GetBrowserAppId() {
return base::WideToUTF8(install_static::GetAppGuid());
}
// Returns the current browser version.
std::string GetBrowserVersion() {
return version_info::GetVersion().GetString();
}
// Instantiates the elevator service, calls its elevator interface, then
// blocks waiting for the recovery processes to exit. Returns the result
// of the recovery as a tuple.
std::tuple<bool, int, int> RunRecoveryCRXElevated(
const base::FilePath& crx_path,
const std::string& browser_appid,
const std::string& browser_version,
const std::string& session_id) {
Microsoft::WRL::ComPtr<IElevator> elevator;
HRESULT hr = CoCreateInstance(
install_static::GetElevatorClsid(), nullptr, CLSCTX_LOCAL_SERVER,
install_static::GetElevatorIid(), IID_PPV_ARGS_Helper(&elevator));
if (FAILED(hr)) {
return {false, static_cast<int>(hr), 0};
}
hr = CoSetProxyBlanket(
elevator.Get(), RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT,
COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_DYNAMIC_CLOAKING);
if (FAILED(hr)) {
return {false, static_cast<int>(hr), 0};
}
ULONG_PTR proc_handle = 0;
hr = elevator->RunRecoveryCRXElevated(
crx_path.value().c_str(), base::UTF8ToWide(browser_appid).c_str(),
base::UTF8ToWide(browser_version).c_str(),
base::UTF8ToWide(session_id).c_str(), base::Process::Current().Pid(),
&proc_handle);
if (FAILED(hr)) {
return {false, static_cast<int>(hr), 0};
}
int exit_code = 0;
const base::TimeDelta kMaxWaitTime = base::Seconds(600);
base::Process process(reinterpret_cast<base::ProcessHandle>(proc_handle));
const bool succeeded =
process.WaitForExitWithTimeout(kMaxWaitTime, &exit_code);
return {succeeded, exit_code, 0};
}
// Handles the |run| action for the recovery component for Windows.
class RecoveryComponentActionHandlerWin
: public RecoveryComponentActionHandler {
public:
RecoveryComponentActionHandlerWin() = default;
RecoveryComponentActionHandlerWin(const RecoveryComponentActionHandlerWin&) =
delete;
RecoveryComponentActionHandlerWin& operator=(
const RecoveryComponentActionHandlerWin&) = delete;
private:
~RecoveryComponentActionHandlerWin() override = default;
// Overrides for RecoveryComponentActionHandler.
base::CommandLine MakeCommandLine(
const base::FilePath& unpack_path) const override;
void PrepareFiles(const base::FilePath& unpack_path) const override;
void Elevate(Callback callback) override;
// Calls the elevator service to handle the CRX. Since the invocation of
// the elevator service consists of several Windows COM IPC calls, a
// certain type of task runner is necessary to initialize a COM apartment.
void RunElevatedInSTA(Callback callback);
};
base::CommandLine RecoveryComponentActionHandlerWin::MakeCommandLine(
const base::FilePath& unpack_path) const {
base::CommandLine command_line(unpack_path.Append(kRecoveryFileName));
command_line.AppendSwitchASCII("browser-version", GetBrowserVersion());
command_line.AppendSwitchASCII("sessionid", session_id());
const auto app_guid = GetBrowserAppId();
if (!app_guid.empty()) {
command_line.AppendSwitchASCII("appguid", app_guid);
}
return command_line;
}
void RecoveryComponentActionHandlerWin::PrepareFiles(
const base::FilePath& unpack_path) const {
// Nothing to do.
}
void RecoveryComponentActionHandlerWin::Elevate(Callback callback) {
base::ThreadPool::CreateCOMSTATaskRunner(
kThreadPoolTaskTraitsRunCommand,
base::SingleThreadTaskRunnerThreadMode::DEDICATED)
->PostTask(
FROM_HERE,
base::BindOnce(&RecoveryComponentActionHandlerWin::RunElevatedInSTA,
this, std::move(callback)));
}
void RecoveryComponentActionHandlerWin::RunElevatedInSTA(Callback callback) {
auto [succeeded, error_code, extra_code] = RunRecoveryCRXElevated(
crx_path(), GetBrowserAppId(), GetBrowserVersion(), session_id());
main_task_runner()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), succeeded, error_code, extra_code));
}
} // namespace
scoped_refptr<update_client::ActionHandler>
RecoveryComponentActionHandler::MakeActionHandler() {
return base::MakeRefCounted<RecoveryComponentActionHandlerWin>();
}
} // namespace component_updater
#endif // GOOGLE_CHROME_BRANDING
|