File: recovery_improved_component_installer_win.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (158 lines) | stat: -rw-r--r-- 5,611 bytes parent folder | download | duplicates (6)
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