1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Implementation of the installation validator. 6 7 #include "chrome/installer/util/installation_validator.h" 8 9 #include <algorithm> 10 #include <set> 11 #include <string> 12 13 #include "base/logging.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/version.h" 16 #include "chrome/common/chrome_switches.h" 17 #include "chrome/installer/util/browser_distribution.h" 18 #include "chrome/installer/util/google_update_constants.h" 19 #include "chrome/installer/util/helper.h" 20 #include "chrome/installer/util/installation_state.h" 21 22 namespace installer { 23 24 BrowserDistribution::Type 25 InstallationValidator::ChromeRules::distribution_type() const { 26 return BrowserDistribution::CHROME_BROWSER; 27 } 28 29 void InstallationValidator::ChromeRules::AddUninstallSwitchExpectations( 30 const ProductContext& ctx, 31 SwitchExpectations* expectations) const { 32 const bool is_multi_install = 33 ctx.state.uninstall_command().HasSwitch(switches::kMultiInstall); 34 35 // --chrome should be present for uninstall iff --multi-install. This wasn't 36 // the case in Chrome 10 (between r68996 and r72497), though, so consider it 37 // optional. 38 } 39 40 void InstallationValidator::ChromeRules::AddRenameSwitchExpectations( 41 const ProductContext& ctx, 42 SwitchExpectations* expectations) const { 43 const bool is_multi_install = 44 ctx.state.uninstall_command().HasSwitch(switches::kMultiInstall); 45 46 // --chrome should not be present for rename. It was for a time, so we'll be 47 // lenient so that mini_installer tests pass. 48 49 // --chrome-frame should never be present. 50 expectations->push_back( 51 std::make_pair(std::string(switches::kChromeFrame), false)); 52 } 53 54 bool InstallationValidator::ChromeRules::UsageStatsAllowed( 55 const ProductContext& ctx) const { 56 // Products must not have usagestats consent values when multi-install 57 // (only the multi-install binaries may). 58 return !ctx.state.is_multi_install(); 59 } 60 61 BrowserDistribution::Type 62 InstallationValidator::ChromeFrameRules::distribution_type() const { 63 return BrowserDistribution::CHROME_FRAME; 64 } 65 66 void InstallationValidator::ChromeFrameRules::AddUninstallSwitchExpectations( 67 const ProductContext& ctx, 68 SwitchExpectations* expectations) const { 69 // --chrome-frame must be present. 70 expectations->push_back(std::make_pair(std::string(switches::kChromeFrame), 71 true)); 72 // --chrome must not be present. 73 expectations->push_back(std::make_pair(std::string(switches::kChrome), 74 false)); 75 } 76 77 void InstallationValidator::ChromeFrameRules::AddRenameSwitchExpectations( 78 const ProductContext& ctx, 79 SwitchExpectations* expectations) const { 80 // --chrome-frame must be present for SxS rename. 81 expectations->push_back(std::make_pair(std::string(switches::kChromeFrame), 82 !ctx.state.is_multi_install())); 83 // --chrome must not be present. 84 expectations->push_back(std::make_pair(std::string(switches::kChrome), 85 false)); 86 } 87 88 bool InstallationValidator::ChromeFrameRules::UsageStatsAllowed( 89 const ProductContext& ctx) const { 90 // Products must not have usagestats consent values when multi-install 91 // (only the multi-install binaries may). 92 return !ctx.state.is_multi_install(); 93 } 94 95 BrowserDistribution::Type 96 InstallationValidator::ChromeAppHostRules::distribution_type() const { 97 return BrowserDistribution::CHROME_APP_HOST; 98 } 99 100 void InstallationValidator::ChromeAppHostRules::AddUninstallSwitchExpectations( 101 const ProductContext& ctx, 102 SwitchExpectations* expectations) const { 103 // --app-launcher must be present. 104 expectations->push_back( 105 std::make_pair(std::string(switches::kChromeAppLauncher), true)); 106 107 // --chrome must not be present. 108 expectations->push_back(std::make_pair(std::string(switches::kChrome), 109 false)); 110 // --chrome-frame must not be present. 111 expectations->push_back(std::make_pair(std::string(switches::kChromeFrame), 112 false)); 113 } 114 115 void InstallationValidator::ChromeAppHostRules::AddRenameSwitchExpectations( 116 const ProductContext& ctx, 117 SwitchExpectations* expectations) const { 118 // TODO(erikwright): I guess there will be none? 119 } 120 121 bool InstallationValidator::ChromeAppHostRules::UsageStatsAllowed( 122 const ProductContext& ctx) const { 123 // App Host doesn't manage usage stats. The Chrome Binaries will. 124 return false; 125 } 126 127 BrowserDistribution::Type 128 InstallationValidator::ChromeBinariesRules::distribution_type() const { 129 return BrowserDistribution::CHROME_BINARIES; 130 } 131 132 void InstallationValidator::ChromeBinariesRules::AddUninstallSwitchExpectations( 133 const ProductContext& ctx, 134 SwitchExpectations* expectations) const { 135 NOTREACHED(); 136 } 137 138 void InstallationValidator::ChromeBinariesRules::AddRenameSwitchExpectations( 139 const ProductContext& ctx, 140 SwitchExpectations* expectations) const { 141 NOTREACHED(); 142 } 143 144 bool InstallationValidator::ChromeBinariesRules::UsageStatsAllowed( 145 const ProductContext& ctx) const { 146 // UsageStats consent values are always allowed on the binaries. 147 return true; 148 } 149 150 // static 151 const InstallationValidator::InstallationType 152 InstallationValidator::kInstallationTypes[] = { 153 NO_PRODUCTS, 154 CHROME_SINGLE, 155 CHROME_MULTI, 156 CHROME_FRAME_SINGLE, 157 CHROME_FRAME_SINGLE_CHROME_SINGLE, 158 CHROME_FRAME_SINGLE_CHROME_MULTI, 159 CHROME_FRAME_MULTI, 160 CHROME_FRAME_MULTI_CHROME_MULTI, 161 CHROME_APP_HOST, 162 CHROME_APP_HOST_CHROME_FRAME_SINGLE, 163 CHROME_APP_HOST_CHROME_FRAME_SINGLE_CHROME_MULTI, 164 CHROME_APP_HOST_CHROME_FRAME_MULTI, 165 CHROME_APP_HOST_CHROME_FRAME_MULTI_CHROME_MULTI, 166 CHROME_APP_HOST_CHROME_MULTI, 167 }; 168 169 void InstallationValidator::ValidateAppCommandFlags( 170 const ProductContext& ctx, 171 const AppCommand& app_cmd, 172 const std::set<base::string16>& flags_exp, 173 const base::string16& name, 174 bool* is_valid) { 175 const struct { 176 const base::string16 exp_key; 177 bool val; 178 const char* msg; 179 } check_list[] = { 180 {google_update::kRegSendsPingsField, 181 app_cmd.sends_pings(), 182 "be configured to send pings"}, 183 {google_update::kRegWebAccessibleField, 184 app_cmd.is_web_accessible(), 185 "be web accessible"}, 186 {google_update::kRegAutoRunOnOSUpgradeField, 187 app_cmd.is_auto_run_on_os_upgrade(), 188 "be marked to run on OS upgrade"}, 189 {google_update::kRegRunAsUserField, 190 app_cmd.is_run_as_user(), 191 "be marked to run as user"}, 192 }; 193 for (int i = 0; i < arraysize(check_list); ++i) { 194 bool expected = flags_exp.find(check_list[i].exp_key) != flags_exp.end(); 195 if (check_list[i].val != expected) { 196 *is_valid = false; 197 LOG(ERROR) << ctx.dist->GetDisplayName() << ": " 198 << name << " command should " << (expected ? "" : "not ") 199 << check_list[i].msg << "."; 200 } 201 } 202 } 203 204 // Validates the "on-os-upgrade" Google Update internal command. 205 void InstallationValidator::ValidateOnOsUpgradeCommand( 206 const ProductContext& ctx, 207 const AppCommand& app_cmd, 208 bool* is_valid) { 209 DCHECK(is_valid); 210 211 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line())); 212 base::string16 name(kCmdOnOsUpgrade); 213 214 ValidateSetupPath(ctx, cmd_line.GetProgram(), name, is_valid); 215 216 SwitchExpectations expected; 217 expected.push_back(std::make_pair(std::string(switches::kOnOsUpgrade), true)); 218 expected.push_back(std::make_pair(std::string(switches::kSystemLevel), 219 ctx.system_install)); 220 expected.push_back(std::make_pair(std::string(switches::kMultiInstall), 221 ctx.state.is_multi_install())); 222 // Expecting kChrome if and only if kMultiInstall. 223 expected.push_back(std::make_pair(std::string(switches::kChrome), 224 ctx.state.is_multi_install())); 225 226 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid); 227 228 std::set<base::string16> flags_exp; 229 flags_exp.insert(google_update::kRegAutoRunOnOSUpgradeField); 230 ValidateAppCommandFlags(ctx, app_cmd, flags_exp, name, is_valid); 231 } 232 233 // Validates the "query-eula-acceptance" Google Update product command. 234 void InstallationValidator::ValidateQueryEULAAcceptanceCommand( 235 const ProductContext& ctx, 236 const AppCommand& app_cmd, 237 bool* is_valid) { 238 DCHECK(is_valid); 239 240 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line())); 241 base::string16 name(kCmdQueryEULAAcceptance); 242 243 ValidateSetupPath(ctx, cmd_line.GetProgram(), name, is_valid); 244 245 SwitchExpectations expected; 246 expected.push_back(std::make_pair(std::string(switches::kQueryEULAAcceptance), 247 true)); 248 expected.push_back(std::make_pair(std::string(switches::kSystemLevel), 249 ctx.system_install)); 250 251 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid); 252 253 std::set<base::string16> flags_exp; 254 flags_exp.insert(google_update::kRegWebAccessibleField); 255 flags_exp.insert(google_update::kRegRunAsUserField); 256 ValidateAppCommandFlags(ctx, app_cmd, flags_exp, name, is_valid); 257 } 258 259 // Validates the "quick-enable-application-host" Google Update product command. 260 void InstallationValidator::ValidateQuickEnableApplicationHostCommand( 261 const ProductContext& ctx, 262 const AppCommand& app_cmd, 263 bool* is_valid) { 264 DCHECK(is_valid); 265 266 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line())); 267 base::string16 name(kCmdQuickEnableApplicationHost); 268 269 ValidateSetupPath(ctx, cmd_line.GetProgram(), name, is_valid); 270 271 SwitchExpectations expected; 272 273 expected.push_back(std::make_pair( 274 std::string(switches::kChromeAppLauncher), true)); 275 expected.push_back(std::make_pair( 276 std::string(switches::kSystemLevel), false)); 277 expected.push_back(std::make_pair( 278 std::string(switches::kMultiInstall), true)); 279 expected.push_back(std::make_pair( 280 std::string(switches::kEnsureGoogleUpdatePresent), true)); 281 282 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid); 283 284 std::set<base::string16> flags_exp; 285 flags_exp.insert(google_update::kRegSendsPingsField); 286 flags_exp.insert(google_update::kRegWebAccessibleField); 287 flags_exp.insert(google_update::kRegRunAsUserField); 288 ValidateAppCommandFlags(ctx, app_cmd, flags_exp, name, is_valid); 289 } 290 291 // Validates a product's set of Google Update product commands against a 292 // collection of expectations. 293 void InstallationValidator::ValidateAppCommandExpectations( 294 const ProductContext& ctx, 295 const CommandExpectations& expectations, 296 bool* is_valid) { 297 DCHECK(is_valid); 298 299 CommandExpectations the_expectations(expectations); 300 301 AppCommands::CommandMapRange cmd_iterators( 302 ctx.state.commands().GetIterators()); 303 CommandExpectations::iterator expectation; 304 for (; cmd_iterators.first != cmd_iterators.second; ++cmd_iterators.first) { 305 const base::string16& cmd_id = cmd_iterators.first->first; 306 // Do we have an expectation for this command? 307 expectation = the_expectations.find(cmd_id); 308 if (expectation != the_expectations.end()) { 309 (expectation->second)(ctx, cmd_iterators.first->second, is_valid); 310 // Remove this command from the set of expectations since we found it. 311 the_expectations.erase(expectation); 312 } else { 313 *is_valid = false; 314 LOG(ERROR) << ctx.dist->GetDisplayName() 315 << " has an unexpected Google Update product command named \"" 316 << cmd_id << "\"."; 317 } 318 } 319 320 // Report on any expected commands that weren't present. 321 CommandExpectations::const_iterator scan(the_expectations.begin()); 322 CommandExpectations::const_iterator end(the_expectations.end()); 323 for (; scan != end; ++scan) { 324 *is_valid = false; 325 LOG(ERROR) << ctx.dist->GetDisplayName() 326 << " is missing the Google Update product command named \"" 327 << scan->first << "\"."; 328 } 329 } 330 331 // Validates the multi-install binaries' Google Update commands. 332 void InstallationValidator::ValidateBinariesCommands( 333 const ProductContext& ctx, 334 bool* is_valid) { 335 DCHECK(is_valid); 336 337 const ProductState* binaries_state = ctx.machine_state.GetProductState( 338 ctx.system_install, BrowserDistribution::CHROME_BINARIES); 339 340 CommandExpectations expectations; 341 342 if (binaries_state != NULL) { 343 expectations[kCmdQuickEnableApplicationHost] = 344 &ValidateQuickEnableApplicationHostCommand; 345 346 expectations[kCmdQueryEULAAcceptance] = &ValidateQueryEULAAcceptanceCommand; 347 } 348 349 ValidateAppCommandExpectations(ctx, expectations, is_valid); 350 } 351 352 // Validates the multi-install binaries at level |system_level|. 353 void InstallationValidator::ValidateBinaries( 354 const InstallationState& machine_state, 355 bool system_install, 356 const ProductState& binaries_state, 357 bool* is_valid) { 358 const ChannelInfo& channel = binaries_state.channel(); 359 360 // ap must have -multi 361 if (!channel.IsMultiInstall()) { 362 *is_valid = false; 363 LOG(ERROR) << "Chrome Binaries are missing \"-multi\" in channel name: \"" 364 << channel.value() << "\""; 365 } 366 367 // ap must have -chrome iff Chrome is installed 368 const ProductState* chrome_state = machine_state.GetProductState( 369 system_install, BrowserDistribution::CHROME_BROWSER); 370 if (chrome_state != NULL) { 371 if (!channel.IsChrome()) { 372 *is_valid = false; 373 LOG(ERROR) << "Chrome Binaries are missing \"chrome\" in channel name:" 374 << " \"" << channel.value() << "\""; 375 } 376 } else if (channel.IsChrome()) { 377 *is_valid = false; 378 LOG(ERROR) << "Chrome Binaries have \"-chrome\" in channel name, yet Chrome" 379 " is not installed: \"" << channel.value() << "\""; 380 } 381 382 // ap must have -chromeframe iff Chrome Frame is installed multi 383 const ProductState* cf_state = machine_state.GetProductState( 384 system_install, BrowserDistribution::CHROME_FRAME); 385 if (cf_state != NULL && cf_state->is_multi_install()) { 386 if (!channel.IsChromeFrame()) { 387 *is_valid = false; 388 LOG(ERROR) << "Chrome Binaries are missing \"-chromeframe\" in channel" 389 " name: \"" << channel.value() << "\""; 390 } 391 } else if (channel.IsChromeFrame()) { 392 *is_valid = false; 393 LOG(ERROR) << "Chrome Binaries have \"-chromeframe\" in channel name, yet " 394 "Chrome Frame is not installed multi: \"" << channel.value() 395 << "\""; 396 } 397 398 // ap must have -applauncher iff Chrome App Launcher is installed multi 399 const ProductState* app_host_state = machine_state.GetProductState( 400 system_install, BrowserDistribution::CHROME_APP_HOST); 401 if (app_host_state != NULL) { 402 if (!app_host_state->is_multi_install()) { 403 *is_valid = false; 404 LOG(ERROR) << "Chrome App Launcher is installed in non-multi mode."; 405 } 406 if (!channel.IsAppLauncher()) { 407 *is_valid = false; 408 LOG(ERROR) << "Chrome Binaries are missing \"-applauncher\" in channel" 409 " name: \"" << channel.value() << "\""; 410 } 411 } else if (channel.IsAppLauncher()) { 412 *is_valid = false; 413 LOG(ERROR) << "Chrome Binaries have \"-applauncher\" in channel name, yet " 414 "Chrome App Launcher is not installed: \"" << channel.value() 415 << "\""; 416 } 417 418 // Chrome, Chrome Frame, or App Host must be present 419 if (chrome_state == NULL && cf_state == NULL && app_host_state == NULL) { 420 *is_valid = false; 421 LOG(ERROR) << "Chrome Binaries are present with no other products."; 422 } 423 424 // Chrome must be multi-install if present. 425 if (chrome_state != NULL && !chrome_state->is_multi_install()) { 426 *is_valid = false; 427 LOG(ERROR) 428 << "Chrome Binaries are present yet Chrome is not multi-install."; 429 } 430 431 // Chrome Frame must be multi-install if Chrome & App Host are not present. 432 if (cf_state != NULL && app_host_state == NULL && chrome_state == NULL && 433 !cf_state->is_multi_install()) { 434 *is_valid = false; 435 LOG(ERROR) << "Chrome Binaries are present without Chrome nor App Launcher " 436 << "yet Chrome Frame is not multi-install."; 437 } 438 439 ChromeBinariesRules binaries_rules; 440 ProductContext ctx(machine_state, system_install, binaries_state, 441 binaries_rules); 442 443 ValidateBinariesCommands(ctx, is_valid); 444 445 ValidateUsageStats(ctx, is_valid); 446 } 447 448 // Validates the path to |setup_exe| for the product described by |ctx|. 449 void InstallationValidator::ValidateSetupPath(const ProductContext& ctx, 450 const base::FilePath& setup_exe, 451 const base::string16& purpose, 452 bool* is_valid) { 453 DCHECK(is_valid); 454 455 BrowserDistribution* bins_dist = ctx.dist; 456 if (ctx.state.is_multi_install()) { 457 bins_dist = BrowserDistribution::GetSpecificDistribution( 458 BrowserDistribution::CHROME_BINARIES); 459 } 460 461 base::FilePath expected_path = installer::GetChromeInstallPath( 462 ctx.system_install, bins_dist); 463 expected_path = expected_path 464 .AppendASCII(ctx.state.version().GetString()) 465 .Append(installer::kInstallerDir) 466 .Append(installer::kSetupExe); 467 if (!base::FilePath::CompareEqualIgnoreCase(expected_path.value(), 468 setup_exe.value())) { 469 *is_valid = false; 470 LOG(ERROR) << ctx.dist->GetDisplayName() << " path to " << purpose 471 << " is not " << expected_path.value() << ": " 472 << setup_exe.value(); 473 } 474 } 475 476 // Validates that |command| meets the expectations described in |expected|. 477 void InstallationValidator::ValidateCommandExpectations( 478 const ProductContext& ctx, 479 const CommandLine& command, 480 const SwitchExpectations& expected, 481 const base::string16& source, 482 bool* is_valid) { 483 for (SwitchExpectations::size_type i = 0, size = expected.size(); i < size; 484 ++i) { 485 const SwitchExpectations::value_type& expectation = expected[i]; 486 if (command.HasSwitch(expectation.first) != expectation.second) { 487 *is_valid = false; 488 LOG(ERROR) << ctx.dist->GetDisplayName() << " " << source 489 << (expectation.second ? " is missing" : " has") << " \"" 490 << expectation.first << "\"" 491 << (expectation.second ? "" : " but shouldn't") << ": " 492 << command.GetCommandLineString(); 493 } 494 } 495 } 496 497 // Validates that |command|, originating from |source|, is formed properly for 498 // the product described by |ctx| 499 void InstallationValidator::ValidateUninstallCommand( 500 const ProductContext& ctx, 501 const CommandLine& command, 502 const base::string16& source, 503 bool* is_valid) { 504 DCHECK(is_valid); 505 506 ValidateSetupPath(ctx, command.GetProgram(), 507 base::ASCIIToUTF16("uninstaller"), 508 is_valid); 509 510 const bool is_multi_install = ctx.state.is_multi_install(); 511 SwitchExpectations expected; 512 513 expected.push_back(std::make_pair(std::string(switches::kUninstall), true)); 514 expected.push_back(std::make_pair(std::string(switches::kSystemLevel), 515 ctx.system_install)); 516 expected.push_back(std::make_pair(std::string(switches::kMultiInstall), 517 is_multi_install)); 518 ctx.rules.AddUninstallSwitchExpectations(ctx, &expected); 519 520 ValidateCommandExpectations(ctx, command, expected, source, is_valid); 521 } 522 523 // Validates the rename command for the product described by |ctx|. 524 void InstallationValidator::ValidateRenameCommand(const ProductContext& ctx, 525 bool* is_valid) { 526 DCHECK(is_valid); 527 DCHECK(!ctx.state.rename_cmd().empty()); 528 529 CommandLine command = CommandLine::FromString(ctx.state.rename_cmd()); 530 base::string16 name(base::ASCIIToUTF16("in-use renamer")); 531 532 ValidateSetupPath(ctx, command.GetProgram(), name, is_valid); 533 534 SwitchExpectations expected; 535 536 expected.push_back(std::make_pair(std::string(switches::kRenameChromeExe), 537 true)); 538 expected.push_back(std::make_pair(std::string(switches::kSystemLevel), 539 ctx.system_install)); 540 expected.push_back(std::make_pair(std::string(switches::kMultiInstall), 541 ctx.state.is_multi_install())); 542 ctx.rules.AddRenameSwitchExpectations(ctx, &expected); 543 544 ValidateCommandExpectations(ctx, command, expected, name, is_valid); 545 } 546 547 // Validates the "opv" and "cmd" values for the product described in |ctx|. 548 void InstallationValidator::ValidateOldVersionValues( 549 const ProductContext& ctx, 550 bool* is_valid) { 551 DCHECK(is_valid); 552 553 // opv and cmd must both be present or both absent 554 if (ctx.state.old_version() == NULL) { 555 if (!ctx.state.rename_cmd().empty()) { 556 *is_valid = false; 557 LOG(ERROR) << ctx.dist->GetDisplayName() 558 << " has a rename command but no opv: " 559 << ctx.state.rename_cmd(); 560 } 561 } else { 562 if (ctx.state.rename_cmd().empty()) { 563 *is_valid = false; 564 LOG(ERROR) << ctx.dist->GetDisplayName() 565 << " has an opv but no rename command: " 566 << ctx.state.old_version()->GetString(); 567 } else { 568 ValidateRenameCommand(ctx, is_valid); 569 } 570 } 571 } 572 573 // Validates the multi-install state of the product described in |ctx|. 574 void InstallationValidator::ValidateMultiInstallProduct( 575 const ProductContext& ctx, 576 bool* is_valid) { 577 DCHECK(is_valid); 578 579 const ProductState* binaries = 580 ctx.machine_state.GetProductState(ctx.system_install, 581 BrowserDistribution::CHROME_BINARIES); 582 if (!binaries) { 583 if (ctx.dist->GetType() == BrowserDistribution::CHROME_APP_HOST) { 584 if (!ctx.machine_state.GetProductState( 585 true, // system-level 586 BrowserDistribution::CHROME_BINARIES) && 587 !ctx.machine_state.GetProductState( 588 true, // system-level 589 BrowserDistribution::CHROME_BROWSER)) { 590 *is_valid = false; 591 LOG(ERROR) << ctx.dist->GetDisplayName() 592 << " (" << ctx.state.version().GetString() << ") is " 593 << "installed without Chrome Binaries or a system-level " 594 << "Chrome."; 595 } 596 } else { 597 *is_valid = false; 598 LOG(ERROR) << ctx.dist->GetDisplayName() 599 << " (" << ctx.state.version().GetString() << ") is installed " 600 << "without Chrome Binaries."; 601 } 602 } else { 603 // Version must match that of binaries. 604 if (ctx.state.version().CompareTo(binaries->version()) != 0) { 605 *is_valid = false; 606 LOG(ERROR) << "Version of " << ctx.dist->GetDisplayName() 607 << " (" << ctx.state.version().GetString() << ") does not " 608 "match that of Chrome Binaries (" 609 << binaries->version().GetString() << ")."; 610 } 611 612 // Channel value must match that of binaries. 613 if (!ctx.state.channel().Equals(binaries->channel())) { 614 *is_valid = false; 615 LOG(ERROR) << "Channel name of " << ctx.dist->GetDisplayName() 616 << " (" << ctx.state.channel().value() 617 << ") does not match that of Chrome Binaries (" 618 << binaries->channel().value() << ")."; 619 } 620 } 621 } 622 623 // Validates the Google Update commands for the product described in |ctx|. 624 void InstallationValidator::ValidateAppCommands( 625 const ProductContext& ctx, 626 bool* is_valid) { 627 DCHECK(is_valid); 628 629 CommandExpectations expectations; 630 631 if (ctx.dist->GetType() == BrowserDistribution::CHROME_BROWSER) 632 expectations[kCmdOnOsUpgrade] = &ValidateOnOsUpgradeCommand; 633 634 ValidateAppCommandExpectations(ctx, expectations, is_valid); 635 } 636 637 // Validates usagestats for the product or binaries in |ctx|. 638 void InstallationValidator::ValidateUsageStats(const ProductContext& ctx, 639 bool* is_valid) { 640 DWORD usagestats = 0; 641 if (ctx.state.GetUsageStats(&usagestats)) { 642 if (!ctx.rules.UsageStatsAllowed(ctx)) { 643 *is_valid = false; 644 LOG(ERROR) << ctx.dist->GetDisplayName() 645 << " has a usagestats value (" << usagestats 646 << "), yet should not."; 647 } else if (usagestats != 0 && usagestats != 1) { 648 *is_valid = false; 649 LOG(ERROR) << ctx.dist->GetDisplayName() 650 << " has an unsupported usagestats value (" << usagestats 651 << ")."; 652 } 653 } 654 } 655 656 // Validates the product described in |product_state| according to |rules|. 657 void InstallationValidator::ValidateProduct( 658 const InstallationState& machine_state, 659 bool system_install, 660 const ProductState& product_state, 661 const ProductRules& rules, 662 bool* is_valid) { 663 DCHECK(is_valid); 664 665 ProductContext ctx(machine_state, system_install, product_state, rules); 666 667 ValidateUninstallCommand(ctx, ctx.state.uninstall_command(), 668 base::ASCIIToUTF16( 669 "Google Update uninstall command"), 670 is_valid); 671 672 ValidateOldVersionValues(ctx, is_valid); 673 674 if (ctx.state.is_multi_install()) 675 ValidateMultiInstallProduct(ctx, is_valid); 676 677 ValidateAppCommands(ctx, is_valid); 678 679 ValidateUsageStats(ctx, is_valid); 680 } 681 682 // static 683 bool InstallationValidator::ValidateInstallationTypeForState( 684 const InstallationState& machine_state, 685 bool system_level, 686 InstallationType* type) { 687 DCHECK(type); 688 bool rock_on = true; 689 *type = NO_PRODUCTS; 690 691 // Does the system have any multi-installed products? 692 const ProductState* multi_state = 693 machine_state.GetProductState(system_level, 694 BrowserDistribution::CHROME_BINARIES); 695 if (multi_state != NULL) 696 ValidateBinaries(machine_state, system_level, *multi_state, &rock_on); 697 698 // Is Chrome installed? 699 const ProductState* product_state = 700 machine_state.GetProductState(system_level, 701 BrowserDistribution::CHROME_BROWSER); 702 if (product_state != NULL) { 703 ChromeRules chrome_rules; 704 ValidateProduct(machine_state, system_level, *product_state, 705 chrome_rules, &rock_on); 706 *type = static_cast<InstallationType>( 707 *type | (product_state->is_multi_install() ? 708 ProductBits::CHROME_MULTI : 709 ProductBits::CHROME_SINGLE)); 710 } 711 712 // Is Chrome Frame installed? 713 product_state = 714 machine_state.GetProductState(system_level, 715 BrowserDistribution::CHROME_FRAME); 716 if (product_state != NULL) { 717 ChromeFrameRules chrome_frame_rules; 718 ValidateProduct(machine_state, system_level, *product_state, 719 chrome_frame_rules, &rock_on); 720 int cf_bit = !product_state->is_multi_install() ? 721 ProductBits::CHROME_FRAME_SINGLE : 722 ProductBits::CHROME_FRAME_MULTI; 723 *type = static_cast<InstallationType>(*type | cf_bit); 724 } 725 726 // Is Chrome App Host installed? 727 product_state = 728 machine_state.GetProductState(system_level, 729 BrowserDistribution::CHROME_APP_HOST); 730 if (product_state != NULL) { 731 ChromeAppHostRules chrome_app_host_rules; 732 ValidateProduct(machine_state, system_level, *product_state, 733 chrome_app_host_rules, &rock_on); 734 *type = static_cast<InstallationType>(*type | ProductBits::CHROME_APP_HOST); 735 if (!product_state->is_multi_install()) { 736 LOG(ERROR) << "Chrome App Launcher must always be multi-install."; 737 rock_on = false; 738 } 739 } 740 741 DCHECK_NE(std::find(&kInstallationTypes[0], 742 &kInstallationTypes[arraysize(kInstallationTypes)], 743 *type), 744 &kInstallationTypes[arraysize(kInstallationTypes)]) 745 << "Invalid combination of products found on system (" << *type << ")"; 746 747 return rock_on; 748 } 749 750 // static 751 bool InstallationValidator::ValidateInstallationType(bool system_level, 752 InstallationType* type) { 753 DCHECK(type); 754 InstallationState machine_state; 755 756 machine_state.Initialize(); 757 758 return ValidateInstallationTypeForState(machine_state, system_level, type); 759 } 760 761 } // namespace installer 762