Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / installer / util / installation_validator.cc
blob6a982b8fc144a10395f36f1c51e407af45e12e82
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 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);
211 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line()));
212 base::string16 name(kCmdOnOsUpgrade);
214 ValidateSetupPath(ctx, cmd_line.GetProgram(), name, is_valid);
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()));
226 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid);
228 std::set<base::string16> flags_exp;
229 flags_exp.insert(google_update::kRegAutoRunOnOSUpgradeField);
230 ValidateAppCommandFlags(ctx, app_cmd, flags_exp, name, is_valid);
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);
240 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line()));
241 base::string16 name(kCmdQueryEULAAcceptance);
243 ValidateSetupPath(ctx, cmd_line.GetProgram(), name, is_valid);
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));
251 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid);
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);
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);
266 CommandLine cmd_line(CommandLine::FromString(app_cmd.command_line()));
267 base::string16 name(kCmdQuickEnableApplicationHost);
269 ValidateSetupPath(ctx, cmd_line.GetProgram(), name, is_valid);
271 SwitchExpectations expected;
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));
282 ValidateCommandExpectations(ctx, cmd_line, expected, name, is_valid);
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);
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);
299 CommandExpectations the_expectations(expectations);
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 << "\".";
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 << "\".";
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);
337 const ProductState* binaries_state = ctx.machine_state.GetProductState(
338 ctx.system_install, BrowserDistribution::CHROME_BINARIES);
340 CommandExpectations expectations;
342 if (binaries_state != NULL) {
343 expectations[kCmdQuickEnableApplicationHost] =
344 &ValidateQuickEnableApplicationHostCommand;
346 expectations[kCmdQueryEULAAcceptance] = &ValidateQueryEULAAcceptanceCommand;
349 ValidateAppCommandExpectations(ctx, expectations, is_valid);
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();
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() << "\"";
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() << "\"";
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() << "\"";
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() << "\"";
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 << "\"";
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.";
406 if (!channel.IsAppLauncher()) {
407 *is_valid = false;
408 LOG(ERROR) << "Chrome Binaries are missing \"-applauncher\" in channel"
409 " name: \"" << channel.value() << "\"";
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 << "\"";
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.";
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.";
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.";
439 ChromeBinariesRules binaries_rules;
440 ProductContext ctx(machine_state, system_install, binaries_state,
441 binaries_rules);
443 ValidateBinariesCommands(ctx, is_valid);
445 ValidateUsageStats(ctx, is_valid);
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);
455 BrowserDistribution* bins_dist = ctx.dist;
456 if (ctx.state.is_multi_install()) {
457 bins_dist = BrowserDistribution::GetSpecificDistribution(
458 BrowserDistribution::CHROME_BINARIES);
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();
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();
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);
506 ValidateSetupPath(ctx, command.GetProgram(),
507 base::ASCIIToUTF16("uninstaller"),
508 is_valid);
510 const bool is_multi_install = ctx.state.is_multi_install();
511 SwitchExpectations expected;
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);
520 ValidateCommandExpectations(ctx, command, expected, source, is_valid);
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());
529 CommandLine command = CommandLine::FromString(ctx.state.rename_cmd());
530 base::string16 name(base::ASCIIToUTF16("in-use renamer"));
532 ValidateSetupPath(ctx, command.GetProgram(), name, is_valid);
534 SwitchExpectations expected;
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);
544 ValidateCommandExpectations(ctx, command, expected, name, is_valid);
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);
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();
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);
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);
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.";
596 } else {
597 *is_valid = false;
598 LOG(ERROR) << ctx.dist->GetDisplayName()
599 << " (" << ctx.state.version().GetString() << ") is installed "
600 << "without Chrome Binaries.";
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() << ").";
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() << ").";
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);
629 CommandExpectations expectations;
631 if (ctx.dist->GetType() == BrowserDistribution::CHROME_BROWSER)
632 expectations[kCmdOnOsUpgrade] = &ValidateOnOsUpgradeCommand;
634 ValidateAppCommandExpectations(ctx, expectations, is_valid);
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 << ").";
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);
665 ProductContext ctx(machine_state, system_install, product_state, rules);
667 ValidateUninstallCommand(ctx, ctx.state.uninstall_command(),
668 base::ASCIIToUTF16(
669 "Google Update uninstall command"),
670 is_valid);
672 ValidateOldVersionValues(ctx, is_valid);
674 if (ctx.state.is_multi_install())
675 ValidateMultiInstallProduct(ctx, is_valid);
677 ValidateAppCommands(ctx, is_valid);
679 ValidateUsageStats(ctx, is_valid);
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;
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);
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));
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);
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;
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 << ")";
747 return rock_on;
750 // static
751 bool InstallationValidator::ValidateInstallationType(bool system_level,
752 InstallationType* type) {
753 DCHECK(type);
754 InstallationState machine_state;
756 machine_state.Initialize();
758 return ValidateInstallationTypeForState(machine_state, system_level, type);
761 } // namespace installer