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 // Implementation of the installation validator. | 5 // Implementation of the installation validator. |
6 | 6 |
7 #include "chrome/installer/util/installation_validator.h" | 7 #include "chrome/installer/util/installation_validator.h" |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <set> |
10 | 11 |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/version.h" | 13 #include "base/version.h" |
13 #include "chrome/installer/util/browser_distribution.h" | 14 #include "chrome/installer/util/browser_distribution.h" |
14 #include "chrome/installer/util/helper.h" | 15 #include "chrome/installer/util/helper.h" |
15 #include "chrome/installer/util/installation_state.h" | 16 #include "chrome/installer/util/installation_state.h" |
16 | 17 |
17 namespace installer { | 18 namespace installer { |
18 | 19 |
19 BrowserDistribution::Type | 20 BrowserDistribution::Type |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 const ProductState& product_state, | 57 const ProductState& product_state, |
57 SwitchExpectations* expectations) const { | 58 SwitchExpectations* expectations) const { |
58 // --chrome-frame must be present. | 59 // --chrome-frame must be present. |
59 expectations->push_back(std::make_pair(std::string(switches::kChromeFrame), | 60 expectations->push_back(std::make_pair(std::string(switches::kChromeFrame), |
60 true)); | 61 true)); |
61 // --chrome must not be present. | 62 // --chrome must not be present. |
62 expectations->push_back(std::make_pair(std::string(switches::kChrome), | 63 expectations->push_back(std::make_pair(std::string(switches::kChrome), |
63 false)); | 64 false)); |
64 } | 65 } |
65 | 66 |
| 67 BrowserDistribution::Type |
| 68 InstallationValidator::ChromeBinariesRules::distribution_type() const { |
| 69 return BrowserDistribution::CHROME_BINARIES; |
| 70 } |
| 71 |
| 72 void InstallationValidator::ChromeBinariesRules::AddProductSwitchExpectations( |
| 73 const InstallationState& machine_state, |
| 74 bool system_install, |
| 75 const ProductState& product_state, |
| 76 SwitchExpectations* expectations) const { |
| 77 NOTREACHED(); |
| 78 } |
| 79 |
66 // static | 80 // static |
67 const InstallationValidator::InstallationType | 81 const InstallationValidator::InstallationType |
68 InstallationValidator::kInstallationTypes[] = { | 82 InstallationValidator::kInstallationTypes[] = { |
69 NO_PRODUCTS, | 83 NO_PRODUCTS, |
70 CHROME_SINGLE, | 84 CHROME_SINGLE, |
71 CHROME_MULTI, | 85 CHROME_MULTI, |
72 CHROME_FRAME_SINGLE, | 86 CHROME_FRAME_SINGLE, |
73 CHROME_FRAME_SINGLE_CHROME_SINGLE, | 87 CHROME_FRAME_SINGLE_CHROME_SINGLE, |
74 CHROME_FRAME_SINGLE_CHROME_MULTI, | 88 CHROME_FRAME_SINGLE_CHROME_MULTI, |
75 CHROME_FRAME_MULTI, | 89 CHROME_FRAME_MULTI, |
76 CHROME_FRAME_MULTI_CHROME_MULTI, | 90 CHROME_FRAME_MULTI_CHROME_MULTI, |
77 CHROME_FRAME_READY_MODE_CHROME_MULTI | 91 CHROME_FRAME_READY_MODE_CHROME_MULTI |
78 }; | 92 }; |
79 | 93 |
| 94 // Validates the "quick-enable-cf" Google Update product command. |
| 95 void InstallationValidator::ValidateQuickEnableCfCommand( |
| 96 const ProductContext& ctx, |
| 97 const ProductCommand& command, |
| 98 bool* is_valid) { |
| 99 DCHECK(is_valid); |
| 100 |
| 101 CommandLine the_command(CommandLine::FromString(command.command_line())); |
| 102 |
| 103 ValidateSetupPath(ctx, the_command.GetProgram(), "quick enable cf", is_valid); |
| 104 |
| 105 SwitchExpectations expected; |
| 106 |
| 107 expected.push_back( |
| 108 std::make_pair(std::string(switches::kChromeFrameQuickEnable), true)); |
| 109 expected.push_back(std::make_pair(std::string(switches::kSystemLevel), |
| 110 ctx.system_install)); |
| 111 expected.push_back(std::make_pair(std::string(switches::kMultiInstall), |
| 112 ctx.state.is_multi_install())); |
| 113 |
| 114 ValidateCommandExpectations(ctx, the_command, expected, "quick enable cf", |
| 115 is_valid); |
| 116 |
| 117 if (!command.sends_pings()) { |
| 118 *is_valid = false; |
| 119 LOG(ERROR) << "Quick-enable-cf command is not configured to send pings."; |
| 120 } |
| 121 |
| 122 if (!command.is_web_accessible()) { |
| 123 *is_valid = false; |
| 124 LOG(ERROR) << "Quick-enable-cf command is not web accessible."; |
| 125 } |
| 126 } |
| 127 |
| 128 // Validates a product's set of Google Update product commands against a |
| 129 // collection of expectations. |
| 130 void InstallationValidator::ValidateProductCommandExpectations( |
| 131 const ProductContext& ctx, |
| 132 const CommandExpectations& expectations, |
| 133 bool* is_valid) { |
| 134 DCHECK(is_valid); |
| 135 |
| 136 CommandExpectations the_expectations(expectations); |
| 137 |
| 138 ProductCommands::CommandMapRange cmd_iterators( |
| 139 ctx.state.commands().GetIterators()); |
| 140 CommandExpectations::iterator expectation; |
| 141 for (; cmd_iterators.first != cmd_iterators.second; ++cmd_iterators.first) { |
| 142 const std::wstring& cmd_id = cmd_iterators.first->first; |
| 143 // Do we have an expectation for this command? |
| 144 expectation = the_expectations.find(cmd_id); |
| 145 if (expectation != the_expectations.end()) { |
| 146 (expectation->second)(ctx, cmd_iterators.first->second, is_valid); |
| 147 // Remove this command from the set of expectations since we found it. |
| 148 the_expectations.erase(expectation); |
| 149 } else { |
| 150 *is_valid = false; |
| 151 LOG(ERROR) << ctx.dist->GetAppShortCutName() |
| 152 << " has an unexpected Google Update product command named \"" |
| 153 << cmd_id << "\"."; |
| 154 } |
| 155 } |
| 156 |
| 157 // Report on any expected commands that weren't present. |
| 158 CommandExpectations::const_iterator scan(the_expectations.begin()); |
| 159 CommandExpectations::const_iterator end(the_expectations.end()); |
| 160 for (; scan != end; ++scan) { |
| 161 *is_valid = false; |
| 162 LOG(ERROR) << ctx.dist->GetAppShortCutName() |
| 163 << " is missing the Google Update product command named \"" |
| 164 << scan->first << "\"."; |
| 165 } |
| 166 } |
| 167 |
| 168 // Validates the multi-install binaries' Google Update commands. |
| 169 void InstallationValidator::ValidateBinariesCommands( |
| 170 const ProductContext& ctx, |
| 171 bool* is_valid) { |
| 172 DCHECK(is_valid); |
| 173 |
| 174 // The quick-enable-cf command must be present if Chrome is installed either |
| 175 // alone or with CF in ready-mode. |
| 176 const ChannelInfo& channel = ctx.state.channel(); |
| 177 const ProductState* chrome_state = ctx.machine_state.GetProductState( |
| 178 ctx.system_install, BrowserDistribution::CHROME_BROWSER); |
| 179 const ProductState* cf_state = ctx.machine_state.GetProductState( |
| 180 ctx.system_install, BrowserDistribution::CHROME_FRAME); |
| 181 |
| 182 CommandExpectations expectations; |
| 183 |
| 184 if (chrome_state != NULL && (cf_state == NULL || channel.IsReadyMode())) |
| 185 expectations[kCmdQuickEnableCf] = &ValidateQuickEnableCfCommand; |
| 186 |
| 187 ValidateProductCommandExpectations(ctx, expectations, is_valid); |
| 188 } |
| 189 |
80 // Validates the multi-install binaries at level |system_level|. | 190 // Validates the multi-install binaries at level |system_level|. |
81 void InstallationValidator::ValidateBinaries( | 191 void InstallationValidator::ValidateBinaries( |
82 const InstallationState& machine_state, | 192 const InstallationState& machine_state, |
83 bool system_install, | 193 bool system_install, |
84 const ProductState& binaries_state, | 194 const ProductState& binaries_state, |
85 bool* is_valid) { | 195 bool* is_valid) { |
86 const ChannelInfo& channel = binaries_state.channel(); | 196 const ChannelInfo& channel = binaries_state.channel(); |
87 | 197 |
88 // ap must have -multi | 198 // ap must have -multi |
89 if (!channel.IsMultiInstall()) { | 199 if (!channel.IsMultiInstall()) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 << "Chrome Binaries are present yet Chrome is not multi-install."; | 262 << "Chrome Binaries are present yet Chrome is not multi-install."; |
153 } | 263 } |
154 | 264 |
155 // Chrome Frame must be multi-install if Chrome is not present. | 265 // Chrome Frame must be multi-install if Chrome is not present. |
156 if (cf_state != NULL && chrome_state == NULL && | 266 if (cf_state != NULL && chrome_state == NULL && |
157 !cf_state->is_multi_install()) { | 267 !cf_state->is_multi_install()) { |
158 *is_valid = false; | 268 *is_valid = false; |
159 LOG(ERROR) << "Chrome Binaries are present without Chrome yet Chrome Frame " | 269 LOG(ERROR) << "Chrome Binaries are present without Chrome yet Chrome Frame " |
160 "is not multi-install."; | 270 "is not multi-install."; |
161 } | 271 } |
| 272 |
| 273 ChromeBinariesRules binaries_rules; |
| 274 ProductContext ctx = { |
| 275 machine_state, |
| 276 system_install, |
| 277 BrowserDistribution::GetSpecificDistribution( |
| 278 BrowserDistribution::CHROME_BINARIES), |
| 279 binaries_state, |
| 280 binaries_rules |
| 281 }; |
| 282 ValidateBinariesCommands(ctx, is_valid); |
162 } | 283 } |
163 | 284 |
164 // Validates the path to |setup_exe| for the product described by |ctx|. | 285 // Validates the path to |setup_exe| for the product described by |ctx|. |
165 void InstallationValidator::ValidateSetupPath(const ProductContext& ctx, | 286 void InstallationValidator::ValidateSetupPath(const ProductContext& ctx, |
166 const FilePath& setup_exe, | 287 const FilePath& setup_exe, |
167 const char* purpose, | 288 const char* purpose, |
168 bool* is_valid) { | 289 bool* is_valid) { |
169 DCHECK(is_valid); | 290 DCHECK(is_valid); |
170 | 291 |
171 BrowserDistribution* bins_dist = ctx.dist; | 292 BrowserDistribution* bins_dist = ctx.dist; |
172 if (ctx.state.is_multi_install()) { | 293 if (ctx.state.is_multi_install()) { |
173 bins_dist = BrowserDistribution::GetSpecificDistribution( | 294 bins_dist = BrowserDistribution::GetSpecificDistribution( |
174 BrowserDistribution::CHROME_BINARIES); | 295 BrowserDistribution::CHROME_BINARIES); |
175 } | 296 } |
176 | 297 |
177 FilePath expected_path = installer::GetChromeInstallPath(ctx.system_install, | 298 FilePath expected_path = installer::GetChromeInstallPath(ctx.system_install, |
178 bins_dist); | 299 bins_dist); |
179 expected_path = expected_path | 300 expected_path = expected_path |
180 .AppendASCII(ctx.state.version().GetString()) | 301 .AppendASCII(ctx.state.version().GetString()) |
181 .Append(installer::kInstallerDir) | 302 .Append(installer::kInstallerDir) |
182 .Append(installer::kSetupExe); | 303 .Append(installer::kSetupExe); |
183 if (!FilePath::CompareEqualIgnoreCase(expected_path.value(), | 304 if (!FilePath::CompareEqualIgnoreCase(expected_path.value(), |
184 setup_exe.value())) { | 305 setup_exe.value())) { |
185 *is_valid = false; | 306 *is_valid = false; |
186 LOG(ERROR) << ctx.dist->GetApplicationName() << " path to " << purpose | 307 LOG(ERROR) << ctx.dist->GetAppShortCutName() << " path to " << purpose |
187 << " is not " << expected_path.value() << ": " | 308 << " is not " << expected_path.value() << ": " |
188 << setup_exe.value(); | 309 << setup_exe.value(); |
189 } | 310 } |
190 } | 311 } |
191 | 312 |
192 // Validates that |command| meets the expectations described in |expected|. | 313 // Validates that |command| meets the expectations described in |expected|. |
193 void InstallationValidator::ValidateCommandExpectations( | 314 void InstallationValidator::ValidateCommandExpectations( |
194 const ProductContext& ctx, | 315 const ProductContext& ctx, |
195 const CommandLine& command, | 316 const CommandLine& command, |
196 const SwitchExpectations& expected, | 317 const SwitchExpectations& expected, |
197 const char* source, | 318 const char* source, |
198 bool* is_valid) { | 319 bool* is_valid) { |
199 for (SwitchExpectations::size_type i = 0, size = expected.size(); i < size; | 320 for (SwitchExpectations::size_type i = 0, size = expected.size(); i < size; |
200 ++i) { | 321 ++i) { |
201 const SwitchExpectations::value_type& expectation = expected[i]; | 322 const SwitchExpectations::value_type& expectation = expected[i]; |
202 if (command.HasSwitch(expectation.first) != expectation.second) { | 323 if (command.HasSwitch(expectation.first) != expectation.second) { |
203 *is_valid = false; | 324 *is_valid = false; |
204 LOG(ERROR) << ctx.dist->GetApplicationName() << " " << source | 325 LOG(ERROR) << ctx.dist->GetAppShortCutName() << " " << source |
205 << (expectation.second ? " is missing" : " has") << " \"" | 326 << (expectation.second ? " is missing" : " has") << " \"" |
206 << expectation.first << "\"" | 327 << expectation.first << "\"" |
207 << (expectation.second ? "" : " but shouldn't") << ": " | 328 << (expectation.second ? "" : " but shouldn't") << ": " |
208 << command.command_line_string(); | 329 << command.command_line_string(); |
209 } | 330 } |
210 } | 331 } |
211 } | 332 } |
212 | 333 |
213 // Validates that |command|, originating from |source|, is formed properly for | 334 // Validates that |command|, originating from |source|, is formed properly for |
214 // the product described by |ctx| | 335 // the product described by |ctx| |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 // Validates the "opv" and "cmd" values for the product described in |ctx|. | 385 // Validates the "opv" and "cmd" values for the product described in |ctx|. |
265 void InstallationValidator::ValidateOldVersionValues( | 386 void InstallationValidator::ValidateOldVersionValues( |
266 const ProductContext& ctx, | 387 const ProductContext& ctx, |
267 bool* is_valid) { | 388 bool* is_valid) { |
268 DCHECK(is_valid); | 389 DCHECK(is_valid); |
269 | 390 |
270 // opv and cmd must both be present or both absent | 391 // opv and cmd must both be present or both absent |
271 if (ctx.state.old_version() == NULL) { | 392 if (ctx.state.old_version() == NULL) { |
272 if (!ctx.state.rename_cmd().empty()) { | 393 if (!ctx.state.rename_cmd().empty()) { |
273 *is_valid = false; | 394 *is_valid = false; |
274 LOG(ERROR) << ctx.dist->GetApplicationName() | 395 LOG(ERROR) << ctx.dist->GetAppShortCutName() |
275 << " has a rename command but no opv: " | 396 << " has a rename command but no opv: " |
276 << ctx.state.rename_cmd(); | 397 << ctx.state.rename_cmd(); |
277 } | 398 } |
278 } else { | 399 } else { |
279 if (ctx.state.rename_cmd().empty()) { | 400 if (ctx.state.rename_cmd().empty()) { |
280 *is_valid = false; | 401 *is_valid = false; |
281 LOG(ERROR) << ctx.dist->GetApplicationName() | 402 LOG(ERROR) << ctx.dist->GetAppShortCutName() |
282 << " has an opv but no rename command: " | 403 << " has an opv but no rename command: " |
283 << ctx.state.old_version()->GetString(); | 404 << ctx.state.old_version()->GetString(); |
284 } else { | 405 } else { |
285 ValidateRenameCommand(ctx, is_valid); | 406 ValidateRenameCommand(ctx, is_valid); |
286 } | 407 } |
287 } | 408 } |
288 } | 409 } |
289 | 410 |
290 // Validates the multi-install state of the product described in |ctx|. | 411 // Validates the multi-install state of the product described in |ctx|. |
291 void InstallationValidator::ValidateMultiInstallProduct( | 412 void InstallationValidator::ValidateMultiInstallProduct( |
292 const ProductContext& ctx, | 413 const ProductContext& ctx, |
293 bool* is_valid) { | 414 bool* is_valid) { |
294 DCHECK(is_valid); | 415 DCHECK(is_valid); |
295 | 416 |
296 const ProductState* binaries = | 417 const ProductState* binaries = |
297 ctx.machine_state.GetProductState(ctx.system_install, | 418 ctx.machine_state.GetProductState(ctx.system_install, |
298 BrowserDistribution::CHROME_BINARIES); | 419 BrowserDistribution::CHROME_BINARIES); |
299 DCHECK(binaries); | 420 DCHECK(binaries); |
300 | 421 |
301 // Version must match that of binaries. | 422 // Version must match that of binaries. |
302 if (ctx.state.version().CompareTo(binaries->version()) != 0) { | 423 if (ctx.state.version().CompareTo(binaries->version()) != 0) { |
303 *is_valid = false; | 424 *is_valid = false; |
304 LOG(ERROR) << "Version of " << ctx.dist->GetApplicationName() | 425 LOG(ERROR) << "Version of " << ctx.dist->GetAppShortCutName() |
305 << " (" << ctx.state.version().GetString() << ") does not " | 426 << " (" << ctx.state.version().GetString() << ") does not " |
306 "match that of Chrome Binaries (" | 427 "match that of Chrome Binaries (" |
307 << binaries->version().GetString() << ")."; | 428 << binaries->version().GetString() << ")."; |
308 } | 429 } |
309 | 430 |
310 // Channel value must match that of binaries. | 431 // Channel value must match that of binaries. |
311 if (!ctx.state.channel().Equals(binaries->channel())) { | 432 if (!ctx.state.channel().Equals(binaries->channel())) { |
312 *is_valid = false; | 433 *is_valid = false; |
313 LOG(ERROR) << "Channel name of " << ctx.dist->GetApplicationName() | 434 LOG(ERROR) << "Channel name of " << ctx.dist->GetAppShortCutName() |
314 << " (" << ctx.state.channel().value() | 435 << " (" << ctx.state.channel().value() |
315 << ") does not match that of Chrome Binaries (" | 436 << ") does not match that of Chrome Binaries (" |
316 << binaries->channel().value() << ")."; | 437 << binaries->channel().value() << ")."; |
317 } | 438 } |
318 } | 439 } |
319 | 440 |
| 441 // Validates the Google Update commands for the product described in |ctx|. |
| 442 void InstallationValidator::ValidateProductCommands( |
| 443 const ProductContext& ctx, |
| 444 bool* is_valid) { |
| 445 DCHECK(is_valid); |
| 446 |
| 447 // Products are not expected to have any commands. |
| 448 ValidateProductCommandExpectations(ctx, CommandExpectations(), is_valid); |
| 449 } |
| 450 |
320 // Validates the product described in |product_state| according to |rules|. | 451 // Validates the product described in |product_state| according to |rules|. |
321 void InstallationValidator::ValidateProduct( | 452 void InstallationValidator::ValidateProduct( |
322 const InstallationState& machine_state, | 453 const InstallationState& machine_state, |
323 bool system_install, | 454 bool system_install, |
324 const ProductState& product_state, | 455 const ProductState& product_state, |
325 const ProductRules& rules, | 456 const ProductRules& rules, |
326 bool* is_valid) { | 457 bool* is_valid) { |
327 DCHECK(is_valid); | 458 DCHECK(is_valid); |
328 ProductContext ctx = { | 459 ProductContext ctx = { |
329 machine_state, | 460 machine_state, |
330 system_install, | 461 system_install, |
331 BrowserDistribution::GetSpecificDistribution(rules.distribution_type()), | 462 BrowserDistribution::GetSpecificDistribution(rules.distribution_type()), |
332 product_state, | 463 product_state, |
333 rules | 464 rules |
334 }; | 465 }; |
335 | 466 |
336 ValidateUninstallCommand(ctx, product_state.uninstall_command(), | 467 ValidateUninstallCommand(ctx, product_state.uninstall_command(), |
337 "Google Update uninstall command", is_valid); | 468 "Google Update uninstall command", is_valid); |
338 | 469 |
339 ValidateOldVersionValues(ctx, is_valid); | 470 ValidateOldVersionValues(ctx, is_valid); |
340 | 471 |
341 if (product_state.is_multi_install()) | 472 if (product_state.is_multi_install()) |
342 ValidateMultiInstallProduct(ctx, is_valid); | 473 ValidateMultiInstallProduct(ctx, is_valid); |
| 474 |
| 475 ValidateProductCommands(ctx, is_valid); |
343 } | 476 } |
344 | 477 |
345 // static | 478 // static |
346 bool InstallationValidator::ValidateInstallationTypeForState( | 479 bool InstallationValidator::ValidateInstallationTypeForState( |
347 const InstallationState& machine_state, | 480 const InstallationState& machine_state, |
348 bool system_level, | 481 bool system_level, |
349 InstallationType* type) { | 482 InstallationType* type) { |
350 DCHECK(type); | 483 DCHECK(type); |
351 bool rock_on = true; | 484 bool rock_on = true; |
352 *type = NO_PRODUCTS; | 485 *type = NO_PRODUCTS; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 InstallationType* type) { | 536 InstallationType* type) { |
404 DCHECK(type); | 537 DCHECK(type); |
405 InstallationState machine_state; | 538 InstallationState machine_state; |
406 | 539 |
407 machine_state.Initialize(); | 540 machine_state.Initialize(); |
408 | 541 |
409 return ValidateInstallationTypeForState(machine_state, system_level, type); | 542 return ValidateInstallationTypeForState(machine_state, system_level, type); |
410 } | 543 } |
411 | 544 |
412 } // namespace installer | 545 } // namespace installer |
OLD | NEW |