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 // This file contains the definitions of the installer functions that build | 5 // This file contains the definitions of the installer functions that build |
6 // the WorkItemList used to install the application. | 6 // the WorkItemList used to install the application. |
7 | 7 |
8 #include "chrome/installer/setup/install_worker.h" | 8 #include "chrome/installer/setup/install_worker.h" |
9 | 9 |
10 #include <shlobj.h> | 10 #include <shlobj.h> |
11 #include <time.h> | 11 #include <time.h> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "base/command_line.h" | 14 #include "base/command_line.h" |
15 #include "base/file_path.h" | 15 #include "base/file_path.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/path_service.h" | 17 #include "base/path_service.h" |
18 #include "base/string_util.h" | 18 #include "base/string_util.h" |
19 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
20 #include "base/version.h" | 20 #include "base/version.h" |
21 #include "base/win/registry.h" | 21 #include "base/win/registry.h" |
22 #include "chrome/installer/setup/install.h" | 22 #include "chrome/installer/setup/install.h" |
23 #include "chrome/installer/setup/setup_constants.h" | 23 #include "chrome/installer/setup/setup_constants.h" |
24 #include "chrome/installer/util/chrome_frame_distribution.h" | |
25 #include "chrome/installer/util/conditional_work_item_list.h" | 24 #include "chrome/installer/util/conditional_work_item_list.h" |
26 #include "chrome/installer/util/create_reg_key_work_item.h" | 25 #include "chrome/installer/util/create_reg_key_work_item.h" |
27 #include "chrome/installer/util/google_update_constants.h" | 26 #include "chrome/installer/util/google_update_constants.h" |
28 #include "chrome/installer/util/helper.h" | 27 #include "chrome/installer/util/helper.h" |
29 #include "chrome/installer/util/installation_state.h" | 28 #include "chrome/installer/util/installation_state.h" |
30 #include "chrome/installer/util/installer_state.h" | 29 #include "chrome/installer/util/installer_state.h" |
31 #include "chrome/installer/util/install_util.h" | 30 #include "chrome/installer/util/install_util.h" |
32 #include "chrome/installer/util/master_preferences.h" | |
33 #include "chrome/installer/util/master_preferences_constants.h" | |
34 #include "chrome/installer/util/package.h" | |
35 #include "chrome/installer/util/package_properties.h" | |
36 #include "chrome/installer/util/product.h" | 31 #include "chrome/installer/util/product.h" |
37 #include "chrome/installer/util/set_reg_value_work_item.h" | 32 #include "chrome/installer/util/set_reg_value_work_item.h" |
38 #include "chrome/installer/util/shell_util.h" | 33 #include "chrome/installer/util/shell_util.h" |
39 #include "chrome/installer/util/util_constants.h" | 34 #include "chrome/installer/util/util_constants.h" |
40 #include "chrome/installer/util/work_item_list.h" | 35 #include "chrome/installer/util/work_item_list.h" |
41 | 36 |
42 using base::win::RegKey; | 37 using base::win::RegKey; |
43 | 38 |
44 namespace { | 39 namespace { |
45 | 40 |
(...skipping 10 matching lines...) Expand all Loading... | |
56 return (is_wow64 != NULL) && | 51 return (is_wow64 != NULL) && |
57 (!(is_wow64)(GetCurrentProcess(), &is_64) || (is_64 != FALSE)); | 52 (!(is_wow64)(GetCurrentProcess(), &is_64) || (is_64 != FALSE)); |
58 } | 53 } |
59 | 54 |
60 } // namespace | 55 } // namespace |
61 | 56 |
62 namespace installer { | 57 namespace installer { |
63 | 58 |
64 // Local helper to call AddRegisterComDllWorkItems for all DLLs in a set of | 59 // Local helper to call AddRegisterComDllWorkItems for all DLLs in a set of |
65 // products managed by a given package. | 60 // products managed by a given package. |
66 void AddRegisterComDllWorkItemsForPackage(const Package& package, | 61 void AddRegisterComDllWorkItemsForPackage(const InstallerState& installer_state, |
67 const Version* old_version, | 62 const Version* old_version, |
68 const Version& new_version, | 63 const Version& new_version, |
69 WorkItemList* work_item_list) { | 64 WorkItemList* work_item_list) { |
70 // First collect the list of DLLs to be registered from each product. | 65 // First collect the list of DLLs to be registered from each product. |
71 const Products& products = package.products(); | |
72 Products::const_iterator product_iter(products.begin()); | |
73 std::vector<FilePath> com_dll_list; | 66 std::vector<FilePath> com_dll_list; |
74 for (; product_iter != products.end(); ++product_iter) { | 67 installer_state.AddComDllList(&com_dll_list); |
75 BrowserDistribution* dist = product_iter->get()->distribution(); | |
76 std::vector<FilePath> dist_dll_list(dist->GetComDllList()); | |
77 com_dll_list.insert(com_dll_list.end(), dist_dll_list.begin(), | |
78 dist_dll_list.end()); | |
79 } | |
80 | 68 |
81 // Then, if we got some, attempt to unregister the DLLs from the old | 69 // Then, if we got some, attempt to unregister the DLLs from the old |
82 // version directory and then re-register them in the new one. | 70 // version directory and then re-register them in the new one. |
83 // Note that if we are migrating the install directory then we will not | 71 // Note that if we are migrating the install directory then we will not |
84 // successfully unregister the old DLLs. | 72 // successfully unregister the old DLLs. |
85 // TODO(robertshield): See whether we need to fix the migration case. | 73 // TODO(robertshield): See whether we need to fix the migration case. |
86 // TODO(robertshield): If we ever remove a DLL from a product, this will | 74 // TODO(robertshield): If we ever remove a DLL from a product, this will |
87 // not unregister it on update. We should build the unregistration list from | 75 // not unregister it on update. We should build the unregistration list from |
88 // saved state instead of assuming it is the same as the registration list. | 76 // saved state instead of assuming it is the same as the registration list. |
89 if (!com_dll_list.empty()) { | 77 if (!com_dll_list.empty()) { |
90 if (old_version) { | 78 if (old_version) { |
91 FilePath old_dll_path( | 79 FilePath old_dll_path(installer_state.target_path().Append( |
92 package.path().Append(UTF8ToWide(old_version->GetString()))); | 80 UTF8ToWide(old_version->GetString()))); |
93 | 81 |
94 installer::AddRegisterComDllWorkItems(old_dll_path, | 82 installer::AddRegisterComDllWorkItems(old_dll_path, |
95 com_dll_list, | 83 com_dll_list, |
96 package.system_level(), | 84 installer_state.system_install(), |
97 false, // Unregister | 85 false, // Unregister |
98 true, // May fail | 86 true, // May fail |
99 work_item_list); | 87 work_item_list); |
100 } | 88 } |
101 | 89 |
102 FilePath dll_path( | 90 FilePath dll_path(installer_state.target_path().Append( |
103 package.path().Append(UTF8ToWide(new_version.GetString()))); | 91 UTF8ToWide(new_version.GetString()))); |
104 installer::AddRegisterComDllWorkItems(dll_path, | 92 installer::AddRegisterComDllWorkItems(dll_path, |
105 com_dll_list, | 93 com_dll_list, |
106 package.system_level(), | 94 installer_state.system_install(), |
107 true, // Register | 95 true, // Register |
108 false, // Must succeed. | 96 false, // Must succeed. |
109 work_item_list); | 97 work_item_list); |
110 } | 98 } |
111 } | 99 } |
112 | 100 |
113 void AddInstallerCopyTasks(const FilePath& setup_path, | 101 void AddInstallerCopyTasks(const InstallerState& installer_state, |
102 const FilePath& setup_path, | |
114 const FilePath& archive_path, | 103 const FilePath& archive_path, |
115 const FilePath& temp_path, | 104 const FilePath& temp_path, |
116 const Version& new_version, | 105 const Version& new_version, |
117 WorkItemList* install_list, | 106 WorkItemList* install_list) { |
118 const Package& package) { | |
119 DCHECK(install_list); | 107 DCHECK(install_list); |
120 FilePath installer_dir(package.GetInstallerDirectory(new_version)); | 108 FilePath installer_dir(installer_state.GetInstallerDirectory(new_version)); |
121 install_list->AddCreateDirWorkItem(installer_dir); | 109 install_list->AddCreateDirWorkItem(installer_dir); |
122 | 110 |
123 FilePath exe_dst(installer_dir.Append(setup_path.BaseName())); | 111 FilePath exe_dst(installer_dir.Append(setup_path.BaseName())); |
124 FilePath archive_dst(installer_dir.Append(archive_path.BaseName())); | 112 FilePath archive_dst(installer_dir.Append(archive_path.BaseName())); |
125 | 113 |
126 install_list->AddCopyTreeWorkItem(setup_path.value(), exe_dst.value(), | 114 install_list->AddCopyTreeWorkItem(setup_path.value(), exe_dst.value(), |
127 temp_path.value(), WorkItem::ALWAYS); | 115 temp_path.value(), WorkItem::ALWAYS); |
128 if (package.system_level()) { | 116 if (installer_state.system_install()) { |
129 install_list->AddCopyTreeWorkItem(archive_path.value(), archive_dst.value(), | 117 install_list->AddCopyTreeWorkItem(archive_path.value(), archive_dst.value(), |
130 temp_path.value(), WorkItem::ALWAYS); | 118 temp_path.value(), WorkItem::ALWAYS); |
131 } else { | 119 } else { |
132 install_list->AddMoveTreeWorkItem(archive_path.value(), archive_dst.value(), | 120 install_list->AddMoveTreeWorkItem(archive_path.value(), archive_dst.value(), |
133 temp_path.value()); | 121 temp_path.value()); |
134 } | 122 } |
135 } | 123 } |
136 | 124 |
137 // This method adds work items to create (or update) Chrome uninstall entry in | 125 // This method adds work items to create (or update) Chrome uninstall entry in |
138 // either the Control Panel->Add/Remove Programs list or in the Omaha client | 126 // either the Control Panel->Add/Remove Programs list or in the Omaha client |
139 // state key if running under an MSI installer. | 127 // state key if running under an MSI installer. |
140 void AddUninstallShortcutWorkItems(const FilePath& setup_path, | 128 void AddUninstallShortcutWorkItems(const InstallerState& installer_state, |
129 const FilePath& setup_path, | |
141 const Version& new_version, | 130 const Version& new_version, |
142 WorkItemList* install_list, | 131 WorkItemList* install_list, |
143 const Product& product) { | 132 const Product& product) { |
144 HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE : | 133 HKEY reg_root = installer_state.root_key(); |
145 HKEY_CURRENT_USER; | |
146 BrowserDistribution* browser_dist = product.distribution(); | 134 BrowserDistribution* browser_dist = product.distribution(); |
147 DCHECK(browser_dist); | 135 DCHECK(browser_dist); |
148 | 136 |
149 // When we are installed via an MSI, we need to store our uninstall strings | 137 // When we are installed via an MSI, we need to store our uninstall strings |
150 // in the Google Update client state key. We do this even for non-MSI | 138 // in the Google Update client state key. We do this even for non-MSI |
151 // managed installs to avoid breaking the edge case whereby an MSI-managed | 139 // managed installs to avoid breaking the edge case whereby an MSI-managed |
152 // install is updated by a non-msi installer (which would confuse the MSI | 140 // install is updated by a non-msi installer (which would confuse the MSI |
153 // machinery if these strings were not also updated). | 141 // machinery if these strings were not also updated). |
154 // Do not quote the command line for the MSI invocation. | 142 // Do not quote the command line for the MSI invocation. |
155 FilePath install_path(product.package().path()); | 143 FilePath install_path(installer_state.target_path()); |
156 FilePath installer_path( | 144 FilePath installer_path(installer_state.GetInstallerDirectory(new_version)); |
157 product.package().GetInstallerDirectory(new_version)); | |
158 installer_path = installer_path.Append(setup_path.BaseName()); | 145 installer_path = installer_path.Append(setup_path.BaseName()); |
159 | 146 |
160 CommandLine uninstall_arguments(CommandLine::NO_PROGRAM); | 147 CommandLine uninstall_arguments(CommandLine::NO_PROGRAM); |
161 AppendUninstallCommandLineFlags(&uninstall_arguments, product); | 148 AppendUninstallCommandLineFlags(installer_state, product, |
149 &uninstall_arguments); | |
162 | 150 |
163 if (product.is_chrome()) { | 151 // The Chrome uninstallation command serves as the master uninstall command |
164 // The Chrome uninstallation command serves as the master uninstall | 152 // for Chrome + all other products (i.e. Chrome Frame) that do not have an |
165 // command for Chrome + all other products (i.e. Chrome Frame) that do | 153 // uninstall entry in the Add/Remove Programs dialog. We skip this processing |
166 // not have an uninstall entry in the Add/Remove Programs dialog. | 154 // in case of uninstall since this means that Chrome Frame is being |
167 const Products& products = product.package().products(); | 155 // uninstalled, so there's no need to do any looping. |
156 if (product.is_chrome() && | |
157 installer_state.operation() != InstallerState::UNINSTALL) { | |
158 const Products& products = installer_state.products(); | |
168 for (size_t i = 0; i < products.size(); ++i) { | 159 for (size_t i = 0; i < products.size(); ++i) { |
169 const Product& p = *products[i]; | 160 const Product& p = *products[i]; |
170 if (!p.is_chrome() && !p.ShouldCreateUninstallEntry()) { | 161 if (!p.is_chrome() && !p.ShouldCreateUninstallEntry()) |
171 p.distribution()->AppendUninstallCommandLineFlags(&uninstall_arguments); | 162 p.AppendProductFlags(&uninstall_arguments); |
172 } | |
173 } | 163 } |
174 } | 164 } |
175 | 165 |
176 std::wstring update_state_key(browser_dist->GetStateKey()); | 166 std::wstring update_state_key(browser_dist->GetStateKey()); |
177 install_list->AddCreateRegKeyWorkItem(reg_root, update_state_key); | 167 install_list->AddCreateRegKeyWorkItem(reg_root, update_state_key); |
178 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, | 168 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, |
179 installer::kUninstallStringField, installer_path.value(), true); | 169 installer::kUninstallStringField, installer_path.value(), true); |
180 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, | 170 install_list->AddSetRegValueWorkItem(reg_root, update_state_key, |
181 installer::kUninstallArgumentsField, | 171 installer::kUninstallArgumentsField, |
182 uninstall_arguments.command_line_string(), true); | 172 uninstall_arguments.command_line_string(), true); |
183 | 173 |
184 if (product.ShouldCreateUninstallEntry()) { | 174 // MSI installations will manage their own uninstall shortcuts. |
175 if (!installer_state.is_msi() && product.ShouldCreateUninstallEntry()) { | |
185 // We need to quote the command line for the Add/Remove Programs dialog. | 176 // We need to quote the command line for the Add/Remove Programs dialog. |
186 CommandLine quoted_uninstall_cmd(installer_path); | 177 CommandLine quoted_uninstall_cmd(installer_path); |
187 DCHECK_EQ(quoted_uninstall_cmd.command_line_string()[0], '"'); | 178 DCHECK_EQ(quoted_uninstall_cmd.command_line_string()[0], '"'); |
188 quoted_uninstall_cmd.AppendArguments(uninstall_arguments, false); | 179 quoted_uninstall_cmd.AppendArguments(uninstall_arguments, false); |
189 | 180 |
190 std::wstring uninstall_reg = browser_dist->GetUninstallRegPath(); | 181 std::wstring uninstall_reg = browser_dist->GetUninstallRegPath(); |
191 install_list->AddCreateRegKeyWorkItem(reg_root, uninstall_reg); | 182 install_list->AddCreateRegKeyWorkItem(reg_root, uninstall_reg); |
192 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, | 183 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, |
193 installer::kUninstallDisplayNameField, | 184 installer::kUninstallDisplayNameField, |
194 browser_dist->GetAppShortCutName(), true); | 185 browser_dist->GetAppShortCutName(), true); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, | 225 install_list->AddSetRegValueWorkItem(reg_root, uninstall_reg, |
235 L"InstallDate", | 226 L"InstallDate", |
236 buffer, false); | 227 buffer, false); |
237 } | 228 } |
238 } | 229 } |
239 } | 230 } |
240 | 231 |
241 // Create Version key for a product (if not already present) and sets the new | 232 // Create Version key for a product (if not already present) and sets the new |
242 // product version as the last step. | 233 // product version as the last step. |
243 void AddVersionKeyWorkItems(HKEY root, | 234 void AddVersionKeyWorkItems(HKEY root, |
244 const Product& product, | 235 BrowserDistribution* dist, |
245 const Version& new_version, | 236 const Version& new_version, |
246 WorkItemList* list) { | 237 WorkItemList* list) { |
247 // Create Version key for each distribution (if not already present) and set | 238 // Create Version key for each distribution (if not already present) and set |
248 // the new product version as the last step. | 239 // the new product version as the last step. |
249 std::wstring version_key(product.distribution()->GetVersionKey()); | 240 std::wstring version_key(dist->GetVersionKey()); |
250 list->AddCreateRegKeyWorkItem(root, version_key); | 241 list->AddCreateRegKeyWorkItem(root, version_key); |
251 | 242 |
252 std::wstring product_name(product.distribution()->GetAppShortCutName()); | 243 std::wstring product_name(dist->GetAppShortCutName()); |
253 list->AddSetRegValueWorkItem(root, version_key, google_update::kRegNameField, | 244 list->AddSetRegValueWorkItem(root, version_key, google_update::kRegNameField, |
254 product_name, true); // overwrite name also | 245 product_name, true); // overwrite name also |
255 list->AddSetRegValueWorkItem(root, version_key, | 246 list->AddSetRegValueWorkItem(root, version_key, |
256 google_update::kRegOopcrashesField, | 247 google_update::kRegOopcrashesField, |
257 static_cast<DWORD>(1), | 248 static_cast<DWORD>(1), |
258 false); // set during first install | 249 false); // set during first install |
259 list->AddSetRegValueWorkItem(root, version_key, | 250 list->AddSetRegValueWorkItem(root, version_key, |
260 google_update::kRegVersionField, | 251 google_update::kRegVersionField, |
261 UTF8ToWide(new_version.GetString()), | 252 UTF8ToWide(new_version.GetString()), |
262 true); // overwrite version | 253 true); // overwrite version |
263 } | 254 } |
264 | 255 |
265 void AddProductSpecificWorkItems(bool install, | 256 void AddProductSpecificWorkItems(const InstallationState& original_state, |
257 const InstallerState& installer_state, | |
266 const FilePath& setup_path, | 258 const FilePath& setup_path, |
267 const Version& new_version, | 259 const Version& new_version, |
268 const Package& package, | |
269 WorkItemList* list) { | 260 WorkItemList* list) { |
270 const Products& products = package.products(); | 261 const Products& products = installer_state.products(); |
271 for (size_t i = 0; i < products.size(); ++i) { | 262 for (size_t i = 0; i < products.size(); ++i) { |
272 const Product& p = *products[i]; | 263 const Product& p = *products[i]; |
273 if (p.is_chrome_frame()) { | 264 if (p.is_chrome_frame()) { |
274 AddChromeFrameWorkItems(install, setup_path, new_version, p, list); | 265 AddChromeFrameWorkItems(original_state, installer_state, setup_path, |
266 new_version, p, list); | |
275 } | 267 } |
276 } | 268 } |
277 } | 269 } |
278 | 270 |
279 // Adds work items that make registry adjustments for Google Update. When a | 271 // Adds work items that make registry adjustments for Google Update. When a |
280 // product is installed (including overinstall), Google Update will write the | 272 // product is installed (including overinstall), Google Update will write the |
281 // channel ("ap") value into either Chrome or Chrome Frame's ClientState key. | 273 // channel ("ap") value into either Chrome or Chrome Frame's ClientState key. |
282 // In the multi-install case, this value is used as the basis upon which the | 274 // In the multi-install case, this value is used as the basis upon which the |
283 // package's channel value is built (by adding the ordered list of installed | 275 // package's channel value is built (by adding the ordered list of installed |
284 // products and their options). | 276 // products and their options). |
285 void AddGoogleUpdateWorkItems(const InstallationState& original_state, | 277 void AddGoogleUpdateWorkItems(const InstallerState& installer_state, |
286 const InstallerState& installer_state, | |
287 const Package& package, | |
288 WorkItemList* install_list) { | 278 WorkItemList* install_list) { |
289 // Is a multi-install product being installed or over-installed? | 279 // Is a multi-install product being installed or over-installed? |
290 if (installer_state.operation() != InstallerState::MULTI_INSTALL) | 280 if (installer_state.operation() != InstallerState::MULTI_INSTALL) |
291 return; | 281 return; |
292 | 282 |
293 const HKEY reg_root = package.system_level() ? HKEY_LOCAL_MACHINE : | 283 const HKEY reg_root = installer_state.root_key(); |
294 HKEY_CURRENT_USER; | |
295 const std::wstring key_path = installer_state.state_key(); | 284 const std::wstring key_path = installer_state.state_key(); |
296 ChannelInfo channel_info; | 285 ChannelInfo channel_info; |
297 | 286 |
298 // Update the "ap" value for the product being installed/updated. | 287 // Update the "ap" value for the product being installed/updated. |
299 // It is completely acceptable for there to be no "ap" value or even no | 288 // It is completely acceptable for there to be no "ap" value or even no |
300 // ClientState key. Note that we check the registry rather than | 289 // ClientState key. Note that we check the registry rather than an |
301 // original_state since on a fresh install the "ap" value will be present | 290 // InstallationState instance since on a fresh install the "ap" value will be |
302 // sans "pv" value. | 291 // present sans "pv" value. |
303 channel_info.Initialize(RegKey(reg_root, key_path.c_str(), KEY_QUERY_VALUE)); | 292 channel_info.Initialize(RegKey(reg_root, key_path.c_str(), KEY_QUERY_VALUE)); |
304 | 293 |
305 // This is a multi-install product. | 294 // This is a multi-install product. |
306 bool modified = channel_info.SetMultiInstall(true); | 295 bool modified = channel_info.SetMultiInstall(true); |
307 | 296 |
308 // Add the appropriate modifiers for all products and their options. | 297 // Add the appropriate modifiers for all products and their options. |
309 Products::const_iterator scan = package.products().begin(); | 298 modified |= installer_state.SetChannelFlags(true, &channel_info); |
310 const Products::const_iterator end = package.products().end(); | |
311 for (; scan != end; ++scan) { | |
312 modified |= scan->get()->distribution()->SetChannelFlags(true, | |
313 &channel_info); | |
314 } | |
315 | 299 |
316 // Write the results if needed. | 300 // Write the results if needed. |
317 if (modified) { | 301 if (modified) { |
318 install_list->AddSetRegValueWorkItem(reg_root, key_path, | 302 install_list->AddSetRegValueWorkItem(reg_root, key_path, |
319 google_update::kRegApField, | 303 google_update::kRegApField, |
320 channel_info.value(), true); | 304 channel_info.value(), true); |
321 } | 305 } |
322 | 306 |
323 // Synchronize the other products and the package with this one. | 307 // Synchronize the other products and the package with this one. |
324 std::wstring other_key; | 308 std::wstring other_key; |
325 std::vector<std::wstring> keys; | 309 std::vector<std::wstring> keys; |
326 | 310 |
327 keys.reserve(package.products().size()); | 311 keys.reserve(installer_state.products().size()); |
328 other_key = package.properties()->GetStateKey(); | 312 other_key = |
313 installer_state.multi_package_binaries_distribution()->GetStateKey(); | |
329 if (other_key != key_path) | 314 if (other_key != key_path) |
330 keys.push_back(other_key); | 315 keys.push_back(other_key); |
331 scan = package.products().begin(); | 316 Products::const_iterator scan = installer_state.products().begin(); |
317 Products::const_iterator end = installer_state.products().end(); | |
332 for (; scan != end; ++scan) { | 318 for (; scan != end; ++scan) { |
333 other_key = scan->get()->distribution()->GetStateKey(); | 319 other_key = (*scan)->distribution()->GetStateKey(); |
334 if (other_key != key_path) | 320 if (other_key != key_path) |
335 keys.push_back(other_key); | 321 keys.push_back(other_key); |
336 } | 322 } |
337 | 323 |
338 RegKey key; | 324 RegKey key; |
339 ChannelInfo other_info; | 325 ChannelInfo other_info; |
340 std::vector<std::wstring>::const_iterator kscan = keys.begin(); | 326 std::vector<std::wstring>::const_iterator kscan = keys.begin(); |
341 std::vector<std::wstring>::const_iterator kend = keys.end(); | 327 std::vector<std::wstring>::const_iterator kend = keys.end(); |
342 for (; kscan != kend; ++kscan) { | 328 for (; kscan != kend; ++kscan) { |
343 // Handle the case where the ClientState key doesn't exist by creating it. | 329 // Handle the case where the ClientState key doesn't exist by creating it. |
(...skipping 13 matching lines...) Expand all Loading... | |
357 } | 343 } |
358 // TODO(grt): check for other keys/values we should put in the package's | 344 // TODO(grt): check for other keys/values we should put in the package's |
359 // ClientState and/or Clients key. | 345 // ClientState and/or Clients key. |
360 } | 346 } |
361 | 347 |
362 // This is called when an MSI installation is run. It may be that a user is | 348 // This is called when an MSI installation is run. It may be that a user is |
363 // attempting to install the MSI on top of a non-MSI managed installation. | 349 // attempting to install the MSI on top of a non-MSI managed installation. |
364 // If so, try and remove any existing uninstallation shortcuts, as we want the | 350 // If so, try and remove any existing uninstallation shortcuts, as we want the |
365 // uninstall to be managed entirely by the MSI machinery (accessible via the | 351 // uninstall to be managed entirely by the MSI machinery (accessible via the |
366 // Add/Remove programs dialog). | 352 // Add/Remove programs dialog). |
367 void AddDeleteUninstallShortcutsForMSIWorkItems(const Product& product, | 353 void AddDeleteUninstallShortcutsForMSIWorkItems( |
368 WorkItemList* work_item_list) { | 354 const InstallerState& installer_state, |
369 DCHECK(product.IsMsi()) << "This must only be called for MSI installations!"; | 355 const Product& product, |
356 WorkItemList* work_item_list) { | |
357 DCHECK(installer_state.is_msi()) | |
358 << "This must only be called for MSI installations!"; | |
370 | 359 |
371 // First attempt to delete the old installation's ARP dialog entry. | 360 // First attempt to delete the old installation's ARP dialog entry. |
372 HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE : | 361 HKEY reg_root = installer_state.root_key(); |
373 HKEY_CURRENT_USER; | |
374 base::win::RegKey root_key(reg_root, L"", KEY_ALL_ACCESS); | |
375 std::wstring uninstall_reg(product.distribution()->GetUninstallRegPath()); | 362 std::wstring uninstall_reg(product.distribution()->GetUninstallRegPath()); |
376 | 363 |
377 WorkItem* delete_reg_key = work_item_list->AddDeleteRegKeyWorkItem( | 364 WorkItem* delete_reg_key = work_item_list->AddDeleteRegKeyWorkItem( |
378 reg_root, uninstall_reg); | 365 reg_root, uninstall_reg); |
379 delete_reg_key->set_ignore_failure(true); | 366 delete_reg_key->set_ignore_failure(true); |
380 | 367 |
381 // Then attempt to delete the old installation's start menu shortcut. | 368 // Then attempt to delete the old installation's start menu shortcut. |
382 FilePath uninstall_link; | 369 FilePath uninstall_link; |
383 if (product.system_level()) { | 370 if (installer_state.system_install()) { |
384 PathService::Get(base::DIR_COMMON_START_MENU, &uninstall_link); | 371 PathService::Get(base::DIR_COMMON_START_MENU, &uninstall_link); |
385 } else { | 372 } else { |
386 PathService::Get(base::DIR_START_MENU, &uninstall_link); | 373 PathService::Get(base::DIR_START_MENU, &uninstall_link); |
387 } | 374 } |
388 | 375 |
389 if (uninstall_link.empty()) { | 376 if (uninstall_link.empty()) { |
390 LOG(ERROR) << "Failed to get location for shortcut."; | 377 LOG(ERROR) << "Failed to get location for shortcut."; |
391 } else { | 378 } else { |
392 uninstall_link = uninstall_link.Append( | 379 uninstall_link = uninstall_link.Append( |
393 product.distribution()->GetAppShortCutName()); | 380 product.distribution()->GetAppShortCutName()); |
(...skipping 11 matching lines...) Expand all Loading... | |
405 | 392 |
406 // After a successful copying of all the files, this function is called to | 393 // After a successful copying of all the files, this function is called to |
407 // do a few post install tasks: | 394 // do a few post install tasks: |
408 // - Handle the case of in-use-update by updating "opv" (old version) key or | 395 // - Handle the case of in-use-update by updating "opv" (old version) key or |
409 // deleting it if not required. | 396 // deleting it if not required. |
410 // - Register any new dlls and unregister old dlls. | 397 // - Register any new dlls and unregister old dlls. |
411 // - If this is an MSI install, ensures that the MSI marker is set, and sets | 398 // - If this is an MSI install, ensures that the MSI marker is set, and sets |
412 // it if not. | 399 // it if not. |
413 // If these operations are successful, the function returns true, otherwise | 400 // If these operations are successful, the function returns true, otherwise |
414 // false. | 401 // false. |
415 bool AppendPostInstallTasks(bool multi_install, | 402 bool AppendPostInstallTasks(const InstallerState& installer_state, |
416 const FilePath& setup_path, | 403 const FilePath& setup_path, |
417 const FilePath& new_chrome_exe, | 404 const FilePath& new_chrome_exe, |
418 const Version* current_version, | 405 const Version* current_version, |
419 const Version& new_version, | 406 const Version& new_version, |
420 const Package& package, | |
421 WorkItemList* post_install_task_list) { | 407 WorkItemList* post_install_task_list) { |
422 DCHECK(post_install_task_list); | 408 DCHECK(post_install_task_list); |
423 HKEY root = package.system_level() ? HKEY_LOCAL_MACHINE : | |
424 HKEY_CURRENT_USER; | |
425 const Products& products = package.products(); | |
426 | 409 |
410 HKEY root = installer_state.root_key(); | |
411 const Products& products = installer_state.products(); | |
427 | 412 |
428 // Append work items that will only be executed if this was an update. | 413 // Append work items that will only be executed if this was an update. |
429 // We update the 'opv' key with the current version that is active and 'cmd' | 414 // We update the 'opv' key with the current version that is active and 'cmd' |
430 // key with the rename command to run. | 415 // key with the rename command to run. |
431 { | 416 { |
432 scoped_ptr<WorkItemList> in_use_update_work_items( | 417 scoped_ptr<WorkItemList> in_use_update_work_items( |
433 WorkItem::CreateConditionalWorkItemList( | 418 WorkItem::CreateConditionalWorkItemList( |
434 new ConditionRunIfFileExists(new_chrome_exe))); | 419 new ConditionRunIfFileExists(new_chrome_exe))); |
435 in_use_update_work_items->set_log_message("InUseUpdateWorkItemList"); | 420 in_use_update_work_items->set_log_message("InUseUpdateWorkItemList"); |
436 | 421 |
437 FilePath installer_path(package.GetInstallerDirectory(new_version) | 422 FilePath installer_path(installer_state.GetInstallerDirectory(new_version) |
438 .Append(setup_path.BaseName())); | 423 .Append(setup_path.BaseName())); |
439 | 424 |
440 CommandLine rename(installer_path); | 425 CommandLine rename(installer_path); |
441 rename.AppendSwitch(installer::switches::kRenameChromeExe); | 426 rename.AppendSwitch(installer::switches::kRenameChromeExe); |
442 if (package.system_level()) | 427 if (installer_state.system_install()) |
443 rename.AppendSwitch(installer::switches::kSystemLevel); | 428 rename.AppendSwitch(installer::switches::kSystemLevel); |
444 | 429 |
445 if (InstallUtil::IsChromeSxSProcess()) | 430 if (InstallUtil::IsChromeSxSProcess()) |
446 rename.AppendSwitch(installer::switches::kChromeSxS); | 431 rename.AppendSwitch(installer::switches::kChromeSxS); |
447 | 432 |
448 if (multi_install) | 433 if (installer_state.is_multi_install()) |
449 rename.AppendSwitch(installer::switches::kMultiInstall); | 434 rename.AppendSwitch(installer::switches::kMultiInstall); |
450 | 435 |
451 std::wstring version_key; | 436 std::wstring version_key; |
452 for (size_t i = 0; i < products.size(); ++i) { | 437 for (size_t i = 0; i < products.size(); ++i) { |
453 BrowserDistribution* dist = products[i]->distribution(); | 438 BrowserDistribution* dist = products[i]->distribution(); |
454 version_key = dist->GetVersionKey(); | 439 version_key = dist->GetVersionKey(); |
455 | 440 |
456 if (current_version != NULL) { | 441 if (current_version != NULL) { |
457 in_use_update_work_items->AddSetRegValueWorkItem(root, version_key, | 442 in_use_update_work_items->AddSetRegValueWorkItem(root, version_key, |
458 google_update::kRegOldVersionField, | 443 google_update::kRegOldVersionField, |
459 UTF8ToWide(current_version->GetString()), true); | 444 UTF8ToWide(current_version->GetString()), true); |
460 } | 445 } |
461 | 446 |
462 // Adding this registry entry for all products is overkill. | 447 // Adding this registry entry for all products is overkill. |
463 // However, as it stands, we don't have a way to know which distribution | 448 // However, as it stands, we don't have a way to know which distribution |
464 // will check the key and run the command, so we add it for all. | 449 // will check the key and run the command, so we add it for all. |
465 // After the first run, the subsequent runs should just be noops. | 450 // After the first run, the subsequent runs should just be noops. |
466 // (see Upgrade::SwapNewChromeExeIfPresent). | 451 // (see Upgrade::SwapNewChromeExeIfPresent). |
467 in_use_update_work_items->AddSetRegValueWorkItem( | 452 in_use_update_work_items->AddSetRegValueWorkItem( |
468 root, | 453 root, |
469 version_key, | 454 version_key, |
470 google_update::kRegRenameCmdField, | 455 google_update::kRegRenameCmdField, |
471 rename.command_line_string(), | 456 rename.command_line_string(), |
472 true); | 457 true); |
473 } | 458 } |
474 | 459 |
475 if (multi_install) { | 460 if (current_version != NULL && installer_state.is_multi_install()) { |
476 PackageProperties* props = package.properties(); | 461 BrowserDistribution* dist = |
477 if (props->ReceivesUpdates() && current_version != NULL) { | 462 installer_state.multi_package_binaries_distribution(); |
478 in_use_update_work_items->AddSetRegValueWorkItem( | 463 in_use_update_work_items->AddSetRegValueWorkItem( |
479 root, | 464 root, |
480 props->GetVersionKey(), | 465 dist->GetVersionKey(), |
481 google_update::kRegOldVersionField, | 466 google_update::kRegOldVersionField, |
482 UTF8ToWide(current_version->GetString()), | 467 UTF8ToWide(current_version->GetString()), |
483 true); | 468 true); |
484 // TODO(tommi): We should move the rename command here. We also need to | 469 // TODO(tommi): We should move the rename command here. We also need to |
485 // update Upgrade::SwapNewChromeExeIfPresent. | 470 // update Upgrade::SwapNewChromeExeIfPresent. |
486 } | |
487 } | 471 } |
488 | 472 |
489 post_install_task_list->AddWorkItem(in_use_update_work_items.release()); | 473 post_install_task_list->AddWorkItem(in_use_update_work_items.release()); |
490 } | 474 } |
491 | 475 |
grt (UTC plus 2)
2011/01/25 03:21:52
self: delete this extra line.
| |
476 | |
492 // Append work items that will be executed if this was NOT an in-use update. | 477 // Append work items that will be executed if this was NOT an in-use update. |
493 { | 478 { |
494 scoped_ptr<WorkItemList> regular_update_work_items( | 479 scoped_ptr<WorkItemList> regular_update_work_items( |
495 WorkItem::CreateConditionalWorkItemList( | 480 WorkItem::CreateConditionalWorkItemList( |
496 new Not(new ConditionRunIfFileExists(new_chrome_exe)))); | 481 new Not(new ConditionRunIfFileExists(new_chrome_exe)))); |
497 regular_update_work_items->set_log_message( | 482 regular_update_work_items->set_log_message("RegularUpdateWorkItemList"); |
498 "RegularUpdateWorkItemList"); | |
499 | 483 |
500 // Since this was not an in-use-update, delete 'opv' and 'cmd' keys. | 484 // Since this was not an in-use-update, delete 'opv' and 'cmd' keys. |
501 for (size_t i = 0; i < products.size(); ++i) { | 485 for (size_t i = 0; i < products.size(); ++i) { |
502 BrowserDistribution* dist = products[i]->distribution(); | 486 BrowserDistribution* dist = products[i]->distribution(); |
503 std::wstring version_key(dist->GetVersionKey()); | 487 std::wstring version_key(dist->GetVersionKey()); |
504 regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key, | 488 regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key, |
505 google_update::kRegOldVersionField); | 489 google_update::kRegOldVersionField); |
506 regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key, | 490 regular_update_work_items->AddDeleteRegValueWorkItem(root, version_key, |
507 google_update::kRegRenameCmdField); | 491 google_update::kRegRenameCmdField); |
508 } | 492 } |
509 | 493 |
510 post_install_task_list->AddWorkItem(regular_update_work_items.release()); | 494 post_install_task_list->AddWorkItem(regular_update_work_items.release()); |
511 } | 495 } |
512 | 496 |
513 AddRegisterComDllWorkItemsForPackage(package, current_version, new_version, | 497 AddRegisterComDllWorkItemsForPackage(installer_state, current_version, |
514 post_install_task_list); | 498 new_version, post_install_task_list); |
515 | 499 |
516 for (size_t i = 0; i < products.size(); ++i) { | 500 // If we're told that we're an MSI install, make sure to set the marker |
517 const Product* product = products[i]; | 501 // in the client state key so that future updates do the right thing. |
518 // If we're told that we're an MSI install, make sure to set the marker | 502 if (installer_state.is_msi()) { |
519 // in the client state key so that future updates do the right thing. | 503 for (size_t i = 0; i < products.size(); ++i) { |
520 if (product->IsMsi()) { | 504 const Product* product = products[i]; |
521 AddSetMsiMarkerWorkItem(*product, true, post_install_task_list); | 505 AddSetMsiMarkerWorkItem(installer_state, product->distribution(), true, |
506 post_install_task_list); | |
522 | 507 |
523 // We want MSI installs to take over the Add/Remove Programs shortcut. | 508 // We want MSI installs to take over the Add/Remove Programs shortcut. |
524 // Make a best-effort attempt to delete any shortcuts left over from | 509 // Make a best-effort attempt to delete any shortcuts left over from |
525 // previous non-MSI installations for the same type of install (system or | 510 // previous non-MSI installations for the same type of install (system or |
526 // per user). | 511 // per user). |
527 AddDeleteUninstallShortcutsForMSIWorkItems(*product, | 512 AddDeleteUninstallShortcutsForMSIWorkItems(installer_state, *product, |
528 post_install_task_list); | 513 post_install_task_list); |
529 } | 514 } |
515 if (installer_state.is_multi_install()) { | |
516 AddSetMsiMarkerWorkItem(installer_state, | |
517 installer_state.multi_package_binaries_distribution(), true, | |
518 post_install_task_list); | |
519 } | |
530 } | 520 } |
531 | 521 |
532 return true; | 522 return true; |
533 } | 523 } |
534 | 524 |
535 void AddInstallWorkItems(const InstallationState& original_state, | 525 void AddInstallWorkItems(const InstallationState& original_state, |
536 const InstallerState& installer_state, | 526 const InstallerState& installer_state, |
537 bool multi_install, | |
538 const FilePath& setup_path, | 527 const FilePath& setup_path, |
539 const FilePath& archive_path, | 528 const FilePath& archive_path, |
540 const FilePath& src_path, | 529 const FilePath& src_path, |
541 const FilePath& temp_dir, | 530 const FilePath& temp_dir, |
542 const Version& new_version, | 531 const Version& new_version, |
543 scoped_ptr<Version>* current_version, | 532 scoped_ptr<Version>* current_version, |
544 const Package& package, | |
545 WorkItemList* install_list) { | 533 WorkItemList* install_list) { |
546 DCHECK(install_list); | 534 DCHECK(install_list); |
547 | 535 |
536 const FilePath& target_path = installer_state.target_path(); | |
537 | |
548 // A temp directory that work items need and the actual install directory. | 538 // A temp directory that work items need and the actual install directory. |
549 install_list->AddCreateDirWorkItem(temp_dir); | 539 install_list->AddCreateDirWorkItem(temp_dir); |
550 install_list->AddCreateDirWorkItem(package.path()); | 540 install_list->AddCreateDirWorkItem(target_path); |
551 | 541 |
552 // Delete any new_chrome.exe if present (we will end up creating a new one | 542 // Delete any new_chrome.exe if present (we will end up creating a new one |
553 // if required) and then copy chrome.exe | 543 // if required) and then copy chrome.exe |
554 FilePath new_chrome_exe( | 544 FilePath new_chrome_exe( |
555 package.path().Append(installer::kChromeNewExe)); | 545 target_path.Append(installer::kChromeNewExe)); |
556 | 546 |
557 install_list->AddDeleteTreeWorkItem(new_chrome_exe); | 547 install_list->AddDeleteTreeWorkItem(new_chrome_exe); |
558 install_list->AddCopyTreeWorkItem( | 548 install_list->AddCopyTreeWorkItem( |
559 src_path.Append(installer::kChromeExe).value(), | 549 src_path.Append(installer::kChromeExe).value(), |
560 package.path().Append(installer::kChromeExe).value(), | 550 target_path.Append(installer::kChromeExe).value(), |
561 temp_dir.value(), WorkItem::NEW_NAME_IF_IN_USE, new_chrome_exe.value()); | 551 temp_dir.value(), WorkItem::NEW_NAME_IF_IN_USE, new_chrome_exe.value()); |
562 | 552 |
563 // Extra executable for 64 bit systems. | 553 // Extra executable for 64 bit systems. |
564 if (Is64bit()) { | 554 if (Is64bit()) { |
565 install_list->AddCopyTreeWorkItem( | 555 install_list->AddCopyTreeWorkItem( |
566 src_path.Append(installer::kWowHelperExe).value(), | 556 src_path.Append(installer::kWowHelperExe).value(), |
567 package.path().Append(installer::kWowHelperExe).value(), | 557 target_path.Append(installer::kWowHelperExe).value(), |
568 temp_dir.value(), WorkItem::ALWAYS); | 558 temp_dir.value(), WorkItem::ALWAYS); |
569 } | 559 } |
570 | 560 |
571 // If it is system level install copy the version folder (since we want to | 561 // If it is system level install copy the version folder (since we want to |
572 // take the permissions of %ProgramFiles% folder) otherwise just move it. | 562 // take the permissions of %ProgramFiles% folder) otherwise just move it. |
573 if (package.system_level()) { | 563 if (installer_state.system_install()) { |
574 install_list->AddCopyTreeWorkItem( | 564 install_list->AddCopyTreeWorkItem( |
575 src_path.Append(UTF8ToWide(new_version.GetString())).value(), | 565 src_path.Append(UTF8ToWide(new_version.GetString())).value(), |
576 package.path().Append(UTF8ToWide(new_version.GetString())).value(), | 566 target_path.Append(UTF8ToWide(new_version.GetString())).value(), |
577 temp_dir.value(), WorkItem::ALWAYS); | 567 temp_dir.value(), WorkItem::ALWAYS); |
578 } else { | 568 } else { |
579 install_list->AddMoveTreeWorkItem( | 569 install_list->AddMoveTreeWorkItem( |
580 src_path.Append(UTF8ToWide(new_version.GetString())).value(), | 570 src_path.Append(UTF8ToWide(new_version.GetString())).value(), |
581 package.path().Append(UTF8ToWide(new_version.GetString())).value(), | 571 target_path.Append(UTF8ToWide(new_version.GetString())).value(), |
582 temp_dir.value()); | 572 temp_dir.value()); |
583 } | 573 } |
584 | 574 |
585 // Copy the default Dictionaries only if the folder doesn't exist already. | 575 // Copy the default Dictionaries only if the folder doesn't exist already. |
586 install_list->AddCopyTreeWorkItem( | 576 install_list->AddCopyTreeWorkItem( |
587 src_path.Append(installer::kDictionaries).value(), | 577 src_path.Append(installer::kDictionaries).value(), |
588 package.path().Append(installer::kDictionaries).value(), | 578 target_path.Append(installer::kDictionaries).value(), |
589 temp_dir.value(), WorkItem::IF_NOT_PRESENT); | 579 temp_dir.value(), WorkItem::IF_NOT_PRESENT); |
590 | 580 |
591 // Delete any old_chrome.exe if present. | 581 // Delete any old_chrome.exe if present. |
592 install_list->AddDeleteTreeWorkItem( | 582 install_list->AddDeleteTreeWorkItem( |
593 package.path().Append(installer::kChromeOldExe)); | 583 target_path.Append(installer::kChromeOldExe)); |
594 | 584 |
595 // Copy installer in install directory and | 585 // Copy installer in install directory and |
596 // add shortcut in Control Panel->Add/Remove Programs. | 586 // add shortcut in Control Panel->Add/Remove Programs. |
597 AddInstallerCopyTasks(setup_path, archive_path, temp_dir, new_version, | 587 AddInstallerCopyTasks(installer_state, setup_path, archive_path, temp_dir, |
598 install_list, package); | 588 new_version, install_list); |
599 | 589 |
600 HKEY root = package.system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | 590 const HKEY root = installer_state.root_key(); |
601 | 591 |
602 const Products& products = package.products(); | 592 const Products& products = installer_state.products(); |
603 for (size_t i = 0; i < products.size(); ++i) { | 593 for (size_t i = 0; i < products.size(); ++i) { |
604 const Product* product = products[i]; | 594 const Product* product = products[i]; |
605 | 595 |
606 AddUninstallShortcutWorkItems(setup_path, new_version, install_list, | 596 AddUninstallShortcutWorkItems(installer_state, setup_path, new_version, |
607 *product); | 597 install_list, *product); |
608 | 598 |
609 AddVersionKeyWorkItems(root, *product, new_version, install_list); | 599 AddVersionKeyWorkItems(root, product->distribution(), new_version, |
600 install_list); | |
610 } | 601 } |
611 | 602 |
612 if (multi_install) { | 603 if (installer_state.is_multi_install()) { |
613 PackageProperties* props = package.properties(); | 604 AddVersionKeyWorkItems(root, |
614 if (props->ReceivesUpdates()) { | 605 installer_state.multi_package_binaries_distribution(), new_version, |
615 std::wstring version_key(props->GetVersionKey()); | 606 install_list); |
616 install_list->AddCreateRegKeyWorkItem(root, version_key); | |
617 install_list->AddSetRegValueWorkItem(root, version_key, | |
618 google_update::kRegVersionField, | |
619 UTF8ToWide(new_version.GetString()), | |
620 true); // overwrite version | |
621 install_list->AddSetRegValueWorkItem(root, version_key, | |
622 google_update::kRegNameField, | |
623 ASCIIToWide(installer::PackageProperties::kPackageProductName), | |
624 true); // overwrite name also | |
625 } | |
626 } | 607 } |
627 | 608 |
628 // Add any remaining work items that involve special settings for | 609 // Add any remaining work items that involve special settings for |
629 // each product. | 610 // each product. |
630 AddProductSpecificWorkItems(true, setup_path, new_version, package, | 611 AddProductSpecificWorkItems(original_state, installer_state, setup_path, |
631 install_list); | 612 new_version, install_list); |
632 | 613 |
633 AddGoogleUpdateWorkItems(original_state, installer_state, package, | 614 AddGoogleUpdateWorkItems(installer_state, install_list); |
634 install_list); | |
635 | 615 |
636 // Append the tasks that run after the installation. | 616 // Append the tasks that run after the installation. |
637 AppendPostInstallTasks(multi_install, | 617 AppendPostInstallTasks(installer_state, |
638 setup_path, | 618 setup_path, |
639 new_chrome_exe, | 619 new_chrome_exe, |
640 current_version->get(), | 620 current_version->get(), |
641 new_version, | 621 new_version, |
642 package, | |
643 install_list); | 622 install_list); |
644 } | 623 } |
645 | 624 |
646 void AddRegisterComDllWorkItems(const FilePath& dll_folder, | 625 void AddRegisterComDllWorkItems(const FilePath& dll_folder, |
647 const std::vector<FilePath>& dll_list, | 626 const std::vector<FilePath>& dll_list, |
648 bool system_level, | 627 bool system_level, |
649 bool do_register, | 628 bool do_register, |
650 bool ignore_failures, | 629 bool ignore_failures, |
651 WorkItemList* work_item_list) { | 630 WorkItemList* work_item_list) { |
652 DCHECK(work_item_list); | 631 DCHECK(work_item_list); |
653 if (dll_list.empty()) { | 632 if (dll_list.empty()) { |
654 VLOG(1) << "No COM DLLs to register"; | 633 VLOG(1) << "No COM DLLs to register"; |
655 } else { | 634 } else { |
656 std::vector<FilePath>::const_iterator dll_iter(dll_list.begin()); | 635 std::vector<FilePath>::const_iterator dll_iter(dll_list.begin()); |
657 for (; dll_iter != dll_list.end(); ++dll_iter) { | 636 for (; dll_iter != dll_list.end(); ++dll_iter) { |
658 FilePath dll_path = dll_folder.Append(*dll_iter); | 637 FilePath dll_path = dll_folder.Append(*dll_iter); |
659 WorkItem* work_item = work_item_list->AddSelfRegWorkItem( | 638 WorkItem* work_item = work_item_list->AddSelfRegWorkItem( |
660 dll_path.value(), do_register, !system_level); | 639 dll_path.value(), do_register, !system_level); |
661 DCHECK(work_item); | 640 DCHECK(work_item); |
662 work_item->set_ignore_failure(ignore_failures); | 641 work_item->set_ignore_failure(ignore_failures); |
663 } | 642 } |
664 } | 643 } |
665 } | 644 } |
666 | 645 |
667 void AddSetMsiMarkerWorkItem(const Product& product, | 646 void AddSetMsiMarkerWorkItem(const InstallerState& installer_state, |
647 BrowserDistribution* dist, | |
668 bool set, | 648 bool set, |
669 WorkItemList* work_item_list) { | 649 WorkItemList* work_item_list) { |
670 DCHECK(work_item_list); | 650 DCHECK(work_item_list); |
671 BrowserDistribution* dist = product.distribution(); | |
672 HKEY reg_root = product.system_level() ? HKEY_LOCAL_MACHINE : | |
673 HKEY_CURRENT_USER; | |
674 DWORD msi_value = set ? 1 : 0; | 651 DWORD msi_value = set ? 1 : 0; |
675 WorkItem* set_msi_work_item = work_item_list->AddSetRegValueWorkItem( | 652 WorkItem* set_msi_work_item = work_item_list->AddSetRegValueWorkItem( |
676 reg_root, dist->GetStateKey(), google_update::kRegMSIField, | 653 installer_state.root_key(), dist->GetStateKey(), |
677 msi_value, true); | 654 google_update::kRegMSIField, msi_value, true); |
678 DCHECK(set_msi_work_item); | 655 DCHECK(set_msi_work_item); |
679 set_msi_work_item->set_ignore_failure(true); | 656 set_msi_work_item->set_ignore_failure(true); |
680 set_msi_work_item->set_log_message("Could not write MSI marker!"); | 657 set_msi_work_item->set_log_message("Could not write MSI marker!"); |
681 } | 658 } |
682 | 659 |
683 void AddChromeFrameWorkItems(bool install, | 660 void AddChromeFrameWorkItems(const InstallationState& original_state, |
661 const InstallerState& installer_state, | |
684 const FilePath& setup_path, | 662 const FilePath& setup_path, |
685 const Version& new_version, | 663 const Version& new_version, |
686 const Product& product, | 664 const Product& product, |
687 WorkItemList* list) { | 665 WorkItemList* list) { |
688 DCHECK(product.is_chrome_frame()); | 666 DCHECK(product.is_chrome_frame()); |
689 if (!product.package().multi_install()) { | 667 if (!installer_state.is_multi_install()) { |
690 VLOG(1) << "Not adding GCF specific work items for single install."; | 668 VLOG(1) << "Not adding GCF specific work items for single install."; |
691 return; | 669 return; |
692 } | 670 } |
693 | 671 |
694 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess(); | 672 std::wstring version_key(product.distribution()->GetVersionKey()); |
695 | 673 bool ready_mode = product.HasOption(kOptionReadyMode); |
696 BrowserDistribution* cf = BrowserDistribution::GetSpecificDistribution( | 674 HKEY root = installer_state.root_key(); |
697 BrowserDistribution::CHROME_FRAME, prefs); | 675 const bool is_install = |
698 std::wstring version_key(cf->GetVersionKey()); | 676 (installer_state.operation() != InstallerState::UNINSTALL); |
699 | |
700 // TODO(tommi): This assumes we know exactly how ShouldCreateUninstallEntry | |
701 // is implemented. Since there is logic in ChromeFrameDistribution for how | |
702 // to determine when this is enabled, this is how we have to figure out if | |
703 // this feature is enabled right now, but it's a hack and we need a cleaner | |
704 // way to figure this out. | |
705 // Note that we cannot just check the master preferences for | |
706 // kChromeFrameReadyMode, since there are other things that need to be correct | |
707 // in the environment in order to enable this feature. | |
708 bool ready_mode = !product.distribution()->ShouldCreateUninstallEntry(); | |
709 | |
710 HKEY root = product.package().system_level() ? HKEY_LOCAL_MACHINE : | |
711 HKEY_CURRENT_USER; | |
712 bool update_chrome_uninstall_command = false; | 677 bool update_chrome_uninstall_command = false; |
678 BrowserDistribution* dist = | |
679 installer_state.multi_package_binaries_distribution(); | |
713 if (ready_mode) { | 680 if (ready_mode) { |
714 // If GCF is being installed in ready mode, we write an entry to the | 681 // If GCF is being installed in ready mode, we write an entry to the |
715 // multi-install state key. If the value already exists, we will not | 682 // multi-install state key. If the value already exists, we will not |
716 // overwrite it since the user might have opted out. | 683 // overwrite it since the user might have opted out. |
717 list->AddCreateRegKeyWorkItem(root, | 684 list->AddCreateRegKeyWorkItem(root, dist->GetStateKey()); |
718 product.package().properties()->GetStateKey()); | 685 list->AddSetRegValueWorkItem(root, dist->GetStateKey(), |
719 list->AddSetRegValueWorkItem(root, | 686 kChromeFrameReadyModeField, |
720 product.package().properties()->GetStateKey(), | 687 static_cast<int64>(is_install ? 1 : 0), // The value we want to set. |
721 installer::kChromeFrameReadyModeField, | 688 is_install ? false : true); // Overwrite existing value. |
722 static_cast<int64>(install ? 1 : 0), // The value we want to set. | 689 if (is_install) { |
723 install ? false : true); // Overwrite existing value. | 690 FilePath installer_path(installer_state |
724 if (install) { | |
725 FilePath installer_path(product.package() | |
726 .GetInstallerDirectory(new_version).Append(setup_path.BaseName())); | 691 .GetInstallerDirectory(new_version).Append(setup_path.BaseName())); |
727 | 692 |
728 CommandLine basic_cl(installer_path); | 693 CommandLine basic_cl(installer_path); |
729 basic_cl.AppendSwitch(installer::switches::kChromeFrame); | 694 basic_cl.AppendSwitch(switches::kChromeFrame); |
730 basic_cl.AppendSwitch(installer::switches::kMultiInstall); | 695 basic_cl.AppendSwitch(switches::kMultiInstall); |
731 | 696 |
732 if (product.package().system_level()) | 697 if (installer_state.system_install()) |
733 basic_cl.AppendSwitch(installer::switches::kSystemLevel); | 698 basic_cl.AppendSwitch(switches::kSystemLevel); |
734 | |
735 if (InstallUtil::IsChromeSxSProcess()) | |
736 basic_cl.AppendSwitch(installer::switches::kChromeSxS); | |
737 | 699 |
738 CommandLine temp_opt_out(basic_cl); | 700 CommandLine temp_opt_out(basic_cl); |
739 temp_opt_out.AppendSwitch( | 701 temp_opt_out.AppendSwitch(switches::kChromeFrameReadyModeTempOptOut); |
740 installer::switches::kChromeFrameReadyModeTempOptOut); | |
741 | 702 |
742 CommandLine end_temp_opt_out(basic_cl); | 703 CommandLine end_temp_opt_out(basic_cl); |
743 end_temp_opt_out.AppendSwitch( | 704 end_temp_opt_out.AppendSwitch( |
744 installer::switches::kChromeFrameReadyModeEndTempOptOut); | 705 switches::kChromeFrameReadyModeEndTempOptOut); |
745 | 706 |
746 CommandLine opt_out(installer_path); | 707 CommandLine opt_out(installer_path); |
747 AppendUninstallCommandLineFlags(&opt_out, product); | 708 AppendUninstallCommandLineFlags(installer_state, product, &opt_out); |
748 // Force Uninstall silences the prompt to reboot to complete uninstall. | 709 // Force Uninstall silences the prompt to reboot to complete uninstall. |
749 opt_out.AppendSwitch(installer::switches::kForceUninstall); | 710 opt_out.AppendSwitch(switches::kForceUninstall); |
750 | 711 |
751 CommandLine opt_in(basic_cl); | 712 CommandLine opt_in(basic_cl); |
752 opt_in.AppendSwitch( | 713 opt_in.AppendSwitch(switches::kChromeFrameReadyModeOptIn); |
753 installer::switches::kChromeFrameReadyModeOptIn); | |
754 | 714 |
755 list->AddSetRegValueWorkItem(root, version_key, | 715 list->AddSetRegValueWorkItem(root, version_key, |
756 google_update::kRegCFTempOptOutCmdField, | 716 google_update::kRegCFTempOptOutCmdField, |
757 temp_opt_out.command_line_string(), true); | 717 temp_opt_out.command_line_string(), true); |
758 list->AddSetRegValueWorkItem(root, version_key, | 718 list->AddSetRegValueWorkItem(root, version_key, |
759 google_update::kRegCFEndTempOptOutCmdField, | 719 google_update::kRegCFEndTempOptOutCmdField, |
760 end_temp_opt_out.command_line_string(), | 720 end_temp_opt_out.command_line_string(), |
761 true); | 721 true); |
762 list->AddSetRegValueWorkItem(root, version_key, | 722 list->AddSetRegValueWorkItem(root, version_key, |
763 google_update::kRegCFOptOutCmdField, | 723 google_update::kRegCFOptOutCmdField, |
764 opt_out.command_line_string(), true); | 724 opt_out.command_line_string(), true); |
765 list->AddSetRegValueWorkItem(root, version_key, | 725 list->AddSetRegValueWorkItem(root, version_key, |
766 google_update::kRegCFOptInCmdField, | 726 google_update::kRegCFOptInCmdField, |
767 opt_in.command_line_string(), true); | 727 opt_in.command_line_string(), true); |
768 } else { | 728 } else { |
769 // If Chrome is not also being uninstalled, we need to update its command | 729 // If Chrome is not also being uninstalled, we need to update its command |
770 // line so that it doesn't include uninstalling Chrome Frame now. | 730 // line so that it doesn't include uninstalling Chrome Frame now. |
771 update_chrome_uninstall_command = | 731 update_chrome_uninstall_command = |
772 (installer::FindProduct(product.package().products(), | 732 (installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER) == |
773 BrowserDistribution::CHROME_BROWSER) == NULL); | 733 NULL); |
774 } | 734 } |
775 } else { | 735 } else { |
776 // It doesn't matter here if we're installing or uninstalling Chrome Frame. | 736 // It doesn't matter here if we're installing or uninstalling Chrome Frame. |
777 // If ready mode isn't specified on the command line for installs, we need | 737 // If ready mode isn't specified on the command line for installs, we need |
778 // to delete the ready mode flag from the registry if it exists - this | 738 // to delete the ready mode flag from the registry if it exists - this |
779 // constitutes an opt-in for the user. If we're uninstalling CF and ready | 739 // constitutes an opt-in for the user. If we're uninstalling CF and ready |
780 // mode isn't specified on the command line, that means that CF wasn't | 740 // mode isn't specified on the command line, that means that CF wasn't |
781 // installed with ready mode enabled (the --ready-mode switch should be set | 741 // installed with ready mode enabled (the --ready-mode switch should be set |
782 // in the registry) so deleting the value should have no effect. | 742 // in the registry) so deleting the value should have no effect. |
783 // In both cases (install/uninstall), we need to make sure that Chrome's | 743 // In both cases (install/uninstall), we need to make sure that Chrome's |
784 // uninstallation command line does not include the --chrome-frame switch | 744 // uninstallation command line does not include the --chrome-frame switch |
785 // so that uninstalling Chrome will no longer uninstall Chrome Frame. | 745 // so that uninstalling Chrome will no longer uninstall Chrome Frame. |
786 | 746 |
787 if (RegKey(root, product.package().properties()->GetStateKey().c_str(), | 747 list->AddDeleteRegValueWorkItem(root, dist->GetStateKey(), |
788 KEY_QUERY_VALUE).Valid()) { | 748 kChromeFrameReadyModeField); |
789 list->AddDeleteRegValueWorkItem(root, | |
790 product.package().properties()->GetStateKey(), | |
791 installer::kChromeFrameReadyModeField); | |
792 } | |
793 | 749 |
794 const Product* chrome = installer::FindProduct(product.package().products(), | 750 const Product* chrome = |
795 BrowserDistribution::CHROME_BROWSER); | 751 installer_state.FindProduct(BrowserDistribution::CHROME_BROWSER); |
796 if (chrome) { | 752 if (chrome) { |
797 // Chrome is already a part of this installation run, so we can assume | 753 // Chrome is already a part of this installation run, so we can assume |
798 // that the uninstallation arguments will be updated correctly. | 754 // that the uninstallation arguments will be updated correctly. |
799 } else { | 755 } else { |
800 // Chrome is not a part of this installation run, so we have to explicitly | 756 // Chrome is not a part of this installation run, so we have to explicitly |
801 // check if Chrome is installed, and if so, update its uninstallation | 757 // check if Chrome is installed, and if so, update its uninstallation |
802 // command lines. | 758 // command lines. |
803 BrowserDistribution* dist = BrowserDistribution::GetSpecificDistribution( | 759 const ProductState* chrome_state = original_state.GetProductState( |
804 BrowserDistribution::CHROME_BROWSER, | 760 installer_state.system_install(), |
805 MasterPreferences::ForCurrentProcess()); | 761 BrowserDistribution::CHROME_BROWSER); |
806 update_chrome_uninstall_command = | 762 update_chrome_uninstall_command = |
807 IsInstalledAsMulti(product.system_level(), dist); | 763 (chrome_state != NULL) && chrome_state->is_multi_install(); |
808 } | 764 } |
809 } | 765 } |
810 | 766 |
811 if (!ready_mode || !install) { | 767 if (!ready_mode || !is_install) { |
812 list->AddDeleteRegValueWorkItem(root, version_key, | 768 list->AddDeleteRegValueWorkItem(root, version_key, |
813 google_update::kRegCFTempOptOutCmdField); | 769 google_update::kRegCFTempOptOutCmdField); |
814 list->AddDeleteRegValueWorkItem(root, version_key, | 770 list->AddDeleteRegValueWorkItem(root, version_key, |
815 google_update::kRegCFEndTempOptOutCmdField); | 771 google_update::kRegCFEndTempOptOutCmdField); |
816 list->AddDeleteRegValueWorkItem(root, version_key, | 772 list->AddDeleteRegValueWorkItem(root, version_key, |
817 google_update::kRegCFOptOutCmdField); | 773 google_update::kRegCFOptOutCmdField); |
818 list->AddDeleteRegValueWorkItem(root, version_key, | 774 list->AddDeleteRegValueWorkItem(root, version_key, |
819 google_update::kRegCFOptInCmdField); | 775 google_update::kRegCFOptInCmdField); |
820 } | 776 } |
821 | 777 |
822 if (update_chrome_uninstall_command) { | 778 if (update_chrome_uninstall_command) { |
823 // Chrome is not a part of this installation run, so we have to explicitly | 779 // Chrome is not a part of this installation run, so we have to explicitly |
824 // check if Chrome is installed, and if so, update its uninstallation | 780 // check if Chrome is installed, and if so, update its uninstallation |
825 // command lines. | 781 // command lines. |
826 BrowserDistribution* chrome_dist = | 782 const ProductState* chrome_state = original_state.GetProductState( |
827 BrowserDistribution::GetSpecificDistribution( | 783 installer_state.system_install(), |
828 BrowserDistribution::CHROME_BROWSER, prefs); | 784 BrowserDistribution::CHROME_BROWSER); |
829 const Package& pack = product.package(); | 785 if (chrome_state != NULL) { |
830 scoped_refptr<Package> package(new Package(pack.multi_install(), | 786 DCHECK(chrome_state->is_multi_install()); |
831 pack.system_level(), pack.path(), pack.properties())); | 787 Product chrome(BrowserDistribution::GetSpecificDistribution( |
832 scoped_refptr<Product> chrome_product(new Product(chrome_dist, package)); | 788 BrowserDistribution::CHROME_BROWSER)); |
833 AddUninstallShortcutWorkItems(setup_path, new_version, list, | 789 chrome.InitializeFromUninstallCommand(chrome_state->uninstall_command()); |
834 *chrome_product.get()); | 790 AddUninstallShortcutWorkItems(installer_state, setup_path, |
791 chrome_state->version(), list, chrome); | |
792 } else { | |
793 NOTREACHED() << "What happened to Chrome?"; | |
794 } | |
835 } | 795 } |
836 } | 796 } |
837 | 797 |
838 void AppendUninstallCommandLineFlags(CommandLine* uninstall_cmd, | 798 void AppendUninstallCommandLineFlags(const InstallerState& installer_state, |
839 const Product& product) { | 799 const Product& product, |
800 CommandLine* uninstall_cmd) { | |
840 DCHECK(uninstall_cmd); | 801 DCHECK(uninstall_cmd); |
841 | 802 |
842 uninstall_cmd->AppendSwitch(installer::switches::kUninstall); | 803 uninstall_cmd->AppendSwitch(installer::switches::kUninstall); |
843 | 804 |
844 // Append the product-specific uninstall flags. | 805 // Append the product-specific uninstall flags. |
845 product.distribution()->AppendUninstallCommandLineFlags(uninstall_cmd); | 806 product.AppendProductFlags(uninstall_cmd); |
846 if (product.IsMsi()) { | 807 if (installer_state.is_msi()) { |
847 uninstall_cmd->AppendSwitch(installer::switches::kMsi); | 808 uninstall_cmd->AppendSwitch(installer::switches::kMsi); |
848 // See comment in uninstall.cc where we check for the kDeleteProfile switch. | 809 // See comment in uninstall.cc where we check for the kDeleteProfile switch. |
849 if (product.is_chrome_frame()) { | 810 if (product.is_chrome_frame()) { |
850 uninstall_cmd->AppendSwitch(installer::switches::kDeleteProfile); | 811 uninstall_cmd->AppendSwitch(installer::switches::kDeleteProfile); |
851 } | 812 } |
852 } | 813 } |
853 if (product.system_level()) | 814 if (installer_state.system_install()) |
854 uninstall_cmd->AppendSwitch(installer::switches::kSystemLevel); | 815 uninstall_cmd->AppendSwitch(installer::switches::kSystemLevel); |
855 | 816 if (installer_state.verbose_logging()) |
856 // Propagate switches obtained from preferences as well. | |
857 const MasterPreferences& prefs = MasterPreferences::ForCurrentProcess(); | |
858 if (prefs.is_multi_install()) { | |
859 uninstall_cmd->AppendSwitch(installer::switches::kMultiInstall); | |
860 } | |
861 bool value = false; | |
862 if (prefs.GetBool(installer::master_preferences::kVerboseLogging, | |
863 &value) && value) | |
864 uninstall_cmd->AppendSwitch(installer::switches::kVerboseLogging); | 817 uninstall_cmd->AppendSwitch(installer::switches::kVerboseLogging); |
865 } | 818 } |
866 | 819 |
867 } // namespace installer | 820 } // namespace installer |
OLD | NEW |