blob: c3b12ea3877ef69808bae2f779629dc2930f3456 [file] [log] [blame]
Avi Drissman4a8573c2022-09-09 19:35:541// Copyright 2012 The Chromium Authors
[email protected]bc38c252011-04-12 21:46:572// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Daniel Cheng7d9e3d52022-02-26 09:03:245#include "chrome/browser/first_run/upgrade_util_win.h"
[email protected]bc38c252011-04-12 21:46:576
Takuto Ikutac8d6b16f2024-04-15 16:59:197#include <objbase.h>
8
[email protected]770c6d82012-09-06 22:21:329#include <windows.h>
Nico Webereaa08412019-08-14 01:24:3710
[email protected]fdbea98d2014-05-16 19:29:2011#include <psapi.h>
[email protected]770c6d82012-09-06 22:21:3212#include <shellapi.h>
Robert Liaob2bc703d2017-10-17 20:52:3513#include <wrl/client.h>
[email protected]770c6d82012-09-06 22:21:3214
[email protected]bc38c252011-04-12 21:46:5715#include <algorithm>
Greg Thompsona1f95122019-01-31 22:46:4516#include <ios>
[email protected]bc38c252011-04-12 21:46:5717#include <string>
18
19#include "base/base_paths.h"
Etienne Bergeron7a0ef612023-09-15 18:28:0820#include "base/check.h"
[email protected]bc38c252011-04-12 21:46:5721#include "base/command_line.h"
[email protected]57999812013-02-24 05:40:5222#include "base/files/file_path.h"
thestig18dfb7a52014-08-26 10:44:0423#include "base/files/file_util.h"
S. Ganeshcad45032024-07-18 17:43:1124#include "base/functional/bind.h"
[email protected]bc38c252011-04-12 21:46:5725#include "base/logging.h"
S. Ganeshcad45032024-07-18 17:43:1126#include "base/memory/ref_counted.h"
27#include "base/memory/scoped_refptr.h"
S. Ganesh48540862024-08-12 18:09:3928#include "base/metrics/histogram_functions.h"
[email protected]bc38c252011-04-12 21:46:5729#include "base/path_service.h"
[email protected]d09a4ce1c2013-07-24 17:37:0230#include "base/process/launch.h"
31#include "base/process/process_handle.h"
[email protected]3ea1b182013-02-08 22:38:4132#include "base/strings/string_number_conversions.h"
[email protected]d8830562013-06-10 22:01:5433#include "base/strings/string_util.h"
S. Ganeshcad45032024-07-18 17:43:1134#include "base/synchronization/waitable_event.h"
S. Ganeshbb1d4fc2024-08-14 19:16:3235#include "base/system/sys_info.h"
S. Ganeshcad45032024-07-18 17:43:1136#include "base/task/sequenced_task_runner.h"
37#include "base/task/task_traits.h"
38#include "base/task/thread_pool.h"
S. Ganesh6822d2a2025-03-31 20:26:4839#include "base/threading/platform_thread.h"
Gabriel Charette12b58ac2021-09-22 18:08:5540#include "base/time/time.h"
S. Ganesh48540862024-08-12 18:09:3941#include "base/timer/elapsed_timer.h"
Gabriel Charette12b58ac2021-09-22 18:08:5542#include "base/trace_event/trace_event.h"
S. Ganesh48540862024-08-12 18:09:3943#include "base/values.h"
[email protected]bc38c252011-04-12 21:46:5744#include "base/win/registry.h"
S. Ganesh6822d2a2025-03-31 20:26:4845#include "base/win/scoped_bstr.h"
46#include "base/win/scoped_variant.h"
[email protected]770c6d82012-09-06 22:21:3247#include "base/win/windows_version.h"
Nico Webereaa08412019-08-14 01:24:3748#include "build/branding_buildflags.h"
ananta069fc882014-09-13 01:22:1249#include "chrome/browser/browser_process.h"
Etienne Bergeron7a0ef612023-09-15 18:28:0850#include "chrome/browser/chrome_process_singleton.h"
Daniel Cheng7d9e3d52022-02-26 09:03:2451#include "chrome/browser/first_run/upgrade_util.h"
[email protected]3f69d6e612012-08-03 18:52:2752#include "chrome/browser/shell_integration.h"
Javier Flores Assad9c26f9b92022-05-21 01:20:4353#include "chrome/browser/win/browser_util.h"
[email protected]80274b92011-07-15 17:20:3854#include "chrome/common/chrome_switches.h"
ananta069fc882014-09-13 01:22:1255#include "chrome/common/pref_names.h"
grt4474dad2017-02-27 21:00:4656#include "chrome/install_static/install_util.h"
S. Ganeshf77e2a52022-11-22 18:40:1957#include "chrome/installer/util/app_command.h"
S. Ganesh48540862024-08-12 18:09:3958#include "chrome/installer/util/per_install_values.h"
[email protected]bc38c252011-04-12 21:46:5759#include "chrome/installer/util/util_constants.h"
brettwb1fc1b82016-02-02 00:19:0860#include "components/prefs/pref_service.h"
S. Ganeshcad45032024-07-18 17:43:1161#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
ananta069fc882014-09-13 01:22:1262#include "ui/base/ui_base_switches.h"
[email protected]bc38c252011-04-12 21:46:5763
Nico Webereaa08412019-08-14 01:24:3764#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
S. Ganesh6adf04c2023-06-07 19:34:5565#include "chrome/updater/app/server/win/updater_legacy_idl.h"
grt235b3f092015-05-27 21:42:4866#endif
67
[email protected]bc38c252011-04-12 21:46:5768namespace {
69
[email protected]650b2d52013-02-10 03:41:4570bool GetNewerChromeFile(base::FilePath* path) {
Avi Drissman9098f9002018-05-04 00:11:5271 if (!base::PathService::Get(base::DIR_EXE, path))
[email protected]bc38c252011-04-12 21:46:5772 return false;
73 *path = path->Append(installer::kChromeNewExe);
74 return true;
75}
76
S. Ganeshcad45032024-07-18 17:43:1177#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
S. Ganesh6822d2a2025-03-31 20:26:4878// Holds the result of the IPC to CoCreate `GoogleUpdate3Web`.
79struct CreateGoogleUpdate3WebResult
80 : public base::RefCountedThreadSafe<CreateGoogleUpdate3WebResult> {
S. Ganeshcad45032024-07-18 17:43:1181 Microsoft::WRL::ComPtr<IStream> stream;
82 base::WaitableEvent completion_event;
83
84 private:
S. Ganesh6822d2a2025-03-31 20:26:4885 friend class base::RefCountedThreadSafe<CreateGoogleUpdate3WebResult>;
86 ~CreateGoogleUpdate3WebResult() = default;
S. Ganeshcad45032024-07-18 17:43:1187};
88
S. Ganesh6822d2a2025-03-31 20:26:4889// CoCreates the `GoogleUpdate3Web` class, and if successful, marshals the
S. Ganeshcad45032024-07-18 17:43:1190// resulting interface into `result->stream`. Signals `result->completion_event`
91// on successful or failed completion.
S. Ganesh6822d2a2025-03-31 20:26:4892void CreateAndMarshalGoogleUpdate3Web(
93 scoped_refptr<CreateGoogleUpdate3WebResult> result) {
S. Ganeshcad45032024-07-18 17:43:1194 const absl::Cleanup signal_completion_event = [&result] {
95 result->completion_event.Signal();
96 };
97
98 Microsoft::WRL::ComPtr<IUnknown> unknown;
99 {
100 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename CoCreateInstance");
101 const HRESULT hr =
S. Ganesh6822d2a2025-03-31 20:26:48102 ::CoCreateInstance(__uuidof(GoogleUpdate3WebSystemClass), nullptr,
103 CLSCTX_ALL, IID_PPV_ARGS(&unknown));
S. Ganeshcad45032024-07-18 17:43:11104 if (FAILED(hr)) {
105 TRACE_EVENT_INSTANT1(
106 "startup", "InvokeGoogleUpdateForRename CoCreateInstance failed",
107 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
S. Ganesh6822d2a2025-03-31 20:26:48108 LOG(ERROR) << "CoCreate GoogleUpdate3WebSystemClass failed; hr = "
109 << std::hex << hr;
S. Ganeshcad45032024-07-18 17:43:11110 return;
111 }
112 }
S. Ganeshcad45032024-07-18 17:43:11113 const HRESULT hr = ::CoMarshalInterThreadInterfaceInStream(
114 __uuidof(IUnknown), unknown.Get(), &result->stream);
115 if (FAILED(hr)) {
116 TRACE_EVENT_INSTANT1("startup",
117 "InvokeGoogleUpdateForRename "
118 "CoMarshalInterThreadInterfaceInStream failed",
119 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
120 LOG(ERROR) << "CoMarshalInterThreadInterfaceInStream "
S. Ganesh6822d2a2025-03-31 20:26:48121 "GoogleUpdate3WebSystemClass failed; hr = "
S. Ganeshcad45032024-07-18 17:43:11122 << std::hex << hr;
123 }
124}
125
S. Ganesh6822d2a2025-03-31 20:26:48126// CoCreates the Google Update `GoogleUpdate3WebSystemClass` in a `ThreadPool`
127// thread with a timeout, if the `ThreadPool` is operational. The starting value
128// for the timeout is 15 seconds. If the CoCreate times out, the timeout is
S. Ganesh48540862024-08-12 18:09:39129// increased by 15 seconds at each failed attempt and persisted for the next
130// attempt.
131//
132// If the `ThreadPool` is not operational, the CoCreate is done
S. Ganeshcad45032024-07-18 17:43:11133// without a timeout.
S. Ganesh6822d2a2025-03-31 20:26:48134Microsoft::WRL::ComPtr<IUnknown> CreateGoogleUpdate3Web() {
S. Ganesh48540862024-08-12 18:09:39135 constexpr int kDefaultTimeoutIncrementSeconds = 15;
S. Ganeshbb1d4fc2024-08-14 19:16:32136 constexpr base::TimeDelta kMaxTimeAfterSystemStartup = base::Seconds(150);
S. Ganesh48540862024-08-12 18:09:39137
S. Ganesh6822d2a2025-03-31 20:26:48138 auto result = base::MakeRefCounted<CreateGoogleUpdate3WebResult>();
S. Ganeshcad45032024-07-18 17:43:11139 if (base::ThreadPool::CreateCOMSTATaskRunner(
140 {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
S. Ganesh6822d2a2025-03-31 20:26:48141 ->PostTask(
142 FROM_HERE,
143 base::BindOnce(&CreateAndMarshalGoogleUpdate3Web, result))) {
S. Ganesh48540862024-08-12 18:09:39144 installer::PerInstallValue creation_timeout(
145 L"ProcessLauncherCreationTimeout");
146 const base::TimeDelta timeout = base::Seconds(
147 creation_timeout.Get()
148 .value_or(base::Value(kDefaultTimeoutIncrementSeconds))
149 .GetIfInt()
150 .value_or(kDefaultTimeoutIncrementSeconds));
151 const base::ElapsedTimer timer;
S. Ganeshbb1d4fc2024-08-14 19:16:32152 const bool is_at_startup =
153 base::SysInfo::Uptime() <= kMaxTimeAfterSystemStartup;
S. Ganesh48540862024-08-12 18:09:39154 if (!result->completion_event.TimedWait(timeout)) {
155 base::UmaHistogramMediumTimes(
S. Ganeshbb1d4fc2024-08-14 19:16:32156 is_at_startup
157 ? "Startup.CreateProcessLauncher2.TimedWaitFailedAtStartup"
158 : "Startup.CreateProcessLauncher2.TimedWaitFailed",
159 timer.Elapsed());
S. Ganesh48540862024-08-12 18:09:39160 creation_timeout.Set(base::Value(static_cast<int>(timeout.InSeconds()) +
161 kDefaultTimeoutIncrementSeconds));
S. Ganeshcad45032024-07-18 17:43:11162 TRACE_EVENT_INSTANT0(
163 "startup", "InvokeGoogleUpdateForRename CoCreateInstance timed out",
164 TRACE_EVENT_SCOPE_THREAD);
S. Ganesh6822d2a2025-03-31 20:26:48165 LOG(ERROR) << "CoCreate GoogleUpdate3WebSystemClass timed out";
S. Ganeshcad45032024-07-18 17:43:11166 return {};
167 }
168
169 if (!result->stream) {
170 return {};
171 }
S. Ganesh48540862024-08-12 18:09:39172 base::UmaHistogramMediumTimes(
S. Ganeshbb1d4fc2024-08-14 19:16:32173 is_at_startup
174 ? "Startup.CreateProcessLauncher2.TimedWaitSucceededAtStartup"
175 : "Startup.CreateProcessLauncher2.TimedWaitSucceeded",
176 timer.Elapsed());
S. Ganeshcad45032024-07-18 17:43:11177
178 Microsoft::WRL::ComPtr<IUnknown> unknown;
179 const HRESULT hr =
180 ::CoUnmarshalInterface(result->stream.Get(), __uuidof(IUnknown),
181 IID_PPV_ARGS_Helper(&unknown));
182 if (FAILED(hr)) {
183 TRACE_EVENT_INSTANT1(
184 "startup", "InvokeGoogleUpdateForRename CoUnmarshalInterface failed",
185 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
S. Ganesh6822d2a2025-03-31 20:26:48186 LOG(ERROR)
187 << "CoUnmarshalInterface GoogleUpdate3WebSystemClass failed; hr = "
188 << std::hex << hr;
S. Ganeshcad45032024-07-18 17:43:11189 return {};
190 }
191
192 return unknown;
193 }
194
195 // The task could not be posted to the task runner, so CoCreate without a
196 // timeout. This could happen in shutdown, where the `ThreadPool` is not
197 // operational.
198 {
199 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename CoCreateInstance");
200 Microsoft::WRL::ComPtr<IUnknown> unknown;
201 const HRESULT hr =
S. Ganesh6822d2a2025-03-31 20:26:48202 ::CoCreateInstance(__uuidof(GoogleUpdate3WebSystemClass), nullptr,
203 CLSCTX_ALL, IID_PPV_ARGS(&unknown));
S. Ganeshcad45032024-07-18 17:43:11204 if (FAILED(hr)) {
205 TRACE_EVENT_INSTANT1(
206 "startup", "InvokeGoogleUpdateForRename CoCreateInstance failed",
207 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
S. Ganesh6822d2a2025-03-31 20:26:48208 LOG(ERROR) << "CoCreate GoogleUpdate3WebSystemClass failed; hr = "
209 << std::hex << hr;
S. Ganeshcad45032024-07-18 17:43:11210 return {};
211 }
212
213 return unknown;
214 }
215}
216#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
217
[email protected]bc38c252011-04-12 21:46:57218bool InvokeGoogleUpdateForRename() {
Nico Webereaa08412019-08-14 01:24:37219#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
Gabriel Charettef7e85712021-12-10 20:46:22220 // This has been identified as very slow on some startups. Detailed trace
221 // events below try to shine a light on each steps. crbug.com/1252004
Gabriel Charette12b58ac2021-09-22 18:08:55222 TRACE_EVENT0("startup", "upgrade_util::InvokeGoogleUpdateForRename");
223
S. Ganesh6822d2a2025-03-31 20:26:48224 Microsoft::WRL::ComPtr<IUnknown> unknown = CreateGoogleUpdate3Web();
S. Ganeshcad45032024-07-18 17:43:11225 if (!unknown) {
226 return false;
227 }
228
S. Ganeshea7ef0872024-03-21 16:28:32229 // Chrome queries for the SxS IIDs first, with a fallback to the legacy IID,
230 // to make sure that marshaling loads the proxy/stub from the correct (HKLM)
231 // hive.
S. Ganesh6822d2a2025-03-31 20:26:48232 Microsoft::WRL::ComPtr<IGoogleUpdate3Web> update3web;
233 if (HRESULT hr = unknown.CopyTo(__uuidof(IGoogleUpdate3WebSystem),
234 IID_PPV_ARGS_Helper(&update3web));
235 FAILED(hr)) {
236 hr = unknown.As(&update3web);
S. Ganeshea7ef0872024-03-21 16:28:32237 if (FAILED(hr)) {
S. Ganesh6822d2a2025-03-31 20:26:48238 TRACE_EVENT_INSTANT1(
239 "startup", "InvokeGoogleUpdateForRename QI IGoogleUpdate3Web failed",
240 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
241 LOG(ERROR) << "QI IGoogleUpdate3Web failed; hr = " << std::hex << hr;
S. Ganeshea7ef0872024-03-21 16:28:32242 return false;
243 }
[email protected]bc38c252011-04-12 21:46:57244 }
Greg Thompsona1f95122019-01-31 22:46:45245
S. Ganesh6822d2a2025-03-31 20:26:48246 Microsoft::WRL::ComPtr<IAppBundleWeb> bundle;
Gabriel Charettef7e85712021-12-10 20:46:22247 {
S. Ganesh6822d2a2025-03-31 20:26:48248 Microsoft::WRL::ComPtr<IDispatch> dispatch;
249 if (HRESULT hr = update3web->createAppBundleWeb(&dispatch); FAILED(hr)) {
250 TRACE_EVENT_INSTANT1(
251 "startup", "InvokeGoogleUpdateForRename createAppBundleWeb failed",
252 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
253 LOG(ERROR) << "createAppBundleWeb failed; hr = " << std::hex << hr;
254 return false;
255 }
256
257 if (HRESULT hr = dispatch.CopyTo(__uuidof(IAppBundleWebSystem),
258 IID_PPV_ARGS_Helper(&bundle));
259 FAILED(hr)) {
260 hr = dispatch.As(&bundle);
261 if (FAILED(hr)) {
262 TRACE_EVENT_INSTANT1(
263 "startup", "InvokeGoogleUpdateForRename QI IAppBundleWeb failed",
264 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
265 LOG(ERROR) << "QI IAppBundleWeb failed; hr = " << std::hex << hr;
266 return false;
267 }
268 }
269 }
270
271 if (HRESULT hr = bundle->initialize(); FAILED(hr)) {
272 TRACE_EVENT_INSTANT1(
273 "startup", "InvokeGoogleUpdateForRename bundle->initialize failed",
274 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
275 LOG(ERROR) << "bundle->initialize failed; hr = " << std::hex << hr;
276 return false;
277 }
278
279 if (HRESULT hr = bundle->createInstalledApp(
280 base::win::ScopedBstr(install_static::GetAppGuid()).Get());
281 FAILED(hr)) {
282 TRACE_EVENT_INSTANT1(
283 "startup",
284 "InvokeGoogleUpdateForRename bundle->createInstalledApp failed",
285 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
286 LOG(ERROR) << "bundle->createInstalledApp failed; hr = " << std::hex << hr;
287 return false;
288 }
289
290 Microsoft::WRL::ComPtr<IAppWeb> app;
291 {
292 Microsoft::WRL::ComPtr<IDispatch> app_dispatch;
293 if (HRESULT hr = bundle->get_appWeb(0, &app_dispatch); FAILED(hr)) {
294 TRACE_EVENT_INSTANT1(
295 "startup", "InvokeGoogleUpdateForRename bundle->get_appWeb failed",
296 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
297 LOG(ERROR) << "bundle->get_appWeb failed; hr = " << std::hex << hr;
298 return false;
299 }
300
301 if (HRESULT hr = app_dispatch.CopyTo(__uuidof(IAppWebSystem),
302 IID_PPV_ARGS_Helper(&app));
303 FAILED(hr)) {
304 hr = app_dispatch.As(&app);
305 if (FAILED(hr)) {
306 TRACE_EVENT_INSTANT1("startup",
307 "InvokeGoogleUpdateForRename QI IAppWeb failed",
308 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
309 LOG(ERROR) << "QI IAppWeb failed; hr = " << std::hex << hr;
310 return false;
311 }
312 }
313 }
314
315 Microsoft::WRL::ComPtr<IAppCommandWeb> app_command_web;
316 {
317 Microsoft::WRL::ComPtr<IDispatch> command_dispatch;
318 if (HRESULT hr = app->get_command(
319 base::win::ScopedBstr(installer::kCmdRenameChromeExe).Get(),
320 &command_dispatch);
321 FAILED(hr)) {
322 TRACE_EVENT_INSTANT1(
323 "startup", "InvokeGoogleUpdateForRename app->get_command failed",
324 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
325 LOG(ERROR) << "app->get_command failed; hr = " << std::hex << hr;
326 return false;
327 }
328
329 if (HRESULT hr =
330 command_dispatch.CopyTo(__uuidof(IAppCommandWebSystem),
331 IID_PPV_ARGS_Helper(&app_command_web));
332 FAILED(hr)) {
333 hr = command_dispatch.As(&app_command_web);
334 if (FAILED(hr)) {
335 TRACE_EVENT_INSTANT1(
336 "startup", "InvokeGoogleUpdateForRename QI IAppCommandWeb failed",
337 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
338 LOG(ERROR) << "QI IAppCommandWeb failed; hr = " << std::hex << hr;
339 return false;
340 }
341 }
342 }
343
344 {
345 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename execute");
346 if (HRESULT hr =
347 app_command_web->execute(base::win::ScopedVariant::kEmptyVariant,
348 base::win::ScopedVariant::kEmptyVariant,
349 base::win::ScopedVariant::kEmptyVariant,
350 base::win::ScopedVariant::kEmptyVariant,
351 base::win::ScopedVariant::kEmptyVariant,
352 base::win::ScopedVariant::kEmptyVariant,
353 base::win::ScopedVariant::kEmptyVariant,
354 base::win::ScopedVariant::kEmptyVariant,
355 base::win::ScopedVariant::kEmptyVariant);
356 FAILED(hr)) {
357 TRACE_EVENT_INSTANT1(
358 "startup",
359 "InvokeGoogleUpdateForRename app_command_web->execute failed",
360 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
361 LOG(ERROR) << "app_command_web->execute failed; hr = " << std::hex << hr;
Gabriel Charettef7e85712021-12-10 20:46:22362 return false;
363 }
Greg Thompsona1f95122019-01-31 22:46:45364
S. Ganesh6822d2a2025-03-31 20:26:48365 UINT status = 0;
366 for (const auto deadline = base::TimeTicks::Now() + base::Seconds(60);
367 base::TimeTicks::Now() < deadline;
368 base::PlatformThread::Sleep(base::Seconds(1))) {
369 if (HRESULT hr = app_command_web->get_status(&status); FAILED(hr)) {
370 TRACE_EVENT_INSTANT1(
371 "startup",
372 "InvokeGoogleUpdateForRename app_command_web->get_status failed",
373 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
374 LOG(ERROR) << "app_command_web->get_status failed; hr = " << std::hex
375 << hr;
376 return false;
377 }
378 if (status == COMMAND_STATUS_COMPLETE) {
379 break;
380 }
381 }
382 if (status != COMMAND_STATUS_COMPLETE) {
383 TRACE_EVENT_INSTANT1(
384 "startup", "InvokeGoogleUpdateForRename !COMMAND_STATUS_COMPLETE",
385 TRACE_EVENT_SCOPE_THREAD, "status", status);
386 LOG(ERROR) << "AppCommand timed out with status code " << status;
Gabriel Charettef7e85712021-12-10 20:46:22387 return false;
388 }
Greg Thompsona1f95122019-01-31 22:46:45389 }
390
S. Ganesh6822d2a2025-03-31 20:26:48391 DWORD exit_code = 0;
392 if (HRESULT hr = app_command_web->get_exitCode(&exit_code); FAILED(hr)) {
393 TRACE_EVENT_INSTANT1(
394 "startup",
395 "InvokeGoogleUpdateForRename app_command_web->get_exitCode failed",
396 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
397 LOG(ERROR) << "app_command_web->get_exitCode failed; hr = " << std::hex
398 << hr;
399 return false;
400 }
401
Greg Thompsona1f95122019-01-31 22:46:45402 if (exit_code != installer::RENAME_SUCCESSFUL) {
S. Ganesh6822d2a2025-03-31 20:26:48403 TRACE_EVENT_INSTANT1("startup",
404 "InvokeGoogleUpdateForRename !RENAME_SUCCESSFUL",
405 TRACE_EVENT_SCOPE_THREAD, "exit_code", exit_code);
Greg Thompsona1f95122019-01-31 22:46:45406 LOG(ERROR) << "Rename process failed with exit code " << exit_code;
407 return false;
408 }
409
S. Ganesh6822d2a2025-03-31 20:26:48410 TRACE_EVENT_INSTANT0("startup",
411 "InvokeGoogleUpdateForRename RENAME_SUCCESSFUL",
412 TRACE_EVENT_SCOPE_THREAD);
Gabriel Charette334775a2021-12-13 18:57:26413
Greg Thompsona1f95122019-01-31 22:46:45414 return true;
Nico Webereaa08412019-08-14 01:24:37415#else // BUILDFLAG(GOOGLE_CHROME_BRANDING)
[email protected]bc38c252011-04-12 21:46:57416 return false;
Nico Webereaa08412019-08-14 01:24:37417#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
[email protected]bc38c252011-04-12 21:46:57418}
419
420} // namespace
421
[email protected]815856722011-04-13 17:19:19422namespace upgrade_util {
423
Greg Thompson87ee38f2019-08-09 06:00:23424bool RelaunchChromeBrowserImpl(const base::CommandLine& command_line) {
Gabriel Charette12b58ac2021-09-22 18:08:55425 TRACE_EVENT0("startup", "upgrade_util::RelaunchChromeBrowserImpl");
426
[email protected]650b2d52013-02-10 03:41:45427 base::FilePath chrome_exe;
Avi Drissman9098f9002018-05-04 00:11:52428 if (!base::PathService::Get(base::FILE_EXE, &chrome_exe)) {
Peter Boström9be37efa2024-11-06 23:34:18429 NOTREACHED();
[email protected]3f69d6e612012-08-03 18:52:27430 }
431
[email protected]fdbea98d2014-05-16 19:29:20432 // Explicitly make sure to relaunch chrome.exe rather than old_chrome.exe.
433 // This can happen when old_chrome.exe is launched by a user.
avi556c05022014-12-22 23:31:43434 base::CommandLine chrome_exe_command_line = command_line;
[email protected]fdbea98d2014-05-16 19:29:20435 chrome_exe_command_line.SetProgram(
436 chrome_exe.DirName().Append(installer::kChromeExe));
437
scottmg20920cb2016-04-07 16:23:59438 // Set the working directory to the exe's directory. This avoids a handle to
439 // the version directory being kept open in the relaunched child process.
440 base::LaunchOptions launch_options;
441 launch_options.current_directory = chrome_exe.DirName();
Greg Thompson47faf202018-05-18 20:59:03442 // Give the new process the right to bring its windows to the foreground.
443 launch_options.grant_foreground_privilege = true;
scottmg20920cb2016-04-07 16:23:59444 return base::LaunchProcess(chrome_exe_command_line, launch_options).IsValid();
[email protected]815856722011-04-13 17:19:19445}
446
447bool IsUpdatePendingRestart() {
Gabriel Charette12b58ac2021-09-22 18:08:55448 TRACE_EVENT0("startup", "upgrade_util::IsUpdatePendingRestart");
[email protected]650b2d52013-02-10 03:41:45449 base::FilePath new_chrome_exe;
[email protected]815856722011-04-13 17:19:19450 if (!GetNewerChromeFile(&new_chrome_exe))
451 return false;
[email protected]7567484142013-07-11 17:36:07452 return base::PathExists(new_chrome_exe);
[email protected]815856722011-04-13 17:19:19453}
454
[email protected]815856722011-04-13 17:19:19455bool SwapNewChromeExeIfPresent() {
grtb35a90b2016-08-30 05:34:21456 if (!IsUpdatePendingRestart())
[email protected]bc38c252011-04-12 21:46:57457 return false;
grtb35a90b2016-08-30 05:34:21458
Gabriel Charette12b58ac2021-09-22 18:08:55459 TRACE_EVENT0("startup", "upgrade_util::SwapNewChromeExeIfPresent");
460
Etienne Bergeron7a0ef612023-09-15 18:28:08461 // Renaming the chrome executable requires the process singleton to avoid
462 // any race condition.
463 CHECK(ChromeProcessSingleton::IsSingletonInstance());
464
fdoraye9c97a02016-10-04 12:05:16465 // If this is a system-level install, ask Google Update to launch an elevated
466 // process to rename Chrome executables.
Greg Thompsond2efb1f2018-08-29 06:12:54467 if (install_static::IsSystemInstall())
fdoraye9c97a02016-10-04 12:05:16468 return InvokeGoogleUpdateForRename();
[email protected]bc38c252011-04-12 21:46:57469
fdoraye9c97a02016-10-04 12:05:16470 // If this is a user-level install, directly launch a process to rename Chrome
471 // executables. Obtain the command to launch the process from the registry.
S. Ganeshf77e2a52022-11-22 18:40:19472 installer::AppCommand rename_cmd(installer::kCmdRenameChromeExe, {});
473 if (!rename_cmd.Initialize(HKEY_CURRENT_USER))
Greg Thompsona1f95122019-01-31 22:46:45474 return false;
Greg Thompsona1f95122019-01-31 22:46:45475
476 base::LaunchOptions options;
477 options.wait = true;
478 options.start_hidden = true;
479 ::SetLastError(ERROR_SUCCESS);
S. Ganeshf77e2a52022-11-22 18:40:19480 base::Process process =
481 base::LaunchProcess(rename_cmd.command_line(), options);
Greg Thompsona1f95122019-01-31 22:46:45482 if (!process.IsValid()) {
483 PLOG(ERROR) << "Launch rename process failed";
484 return false;
485 }
486
487 DWORD exit_code;
488 if (!::GetExitCodeProcess(process.Handle(), &exit_code)) {
489 PLOG(ERROR) << "GetExitCodeProcess of rename process failed";
490 return false;
491 }
492
493 if (exit_code != installer::RENAME_SUCCESSFUL) {
494 LOG(ERROR) << "Rename process failed with exit code " << exit_code;
495 return false;
496 }
497
498 return true;
[email protected]bc38c252011-04-12 21:46:57499}
500
[email protected]fdbea98d2014-05-16 19:29:20501bool IsRunningOldChrome() {
Gabriel Charette12b58ac2021-09-22 18:08:55502 TRACE_EVENT0("startup", "upgrade_util::IsRunningOldChrome");
[email protected]fdbea98d2014-05-16 19:29:20503 // This figures out the actual file name that the section containing the
504 // mapped exe refers to. This is used instead of GetModuleFileName because the
505 // .exe may have been renamed out from under us while we've been running which
506 // GetModuleFileName won't notice.
507 wchar_t mapped_file_name[MAX_PATH * 2] = {};
508
509 if (!::GetMappedFileName(::GetCurrentProcess(),
510 reinterpret_cast<void*>(::GetModuleHandle(NULL)),
Daniel Cheng7d9e3d52022-02-26 09:03:24511 mapped_file_name, std::size(mapped_file_name))) {
[email protected]fdbea98d2014-05-16 19:29:20512 return false;
513 }
514
515 base::FilePath file_name(base::FilePath(mapped_file_name).BaseName());
516 return base::FilePath::CompareEqualIgnoreCase(file_name.value(),
517 installer::kChromeOldExe);
518}
519
avi556c05022014-12-22 23:31:43520bool DoUpgradeTasks(const base::CommandLine& command_line) {
Gabriel Charette12b58ac2021-09-22 18:08:55521 TRACE_EVENT0("startup", "upgrade_util::DoUpgradeTasks");
Javier Flores Assad9c26f9b92022-05-21 01:20:43522 // If there is no other instance already running then check if there is a
523 // pending update and complete it by performing the swap and then relaunch.
Etienne Bergeron7a0ef612023-09-15 18:28:08524
525 // Upgrade tasks require the process singleton to avoid any race condition.
526 CHECK(ChromeProcessSingleton::IsSingletonInstance());
527
Javier Flores Assad9c26f9b92022-05-21 01:20:43528 bool did_swap = false;
529 if (!browser_util::IsBrowserAlreadyRunning())
530 did_swap = SwapNewChromeExeIfPresent();
531
532 // We don't need to relaunch if we didn't swap and we aren't running stale
533 // binaries.
534 if (!did_swap && !IsRunningOldChrome()) {
[email protected]bc38c252011-04-12 21:46:57535 return false;
Gabriel Charette12b58ac2021-09-22 18:08:55536 }
Javier Flores Assad9c26f9b92022-05-21 01:20:43537
[email protected]bc38c252011-04-12 21:46:57538 // At this point the chrome.exe has been swapped with the new one.
Wissem Gamra8e67a95d2023-03-17 17:41:21539 if (!RelaunchChromeBrowser(command_line)) {
Javier Flores Assad9c26f9b92022-05-21 01:20:43540 // The relaunch failed. Feel free to panic now.
Peter Boström69e4bbf02024-08-30 06:26:16541 DUMP_WILL_BE_NOTREACHED();
[email protected]bc38c252011-04-12 21:46:57542 }
543 return true;
544}
545
[email protected]815856722011-04-13 17:19:19546} // namespace upgrade_util