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"
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"
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
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
),
72 // --chrome must not be present.
73 expectations
->push_back(std::make_pair(std::string(switches::kChrome
),
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
),
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
),
110 // --chrome-frame must not be present.
111 expectations
->push_back(std::make_pair(std::string(switches::kChromeFrame
),
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.
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 {
138 void InstallationValidator::ChromeBinariesRules::AddRenameSwitchExpectations(
139 const ProductContext
& ctx
,
140 SwitchExpectations
* expectations
) const {
144 bool InstallationValidator::ChromeBinariesRules::UsageStatsAllowed(
145 const ProductContext
& ctx
) const {
146 // UsageStats consent values are always allowed on the binaries.
151 const InstallationValidator::InstallationType
152 InstallationValidator::kInstallationTypes
[] = {
157 CHROME_FRAME_SINGLE_CHROME_SINGLE
,
158 CHROME_FRAME_SINGLE_CHROME_MULTI
,
160 CHROME_FRAME_MULTI_CHROME_MULTI
,
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
,
176 const base::string16 exp_key
;
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
) {
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
,
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())) {
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
,
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
,
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
,
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
,
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
),
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
,
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
,
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
);
372 LOG(ERROR
) << ctx
.dist
->GetDisplayName()
373 << " has an unexpected Google Update product command named \""
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
) {
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
,
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
,
414 const ProductState
& binaries_state
,
416 const ChannelInfo
& channel
= binaries_state
.channel();
418 // ap must have -multi
419 if (!channel
.IsMultiInstall()) {
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()) {
431 LOG(ERROR
) << "Chrome Binaries are missing \"chrome\" in channel name:"
432 << " \"" << channel
.value() << "\"";
434 } else if (channel
.IsChrome()) {
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()) {
446 LOG(ERROR
) << "Chrome Binaries are missing \"-chromeframe\" in channel"
447 " name: \"" << channel
.value() << "\"";
449 } else if (channel
.IsChromeFrame()) {
451 LOG(ERROR
) << "Chrome Binaries have \"-chromeframe\" in channel name, yet "
452 "Chrome Frame is not installed multi: \"" << channel
.value()
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()) {
462 LOG(ERROR
) << "Chrome App Launcher is installed in non-multi mode.";
464 if (!channel
.IsAppLauncher()) {
466 LOG(ERROR
) << "Chrome Binaries are missing \"-applauncher\" in channel"
467 " name: \"" << channel
.value() << "\"";
469 } else if (channel
.IsAppLauncher()) {
471 LOG(ERROR
) << "Chrome Binaries have \"-applauncher\" in channel name, yet "
472 "Chrome App Launcher is not installed: \"" << channel
.value()
476 // Chrome, Chrome Frame, or App Host must be present
477 if (chrome_state
== NULL
&& cf_state
== NULL
&& app_host_state
== NULL
) {
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()) {
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()) {
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
,
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
,
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())) {
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
,
541 for (SwitchExpectations::size_type i
= 0, size
= expected
.size(); i
< size
;
543 const SwitchExpectations::value_type
& expectation
= expected
[i
];
544 if (command
.HasSwitch(expectation
.first
) != expectation
.second
) {
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
,
564 ValidateSetupPath(ctx
, command
.GetProgram(),
565 base::ASCIIToUTF16("uninstaller"),
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
),
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
,
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
),
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
,
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()) {
615 LOG(ERROR
) << ctx
.dist
->GetDisplayName()
616 << " has a rename command but no opv: "
617 << ctx
.state
.rename_cmd();
620 if (ctx
.state
.rename_cmd().empty()) {
622 LOG(ERROR
) << ctx
.dist
->GetDisplayName()
623 << " has an opv but no rename command: "
624 << ctx
.state
.old_version()->GetString();
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
,
637 const ProductState
* binaries
=
638 ctx
.machine_state
.GetProductState(ctx
.system_install
,
639 BrowserDistribution::CHROME_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
)) {
649 LOG(ERROR
) << ctx
.dist
->GetDisplayName()
650 << " (" << ctx
.state
.version().GetString() << ") is "
651 << "installed without Chrome Binaries or a system-level "
656 LOG(ERROR
) << ctx
.dist
->GetDisplayName()
657 << " (" << ctx
.state
.version().GetString() << ") is installed "
658 << "without Chrome Binaries.";
661 // Version must match that of binaries.
662 if (ctx
.state
.version().CompareTo(binaries
->version()) != 0) {
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())) {
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
,
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
,
703 DWORD usagestats
= 0;
704 if (ctx
.state
.GetUsageStats(&usagestats
)) {
705 if (!ctx
.rules
.UsageStatsAllowed(ctx
)) {
707 LOG(ERROR
) << ctx
.dist
->GetDisplayName()
708 << " has a usagestats value (" << usagestats
709 << "), yet should not.";
710 } else if (usagestats
!= 0 && usagestats
!= 1) {
712 LOG(ERROR
) << ctx
.dist
->GetDisplayName()
713 << " has an unsupported usagestats value (" << usagestats
719 // Validates the product described in |product_state| according to |rules|.
720 void InstallationValidator::ValidateProduct(
721 const InstallationState
& machine_state
,
723 const ProductState
& product_state
,
724 const ProductRules
& rules
,
728 ProductContext
ctx(machine_state
, system_install
, product_state
, rules
);
730 ValidateUninstallCommand(ctx
, ctx
.state
.uninstall_command(),
732 "Google Update uninstall command"),
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
);
746 bool InstallationValidator::ValidateInstallationTypeForState(
747 const InstallationState
& machine_state
,
749 InstallationType
* type
) {
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?
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?
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.";
804 DCHECK_NE(std::find(&kInstallationTypes
[0],
805 &kInstallationTypes
[arraysize(kInstallationTypes
)],
807 &kInstallationTypes
[arraysize(kInstallationTypes
)])
808 << "Invalid combination of products found on system (" << *type
<< ")";
814 bool InstallationValidator::ValidateInstallationType(bool system_level
,
815 InstallationType
* type
) {
817 InstallationState machine_state
;
819 machine_state
.Initialize();
821 return ValidateInstallationTypeForState(machine_state
, system_level
, type
);
824 } // namespace installer