blob: 26092f4cd4c0ccfdbd7fe4af07ec9397d2fbe88f [file] [log] [blame]
[email protected]cec99842012-02-10 03:24:231// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[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
[email protected]815856722011-04-13 17:19:195#include "chrome/browser/first_run/upgrade_util.h"
[email protected]bc38c252011-04-12 21:46:576
[email protected]770c6d82012-09-06 22:21:327#include <windows.h>
robliaoa872e992017-05-18 06:36:198#include <objbase.h>
[email protected]fdbea98d2014-05-16 19:29:209#include <psapi.h>
[email protected]770c6d82012-09-06 22:21:3210#include <shellapi.h>
Robert Liaob2bc703d2017-10-17 20:52:3511#include <wrl/client.h>
[email protected]770c6d82012-09-06 22:21:3212
[email protected]bc38c252011-04-12 21:46:5713#include <algorithm>
14#include <string>
15
16#include "base/base_paths.h"
17#include "base/command_line.h"
[email protected]57999812013-02-24 05:40:5218#include "base/files/file_path.h"
thestig18dfb7a52014-08-26 10:44:0419#include "base/files/file_util.h"
[email protected]bc38c252011-04-12 21:46:5720#include "base/logging.h"
avi6846aef2015-12-26 01:09:3821#include "base/macros.h"
[email protected]bc38c252011-04-12 21:46:5722#include "base/path_service.h"
[email protected]d09a4ce1c2013-07-24 17:37:0223#include "base/process/launch.h"
24#include "base/process/process_handle.h"
[email protected]3ea1b182013-02-08 22:38:4125#include "base/strings/string_number_conversions.h"
[email protected]d8830562013-06-10 22:01:5426#include "base/strings/string_util.h"
[email protected]bc38c252011-04-12 21:46:5727#include "base/win/registry.h"
[email protected]770c6d82012-09-06 22:21:3228#include "base/win/windows_version.h"
ananta069fc882014-09-13 01:22:1229#include "chrome/browser/browser_process.h"
[email protected]3e087992011-04-14 22:28:1230#include "chrome/browser/first_run/upgrade_util_win.h"
[email protected]3f69d6e612012-08-03 18:52:2731#include "chrome/browser/shell_integration.h"
[email protected]80274b92011-07-15 17:20:3832#include "chrome/common/chrome_switches.h"
ananta069fc882014-09-13 01:22:1233#include "chrome/common/pref_names.h"
grt4474dad2017-02-27 21:00:4634#include "chrome/install_static/install_util.h"
[email protected]bc38c252011-04-12 21:46:5735#include "chrome/installer/util/browser_distribution.h"
36#include "chrome/installer/util/google_update_constants.h"
37#include "chrome/installer/util/install_util.h"
[email protected]bc38c252011-04-12 21:46:5738#include "chrome/installer/util/util_constants.h"
brettwb1fc1b82016-02-02 00:19:0839#include "components/prefs/pref_service.h"
ananta069fc882014-09-13 01:22:1240#include "ui/base/ui_base_switches.h"
[email protected]bc38c252011-04-12 21:46:5741
grt235b3f092015-05-27 21:42:4842#if defined(GOOGLE_CHROME_BUILD)
43#include "google_update/google_update_idl.h"
44#endif
45
[email protected]bc38c252011-04-12 21:46:5746namespace {
47
[email protected]650b2d52013-02-10 03:41:4548bool GetNewerChromeFile(base::FilePath* path) {
Avi Drissman9098f9002018-05-04 00:11:5249 if (!base::PathService::Get(base::DIR_EXE, path))
[email protected]bc38c252011-04-12 21:46:5750 return false;
51 *path = path->Append(installer::kChromeNewExe);
52 return true;
53}
54
55bool InvokeGoogleUpdateForRename() {
grt235b3f092015-05-27 21:42:4856#if defined(GOOGLE_CHROME_BUILD)
Robert Liaob2bc703d2017-10-17 20:52:3557 Microsoft::WRL::ComPtr<IProcessLauncher> ipl;
robliaoa872e992017-05-18 06:36:1958 if (!FAILED(::CoCreateInstance(__uuidof(ProcessLauncherClass), nullptr,
59 CLSCTX_ALL, IID_PPV_ARGS(&ipl)))) {
[email protected]bc38c252011-04-12 21:46:5760 ULONG_PTR phandle = NULL;
61 DWORD id = GetCurrentProcessId();
grt4474dad2017-02-27 21:00:4662 if (!FAILED(ipl->LaunchCmdElevated(install_static::GetAppGuid(),
63 google_update::kRegRenameCmdField, id,
[email protected]bc38c252011-04-12 21:46:5764 &phandle))) {
65 HANDLE handle = HANDLE(phandle);
66 WaitForSingleObject(handle, INFINITE);
67 DWORD exit_code;
68 ::GetExitCodeProcess(handle, &exit_code);
69 ::CloseHandle(handle);
70 if (exit_code == installer::RENAME_SUCCESSFUL)
71 return true;
72 }
73 }
grt235b3f092015-05-27 21:42:4874#endif // GOOGLE_CHROME_BUILD
[email protected]bc38c252011-04-12 21:46:5775 return false;
76}
77
78} // namespace
79
[email protected]815856722011-04-13 17:19:1980namespace upgrade_util {
81
scottmg812f1acf2016-03-18 23:09:0582bool RelaunchChromeBrowser(const base::CommandLine& command_line) {
[email protected]650b2d52013-02-10 03:41:4583 base::FilePath chrome_exe;
Avi Drissman9098f9002018-05-04 00:11:5284 if (!base::PathService::Get(base::FILE_EXE, &chrome_exe)) {
[email protected]3f69d6e612012-08-03 18:52:2785 NOTREACHED();
86 return false;
87 }
88
[email protected]fdbea98d2014-05-16 19:29:2089 // Explicitly make sure to relaunch chrome.exe rather than old_chrome.exe.
90 // This can happen when old_chrome.exe is launched by a user.
avi556c05022014-12-22 23:31:4391 base::CommandLine chrome_exe_command_line = command_line;
[email protected]fdbea98d2014-05-16 19:29:2092 chrome_exe_command_line.SetProgram(
93 chrome_exe.DirName().Append(installer::kChromeExe));
94
scottmg20920cb2016-04-07 16:23:5995 // Set the working directory to the exe's directory. This avoids a handle to
96 // the version directory being kept open in the relaunched child process.
97 base::LaunchOptions launch_options;
98 launch_options.current_directory = chrome_exe.DirName();
Greg Thompson47faf202018-05-18 20:59:0399 // Give the new process the right to bring its windows to the foreground.
100 launch_options.grant_foreground_privilege = true;
scottmg20920cb2016-04-07 16:23:59101 return base::LaunchProcess(chrome_exe_command_line, launch_options).IsValid();
[email protected]815856722011-04-13 17:19:19102}
103
104bool IsUpdatePendingRestart() {
[email protected]650b2d52013-02-10 03:41:45105 base::FilePath new_chrome_exe;
[email protected]815856722011-04-13 17:19:19106 if (!GetNewerChromeFile(&new_chrome_exe))
107 return false;
[email protected]7567484142013-07-11 17:36:07108 return base::PathExists(new_chrome_exe);
[email protected]815856722011-04-13 17:19:19109}
110
[email protected]815856722011-04-13 17:19:19111bool SwapNewChromeExeIfPresent() {
grtb35a90b2016-08-30 05:34:21112 if (!IsUpdatePendingRestart())
[email protected]bc38c252011-04-12 21:46:57113 return false;
grtb35a90b2016-08-30 05:34:21114
fdoraye9c97a02016-10-04 12:05:16115 // If this is a system-level install, ask Google Update to launch an elevated
116 // process to rename Chrome executables.
grt973412f2017-02-25 08:04:21117 if (!InstallUtil::IsPerUserInstall())
fdoraye9c97a02016-10-04 12:05:16118 return InvokeGoogleUpdateForRename();
[email protected]bc38c252011-04-12 21:46:57119
fdoraye9c97a02016-10-04 12:05:16120 // If this is a user-level install, directly launch a process to rename Chrome
121 // executables. Obtain the command to launch the process from the registry.
[email protected]bc38c252011-04-12 21:46:57122 base::win::RegKey key;
fdoraye9c97a02016-10-04 12:05:16123 if (key.Open(HKEY_CURRENT_USER,
124 BrowserDistribution::GetDistribution()->GetVersionKey().c_str(),
grtb35a90b2016-08-30 05:34:21125 KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
[email protected]80274b92011-07-15 17:20:38126 std::wstring rename_cmd;
127 if (key.ReadValue(google_update::kRegRenameCmdField,
128 &rename_cmd) == ERROR_SUCCESS) {
[email protected]89a56162011-07-18 21:38:02129 base::LaunchOptions options;
130 options.wait = true;
131 options.start_hidden = true;
rvargas61812772014-12-05 03:14:54132 base::Process process = base::LaunchProcess(rename_cmd, options);
133 if (process.IsValid()) {
[email protected]80274b92011-07-15 17:20:38134 DWORD exit_code;
rvargas61812772014-12-05 03:14:54135 ::GetExitCodeProcess(process.Handle(), &exit_code);
[email protected]80274b92011-07-15 17:20:38136 if (exit_code == installer::RENAME_SUCCESSFUL)
137 return true;
138 }
[email protected]bc38c252011-04-12 21:46:57139 }
140 }
141
grtb35a90b2016-08-30 05:34:21142 return false;
[email protected]bc38c252011-04-12 21:46:57143}
144
[email protected]fdbea98d2014-05-16 19:29:20145bool IsRunningOldChrome() {
146 // This figures out the actual file name that the section containing the
147 // mapped exe refers to. This is used instead of GetModuleFileName because the
148 // .exe may have been renamed out from under us while we've been running which
149 // GetModuleFileName won't notice.
150 wchar_t mapped_file_name[MAX_PATH * 2] = {};
151
152 if (!::GetMappedFileName(::GetCurrentProcess(),
153 reinterpret_cast<void*>(::GetModuleHandle(NULL)),
154 mapped_file_name,
155 arraysize(mapped_file_name))) {
156 return false;
157 }
158
159 base::FilePath file_name(base::FilePath(mapped_file_name).BaseName());
160 return base::FilePath::CompareEqualIgnoreCase(file_name.value(),
161 installer::kChromeOldExe);
162}
163
avi556c05022014-12-22 23:31:43164bool DoUpgradeTasks(const base::CommandLine& command_line) {
[email protected]fdbea98d2014-05-16 19:29:20165 if (!SwapNewChromeExeIfPresent() && !IsRunningOldChrome())
[email protected]bc38c252011-04-12 21:46:57166 return false;
167 // At this point the chrome.exe has been swapped with the new one.
[email protected]815856722011-04-13 17:19:19168 if (!RelaunchChromeBrowser(command_line)) {
[email protected]bc38c252011-04-12 21:46:57169 // The re-launch fails. Feel free to panic now.
170 NOTREACHED();
171 }
172 return true;
173}
174
[email protected]815856722011-04-13 17:19:19175} // namespace upgrade_util