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
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/first_run/upgrade_util.h"
#include <algorithm>
#include <string>
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_util.h"
#include "base/win/registry.h"
#include "base/win/scoped_comptr.h"
#include "chrome/browser/first_run/upgrade_util_win.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/shell_util.h"
#include "chrome/installer/util/util_constants.h"
#include "google_update_idl.h"
namespace {
bool GetNewerChromeFile(FilePath* path) {
if (!PathService::Get(base::DIR_EXE, path))
return false;
*path = path->Append(installer::kChromeNewExe);
return true;
}
bool InvokeGoogleUpdateForRename() {
base::win::ScopedComPtr<IProcessLauncher> ipl;
if (!FAILED(ipl.CreateInstance(__uuidof(ProcessLauncherClass)))) {
ULONG_PTR phandle = NULL;
DWORD id = GetCurrentProcessId();
BrowserDistribution* dist = BrowserDistribution::GetDistribution();
if (!FAILED(ipl->LaunchCmdElevated(dist->GetAppGuid().c_str(),
google_update::kRegRenameCmdField,
id,
&phandle))) {
HANDLE handle = HANDLE(phandle);
WaitForSingleObject(handle, INFINITE);
DWORD exit_code;
::GetExitCodeProcess(handle, &exit_code);
::CloseHandle(handle);
if (exit_code == installer::RENAME_SUCCESSFUL)
return true;
}
}
return false;
}
} // namespace
namespace upgrade_util {
bool RelaunchChromeBrowser(const CommandLine& command_line) {
scoped_ptr<base::Environment> env(base::Environment::Create());
env->UnSetVar(chrome::kChromeVersionEnvVar);
return base::LaunchProcess(command_line, base::LaunchOptions(), NULL);
}
bool IsUpdatePendingRestart() {
FilePath new_chrome_exe;
if (!GetNewerChromeFile(&new_chrome_exe))
return false;
return file_util::PathExists(new_chrome_exe);
}
bool SwapNewChromeExeIfPresent() {
FilePath new_chrome_exe;
if (!GetNewerChromeFile(&new_chrome_exe))
return false;
if (!file_util::PathExists(new_chrome_exe))
return false;
FilePath cur_chrome_exe;
if (!PathService::Get(base::FILE_EXE, &cur_chrome_exe))
return false;
// Open up the registry key containing current version and rename information.
bool user_install =
InstallUtil::IsPerUserInstall(cur_chrome_exe.value().c_str());
HKEY reg_root = user_install ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
BrowserDistribution *dist = BrowserDistribution::GetDistribution();
base::win::RegKey key;
if (key.Open(reg_root, dist->GetVersionKey().c_str(),
KEY_QUERY_VALUE) == ERROR_SUCCESS) {
// Having just ascertained that we can swap, now check that we should: if
// we are given an explicit --chrome-version flag, don't rename unless the
// specified version matches the "pv" value. In practice, this is used to
// defer Chrome Frame updates until the current version of the Chrome Frame
// DLL component is loaded.
const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
if (cmd_line.HasSwitch(switches::kChromeVersion)) {
std::string version_string =
cmd_line.GetSwitchValueASCII(switches::kChromeVersion);
scoped_ptr<Version> cmd_version(
Version::GetVersionFromString(version_string));
std::wstring pv_value;
if (key.ReadValue(google_update::kRegVersionField,
&pv_value) == ERROR_SUCCESS) {
scoped_ptr<Version> pv_version(
Version::GetVersionFromString(WideToASCII(pv_value)));
if (cmd_version.get() && pv_version.get() &&
!cmd_version->Equals(*pv_version.get())) {
return false;
}
}
}
// First try to rename exe by launching rename command ourselves.
std::wstring rename_cmd;
if (key.ReadValue(google_update::kRegRenameCmdField,
&rename_cmd) == ERROR_SUCCESS) {
base::ProcessHandle handle;
base::LaunchOptions options;
options.wait = true;
options.start_hidden = true;
if (base::LaunchProcess(rename_cmd, options, &handle)) {
DWORD exit_code;
::GetExitCodeProcess(handle, &exit_code);
::CloseHandle(handle);
if (exit_code == installer::RENAME_SUCCESSFUL)
return true;
}
}
}
// Rename didn't work so try to rename by calling Google Update
return InvokeGoogleUpdateForRename();
}
bool DoUpgradeTasks(const CommandLine& command_line) {
if (!SwapNewChromeExeIfPresent())
return false;
// At this point the chrome.exe has been swapped with the new one.
if (!RelaunchChromeBrowser(command_line)) {
// The re-launch fails. Feel free to panic now.
NOTREACHED();
}
return true;
}
} // namespace upgrade_util
|