blob: 734c88f07a8c3166d86d14a868d24889542bfed3 [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"
Gabriel Charette12b58ac2021-09-22 18:08:5539#include "base/time/time.h"
S. Ganesh48540862024-08-12 18:09:3940#include "base/timer/elapsed_timer.h"
Gabriel Charette12b58ac2021-09-22 18:08:5541#include "base/trace_event/trace_event.h"
S. Ganesh48540862024-08-12 18:09:3942#include "base/values.h"
[email protected]bc38c252011-04-12 21:46:5743#include "base/win/registry.h"
[email protected]770c6d82012-09-06 22:21:3244#include "base/win/windows_version.h"
Nico Webereaa08412019-08-14 01:24:3745#include "build/branding_buildflags.h"
ananta069fc882014-09-13 01:22:1246#include "chrome/browser/browser_process.h"
Etienne Bergeron7a0ef612023-09-15 18:28:0847#include "chrome/browser/chrome_process_singleton.h"
Daniel Cheng7d9e3d52022-02-26 09:03:2448#include "chrome/browser/first_run/upgrade_util.h"
[email protected]3f69d6e612012-08-03 18:52:2749#include "chrome/browser/shell_integration.h"
Javier Flores Assad9c26f9b92022-05-21 01:20:4350#include "chrome/browser/win/browser_util.h"
[email protected]80274b92011-07-15 17:20:3851#include "chrome/common/chrome_switches.h"
ananta069fc882014-09-13 01:22:1252#include "chrome/common/pref_names.h"
grt4474dad2017-02-27 21:00:4653#include "chrome/install_static/install_util.h"
S. Ganeshf77e2a52022-11-22 18:40:1954#include "chrome/installer/util/app_command.h"
S. Ganesh48540862024-08-12 18:09:3955#include "chrome/installer/util/per_install_values.h"
[email protected]bc38c252011-04-12 21:46:5756#include "chrome/installer/util/util_constants.h"
brettwb1fc1b82016-02-02 00:19:0857#include "components/prefs/pref_service.h"
S. Ganeshcad45032024-07-18 17:43:1158#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
ananta069fc882014-09-13 01:22:1259#include "ui/base/ui_base_switches.h"
[email protected]bc38c252011-04-12 21:46:5760
Nico Webereaa08412019-08-14 01:24:3761#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
S. Ganesh6adf04c2023-06-07 19:34:5562#include "chrome/updater/app/server/win/updater_legacy_idl.h"
grt235b3f092015-05-27 21:42:4863#endif
64
[email protected]bc38c252011-04-12 21:46:5765namespace {
66
[email protected]650b2d52013-02-10 03:41:4567bool GetNewerChromeFile(base::FilePath* path) {
Avi Drissman9098f9002018-05-04 00:11:5268 if (!base::PathService::Get(base::DIR_EXE, path))
[email protected]bc38c252011-04-12 21:46:5769 return false;
70 *path = path->Append(installer::kChromeNewExe);
71 return true;
72}
73
S. Ganeshcad45032024-07-18 17:43:1174#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
75// Holds the result of the IPC to CoCreate the process launcher.
76struct CreateProcessLauncherResult
77 : public base::RefCountedThreadSafe<CreateProcessLauncherResult> {
78 Microsoft::WRL::ComPtr<IStream> stream;
79 base::WaitableEvent completion_event;
80
81 private:
82 friend class base::RefCountedThreadSafe<CreateProcessLauncherResult>;
83 virtual ~CreateProcessLauncherResult() = default;
84};
85
86// CoCreates the `ProcessLauncher` class, and if successful, marshals the
87// resulting interface into `result->stream`. Signals `result->completion_event`
88// on successful or failed completion.
89void CreateAndMarshalProcessLauncher(
90 scoped_refptr<CreateProcessLauncherResult> result) {
91 const absl::Cleanup signal_completion_event = [&result] {
92 result->completion_event.Signal();
93 };
94
95 Microsoft::WRL::ComPtr<IUnknown> unknown;
96 {
97 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename CoCreateInstance");
98 const HRESULT hr =
99 ::CoCreateInstance(__uuidof(ProcessLauncherClass), nullptr, CLSCTX_ALL,
100 IID_PPV_ARGS(&unknown));
101 if (FAILED(hr)) {
102 TRACE_EVENT_INSTANT1(
103 "startup", "InvokeGoogleUpdateForRename CoCreateInstance failed",
104 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
105 LOG(ERROR) << "CoCreate ProcessLauncherClass failed; hr = " << std::hex
106 << hr;
107 return;
108 }
109 }
S. Ganeshcad45032024-07-18 17:43:11110 const HRESULT hr = ::CoMarshalInterThreadInterfaceInStream(
111 __uuidof(IUnknown), unknown.Get(), &result->stream);
112 if (FAILED(hr)) {
113 TRACE_EVENT_INSTANT1("startup",
114 "InvokeGoogleUpdateForRename "
115 "CoMarshalInterThreadInterfaceInStream failed",
116 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
117 LOG(ERROR) << "CoMarshalInterThreadInterfaceInStream "
118 "ProcessLauncherClass failed; hr = "
119 << std::hex << hr;
120 }
121}
122
123// CoCreates the Google Update `ProcessLauncherClass` in a `ThreadPool` thread
S. Ganesh48540862024-08-12 18:09:39124// with a timeout, if the `ThreadPool` is operational. The starting value for
125// the timeout is 15 seconds. If the CoCreate times out, the timeout is
126// increased by 15 seconds at each failed attempt and persisted for the next
127// attempt.
128//
129// If the `ThreadPool` is not operational, the CoCreate is done
S. Ganeshcad45032024-07-18 17:43:11130// without a timeout.
S. Ganeshcad45032024-07-18 17:43:11131Microsoft::WRL::ComPtr<IUnknown> CreateProcessLauncher() {
S. Ganesh48540862024-08-12 18:09:39132 constexpr int kDefaultTimeoutIncrementSeconds = 15;
S. Ganeshbb1d4fc2024-08-14 19:16:32133 constexpr base::TimeDelta kMaxTimeAfterSystemStartup = base::Seconds(150);
S. Ganesh48540862024-08-12 18:09:39134
S. Ganeshcad45032024-07-18 17:43:11135 auto result = base::MakeRefCounted<CreateProcessLauncherResult>();
136 if (base::ThreadPool::CreateCOMSTATaskRunner(
137 {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
138 ->PostTask(FROM_HERE, base::BindOnce(&CreateAndMarshalProcessLauncher,
139 result))) {
S. Ganesh48540862024-08-12 18:09:39140 installer::PerInstallValue creation_timeout(
141 L"ProcessLauncherCreationTimeout");
142 const base::TimeDelta timeout = base::Seconds(
143 creation_timeout.Get()
144 .value_or(base::Value(kDefaultTimeoutIncrementSeconds))
145 .GetIfInt()
146 .value_or(kDefaultTimeoutIncrementSeconds));
147 const base::ElapsedTimer timer;
S. Ganeshbb1d4fc2024-08-14 19:16:32148 const bool is_at_startup =
149 base::SysInfo::Uptime() <= kMaxTimeAfterSystemStartup;
S. Ganesh48540862024-08-12 18:09:39150 if (!result->completion_event.TimedWait(timeout)) {
151 base::UmaHistogramMediumTimes(
S. Ganeshbb1d4fc2024-08-14 19:16:32152 is_at_startup
153 ? "Startup.CreateProcessLauncher2.TimedWaitFailedAtStartup"
154 : "Startup.CreateProcessLauncher2.TimedWaitFailed",
155 timer.Elapsed());
S. Ganesh48540862024-08-12 18:09:39156 creation_timeout.Set(base::Value(static_cast<int>(timeout.InSeconds()) +
157 kDefaultTimeoutIncrementSeconds));
S. Ganeshcad45032024-07-18 17:43:11158 TRACE_EVENT_INSTANT0(
159 "startup", "InvokeGoogleUpdateForRename CoCreateInstance timed out",
160 TRACE_EVENT_SCOPE_THREAD);
161 LOG(ERROR) << "CoCreate ProcessLauncherClass timed out";
162 return {};
163 }
164
165 if (!result->stream) {
166 return {};
167 }
S. Ganesh48540862024-08-12 18:09:39168 base::UmaHistogramMediumTimes(
S. Ganeshbb1d4fc2024-08-14 19:16:32169 is_at_startup
170 ? "Startup.CreateProcessLauncher2.TimedWaitSucceededAtStartup"
171 : "Startup.CreateProcessLauncher2.TimedWaitSucceeded",
172 timer.Elapsed());
S. Ganeshcad45032024-07-18 17:43:11173
174 Microsoft::WRL::ComPtr<IUnknown> unknown;
175 const HRESULT hr =
176 ::CoUnmarshalInterface(result->stream.Get(), __uuidof(IUnknown),
177 IID_PPV_ARGS_Helper(&unknown));
178 if (FAILED(hr)) {
179 TRACE_EVENT_INSTANT1(
180 "startup", "InvokeGoogleUpdateForRename CoUnmarshalInterface failed",
181 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
182 LOG(ERROR) << "CoUnmarshalInterface ProcessLauncherClass failed; hr = "
183 << std::hex << hr;
184 return {};
185 }
186
187 return unknown;
188 }
189
190 // The task could not be posted to the task runner, so CoCreate without a
191 // timeout. This could happen in shutdown, where the `ThreadPool` is not
192 // operational.
193 {
194 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename CoCreateInstance");
195 Microsoft::WRL::ComPtr<IUnknown> unknown;
196 const HRESULT hr =
197 ::CoCreateInstance(__uuidof(ProcessLauncherClass), nullptr, CLSCTX_ALL,
198 IID_PPV_ARGS(&unknown));
199 if (FAILED(hr)) {
200 TRACE_EVENT_INSTANT1(
201 "startup", "InvokeGoogleUpdateForRename CoCreateInstance failed",
202 TRACE_EVENT_SCOPE_THREAD, "hr", hr);
203 LOG(ERROR) << "CoCreate ProcessLauncherClass failed; hr = " << std::hex
204 << hr;
205 return {};
206 }
207
208 return unknown;
209 }
210}
211#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
212
[email protected]bc38c252011-04-12 21:46:57213bool InvokeGoogleUpdateForRename() {
Nico Webereaa08412019-08-14 01:24:37214#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
Gabriel Charettef7e85712021-12-10 20:46:22215 // This has been identified as very slow on some startups. Detailed trace
216 // events below try to shine a light on each steps. crbug.com/1252004
Gabriel Charette12b58ac2021-09-22 18:08:55217 TRACE_EVENT0("startup", "upgrade_util::InvokeGoogleUpdateForRename");
218
S. Ganeshcad45032024-07-18 17:43:11219 Microsoft::WRL::ComPtr<IUnknown> unknown = CreateProcessLauncher();
220 if (!unknown) {
221 return false;
222 }
223
S. Ganeshea7ef0872024-03-21 16:28:32224 // Chrome queries for the SxS IIDs first, with a fallback to the legacy IID,
225 // to make sure that marshaling loads the proxy/stub from the correct (HKLM)
226 // hive.
Robert Liaob2bc703d2017-10-17 20:52:35227 Microsoft::WRL::ComPtr<IProcessLauncher> ipl;
Gabriel Charettef7e85712021-12-10 20:46:22228 {
S. Ganeshcad45032024-07-18 17:43:11229 HRESULT hr = unknown.CopyTo(__uuidof(IProcessLauncherSystem),
230 IID_PPV_ARGS_Helper(&ipl));
S. Ganeshea7ef0872024-03-21 16:28:32231 if (FAILED(hr)) {
232 hr = unknown.As(&ipl);
233 }
234 if (FAILED(hr)) {
235 TRACE_EVENT0("startup",
236 "InvokeGoogleUpdateForRename QueryInterface failed");
237 LOG(ERROR) << "QueryInterface failed; hr = " << std::hex << hr;
238 return false;
239 }
[email protected]bc38c252011-04-12 21:46:57240 }
Greg Thompsona1f95122019-01-31 22:46:45241
S. Ganesh74432c12022-11-02 06:35:34242 ULONG_PTR process_handle = 0;
Gabriel Charettef7e85712021-12-10 20:46:22243 {
244 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename LaunchCmdElevated");
Dominique Fauteux-Chapleau269cabf2021-12-10 22:10:31245 HRESULT hr = ipl->LaunchCmdElevated(
S. Ganeshf77e2a52022-11-22 18:40:19246 install_static::GetAppGuid(), installer::kCmdRenameChromeExe,
Dominique Fauteux-Chapleau269cabf2021-12-10 22:10:31247 ::GetCurrentProcessId(), &process_handle);
Gabriel Charettef7e85712021-12-10 20:46:22248 if (FAILED(hr)) {
249 TRACE_EVENT0("startup",
250 "InvokeGoogleUpdateForRename LaunchCmdElevated failed");
251 LOG(ERROR) << "IProcessLauncher::LaunchCmdElevated failed; hr = "
252 << std::hex << hr;
253 return false;
254 }
Greg Thompsona1f95122019-01-31 22:46:45255 }
256
257 base::Process rename_process(
258 reinterpret_cast<base::ProcessHandle>(process_handle));
259 int exit_code;
Gabriel Charettef7e85712021-12-10 20:46:22260 {
261 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename WaitForExit");
262 if (!rename_process.WaitForExit(&exit_code)) {
263 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename WaitForExit failed");
264 PLOG(ERROR) << "WaitForExit of rename process failed";
265 return false;
266 }
Greg Thompsona1f95122019-01-31 22:46:45267 }
268
269 if (exit_code != installer::RENAME_SUCCESSFUL) {
Gabriel Charettef7e85712021-12-10 20:46:22270 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename !RENAME_SUCCESSFUL");
Greg Thompsona1f95122019-01-31 22:46:45271 LOG(ERROR) << "Rename process failed with exit code " << exit_code;
272 return false;
273 }
274
Gabriel Charette334775a2021-12-13 18:57:26275 TRACE_EVENT0("startup", "InvokeGoogleUpdateForRename RENAME_SUCCESSFUL");
276
Greg Thompsona1f95122019-01-31 22:46:45277 return true;
Nico Webereaa08412019-08-14 01:24:37278#else // BUILDFLAG(GOOGLE_CHROME_BRANDING)
[email protected]bc38c252011-04-12 21:46:57279 return false;
Nico Webereaa08412019-08-14 01:24:37280#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
[email protected]bc38c252011-04-12 21:46:57281}
282
283} // namespace
284
[email protected]815856722011-04-13 17:19:19285namespace upgrade_util {
286
Greg Thompson87ee38f2019-08-09 06:00:23287bool RelaunchChromeBrowserImpl(const base::CommandLine& command_line) {
Gabriel Charette12b58ac2021-09-22 18:08:55288 TRACE_EVENT0("startup", "upgrade_util::RelaunchChromeBrowserImpl");
289
[email protected]650b2d52013-02-10 03:41:45290 base::FilePath chrome_exe;
Avi Drissman9098f9002018-05-04 00:11:52291 if (!base::PathService::Get(base::FILE_EXE, &chrome_exe)) {
Peter Boström3e79afa2024-05-15 00:49:26292 NOTREACHED_IN_MIGRATION();
[email protected]3f69d6e612012-08-03 18:52:27293 return false;
294 }
295
[email protected]fdbea98d2014-05-16 19:29:20296 // Explicitly make sure to relaunch chrome.exe rather than old_chrome.exe.
297 // This can happen when old_chrome.exe is launched by a user.
avi556c05022014-12-22 23:31:43298 base::CommandLine chrome_exe_command_line = command_line;
[email protected]fdbea98d2014-05-16 19:29:20299 chrome_exe_command_line.SetProgram(
300 chrome_exe.DirName().Append(installer::kChromeExe));
301
scottmg20920cb2016-04-07 16:23:59302 // Set the working directory to the exe's directory. This avoids a handle to
303 // the version directory being kept open in the relaunched child process.
304 base::LaunchOptions launch_options;
305 launch_options.current_directory = chrome_exe.DirName();
Greg Thompson47faf202018-05-18 20:59:03306 // Give the new process the right to bring its windows to the foreground.
307 launch_options.grant_foreground_privilege = true;
scottmg20920cb2016-04-07 16:23:59308 return base::LaunchProcess(chrome_exe_command_line, launch_options).IsValid();
[email protected]815856722011-04-13 17:19:19309}
310
311bool IsUpdatePendingRestart() {
Gabriel Charette12b58ac2021-09-22 18:08:55312 TRACE_EVENT0("startup", "upgrade_util::IsUpdatePendingRestart");
[email protected]650b2d52013-02-10 03:41:45313 base::FilePath new_chrome_exe;
[email protected]815856722011-04-13 17:19:19314 if (!GetNewerChromeFile(&new_chrome_exe))
315 return false;
[email protected]7567484142013-07-11 17:36:07316 return base::PathExists(new_chrome_exe);
[email protected]815856722011-04-13 17:19:19317}
318
[email protected]815856722011-04-13 17:19:19319bool SwapNewChromeExeIfPresent() {
grtb35a90b2016-08-30 05:34:21320 if (!IsUpdatePendingRestart())
[email protected]bc38c252011-04-12 21:46:57321 return false;
grtb35a90b2016-08-30 05:34:21322
Gabriel Charette12b58ac2021-09-22 18:08:55323 TRACE_EVENT0("startup", "upgrade_util::SwapNewChromeExeIfPresent");
324
Etienne Bergeron7a0ef612023-09-15 18:28:08325 // Renaming the chrome executable requires the process singleton to avoid
326 // any race condition.
327 CHECK(ChromeProcessSingleton::IsSingletonInstance());
328
fdoraye9c97a02016-10-04 12:05:16329 // If this is a system-level install, ask Google Update to launch an elevated
330 // process to rename Chrome executables.
Greg Thompsond2efb1f2018-08-29 06:12:54331 if (install_static::IsSystemInstall())
fdoraye9c97a02016-10-04 12:05:16332 return InvokeGoogleUpdateForRename();
[email protected]bc38c252011-04-12 21:46:57333
fdoraye9c97a02016-10-04 12:05:16334 // If this is a user-level install, directly launch a process to rename Chrome
335 // executables. Obtain the command to launch the process from the registry.
S. Ganeshf77e2a52022-11-22 18:40:19336 installer::AppCommand rename_cmd(installer::kCmdRenameChromeExe, {});
337 if (!rename_cmd.Initialize(HKEY_CURRENT_USER))
Greg Thompsona1f95122019-01-31 22:46:45338 return false;
Greg Thompsona1f95122019-01-31 22:46:45339
340 base::LaunchOptions options;
341 options.wait = true;
342 options.start_hidden = true;
343 ::SetLastError(ERROR_SUCCESS);
S. Ganeshf77e2a52022-11-22 18:40:19344 base::Process process =
345 base::LaunchProcess(rename_cmd.command_line(), options);
Greg Thompsona1f95122019-01-31 22:46:45346 if (!process.IsValid()) {
347 PLOG(ERROR) << "Launch rename process failed";
348 return false;
349 }
350
351 DWORD exit_code;
352 if (!::GetExitCodeProcess(process.Handle(), &exit_code)) {
353 PLOG(ERROR) << "GetExitCodeProcess of rename process failed";
354 return false;
355 }
356
357 if (exit_code != installer::RENAME_SUCCESSFUL) {
358 LOG(ERROR) << "Rename process failed with exit code " << exit_code;
359 return false;
360 }
361
362 return true;
[email protected]bc38c252011-04-12 21:46:57363}
364
[email protected]fdbea98d2014-05-16 19:29:20365bool IsRunningOldChrome() {
Gabriel Charette12b58ac2021-09-22 18:08:55366 TRACE_EVENT0("startup", "upgrade_util::IsRunningOldChrome");
[email protected]fdbea98d2014-05-16 19:29:20367 // This figures out the actual file name that the section containing the
368 // mapped exe refers to. This is used instead of GetModuleFileName because the
369 // .exe may have been renamed out from under us while we've been running which
370 // GetModuleFileName won't notice.
371 wchar_t mapped_file_name[MAX_PATH * 2] = {};
372
373 if (!::GetMappedFileName(::GetCurrentProcess(),
374 reinterpret_cast<void*>(::GetModuleHandle(NULL)),
Daniel Cheng7d9e3d52022-02-26 09:03:24375 mapped_file_name, std::size(mapped_file_name))) {
[email protected]fdbea98d2014-05-16 19:29:20376 return false;
377 }
378
379 base::FilePath file_name(base::FilePath(mapped_file_name).BaseName());
380 return base::FilePath::CompareEqualIgnoreCase(file_name.value(),
381 installer::kChromeOldExe);
382}
383
avi556c05022014-12-22 23:31:43384bool DoUpgradeTasks(const base::CommandLine& command_line) {
Gabriel Charette12b58ac2021-09-22 18:08:55385 TRACE_EVENT0("startup", "upgrade_util::DoUpgradeTasks");
Javier Flores Assad9c26f9b92022-05-21 01:20:43386 // If there is no other instance already running then check if there is a
387 // pending update and complete it by performing the swap and then relaunch.
Etienne Bergeron7a0ef612023-09-15 18:28:08388
389 // Upgrade tasks require the process singleton to avoid any race condition.
390 CHECK(ChromeProcessSingleton::IsSingletonInstance());
391
Javier Flores Assad9c26f9b92022-05-21 01:20:43392 bool did_swap = false;
393 if (!browser_util::IsBrowserAlreadyRunning())
394 did_swap = SwapNewChromeExeIfPresent();
395
396 // We don't need to relaunch if we didn't swap and we aren't running stale
397 // binaries.
398 if (!did_swap && !IsRunningOldChrome()) {
[email protected]bc38c252011-04-12 21:46:57399 return false;
Gabriel Charette12b58ac2021-09-22 18:08:55400 }
Javier Flores Assad9c26f9b92022-05-21 01:20:43401
[email protected]bc38c252011-04-12 21:46:57402 // At this point the chrome.exe has been swapped with the new one.
Wissem Gamra8e67a95d2023-03-17 17:41:21403 if (!RelaunchChromeBrowser(command_line)) {
Javier Flores Assad9c26f9b92022-05-21 01:20:43404 // The relaunch failed. Feel free to panic now.
Peter Boström3e79afa2024-05-15 00:49:26405 NOTREACHED_IN_MIGRATION();
[email protected]bc38c252011-04-12 21:46:57406 }
407 return true;
408}
409
[email protected]815856722011-04-13 17:19:19410} // namespace upgrade_util