OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/installer/setup/install.h" | 5 #include "chrome/installer/setup/install.h" |
6 | 6 |
7 #include <shlobj.h> | 7 #include <shlobj.h> |
8 #include <time.h> | 8 #include <time.h> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/file_path.h" | 12 #include "base/file_path.h" |
13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/path_service.h" | 15 #include "base/path_service.h" |
16 #include "base/scoped_ptr.h" | 16 #include "base/scoped_ptr.h" |
17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
18 #include "base/utf_string_conversions.h" | 18 #include "base/utf_string_conversions.h" |
19 #include "base/win/registry.h" | |
20 #include "chrome/installer/setup/setup_constants.h" | 19 #include "chrome/installer/setup/setup_constants.h" |
21 #include "chrome/installer/setup/install_worker.h" | 20 #include "chrome/installer/setup/install_worker.h" |
22 #include "chrome/installer/util/browser_distribution.h" | 21 #include "chrome/installer/util/browser_distribution.h" |
23 #include "chrome/installer/util/channel_info.h" | |
24 #include "chrome/installer/util/chrome_frame_distribution.h" | |
25 #include "chrome/installer/util/conditional_work_item_list.h" | |
26 #include "chrome/installer/util/create_reg_key_work_item.h" | 22 #include "chrome/installer/util/create_reg_key_work_item.h" |
27 #include "chrome/installer/util/delete_after_reboot_helper.h" | 23 #include "chrome/installer/util/delete_after_reboot_helper.h" |
28 #include "chrome/installer/util/google_update_constants.h" | 24 #include "chrome/installer/util/google_update_constants.h" |
29 #include "chrome/installer/util/helper.h" | 25 #include "chrome/installer/util/helper.h" |
30 #include "chrome/installer/util/install_util.h" | 26 #include "chrome/installer/util/install_util.h" |
31 #include "chrome/installer/util/installation_state.h" | 27 #include "chrome/installer/util/installation_state.h" |
32 #include "chrome/installer/util/installer_state.h" | 28 #include "chrome/installer/util/installer_state.h" |
33 #include "chrome/installer/util/master_preferences.h" | 29 #include "chrome/installer/util/master_preferences.h" |
34 #include "chrome/installer/util/master_preferences_constants.h" | 30 #include "chrome/installer/util/master_preferences_constants.h" |
35 #include "chrome/installer/util/package.h" | |
36 #include "chrome/installer/util/package_properties.h" | |
37 #include "chrome/installer/util/product.h" | 31 #include "chrome/installer/util/product.h" |
38 #include "chrome/installer/util/set_reg_value_work_item.h" | 32 #include "chrome/installer/util/set_reg_value_work_item.h" |
39 #include "chrome/installer/util/shell_util.h" | 33 #include "chrome/installer/util/shell_util.h" |
40 #include "chrome/installer/util/util_constants.h" | 34 #include "chrome/installer/util/util_constants.h" |
41 #include "chrome/installer/util/work_item_list.h" | 35 #include "chrome/installer/util/work_item_list.h" |
42 | 36 |
43 // Build-time generated include file. | 37 // Build-time generated include file. |
44 #include "installer_util_strings.h" // NOLINT | 38 #include "installer_util_strings.h" // NOLINT |
45 #include "registered_dlls.h" // NOLINT | 39 #include "registered_dlls.h" // NOLINT |
46 | 40 |
47 using base::win::RegKey; | |
48 using installer::ChannelInfo; | |
49 using installer::InstallerState; | 41 using installer::InstallerState; |
50 using installer::InstallationState; | 42 using installer::InstallationState; |
51 using installer::MasterPreferences; | |
52 using installer::Products; | |
53 using installer::Product; | 43 using installer::Product; |
54 using installer::Package; | |
55 using installer::PackageProperties; | |
56 | 44 |
57 namespace { | 45 namespace { |
58 | 46 |
59 void AddChromeToMediaPlayerList() { | 47 void AddChromeToMediaPlayerList() { |
60 std::wstring reg_path(installer::kMediaPlayerRegPath); | 48 std::wstring reg_path(installer::kMediaPlayerRegPath); |
61 // registry paths can also be appended like file system path | 49 // registry paths can also be appended like file system path |
62 file_util::AppendToPath(®_path, installer::kChromeExe); | 50 file_util::AppendToPath(®_path, installer::kChromeExe); |
63 VLOG(1) << "Adding Chrome to Media player list at " << reg_path; | 51 VLOG(1) << "Adding Chrome to Media player list at " << reg_path; |
64 scoped_ptr<WorkItem> work_item(WorkItem::CreateCreateRegKeyWorkItem( | 52 scoped_ptr<WorkItem> work_item(WorkItem::CreateCreateRegKeyWorkItem( |
65 HKEY_LOCAL_MACHINE, reg_path)); | 53 HKEY_LOCAL_MACHINE, reg_path)); |
66 | 54 |
67 // if the operation fails we log the error but still continue | 55 // if the operation fails we log the error but still continue |
68 if (!work_item.get()->Do()) | 56 if (!work_item.get()->Do()) |
69 LOG(ERROR) << "Could not add Chrome to media player inclusion list."; | 57 LOG(ERROR) << "Could not add Chrome to media player inclusion list."; |
70 } | 58 } |
71 | 59 |
72 void AddInstallerCopyTasks(const FilePath& setup_path, | 60 void AddInstallerCopyTasks(const InstallerState& installer_state, |
61 const FilePath& setup_path, | |
73 const FilePath& archive_path, | 62 const FilePath& archive_path, |
74 const FilePath& temp_path, | 63 const FilePath& temp_path, |
75 const Version& new_version, | 64 const Version& new_version, |
76 WorkItemList* install_list, | 65 WorkItemList* install_list) { |
77 const Package& package) { | |
78 DCHECK(install_list); | 66 DCHECK(install_list); |
79 FilePath installer_dir(package.GetInstallerDirectory(new_version)); | 67 FilePath installer_dir(installer_state.GetInstallerDirectory(new_version)); |
80 install_list->AddCreateDirWorkItem(installer_dir); | 68 install_list->AddCreateDirWorkItem(installer_dir); |
81 | 69 |
82 FilePath exe_dst(installer_dir.Append(setup_path.BaseName())); | 70 FilePath exe_dst(installer_dir.Append(setup_path.BaseName())); |
83 FilePath archive_dst(installer_dir.Append(archive_path.BaseName())); | 71 FilePath archive_dst(installer_dir.Append(archive_path.BaseName())); |
84 | 72 |
85 install_list->AddCopyTreeWorkItem(setup_path.value(), exe_dst.value(), | 73 install_list->AddCopyTreeWorkItem(setup_path.value(), exe_dst.value(), |
86 temp_path.value(), WorkItem::ALWAYS); | 74 temp_path.value(), WorkItem::ALWAYS); |
87 if (package.system_level()) { | 75 if (installer_state.system_install()) { |
88 install_list->AddCopyTreeWorkItem(archive_path.value(), archive_dst.value(), | 76 install_list->AddCopyTreeWorkItem(archive_path.value(), archive_dst.value(), |
89 temp_path.value(), WorkItem::ALWAYS); | 77 temp_path.value(), WorkItem::ALWAYS); |
90 } else { | 78 } else { |
91 install_list->AddMoveTreeWorkItem(archive_path.value(), archive_dst.value(), | 79 install_list->AddMoveTreeWorkItem(archive_path.value(), archive_dst.value(), |
92 temp_path.value()); | 80 temp_path.value()); |
93 } | 81 } |
94 } | 82 } |
95 | 83 |
96 // Adds work items that make registry adjustments for Google Update. When a | |
97 // product is installed (including overinstall), Google Update will write the | |
98 // channel ("ap") value into either Chrome or Chrome Frame's ClientState key. | |
99 // In the multi-install case, this value is used as the basis upon which the | |
100 // package's channel value is built (by adding the ordered list of installed | |
101 // products and their options). | |
102 void AddGoogleUpdateWorkItems(const InstallationState& original_state, | |
103 const InstallerState& installer_state, | |
104 const Package& package, | |
105 WorkItemList* install_list) { | |
106 // Is a multi-install product being installed or over-installed? | |
107 if (installer_state.operation() != InstallerState::MULTI_INSTALL) | |
108 return; | |
109 | |
110 const HKEY reg_root = package.system_level() ? HKEY_LOCAL_MACHINE : | |
111 HKEY_CURRENT_USER; | |
112 const std::wstring key_path = installer_state.state_key(); | |
113 ChannelInfo channel_info; | |
114 | |
115 // Update the "ap" value for the product being installed/updated. | |
116 // It is completely acceptable for there to be no "ap" value or even no | |
117 // ClientState key. Note that we check the registry rather than | |
118 // original_state since on a fresh install the "ap" value will be present | |
119 // sans "pv" value. | |
120 channel_info.Initialize(RegKey(reg_root, key_path.c_str(), KEY_QUERY_VALUE)); | |
121 | |
122 // This is a multi-install product. | |
123 bool modified = channel_info.SetMultiInstall(true); | |
124 | |
125 // Add the appropriate modifiers for all products and their options. | |
126 Products::const_iterator scan = package.products().begin(); | |
127 const Products::const_iterator end = package.products().end(); | |
128 for (; scan != end; ++scan) { | |
129 modified |= scan->get()->distribution()->SetChannelFlags(true, | |
130 &channel_info); | |
131 } | |
132 | |
133 // Write the results if needed. | |
134 if (modified) { | |
135 install_list->AddSetRegValueWorkItem(reg_root, key_path, | |
136 google_update::kRegApField, | |
137 channel_info.value(), true); | |
138 } | |
139 | |
140 // Synchronize the other products and the package with this one. | |
141 std::wstring other_key; | |
142 std::vector<std::wstring> keys; | |
143 | |
144 keys.reserve(package.products().size()); | |
145 other_key = package.properties()->GetStateKey(); | |
146 if (other_key != key_path) | |
147 keys.push_back(other_key); | |
148 scan = package.products().begin(); | |
149 for (; scan != end; ++scan) { | |
150 other_key = scan->get()->distribution()->GetStateKey(); | |
151 if (other_key != key_path) | |
152 keys.push_back(other_key); | |
153 } | |
154 | |
155 RegKey key; | |
156 ChannelInfo other_info; | |
157 std::vector<std::wstring>::const_iterator kscan = keys.begin(); | |
158 std::vector<std::wstring>::const_iterator kend = keys.end(); | |
159 for (; kscan != kend; ++kscan) { | |
160 // Handle the case where the ClientState key doesn't exist by creating it. | |
161 // This takes care of the multi-installer's package key, which is not | |
162 // created by Google Update for us. | |
163 if (key.Open(reg_root, kscan->c_str(), KEY_QUERY_VALUE) != ERROR_SUCCESS || | |
164 !other_info.Initialize(key)) { | |
165 other_info.set_value(std::wstring()); | |
166 } | |
167 if (!other_info.Equals(channel_info)) { | |
168 if (!key.Valid()) | |
169 install_list->AddCreateRegKeyWorkItem(reg_root, *kscan); | |
170 install_list->AddSetRegValueWorkItem(reg_root, *kscan, | |
171 google_update::kRegApField, | |
172 channel_info.value(), true); | |
173 } | |
174 } | |
175 // TODO(grt): check for other keys/values we should put in the package's | |
176 // ClientState and/or Clients key. | |
177 } | |
178 | |
179 // This is called when an MSI installation is run. It may be that a user is | |
180 // attempting to install the MSI on top of a non-MSI managed installation. | |
181 // If so, try and remove any existing uninstallation shortcuts, as we want the | |
182 // uninstall to be managed entirely by the MSI machinery (accessible via the | |
183 // Add/Remove programs dialog). | |
184 void AddDeleteUninstallShortcutsForMSIWorkItems(const Product& product, | |
185 WorkItemList* work_item_list) { | |
186 DCHECK(product.IsMsi()) << "This must only be called for MSI installations!"; | |
187 | |
188 // First attempt to delete the old installation's ARP dialog entry. | |
189 HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE : | |
190 HKEY_CURRENT_USER; | |
191 base::win::RegKey root_key(reg_root, L"", KEY_ALL_ACCESS); | |
192 std::wstring uninstall_reg(product.distribution()->GetUninstallRegPath()); | |
193 | |
194 WorkItem* delete_reg_key = work_item_list->AddDeleteRegKeyWorkItem( | |
195 reg_root, uninstall_reg); | |
196 delete_reg_key->set_ignore_failure(true); | |
197 | |
198 // Then attempt to delete the old installation's start menu shortcut. | |
199 FilePath uninstall_link; | |
200 if (product.system_level()) { | |
201 PathService::Get(base::DIR_COMMON_START_MENU, &uninstall_link); | |
202 } else { | |
203 PathService::Get(base::DIR_START_MENU, &uninstall_link); | |
204 } | |
205 | |
206 if (uninstall_link.empty()) { | |
207 LOG(ERROR) << "Failed to get location for shortcut."; | |
208 } else { | |
209 uninstall_link = uninstall_link.Append( | |
210 product.distribution()->GetAppShortCutName()); | |
211 uninstall_link = uninstall_link.Append( | |
212 product.distribution()->GetUninstallLinkName() + L".lnk"); | |
213 VLOG(1) << "Deleting old uninstall shortcut (if present): " | |
214 << uninstall_link.value(); | |
215 WorkItem* delete_link = work_item_list->AddDeleteTreeWorkItem( | |
216 uninstall_link); | |
217 delete_link->set_ignore_failure(true); | |
218 delete_link->set_log_message( | |
219 "Failed to delete old uninstall shortcut."); | |
220 } | |
221 } | |
222 | |
223 // Copy master preferences file provided to installer, in the same folder | 84 // Copy master preferences file provided to installer, in the same folder |
224 // as chrome.exe so Chrome first run can find it. This function will be called | 85 // as chrome.exe so Chrome first run can find it. This function will be called |
225 // only on the first install of Chrome. | 86 // only on the first install of Chrome. |
226 void CopyPreferenceFileForFirstRun(const Package& package, | 87 void CopyPreferenceFileForFirstRun(const InstallerState& installer_state, |
227 const FilePath& prefs_source_path) { | 88 const FilePath& prefs_source_path) { |
228 FilePath prefs_dest_path(package.path().AppendASCII( | 89 FilePath prefs_dest_path(installer_state.target_path().AppendASCII( |
229 installer::kDefaultMasterPrefs)); | 90 installer::kDefaultMasterPrefs)); |
230 if (!file_util::CopyFile(prefs_source_path, prefs_dest_path)) { | 91 if (!file_util::CopyFile(prefs_source_path, prefs_dest_path)) { |
231 VLOG(1) << "Failed to copy master preferences from:" | 92 VLOG(1) << "Failed to copy master preferences from:" |
232 << prefs_source_path.value() << " gle: " << ::GetLastError(); | 93 << prefs_source_path.value() << " gle: " << ::GetLastError(); |
233 } | 94 } |
234 } | 95 } |
235 | 96 |
236 // This method creates Chrome shortcuts in Start->Programs for all users or | 97 // This method creates Chrome shortcuts in Start->Programs for all users or |
237 // only for current user depending on whether it is system wide install or | 98 // only for current user depending on whether it is system wide install or |
238 // user only install. | 99 // user only install. |
239 // | 100 // |
240 // If first_install is true, it creates shortcuts for launching and | 101 // If first_install is true, it creates shortcuts for launching and |
241 // uninstalling chrome. | 102 // uninstalling chrome. |
242 // If first_install is false, the function only updates the shortcut for | 103 // If first_install is false, the function only updates the shortcut for |
243 // uninstalling chrome. According to | 104 // uninstalling chrome. According to |
244 // http://blogs.msdn.com/oldnewthing/archive/2005/11/24/496690.aspx, | 105 // http://blogs.msdn.com/oldnewthing/archive/2005/11/24/496690.aspx, |
245 // updating uninstall shortcut should not trigger Windows "new application | 106 // updating uninstall shortcut should not trigger Windows "new application |
246 // installed" notification. | 107 // installed" notification. |
247 // | 108 // |
248 // If the shortcuts do not exist, the function does not recreate them during | 109 // If the shortcuts do not exist, the function does not recreate them during |
249 // update. | 110 // update. |
250 bool CreateOrUpdateChromeShortcuts(const FilePath& setup_path, | 111 bool CreateOrUpdateChromeShortcuts(const InstallerState& installer_state, |
112 const FilePath& setup_path, | |
251 const Version& new_version, | 113 const Version& new_version, |
252 installer::InstallStatus install_status, | 114 installer::InstallStatus install_status, |
253 const Product& product, | 115 const Product& product, |
254 bool create_all_shortcut, | 116 bool create_all_shortcut, |
255 bool alt_shortcut) { | 117 bool alt_shortcut) { |
256 // TODO(tommi): Change this function to use WorkItemList. | 118 // TODO(tommi): Change this function to use WorkItemList. |
257 DCHECK(product.is_chrome()); | 119 DCHECK(product.is_chrome()); |
258 | 120 |
259 FilePath shortcut_path; | 121 FilePath shortcut_path; |
260 int dir_enum = product.system_level() ? | 122 int dir_enum = installer_state.system_install() ? |
261 base::DIR_COMMON_START_MENU : base::DIR_START_MENU; | 123 base::DIR_COMMON_START_MENU : base::DIR_START_MENU; |
262 if (!PathService::Get(dir_enum, &shortcut_path)) { | 124 if (!PathService::Get(dir_enum, &shortcut_path)) { |
263 LOG(ERROR) << "Failed to get location for shortcut."; | 125 LOG(ERROR) << "Failed to get location for shortcut."; |
264 return false; | 126 return false; |
265 } | 127 } |
266 | 128 |
267 BrowserDistribution* browser_dist = product.distribution(); | 129 BrowserDistribution* browser_dist = product.distribution(); |
268 | 130 |
269 // The location of Start->Programs->Google Chrome folder | 131 // The location of Start->Programs->Google Chrome folder |
270 const std::wstring product_name(browser_dist->GetAppShortCutName()); | 132 const std::wstring product_name(browser_dist->GetAppShortCutName()); |
271 const std::wstring product_desc(browser_dist->GetAppDescription()); | 133 const std::wstring product_desc(browser_dist->GetAppDescription()); |
272 shortcut_path = shortcut_path.Append(product_name); | 134 shortcut_path = shortcut_path.Append(product_name); |
273 | 135 |
274 // Create/update Chrome link (points to chrome.exe) & Uninstall Chrome link | 136 // Create/update Chrome link (points to chrome.exe) & Uninstall Chrome link |
275 // (which points to setup.exe) under this folder only if: | 137 // (which points to setup.exe) under this folder only if: |
276 // - This is a new install or install repair | 138 // - This is a new install or install repair |
277 // OR | 139 // OR |
278 // - The shortcut already exists in case of updates (user may have deleted | 140 // - The shortcut already exists in case of updates (user may have deleted |
279 // shortcuts since our install. So on updates we only update if shortcut | 141 // shortcuts since our install. So on updates we only update if shortcut |
280 // already exists) | 142 // already exists) |
281 bool ret = true; | 143 bool ret = true; |
282 FilePath chrome_link(shortcut_path); // Chrome link (launches Chrome) | 144 FilePath chrome_link(shortcut_path); // Chrome link (launches Chrome) |
283 chrome_link = chrome_link.Append(product_name + L".lnk"); | 145 chrome_link = chrome_link.Append(product_name + L".lnk"); |
284 // Chrome link target | 146 // Chrome link target |
285 FilePath chrome_exe( | 147 FilePath chrome_exe( |
286 product.package().path().Append(installer::kChromeExe)); | 148 installer_state.target_path().Append(installer::kChromeExe)); |
287 | 149 |
288 if ((install_status == installer::FIRST_INSTALL_SUCCESS) || | 150 if ((install_status == installer::FIRST_INSTALL_SUCCESS) || |
289 (install_status == installer::INSTALL_REPAIRED)) { | 151 (install_status == installer::INSTALL_REPAIRED)) { |
290 if (!file_util::PathExists(shortcut_path)) | 152 if (!file_util::PathExists(shortcut_path)) |
291 file_util::CreateDirectoryW(shortcut_path); | 153 file_util::CreateDirectoryW(shortcut_path); |
292 | 154 |
293 VLOG(1) << "Creating shortcut to " << chrome_exe.value() << " at " | 155 VLOG(1) << "Creating shortcut to " << chrome_exe.value() << " at " |
294 << chrome_link.value(); | 156 << chrome_link.value(); |
295 ret = ShellUtil::UpdateChromeShortcut(browser_dist, chrome_exe.value(), | 157 ret = ShellUtil::UpdateChromeShortcut(browser_dist, chrome_exe.value(), |
296 chrome_link.value(), product_desc, true); | 158 chrome_link.value(), product_desc, true); |
297 } else if (file_util::PathExists(chrome_link)) { | 159 } else if (file_util::PathExists(chrome_link)) { |
298 VLOG(1) << "Updating shortcut at " << chrome_link.value() | 160 VLOG(1) << "Updating shortcut at " << chrome_link.value() |
299 << " to point to " << chrome_exe.value(); | 161 << " to point to " << chrome_exe.value(); |
300 ret = ShellUtil::UpdateChromeShortcut(browser_dist, chrome_exe.value(), | 162 ret = ShellUtil::UpdateChromeShortcut(browser_dist, chrome_exe.value(), |
301 chrome_link.value(), product_desc, false); | 163 chrome_link.value(), product_desc, false); |
302 } else { | 164 } else { |
303 VLOG(1) | 165 VLOG(1) |
304 << "not first or repaired install, link file doesn't exist. status: " | 166 << "not first or repaired install, link file doesn't exist. status: " |
305 << install_status; | 167 << install_status; |
306 } | 168 } |
307 | 169 |
308 // Create/update uninstall link if we are not an MSI install. MSI | 170 // Create/update uninstall link if we are not an MSI install. MSI |
309 // installations are, for the time being, managed only through the | 171 // installations are, for the time being, managed only through the |
310 // Add/Remove Programs dialog. | 172 // Add/Remove Programs dialog. |
311 // TODO(robertshield): We could add a shortcut to msiexec /X {GUID} here. | 173 // TODO(robertshield): We could add a shortcut to msiexec /X {GUID} here. |
312 if (ret && !product.IsMsi()) { | 174 if (ret && !installer_state.msi()) { |
313 FilePath uninstall_link(shortcut_path); // Uninstall Chrome link | 175 FilePath uninstall_link(shortcut_path); // Uninstall Chrome link |
314 uninstall_link = uninstall_link.Append( | 176 uninstall_link = uninstall_link.Append( |
315 browser_dist->GetUninstallLinkName() + L".lnk"); | 177 browser_dist->GetUninstallLinkName() + L".lnk"); |
316 if ((install_status == installer::FIRST_INSTALL_SUCCESS) || | 178 if ((install_status == installer::FIRST_INSTALL_SUCCESS) || |
317 (install_status == installer::INSTALL_REPAIRED) || | 179 (install_status == installer::INSTALL_REPAIRED) || |
318 (file_util::PathExists(uninstall_link))) { | 180 (file_util::PathExists(uninstall_link))) { |
319 if (!file_util::PathExists(shortcut_path)) | 181 if (!file_util::PathExists(shortcut_path)) |
320 file_util::CreateDirectory(shortcut_path); | 182 file_util::CreateDirectory(shortcut_path); |
321 | 183 |
322 FilePath setup_exe( | 184 FilePath setup_exe(installer_state.GetInstallerDirectory(new_version) |
323 product.package().GetInstallerDirectory(new_version) | 185 .Append(setup_path.BaseName())); |
324 .Append(setup_path.BaseName())); | |
325 | 186 |
326 CommandLine arguments(CommandLine::NO_PROGRAM); | 187 CommandLine arguments(CommandLine::NO_PROGRAM); |
327 AppendUninstallCommandLineFlags(&arguments, product); | 188 AppendUninstallCommandLineFlags(installer_state, product, &arguments); |
328 VLOG(1) << "Creating/updating uninstall link at " | 189 VLOG(1) << "Creating/updating uninstall link at " |
329 << uninstall_link.value(); | 190 << uninstall_link.value(); |
330 ret = file_util::CreateShortcutLink(setup_exe.value().c_str(), | 191 ret = file_util::CreateShortcutLink(setup_exe.value().c_str(), |
331 uninstall_link.value().c_str(), | 192 uninstall_link.value().c_str(), |
332 NULL, | 193 NULL, |
333 arguments.command_line_string().c_str(), | 194 arguments.command_line_string().c_str(), |
334 NULL, | 195 NULL, |
335 setup_exe.value().c_str(), | 196 setup_exe.value().c_str(), |
336 0, | 197 0, |
337 NULL); | 198 NULL); |
338 } | 199 } |
339 } | 200 } |
340 | 201 |
341 // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts | 202 // Update Desktop and Quick Launch shortcuts. If --create-new-shortcuts |
342 // is specified we want to create them, otherwise we update them only if | 203 // is specified we want to create them, otherwise we update them only if |
343 // they exist. | 204 // they exist. |
344 if (ret) { | 205 if (ret) { |
345 if (product.system_level()) { | 206 if (installer_state.system_install()) { |
346 ret = ShellUtil::CreateChromeDesktopShortcut(product.distribution(), | 207 ret = ShellUtil::CreateChromeDesktopShortcut(product.distribution(), |
347 chrome_exe.value(), product_desc, ShellUtil::SYSTEM_LEVEL, | 208 chrome_exe.value(), product_desc, ShellUtil::SYSTEM_LEVEL, |
348 alt_shortcut, create_all_shortcut); | 209 alt_shortcut, create_all_shortcut); |
349 if (ret) { | 210 if (ret) { |
350 ret = ShellUtil::CreateChromeQuickLaunchShortcut( | 211 ret = ShellUtil::CreateChromeQuickLaunchShortcut( |
351 product.distribution(), chrome_exe.value(), | 212 product.distribution(), chrome_exe.value(), |
352 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, | 213 ShellUtil::CURRENT_USER | ShellUtil::SYSTEM_LEVEL, |
353 create_all_shortcut); | 214 create_all_shortcut); |
354 } | 215 } |
355 } else { | 216 } else { |
356 ret = ShellUtil::CreateChromeDesktopShortcut(product.distribution(), | 217 ret = ShellUtil::CreateChromeDesktopShortcut(product.distribution(), |
357 chrome_exe.value(), product_desc, ShellUtil::CURRENT_USER, | 218 chrome_exe.value(), product_desc, ShellUtil::CURRENT_USER, |
358 alt_shortcut, create_all_shortcut); | 219 alt_shortcut, create_all_shortcut); |
359 if (ret) { | 220 if (ret) { |
360 ret = ShellUtil::CreateChromeQuickLaunchShortcut( | 221 ret = ShellUtil::CreateChromeQuickLaunchShortcut( |
361 product.distribution(), chrome_exe.value(), ShellUtil::CURRENT_USER, | 222 product.distribution(), chrome_exe.value(), ShellUtil::CURRENT_USER, |
362 create_all_shortcut); | 223 create_all_shortcut); |
363 } | 224 } |
364 } | 225 } |
365 } | 226 } |
366 | 227 |
367 return ret; | 228 return ret; |
368 } | 229 } |
369 | 230 |
370 | 231 void RegisterChromeOnMachine(const InstallerState& installer_state, |
371 void RegisterChromeOnMachine(const Product& product, | 232 const Product& product, |
372 bool make_chrome_default) { | 233 bool make_chrome_default) { |
373 DCHECK(product.is_chrome()); | 234 DCHECK(product.is_chrome()); |
374 | 235 |
375 // Try to add Chrome to Media Player shim inclusion list. We don't do any | 236 // Try to add Chrome to Media Player shim inclusion list. We don't do any |
376 // error checking here because this operation will fail if user doesn't | 237 // error checking here because this operation will fail if user doesn't |
377 // have admin rights and we want to ignore the error. | 238 // have admin rights and we want to ignore the error. |
378 AddChromeToMediaPlayerList(); | 239 AddChromeToMediaPlayerList(); |
379 | 240 |
380 // Is --make-chrome-default option is given we make Chrome default browser | 241 // Is --make-chrome-default option is given we make Chrome default browser |
381 // otherwise we only register it on the machine as a valid browser. | 242 // otherwise we only register it on the machine as a valid browser. |
382 FilePath chrome_exe( | 243 FilePath chrome_exe( |
383 product.package().path().Append(installer::kChromeExe)); | 244 installer_state.target_path().Append(installer::kChromeExe)); |
384 VLOG(1) << "Registering Chrome as browser: " << chrome_exe.value(); | 245 VLOG(1) << "Registering Chrome as browser: " << chrome_exe.value(); |
385 if (make_chrome_default) { | 246 if (make_chrome_default) { |
386 int level = ShellUtil::CURRENT_USER; | 247 int level = ShellUtil::CURRENT_USER; |
387 if (product.system_level()) | 248 if (installer_state.system_install()) |
388 level = level | ShellUtil::SYSTEM_LEVEL; | 249 level = level | ShellUtil::SYSTEM_LEVEL; |
389 ShellUtil::MakeChromeDefault(product.distribution(), level, | 250 ShellUtil::MakeChromeDefault(product.distribution(), level, |
390 chrome_exe.value(), true); | 251 chrome_exe.value(), true); |
391 } else { | 252 } else { |
392 ShellUtil::RegisterChromeBrowser(product.distribution(), chrome_exe.value(), | 253 ShellUtil::RegisterChromeBrowser(product.distribution(), chrome_exe.value(), |
393 L"", false); | 254 L"", false); |
394 } | 255 } |
395 } | 256 } |
396 | 257 |
397 // This function installs a new version of Chrome to the specified location. | 258 // This function installs a new version of Chrome to the specified location. |
(...skipping 12 matching lines...) Expand all Loading... | |
410 // This function makes best effort to do installation in a transactional | 271 // This function makes best effort to do installation in a transactional |
411 // manner. If failed it tries to rollback all changes on the file system | 272 // manner. If failed it tries to rollback all changes on the file system |
412 // and registry. For example, if package exists before calling the | 273 // and registry. For example, if package exists before calling the |
413 // function, it rolls back all new file and directory changes under | 274 // function, it rolls back all new file and directory changes under |
414 // package. If package does not exist before calling the function | 275 // package. If package does not exist before calling the function |
415 // (typical new install), the function creates package during install | 276 // (typical new install), the function creates package during install |
416 // and removes the whole directory during rollback. | 277 // and removes the whole directory during rollback. |
417 installer::InstallStatus InstallNewVersion( | 278 installer::InstallStatus InstallNewVersion( |
418 const InstallationState& original_state, | 279 const InstallationState& original_state, |
419 const InstallerState& installer_state, | 280 const InstallerState& installer_state, |
420 bool multi_install, | |
421 const FilePath& setup_path, | 281 const FilePath& setup_path, |
422 const FilePath& archive_path, | 282 const FilePath& archive_path, |
423 const FilePath& src_path, | 283 const FilePath& src_path, |
424 const FilePath& temp_dir, | 284 const FilePath& temp_dir, |
425 const Version& new_version, | 285 const Version& new_version, |
426 scoped_ptr<Version>* current_version, | 286 scoped_ptr<Version>* current_version) { |
427 const Package& package) { | |
428 DCHECK(current_version); | 287 DCHECK(current_version); |
429 | 288 |
430 current_version->reset(package.GetCurrentVersion()); | 289 current_version->reset(installer_state.GetCurrentVersion(original_state)); |
431 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); | 290 scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList()); |
432 | 291 |
433 AddInstallWorkItems(original_state, | 292 AddInstallWorkItems(original_state, |
434 installer_state, | 293 installer_state, |
435 multi_install, | |
436 setup_path, | 294 setup_path, |
437 archive_path, | 295 archive_path, |
438 src_path, | 296 src_path, |
439 temp_dir, | 297 temp_dir, |
440 new_version, | 298 new_version, |
441 current_version, | 299 current_version, |
442 package, | |
443 install_list.get()); | 300 install_list.get()); |
444 | 301 |
445 FilePath new_chrome_exe( | 302 FilePath new_chrome_exe( |
446 package.path().Append(installer::kChromeNewExe)); | 303 installer_state.target_path().Append(installer::kChromeNewExe)); |
447 | 304 |
448 if (!install_list->Do()) { | 305 if (!install_list->Do()) { |
449 installer::InstallStatus result = | 306 installer::InstallStatus result = |
450 file_util::PathExists(new_chrome_exe) && current_version->get() && | 307 file_util::PathExists(new_chrome_exe) && current_version->get() && |
451 new_version.Equals(*current_version->get()) ? | 308 new_version.Equals(*current_version->get()) ? |
452 installer::SAME_VERSION_REPAIR_FAILED : | 309 installer::SAME_VERSION_REPAIR_FAILED : |
453 installer::INSTALL_FAILED; | 310 installer::INSTALL_FAILED; |
454 LOG(ERROR) << "Install failed, rolling back... result: " << result; | 311 LOG(ERROR) << "Install failed, rolling back... result: " << result; |
455 install_list->Rollback(); | 312 install_list->Rollback(); |
456 LOG(ERROR) << "Rollback complete. "; | 313 LOG(ERROR) << "Rollback complete. "; |
(...skipping 24 matching lines...) Expand all Loading... | |
481 << ", new version: " << new_version.GetString() | 338 << ", new version: " << new_version.GetString() |
482 << ", old version: " << (*current_version)->GetString(); | 339 << ", old version: " << (*current_version)->GetString(); |
483 | 340 |
484 return installer::INSTALL_FAILED; | 341 return installer::INSTALL_FAILED; |
485 } | 342 } |
486 | 343 |
487 } // end namespace | 344 } // end namespace |
488 | 345 |
489 namespace installer { | 346 namespace installer { |
490 | 347 |
491 installer::InstallStatus InstallOrUpdateProduct( | 348 InstallStatus InstallOrUpdateProduct( |
492 const InstallationState& original_state, | 349 const InstallationState& original_state, |
493 const InstallerState& installer_state, | 350 const InstallerState& installer_state, |
494 const FilePath& setup_path, const FilePath& archive_path, | 351 const FilePath& setup_path, const FilePath& archive_path, |
495 const FilePath& install_temp_path, const FilePath& prefs_path, | 352 const FilePath& install_temp_path, const FilePath& prefs_path, |
496 const installer::MasterPreferences& prefs, const Version& new_version, | 353 const MasterPreferences& prefs, const Version& new_version) { |
robertshield
2011/01/20 22:06:06
could we put each of these parameters on a separat
grt (UTC plus 2)
2011/01/21 05:27:51
Done.
| |
497 const Package& install) { | |
498 FilePath src_path(install_temp_path); | 354 FilePath src_path(install_temp_path); |
499 src_path = src_path.Append(kInstallSourceDir).Append(kInstallSourceChromeDir); | 355 src_path = src_path.Append(kInstallSourceDir).Append(kInstallSourceChromeDir); |
500 | 356 |
501 // TODO(robertshield): Removing the pending on-reboot moves should be done | 357 // TODO(robertshield): Removing the pending on-reboot moves should be done |
502 // elsewhere. | 358 // elsewhere. |
503 const Products& products = install.products(); | 359 const Products& products = installer_state.products(); |
504 DCHECK(products.size()); | 360 DCHECK(products.size()); |
505 if (FindProduct(products, BrowserDistribution::CHROME_FRAME)) { | 361 if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) { |
506 // Make sure that we don't end up deleting installed files on next reboot. | 362 // Make sure that we don't end up deleting installed files on next reboot. |
507 if (!RemoveFromMovesPendingReboot(install.path().value().c_str())) { | 363 if (!RemoveFromMovesPendingReboot( |
364 installer_state.target_path().value().c_str())) { | |
508 LOG(ERROR) << "Error accessing pending moves value."; | 365 LOG(ERROR) << "Error accessing pending moves value."; |
509 } | 366 } |
510 } | 367 } |
511 | 368 |
512 scoped_ptr<Version> existing_version; | 369 scoped_ptr<Version> existing_version; |
513 installer::InstallStatus result = InstallNewVersion(original_state, | 370 InstallStatus result = InstallNewVersion(original_state, installer_state, |
514 installer_state, prefs.is_multi_install(), setup_path, archive_path, | 371 setup_path, archive_path, src_path, install_temp_path, new_version, |
515 src_path, install_temp_path, new_version, &existing_version, install); | 372 &existing_version); |
516 | 373 |
517 // TODO(robertshield): Everything below this line should instead be captured | 374 // TODO(robertshield): Everything below this line should instead be captured |
518 // by WorkItems. | 375 // by WorkItems. |
519 if (!InstallUtil::GetInstallReturnCode(result)) { | 376 if (!InstallUtil::GetInstallReturnCode(result)) { |
520 if (result == installer::FIRST_INSTALL_SUCCESS && !prefs_path.empty()) | 377 if (result == FIRST_INSTALL_SUCCESS && !prefs_path.empty()) |
521 CopyPreferenceFileForFirstRun(install, prefs_path); | 378 CopyPreferenceFileForFirstRun(installer_state, prefs_path); |
522 | 379 |
523 bool do_not_create_shortcuts = false; | 380 bool do_not_create_shortcuts = false; |
524 prefs.GetBool(installer::master_preferences::kDoNotCreateShortcuts, | 381 prefs.GetBool(master_preferences::kDoNotCreateShortcuts, |
525 &do_not_create_shortcuts); | 382 &do_not_create_shortcuts); |
526 | 383 |
527 // Currently this only creates shortcuts for Chrome, but for other products | 384 // Currently this only creates shortcuts for Chrome, but for other products |
528 // we might want to create shortcuts. | 385 // we might want to create shortcuts. |
529 const Product* chrome_install = | 386 const Product* chrome_install = |
530 FindProduct(install.products(), BrowserDistribution::CHROME_BROWSER); | 387 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); |
531 if (chrome_install && !do_not_create_shortcuts) { | 388 if (chrome_install && !do_not_create_shortcuts) { |
532 bool create_all_shortcut = false; | 389 bool create_all_shortcut = false; |
533 prefs.GetBool(installer::master_preferences::kCreateAllShortcuts, | 390 prefs.GetBool(master_preferences::kCreateAllShortcuts, |
534 &create_all_shortcut); | 391 &create_all_shortcut); |
535 bool alt_shortcut = false; | 392 bool alt_shortcut = false; |
536 prefs.GetBool(installer::master_preferences::kAltShortcutText, | 393 prefs.GetBool(master_preferences::kAltShortcutText, &alt_shortcut); |
537 &alt_shortcut); | 394 if (!CreateOrUpdateChromeShortcuts(installer_state, setup_path, |
538 if (!CreateOrUpdateChromeShortcuts(setup_path, new_version, result, | 395 new_version, result, *chrome_install, |
539 *chrome_install, create_all_shortcut, | 396 create_all_shortcut, alt_shortcut)) { |
540 alt_shortcut)) { | |
541 PLOG(WARNING) << "Failed to create/update start menu shortcut."; | 397 PLOG(WARNING) << "Failed to create/update start menu shortcut."; |
542 } | 398 } |
543 | 399 |
544 bool make_chrome_default = false; | 400 bool make_chrome_default = false; |
545 prefs.GetBool(installer::master_preferences::kMakeChromeDefault, | 401 prefs.GetBool(master_preferences::kMakeChromeDefault, |
546 &make_chrome_default); | 402 &make_chrome_default); |
547 | 403 |
548 // If this is not the user's first Chrome install, but they have chosen | 404 // If this is not the user's first Chrome install, but they have chosen |
549 // Chrome to become their default browser on the download page, we must | 405 // Chrome to become their default browser on the download page, we must |
550 // force it here because the master_preferences file will not get copied | 406 // force it here because the master_preferences file will not get copied |
551 // into the build. | 407 // into the build. |
552 bool force_chrome_default_for_user = false; | 408 bool force_chrome_default_for_user = false; |
553 if (result == installer::NEW_VERSION_UPDATED || | 409 if (result == NEW_VERSION_UPDATED || |
554 result == installer::INSTALL_REPAIRED) { | 410 result == INSTALL_REPAIRED) { |
555 prefs.GetBool( | 411 prefs.GetBool(master_preferences::kMakeChromeDefaultForUser, |
556 installer::master_preferences::kMakeChromeDefaultForUser, | 412 &force_chrome_default_for_user); |
557 &force_chrome_default_for_user); | |
558 } | 413 } |
559 | 414 |
560 RegisterChromeOnMachine(*chrome_install, | 415 RegisterChromeOnMachine(installer_state, *chrome_install, |
561 make_chrome_default || force_chrome_default_for_user); | 416 make_chrome_default || force_chrome_default_for_user); |
562 } | 417 } |
563 | 418 |
564 install.RemoveOldVersionDirectories(existing_version.get() ? | 419 installer_state.RemoveOldVersionDirectories(existing_version.get() ? |
565 *existing_version.get() : new_version); | 420 *existing_version.get() : new_version); |
566 } | 421 } |
567 | 422 |
568 return result; | 423 return result; |
569 } | 424 } |
570 | 425 |
571 } // namespace installer | 426 } // namespace installer |
OLD | NEW |