Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / installer / util / installation_validator.cc
blobce18722bc2b727c956718fa7fdafdb364bd682e0
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.
5 // Implementation of the installation validator.
7 #include "chrome/installer/util/installation_validator.h"
9 #include <algorithm>
10 #include <set>
11 #include <string>
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"
22 namespace installer {
24 BrowserDistribution::Type
25 InstallationValidator::ChromeRules::distribution_type() const {
26 return BrowserDistribution::CHROME_BROWSER;
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);
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.
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);
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.
49 // --chrome-frame should never be present.
50 expectations->push_back(
51 std::make_pair(std::string(switches::kChromeFrame), false));
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();
61 BrowserDistribution::Type
62 InstallationValidator::ChromeFrameRules::distribution_type() const {
63 return BrowserDistribution::CHROME_FRAME;
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));
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));
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();
95 BrowserDistribution::Type
96 InstallationValidator::ChromeAppHostRules::distribution_type() const {
97 return BrowserDistribution::CHROME_APP_HOST;
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));
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));
115 void InstallationValidator::ChromeAppHostRules::AddRenameSwitchExpectations(
116 const ProductContext& ctx,
117 SwitchExpectations* expectations) const {
118 // TODO(erikwright): I guess there will be none?
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;
127 BrowserDistribution::Type
128 InstallationValidator::ChromeBinariesRules::distribution_type() const {
129 return BrowserDistribution::CHROME_BINARIES;
132 void InstallationValidator::ChromeBinariesRules::AddUninstallSwitchExpectations(
133 const ProductContext& ctx,
134 SwitchExpectations* expectations) const {
135 NOTREACHED();
138 void InstallationValidator::ChromeBinariesRules::AddRenameSwitchExpectations(
139 const ProductContext& ctx,
140 SwitchExpectations* expectations) const {
141 NOTREACHED();
144 bool InstallationValidator::ChromeBinariesRules::UsageStatsAllowed(
145 const ProductContext& ctx) const {
146 // UsageStats consent values are always allowed on the binaries.
147 return true;
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,
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"},
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 << ".";
204 // Validates both "install-application" and "install-extension" depending on
205 // what is passed in.
206 void InstallationValidator::ValidateInstallCommand(
207 const ProductContext& ctx,
208 const AppCommand& app_cmd,
209 const wchar_t* expected_command,
210 const wchar_t* expected_app_name,
211 const char* expected_switch,
212 bool* is_valid) {
213 DCHECK(is_valid);
215 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line()));
216 base::string16 name(expected_command);
218 base::FilePath expected_path(
219 installer::GetChromeInstallPath(ctx.system_install, ctx.dist)
220 .Append(expected_app_name));
222 if (!base::FilePath::CompareEqualIgnoreCase(expected_path.value(),
223 cmd_line.GetProgram().value())) {
224 *is_valid = false;
225 LOG(ERROR) << name << "'s path is not "
226 << expected_path.value() << ": "
227 << cmd_line.GetProgram().value();
230 SwitchExpectations expected;
231 expected.push_back(std::make_pair(std::string(expected_switch), true));
233 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid);
235 std::set<base::string16> flags_exp;
236 flags_exp.insert(google_update::kRegSendsPingsField);
237 flags_exp.insert(google_update::kRegWebAccessibleField);
238 flags_exp.insert(google_update::kRegRunAsUserField);
239 ValidateAppCommandFlags(ctx, app_cmd, flags_exp, name, is_valid);
242 // Validates the "install-application" Google Update product command.
243 void InstallationValidator::ValidateInstallAppCommand(
244 const ProductContext& ctx,
245 const AppCommand& app_cmd,
246 bool* is_valid) {
247 ValidateInstallCommand(ctx, app_cmd, kCmdInstallApp,
248 installer::kChromeAppHostExe,
249 ::switches::kInstallFromWebstore, is_valid);
252 // Validates the "install-extension" Google Update product command.
253 void InstallationValidator::ValidateInstallExtensionCommand(
254 const ProductContext& ctx,
255 const AppCommand& app_cmd,
256 bool* is_valid) {
257 ValidateInstallCommand(ctx, app_cmd, kCmdInstallExtension,
258 installer::kChromeExe,
259 ::switches::kLimitedInstallFromWebstore, is_valid);
262 // Validates the "on-os-upgrade" Google Update internal command.
263 void InstallationValidator::ValidateOnOsUpgradeCommand(
264 const ProductContext& ctx,
265 const AppCommand& app_cmd,
266 bool* is_valid) {
267 DCHECK(is_valid);
269 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line()));
270 base::string16 name(kCmdOnOsUpgrade);
272 ValidateSetupPath(ctx, cmd_line.GetProgram(), name, is_valid);
274 SwitchExpectations expected;
275 expected.push_back(std::make_pair(std::string(switches::kOnOsUpgrade), true));
276 expected.push_back(std::make_pair(std::string(switches::kSystemLevel),
277 ctx.system_install));
278 expected.push_back(std::make_pair(std::string(switches::kMultiInstall),
279 ctx.state.is_multi_install()));
280 // Expecting kChrome if and only if kMultiInstall.
281 expected.push_back(std::make_pair(std::string(switches::kChrome),
282 ctx.state.is_multi_install()));
284 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid);
286 std::set<base::string16> flags_exp;
287 flags_exp.insert(google_update::kRegAutoRunOnOSUpgradeField);
288 ValidateAppCommandFlags(ctx, app_cmd, flags_exp, name, is_valid);
291 // Validates the "query-eula-acceptance" Google Update product command.
292 void InstallationValidator::ValidateQueryEULAAcceptanceCommand(
293 const ProductContext& ctx,
294 const AppCommand& app_cmd,
295 bool* is_valid) {
296 DCHECK(is_valid);
298 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line()));
299 base::string16 name(kCmdQueryEULAAcceptance);
301 ValidateSetupPath(ctx, cmd_line.GetProgram(), name, is_valid);
303 SwitchExpectations expected;
304 expected.push_back(std::make_pair(std::string(switches::kQueryEULAAcceptance),
305 true));
306 expected.push_back(std::make_pair(std::string(switches::kSystemLevel),
307 ctx.system_install));
309 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid);
311 std::set<base::string16> flags_exp;
312 flags_exp.insert(google_update::kRegWebAccessibleField);
313 flags_exp.insert(google_update::kRegRunAsUserField);
314 ValidateAppCommandFlags(ctx, app_cmd, flags_exp, name, is_valid);
317 // Validates the "quick-enable-application-host" Google Update product command.
318 void InstallationValidator::ValidateQuickEnableApplicationHostCommand(
319 const ProductContext& ctx,
320 const AppCommand& app_cmd,
321 bool* is_valid) {
322 DCHECK(is_valid);
324 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line()));
325 base::string16 name(kCmdQuickEnableApplicationHost);
327 ValidateSetupPath(ctx, cmd_line.GetProgram(), name, is_valid);
329 SwitchExpectations expected;
331 expected.push_back(std::make_pair(
332 std::string(switches::kChromeAppLauncher), true));
333 expected.push_back(std::make_pair(
334 std::string(switches::kSystemLevel), false));
335 expected.push_back(std::make_pair(
336 std::string(switches::kMultiInstall), true));
337 expected.push_back(std::make_pair(
338 std::string(switches::kEnsureGoogleUpdatePresent), true));
340 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid);
342 std::set<base::string16> flags_exp;
343 flags_exp.insert(google_update::kRegSendsPingsField);
344 flags_exp.insert(google_update::kRegWebAccessibleField);
345 flags_exp.insert(google_update::kRegRunAsUserField);
346 ValidateAppCommandFlags(ctx, app_cmd, flags_exp, name, is_valid);
349 // Validates a product's set of Google Update product commands against a
350 // collection of expectations.
351 void InstallationValidator::ValidateAppCommandExpectations(
352 const ProductContext& ctx,
353 const CommandExpectations& expectations,
354 bool* is_valid) {
355 DCHECK(is_valid);
357 CommandExpectations the_expectations(expectations);
359 AppCommands::CommandMapRange cmd_iterators(
360 ctx.state.commands().GetIterators());
361 CommandExpectations::iterator expectation;
362 for (; cmd_iterators.first != cmd_iterators.second; ++cmd_iterators.first) {
363 const base::string16& cmd_id = cmd_iterators.first->first;
364 // Do we have an expectation for this command?
365 expectation = the_expectations.find(cmd_id);
366 if (expectation != the_expectations.end()) {
367 (expectation->second)(ctx, cmd_iterators.first->second, is_valid);
368 // Remove this command from the set of expectations since we found it.
369 the_expectations.erase(expectation);
370 } else {
371 *is_valid = false;
372 LOG(ERROR) << ctx.dist->GetDisplayName()
373 << " has an unexpected Google Update product command named \""
374 << cmd_id << "\".";
378 // Report on any expected commands that weren't present.
379 CommandExpectations::const_iterator scan(the_expectations.begin());
380 CommandExpectations::const_iterator end(the_expectations.end());
381 for (; scan != end; ++scan) {
382 *is_valid = false;
383 LOG(ERROR) << ctx.dist->GetDisplayName()
384 << " is missing the Google Update product command named \""
385 << scan->first << "\".";
389 // Validates the multi-install binaries' Google Update commands.
390 void InstallationValidator::ValidateBinariesCommands(
391 const ProductContext& ctx,
392 bool* is_valid) {
393 DCHECK(is_valid);
395 const ProductState* binaries_state = ctx.machine_state.GetProductState(
396 ctx.system_install, BrowserDistribution::CHROME_BINARIES);
398 CommandExpectations expectations;
400 if (binaries_state != NULL) {
401 expectations[kCmdQuickEnableApplicationHost] =
402 &ValidateQuickEnableApplicationHostCommand;
404 expectations[kCmdQueryEULAAcceptance] = &ValidateQueryEULAAcceptanceCommand;
407 ValidateAppCommandExpectations(ctx, expectations, is_valid);
410 // Validates the multi-install binaries at level |system_level|.
411 void InstallationValidator::ValidateBinaries(
412 const InstallationState& machine_state,
413 bool system_install,
414 const ProductState& binaries_state,
415 bool* is_valid) {
416 const ChannelInfo& channel = binaries_state.channel();
418 // ap must have -multi
419 if (!channel.IsMultiInstall()) {
420 *is_valid = false;
421 LOG(ERROR) << "Chrome Binaries are missing \"-multi\" in channel name: \""
422 << channel.value() << "\"";
425 // ap must have -chrome iff Chrome is installed
426 const ProductState* chrome_state = machine_state.GetProductState(
427 system_install, BrowserDistribution::CHROME_BROWSER);
428 if (chrome_state != NULL) {
429 if (!channel.IsChrome()) {
430 *is_valid = false;
431 LOG(ERROR) << "Chrome Binaries are missing \"chrome\" in channel name:"
432 << " \"" << channel.value() << "\"";
434 } else if (channel.IsChrome()) {
435 *is_valid = false;
436 LOG(ERROR) << "Chrome Binaries have \"-chrome\" in channel name, yet Chrome"
437 " is not installed: \"" << channel.value() << "\"";
440 // ap must have -chromeframe iff Chrome Frame is installed multi
441 const ProductState* cf_state = machine_state.GetProductState(
442 system_install, BrowserDistribution::CHROME_FRAME);
443 if (cf_state != NULL && cf_state->is_multi_install()) {
444 if (!channel.IsChromeFrame()) {
445 *is_valid = false;
446 LOG(ERROR) << "Chrome Binaries are missing \"-chromeframe\" in channel"
447 " name: \"" << channel.value() << "\"";
449 } else if (channel.IsChromeFrame()) {
450 *is_valid = false;
451 LOG(ERROR) << "Chrome Binaries have \"-chromeframe\" in channel name, yet "
452 "Chrome Frame is not installed multi: \"" << channel.value()
453 << "\"";
456 // ap must have -applauncher iff Chrome App Launcher is installed multi
457 const ProductState* app_host_state = machine_state.GetProductState(
458 system_install, BrowserDistribution::CHROME_APP_HOST);
459 if (app_host_state != NULL) {
460 if (!app_host_state->is_multi_install()) {
461 *is_valid = false;
462 LOG(ERROR) << "Chrome App Launcher is installed in non-multi mode.";
464 if (!channel.IsAppLauncher()) {
465 *is_valid = false;
466 LOG(ERROR) << "Chrome Binaries are missing \"-applauncher\" in channel"
467 " name: \"" << channel.value() << "\"";
469 } else if (channel.IsAppLauncher()) {
470 *is_valid = false;
471 LOG(ERROR) << "Chrome Binaries have \"-applauncher\" in channel name, yet "
472 "Chrome App Launcher is not installed: \"" << channel.value()
473 << "\"";
476 // Chrome, Chrome Frame, or App Host must be present
477 if (chrome_state == NULL && cf_state == NULL && app_host_state == NULL) {
478 *is_valid = false;
479 LOG(ERROR) << "Chrome Binaries are present with no other products.";
482 // Chrome must be multi-install if present.
483 if (chrome_state != NULL && !chrome_state->is_multi_install()) {
484 *is_valid = false;
485 LOG(ERROR)
486 << "Chrome Binaries are present yet Chrome is not multi-install.";
489 // Chrome Frame must be multi-install if Chrome & App Host are not present.
490 if (cf_state != NULL && app_host_state == NULL && chrome_state == NULL &&
491 !cf_state->is_multi_install()) {
492 *is_valid = false;
493 LOG(ERROR) << "Chrome Binaries are present without Chrome nor App Launcher "
494 << "yet Chrome Frame is not multi-install.";
497 ChromeBinariesRules binaries_rules;
498 ProductContext ctx(machine_state, system_install, binaries_state,
499 binaries_rules);
501 ValidateBinariesCommands(ctx, is_valid);
503 ValidateUsageStats(ctx, is_valid);
506 // Validates the path to |setup_exe| for the product described by |ctx|.
507 void InstallationValidator::ValidateSetupPath(const ProductContext& ctx,
508 const base::FilePath& setup_exe,
509 const base::string16& purpose,
510 bool* is_valid) {
511 DCHECK(is_valid);
513 BrowserDistribution* bins_dist = ctx.dist;
514 if (ctx.state.is_multi_install()) {
515 bins_dist = BrowserDistribution::GetSpecificDistribution(
516 BrowserDistribution::CHROME_BINARIES);
519 base::FilePath expected_path = installer::GetChromeInstallPath(
520 ctx.system_install, bins_dist);
521 expected_path = expected_path
522 .AppendASCII(ctx.state.version().GetString())
523 .Append(installer::kInstallerDir)
524 .Append(installer::kSetupExe);
525 if (!base::FilePath::CompareEqualIgnoreCase(expected_path.value(),
526 setup_exe.value())) {
527 *is_valid = false;
528 LOG(ERROR) << ctx.dist->GetDisplayName() << " path to " << purpose
529 << " is not " << expected_path.value() << ": "
530 << setup_exe.value();
534 // Validates that |command| meets the expectations described in |expected|.
535 void InstallationValidator::ValidateCommandExpectations(
536 const ProductContext& ctx,
537 const CommandLine& command,
538 const SwitchExpectations& expected,
539 const base::string16& source,
540 bool* is_valid) {
541 for (SwitchExpectations::size_type i = 0, size = expected.size(); i < size;
542 ++i) {
543 const SwitchExpectations::value_type& expectation = expected[i];
544 if (command.HasSwitch(expectation.first) != expectation.second) {
545 *is_valid = false;
546 LOG(ERROR) << ctx.dist->GetDisplayName() << " " << source
547 << (expectation.second ? " is missing" : " has") << " \""
548 << expectation.first << "\""
549 << (expectation.second ? "" : " but shouldn't") << ": "
550 << command.GetCommandLineString();
555 // Validates that |command|, originating from |source|, is formed properly for
556 // the product described by |ctx|
557 void InstallationValidator::ValidateUninstallCommand(
558 const ProductContext& ctx,
559 const CommandLine& command,
560 const base::string16& source,
561 bool* is_valid) {
562 DCHECK(is_valid);
564 ValidateSetupPath(ctx, command.GetProgram(),
565 base::ASCIIToUTF16("uninstaller"),
566 is_valid);
568 const bool is_multi_install = ctx.state.is_multi_install();
569 SwitchExpectations expected;
571 expected.push_back(std::make_pair(std::string(switches::kUninstall), true));
572 expected.push_back(std::make_pair(std::string(switches::kSystemLevel),
573 ctx.system_install));
574 expected.push_back(std::make_pair(std::string(switches::kMultiInstall),
575 is_multi_install));
576 ctx.rules.AddUninstallSwitchExpectations(ctx, &expected);
578 ValidateCommandExpectations(ctx, command, expected, source, is_valid);
581 // Validates the rename command for the product described by |ctx|.
582 void InstallationValidator::ValidateRenameCommand(const ProductContext& ctx,
583 bool* is_valid) {
584 DCHECK(is_valid);
585 DCHECK(!ctx.state.rename_cmd().empty());
587 CommandLine command = CommandLine::FromString(ctx.state.rename_cmd());
588 base::string16 name(base::ASCIIToUTF16("in-use renamer"));
590 ValidateSetupPath(ctx, command.GetProgram(), name, is_valid);
592 SwitchExpectations expected;
594 expected.push_back(std::make_pair(std::string(switches::kRenameChromeExe),
595 true));
596 expected.push_back(std::make_pair(std::string(switches::kSystemLevel),
597 ctx.system_install));
598 expected.push_back(std::make_pair(std::string(switches::kMultiInstall),
599 ctx.state.is_multi_install()));
600 ctx.rules.AddRenameSwitchExpectations(ctx, &expected);
602 ValidateCommandExpectations(ctx, command, expected, name, is_valid);
605 // Validates the "opv" and "cmd" values for the product described in |ctx|.
606 void InstallationValidator::ValidateOldVersionValues(
607 const ProductContext& ctx,
608 bool* is_valid) {
609 DCHECK(is_valid);
611 // opv and cmd must both be present or both absent
612 if (ctx.state.old_version() == NULL) {
613 if (!ctx.state.rename_cmd().empty()) {
614 *is_valid = false;
615 LOG(ERROR) << ctx.dist->GetDisplayName()
616 << " has a rename command but no opv: "
617 << ctx.state.rename_cmd();
619 } else {
620 if (ctx.state.rename_cmd().empty()) {
621 *is_valid = false;
622 LOG(ERROR) << ctx.dist->GetDisplayName()
623 << " has an opv but no rename command: "
624 << ctx.state.old_version()->GetString();
625 } else {
626 ValidateRenameCommand(ctx, is_valid);
631 // Validates the multi-install state of the product described in |ctx|.
632 void InstallationValidator::ValidateMultiInstallProduct(
633 const ProductContext& ctx,
634 bool* is_valid) {
635 DCHECK(is_valid);
637 const ProductState* binaries =
638 ctx.machine_state.GetProductState(ctx.system_install,
639 BrowserDistribution::CHROME_BINARIES);
640 if (!binaries) {
641 if (ctx.dist->GetType() == BrowserDistribution::CHROME_APP_HOST) {
642 if (!ctx.machine_state.GetProductState(
643 true, // system-level
644 BrowserDistribution::CHROME_BINARIES) &&
645 !ctx.machine_state.GetProductState(
646 true, // system-level
647 BrowserDistribution::CHROME_BROWSER)) {
648 *is_valid = false;
649 LOG(ERROR) << ctx.dist->GetDisplayName()
650 << " (" << ctx.state.version().GetString() << ") is "
651 << "installed without Chrome Binaries or a system-level "
652 << "Chrome.";
654 } else {
655 *is_valid = false;
656 LOG(ERROR) << ctx.dist->GetDisplayName()
657 << " (" << ctx.state.version().GetString() << ") is installed "
658 << "without Chrome Binaries.";
660 } else {
661 // Version must match that of binaries.
662 if (ctx.state.version().CompareTo(binaries->version()) != 0) {
663 *is_valid = false;
664 LOG(ERROR) << "Version of " << ctx.dist->GetDisplayName()
665 << " (" << ctx.state.version().GetString() << ") does not "
666 "match that of Chrome Binaries ("
667 << binaries->version().GetString() << ").";
670 // Channel value must match that of binaries.
671 if (!ctx.state.channel().Equals(binaries->channel())) {
672 *is_valid = false;
673 LOG(ERROR) << "Channel name of " << ctx.dist->GetDisplayName()
674 << " (" << ctx.state.channel().value()
675 << ") does not match that of Chrome Binaries ("
676 << binaries->channel().value() << ").";
681 // Validates the Google Update commands for the product described in |ctx|.
682 void InstallationValidator::ValidateAppCommands(
683 const ProductContext& ctx,
684 bool* is_valid) {
685 DCHECK(is_valid);
687 CommandExpectations expectations;
689 if (ctx.dist->GetType() == BrowserDistribution::CHROME_APP_HOST) {
690 expectations[kCmdInstallApp] = &ValidateInstallAppCommand;
692 if (ctx.dist->GetType() == BrowserDistribution::CHROME_BROWSER) {
693 expectations[kCmdInstallExtension] = &ValidateInstallExtensionCommand;
694 expectations[kCmdOnOsUpgrade] = &ValidateOnOsUpgradeCommand;
697 ValidateAppCommandExpectations(ctx, expectations, is_valid);
700 // Validates usagestats for the product or binaries in |ctx|.
701 void InstallationValidator::ValidateUsageStats(const ProductContext& ctx,
702 bool* is_valid) {
703 DWORD usagestats = 0;
704 if (ctx.state.GetUsageStats(&usagestats)) {
705 if (!ctx.rules.UsageStatsAllowed(ctx)) {
706 *is_valid = false;
707 LOG(ERROR) << ctx.dist->GetDisplayName()
708 << " has a usagestats value (" << usagestats
709 << "), yet should not.";
710 } else if (usagestats != 0 && usagestats != 1) {
711 *is_valid = false;
712 LOG(ERROR) << ctx.dist->GetDisplayName()
713 << " has an unsupported usagestats value (" << usagestats
714 << ").";
719 // Validates the product described in |product_state| according to |rules|.
720 void InstallationValidator::ValidateProduct(
721 const InstallationState& machine_state,
722 bool system_install,
723 const ProductState& product_state,
724 const ProductRules& rules,
725 bool* is_valid) {
726 DCHECK(is_valid);
728 ProductContext ctx(machine_state, system_install, product_state, rules);
730 ValidateUninstallCommand(ctx, ctx.state.uninstall_command(),
731 base::ASCIIToUTF16(
732 "Google Update uninstall command"),
733 is_valid);
735 ValidateOldVersionValues(ctx, is_valid);
737 if (ctx.state.is_multi_install())
738 ValidateMultiInstallProduct(ctx, is_valid);
740 ValidateAppCommands(ctx, is_valid);
742 ValidateUsageStats(ctx, is_valid);
745 // static
746 bool InstallationValidator::ValidateInstallationTypeForState(
747 const InstallationState& machine_state,
748 bool system_level,
749 InstallationType* type) {
750 DCHECK(type);
751 bool rock_on = true;
752 *type = NO_PRODUCTS;
754 // Does the system have any multi-installed products?
755 const ProductState* multi_state =
756 machine_state.GetProductState(system_level,
757 BrowserDistribution::CHROME_BINARIES);
758 if (multi_state != NULL)
759 ValidateBinaries(machine_state, system_level, *multi_state, &rock_on);
761 // Is Chrome installed?
762 const ProductState* product_state =
763 machine_state.GetProductState(system_level,
764 BrowserDistribution::CHROME_BROWSER);
765 if (product_state != NULL) {
766 ChromeRules chrome_rules;
767 ValidateProduct(machine_state, system_level, *product_state,
768 chrome_rules, &rock_on);
769 *type = static_cast<InstallationType>(
770 *type | (product_state->is_multi_install() ?
771 ProductBits::CHROME_MULTI :
772 ProductBits::CHROME_SINGLE));
775 // Is Chrome Frame installed?
776 product_state =
777 machine_state.GetProductState(system_level,
778 BrowserDistribution::CHROME_FRAME);
779 if (product_state != NULL) {
780 ChromeFrameRules chrome_frame_rules;
781 ValidateProduct(machine_state, system_level, *product_state,
782 chrome_frame_rules, &rock_on);
783 int cf_bit = !product_state->is_multi_install() ?
784 ProductBits::CHROME_FRAME_SINGLE :
785 ProductBits::CHROME_FRAME_MULTI;
786 *type = static_cast<InstallationType>(*type | cf_bit);
789 // Is Chrome App Host installed?
790 product_state =
791 machine_state.GetProductState(system_level,
792 BrowserDistribution::CHROME_APP_HOST);
793 if (product_state != NULL) {
794 ChromeAppHostRules chrome_app_host_rules;
795 ValidateProduct(machine_state, system_level, *product_state,
796 chrome_app_host_rules, &rock_on);
797 *type = static_cast<InstallationType>(*type | ProductBits::CHROME_APP_HOST);
798 if (!product_state->is_multi_install()) {
799 LOG(ERROR) << "Chrome App Launcher must always be multi-install.";
800 rock_on = false;
804 DCHECK_NE(std::find(&kInstallationTypes[0],
805 &kInstallationTypes[arraysize(kInstallationTypes)],
806 *type),
807 &kInstallationTypes[arraysize(kInstallationTypes)])
808 << "Invalid combination of products found on system (" << *type << ")";
810 return rock_on;
813 // static
814 bool InstallationValidator::ValidateInstallationType(bool system_level,
815 InstallationType* type) {
816 DCHECK(type);
817 InstallationState machine_state;
819 machine_state.Initialize();
821 return ValidateInstallationTypeForState(machine_state, system_level, type);
824 } // namespace installer