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
39 // --chrome-frame --ready-mode should be present for uninstall iff CF in ready
41 const ProductState
* cf_state
=
42 ctx
.machine_state
.GetProductState(ctx
.system_install
,
43 BrowserDistribution::CHROME_FRAME
);
44 const bool ready_mode
=
46 cf_state
->uninstall_command().HasSwitch(switches::kChromeFrameReadyMode
);
47 expectations
->push_back(std::make_pair(std::string(switches::kChromeFrame
),
49 expectations
->push_back(
50 std::make_pair(std::string(switches::kChromeFrameReadyMode
), ready_mode
));
53 void InstallationValidator::ChromeRules::AddRenameSwitchExpectations(
54 const ProductContext
& ctx
,
55 SwitchExpectations
* expectations
) const {
56 const bool is_multi_install
=
57 ctx
.state
.uninstall_command().HasSwitch(switches::kMultiInstall
);
59 // --chrome should not be present for rename. It was for a time, so we'll be
60 // lenient so that mini_installer tests pass.
62 // --chrome-frame --ready-mode should never be present.
63 expectations
->push_back(
64 std::make_pair(std::string(switches::kChromeFrame
), false));
65 expectations
->push_back(
66 std::make_pair(std::string(switches::kChromeFrameReadyMode
), false));
69 bool InstallationValidator::ChromeRules::UsageStatsAllowed(
70 const ProductContext
& ctx
) const {
71 // Products must not have usagestats consent values when multi-install
72 // (only the multi-install binaries may).
73 return !ctx
.state
.is_multi_install();
76 BrowserDistribution::Type
77 InstallationValidator::ChromeFrameRules::distribution_type() const {
78 return BrowserDistribution::CHROME_FRAME
;
81 void InstallationValidator::ChromeFrameRules::AddUninstallSwitchExpectations(
82 const ProductContext
& ctx
,
83 SwitchExpectations
* expectations
) const {
84 // --chrome-frame must be present.
85 expectations
->push_back(std::make_pair(std::string(switches::kChromeFrame
),
87 // --chrome must not be present.
88 expectations
->push_back(std::make_pair(std::string(switches::kChrome
),
92 void InstallationValidator::ChromeFrameRules::AddRenameSwitchExpectations(
93 const ProductContext
& ctx
,
94 SwitchExpectations
* expectations
) const {
95 // --chrome-frame must be present for SxS rename.
96 expectations
->push_back(std::make_pair(std::string(switches::kChromeFrame
),
97 !ctx
.state
.is_multi_install()));
98 // --chrome must not be present.
99 expectations
->push_back(std::make_pair(std::string(switches::kChrome
),
103 bool InstallationValidator::ChromeFrameRules::UsageStatsAllowed(
104 const ProductContext
& ctx
) const {
105 // Products must not have usagestats consent values when multi-install
106 // (only the multi-install binaries may).
107 return !ctx
.state
.is_multi_install();
110 BrowserDistribution::Type
111 InstallationValidator::ChromeAppHostRules::distribution_type() const {
112 return BrowserDistribution::CHROME_APP_HOST
;
115 void InstallationValidator::ChromeAppHostRules::AddUninstallSwitchExpectations(
116 const ProductContext
& ctx
,
117 SwitchExpectations
* expectations
) const {
118 // --app-launcher must be present.
119 expectations
->push_back(
120 std::make_pair(std::string(switches::kChromeAppLauncher
), true));
122 // --chrome must not be present.
123 expectations
->push_back(std::make_pair(std::string(switches::kChrome
),
125 // --chrome-frame must not be present.
126 expectations
->push_back(std::make_pair(std::string(switches::kChromeFrame
),
130 void InstallationValidator::ChromeAppHostRules::AddRenameSwitchExpectations(
131 const ProductContext
& ctx
,
132 SwitchExpectations
* expectations
) const {
133 // TODO(erikwright): I guess there will be none?
136 bool InstallationValidator::ChromeAppHostRules::UsageStatsAllowed(
137 const ProductContext
& ctx
) const {
138 // App Host doesn't manage usage stats. The Chrome Binaries will.
142 BrowserDistribution::Type
143 InstallationValidator::ChromeBinariesRules::distribution_type() const {
144 return BrowserDistribution::CHROME_BINARIES
;
147 void InstallationValidator::ChromeBinariesRules::AddUninstallSwitchExpectations(
148 const ProductContext
& ctx
,
149 SwitchExpectations
* expectations
) const {
153 void InstallationValidator::ChromeBinariesRules::AddRenameSwitchExpectations(
154 const ProductContext
& ctx
,
155 SwitchExpectations
* expectations
) const {
159 bool InstallationValidator::ChromeBinariesRules::UsageStatsAllowed(
160 const ProductContext
& ctx
) const {
161 // UsageStats consent values are always allowed on the binaries.
166 const InstallationValidator::InstallationType
167 InstallationValidator::kInstallationTypes
[] = {
172 CHROME_FRAME_SINGLE_CHROME_SINGLE
,
173 CHROME_FRAME_SINGLE_CHROME_MULTI
,
175 CHROME_FRAME_MULTI_CHROME_MULTI
,
176 CHROME_FRAME_READY_MODE_CHROME_MULTI
,
178 CHROME_APP_HOST_CHROME_FRAME_SINGLE
,
179 CHROME_APP_HOST_CHROME_FRAME_SINGLE_CHROME_MULTI
,
180 CHROME_APP_HOST_CHROME_FRAME_MULTI
,
181 CHROME_APP_HOST_CHROME_FRAME_MULTI_CHROME_MULTI
,
182 CHROME_APP_HOST_CHROME_MULTI
,
183 CHROME_APP_HOST_CHROME_MULTI_CHROME_FRAME_READY_MODE
,
186 void InstallationValidator::ValidateAppCommandFlags(
187 const ProductContext
& ctx
,
188 const AppCommand
& app_cmd
,
189 const std::set
<string16
>& flags_exp
,
190 const string16
& name
,
193 const string16 exp_key
;
197 {google_update::kRegSendsPingsField
,
198 app_cmd
.sends_pings(),
199 "be configured to send pings"},
200 {google_update::kRegWebAccessibleField
,
201 app_cmd
.is_web_accessible(),
202 "be web accessible"},
203 {google_update::kRegAutoRunOnOSUpgradeField
,
204 app_cmd
.is_auto_run_on_os_upgrade(),
205 "be marked to run on OS upgrade"},
206 {google_update::kRegRunAsUserField
,
207 app_cmd
.is_run_as_user(),
208 "be marked to run as user"},
210 for (int i
= 0; i
< arraysize(check_list
); ++i
) {
211 bool expected
= flags_exp
.find(check_list
[i
].exp_key
) != flags_exp
.end();
212 if (check_list
[i
].val
!= expected
) {
214 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName() << ": "
215 << name
<< " command should " << (expected
? "" : "not ")
216 << check_list
[i
].msg
<< ".";
221 // Validates both "install-application" and "install-extension" depending on
222 // what is passed in.
223 void InstallationValidator::ValidateInstallCommand(
224 const ProductContext
& ctx
,
225 const AppCommand
& app_cmd
,
226 const wchar_t* expected_command
,
227 const wchar_t* expected_app_name
,
228 const char* expected_switch
,
232 CommandLine
cmd_line(CommandLine::FromString(app_cmd
.command_line()));
233 string16
name(expected_command
);
235 base::FilePath
expected_path(
236 installer::GetChromeInstallPath(ctx
.system_install
, ctx
.dist
)
237 .Append(expected_app_name
));
239 if (!base::FilePath::CompareEqualIgnoreCase(expected_path
.value(),
240 cmd_line
.GetProgram().value())) {
242 LOG(ERROR
) << name
<< "'s path is not "
243 << expected_path
.value() << ": "
244 << cmd_line
.GetProgram().value();
247 SwitchExpectations expected
;
248 expected
.push_back(std::make_pair(std::string(expected_switch
), true));
250 ValidateCommandExpectations(ctx
, cmd_line
, expected
, name
, is_valid
);
252 std::set
<string16
> flags_exp
;
253 flags_exp
.insert(google_update::kRegSendsPingsField
);
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 "install-application" Google Update product command.
260 void InstallationValidator::ValidateInstallAppCommand(
261 const ProductContext
& ctx
,
262 const AppCommand
& app_cmd
,
264 ValidateInstallCommand(ctx
, app_cmd
, kCmdInstallApp
,
265 installer::kChromeAppHostExe
,
266 ::switches::kInstallFromWebstore
, is_valid
);
269 // Validates the "install-extension" Google Update product command.
270 void InstallationValidator::ValidateInstallExtensionCommand(
271 const ProductContext
& ctx
,
272 const AppCommand
& app_cmd
,
274 ValidateInstallCommand(ctx
, app_cmd
, kCmdInstallExtension
,
275 installer::kChromeExe
,
276 ::switches::kLimitedInstallFromWebstore
, is_valid
);
279 // Validates the "on-os-upgrade" Google Update internal command.
280 void InstallationValidator::ValidateOnOsUpgradeCommand(
281 const ProductContext
& ctx
,
282 const AppCommand
& app_cmd
,
286 CommandLine
cmd_line(CommandLine::FromString(app_cmd
.command_line()));
287 string16
name(kCmdOnOsUpgrade
);
289 ValidateSetupPath(ctx
, cmd_line
.GetProgram(), name
, is_valid
);
291 SwitchExpectations expected
;
292 expected
.push_back(std::make_pair(std::string(switches::kOnOsUpgrade
), true));
293 expected
.push_back(std::make_pair(std::string(switches::kSystemLevel
),
294 ctx
.system_install
));
295 expected
.push_back(std::make_pair(std::string(switches::kMultiInstall
),
296 ctx
.state
.is_multi_install()));
297 // Expecting kChrome if and only if kMultiInstall.
298 expected
.push_back(std::make_pair(std::string(switches::kChrome
),
299 ctx
.state
.is_multi_install()));
301 ValidateCommandExpectations(ctx
, cmd_line
, expected
, name
, is_valid
);
303 std::set
<string16
> flags_exp
;
304 flags_exp
.insert(google_update::kRegAutoRunOnOSUpgradeField
);
305 ValidateAppCommandFlags(ctx
, app_cmd
, flags_exp
, name
, is_valid
);
308 // Validates the "query-eula-acceptance" Google Update product command.
309 void InstallationValidator::ValidateQueryEULAAcceptanceCommand(
310 const ProductContext
& ctx
,
311 const AppCommand
& app_cmd
,
315 CommandLine
cmd_line(CommandLine::FromString(app_cmd
.command_line()));
316 string16
name(kCmdQueryEULAAcceptance
);
318 ValidateSetupPath(ctx
, cmd_line
.GetProgram(), name
, is_valid
);
320 SwitchExpectations expected
;
321 expected
.push_back(std::make_pair(std::string(switches::kQueryEULAAcceptance
),
323 expected
.push_back(std::make_pair(std::string(switches::kSystemLevel
),
324 ctx
.system_install
));
326 ValidateCommandExpectations(ctx
, cmd_line
, expected
, name
, is_valid
);
328 std::set
<string16
> flags_exp
;
329 flags_exp
.insert(google_update::kRegWebAccessibleField
);
330 flags_exp
.insert(google_update::kRegRunAsUserField
);
331 ValidateAppCommandFlags(ctx
, app_cmd
, flags_exp
, name
, is_valid
);
334 // Validates the "quick-enable-cf" Google Update product command.
335 void InstallationValidator::ValidateQuickEnableCfCommand(
336 const ProductContext
& ctx
,
337 const AppCommand
& app_cmd
,
341 CommandLine
cmd_line(CommandLine::FromString(app_cmd
.command_line()));
342 string16
name(kCmdQuickEnableCf
);
344 ValidateSetupPath(ctx
, cmd_line
.GetProgram(), name
, is_valid
);
346 SwitchExpectations expected
;
349 std::make_pair(std::string(switches::kChromeFrameQuickEnable
), true));
350 expected
.push_back(std::make_pair(std::string(switches::kSystemLevel
),
351 ctx
.system_install
));
352 expected
.push_back(std::make_pair(std::string(switches::kMultiInstall
),
353 ctx
.state
.is_multi_install()));
355 ValidateCommandExpectations(ctx
, cmd_line
, expected
, name
, is_valid
);
357 std::set
<string16
> flags_exp
;
358 flags_exp
.insert(google_update::kRegSendsPingsField
);
359 flags_exp
.insert(google_update::kRegWebAccessibleField
);
360 ValidateAppCommandFlags(ctx
, app_cmd
, flags_exp
, name
, is_valid
);
363 // Validates the "quick-enable-application-host" Google Update product command.
364 void InstallationValidator::ValidateQuickEnableApplicationHostCommand(
365 const ProductContext
& ctx
,
366 const AppCommand
& app_cmd
,
370 CommandLine
cmd_line(CommandLine::FromString(app_cmd
.command_line()));
371 string16
name(kCmdQuickEnableApplicationHost
);
373 ValidateSetupPath(ctx
, cmd_line
.GetProgram(), name
, is_valid
);
375 SwitchExpectations expected
;
377 expected
.push_back(std::make_pair(
378 std::string(switches::kChromeAppLauncher
), true));
379 expected
.push_back(std::make_pair(
380 std::string(switches::kSystemLevel
), false));
381 expected
.push_back(std::make_pair(
382 std::string(switches::kMultiInstall
), true));
383 expected
.push_back(std::make_pair(
384 std::string(switches::kEnsureGoogleUpdatePresent
), true));
386 ValidateCommandExpectations(ctx
, cmd_line
, expected
, name
, is_valid
);
388 std::set
<string16
> flags_exp
;
389 flags_exp
.insert(google_update::kRegSendsPingsField
);
390 flags_exp
.insert(google_update::kRegWebAccessibleField
);
391 flags_exp
.insert(google_update::kRegRunAsUserField
);
392 ValidateAppCommandFlags(ctx
, app_cmd
, flags_exp
, name
, is_valid
);
395 // Validates a product's set of Google Update product commands against a
396 // collection of expectations.
397 void InstallationValidator::ValidateAppCommandExpectations(
398 const ProductContext
& ctx
,
399 const CommandExpectations
& expectations
,
403 CommandExpectations
the_expectations(expectations
);
405 AppCommands::CommandMapRange
cmd_iterators(
406 ctx
.state
.commands().GetIterators());
407 CommandExpectations::iterator expectation
;
408 for (; cmd_iterators
.first
!= cmd_iterators
.second
; ++cmd_iterators
.first
) {
409 const string16
& cmd_id
= cmd_iterators
.first
->first
;
410 // Do we have an expectation for this command?
411 expectation
= the_expectations
.find(cmd_id
);
412 if (expectation
!= the_expectations
.end()) {
413 (expectation
->second
)(ctx
, cmd_iterators
.first
->second
, is_valid
);
414 // Remove this command from the set of expectations since we found it.
415 the_expectations
.erase(expectation
);
418 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName()
419 << " has an unexpected Google Update product command named \""
424 // Report on any expected commands that weren't present.
425 CommandExpectations::const_iterator
scan(the_expectations
.begin());
426 CommandExpectations::const_iterator
end(the_expectations
.end());
427 for (; scan
!= end
; ++scan
) {
429 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName()
430 << " is missing the Google Update product command named \""
431 << scan
->first
<< "\".";
435 // Validates the multi-install binaries' Google Update commands.
436 void InstallationValidator::ValidateBinariesCommands(
437 const ProductContext
& ctx
,
441 // The quick-enable-cf command must be present if Chrome Binaries are
442 // installed and Chrome Frame is not installed (or installed in ready mode).
443 const ChannelInfo
& channel
= ctx
.state
.channel();
444 const ProductState
* binaries_state
= ctx
.machine_state
.GetProductState(
445 ctx
.system_install
, BrowserDistribution::CHROME_BINARIES
);
446 const ProductState
* cf_state
= ctx
.machine_state
.GetProductState(
447 ctx
.system_install
, BrowserDistribution::CHROME_FRAME
);
449 CommandExpectations expectations
;
451 if (binaries_state
!= NULL
) {
452 if (cf_state
== NULL
|| channel
.IsReadyMode())
453 expectations
[kCmdQuickEnableCf
] = &ValidateQuickEnableCfCommand
;
455 expectations
[kCmdQuickEnableApplicationHost
] =
456 &ValidateQuickEnableApplicationHostCommand
;
458 expectations
[kCmdQueryEULAAcceptance
] = &ValidateQueryEULAAcceptanceCommand
;
461 ValidateAppCommandExpectations(ctx
, expectations
, is_valid
);
464 // Validates the multi-install binaries at level |system_level|.
465 void InstallationValidator::ValidateBinaries(
466 const InstallationState
& machine_state
,
468 const ProductState
& binaries_state
,
470 const ChannelInfo
& channel
= binaries_state
.channel();
472 // ap must have -multi
473 if (!channel
.IsMultiInstall()) {
475 LOG(ERROR
) << "Chrome Binaries are missing \"-multi\" in channel name: \""
476 << channel
.value() << "\"";
479 // ap must have -chrome iff Chrome is installed
480 const ProductState
* chrome_state
= machine_state
.GetProductState(
481 system_install
, BrowserDistribution::CHROME_BROWSER
);
482 if (chrome_state
!= NULL
) {
483 if (!channel
.IsChrome()) {
485 LOG(ERROR
) << "Chrome Binaries are missing \"chrome\" in channel name:"
486 << " \"" << channel
.value() << "\"";
488 } else if (channel
.IsChrome()) {
490 LOG(ERROR
) << "Chrome Binaries have \"-chrome\" in channel name, yet Chrome"
491 " is not installed: \"" << channel
.value() << "\"";
494 // ap must have -chromeframe iff Chrome Frame is installed multi
495 const ProductState
* cf_state
= machine_state
.GetProductState(
496 system_install
, BrowserDistribution::CHROME_FRAME
);
497 if (cf_state
!= NULL
&& cf_state
->is_multi_install()) {
498 if (!channel
.IsChromeFrame()) {
500 LOG(ERROR
) << "Chrome Binaries are missing \"-chromeframe\" in channel"
501 " name: \"" << channel
.value() << "\"";
503 } else if (channel
.IsChromeFrame()) {
505 LOG(ERROR
) << "Chrome Binaries have \"-chromeframe\" in channel name, yet "
506 "Chrome Frame is not installed multi: \"" << channel
.value()
510 // ap must have -readymode iff Chrome Frame is installed in ready-mode
511 if (cf_state
!= NULL
&&
512 cf_state
->uninstall_command().HasSwitch(
513 installer::switches::kChromeFrameReadyMode
)) {
514 if (!channel
.IsReadyMode()) {
516 LOG(ERROR
) << "Chrome Binaries are missing \"-readymode\" in channel"
517 " name: \"" << channel
.value() << "\"";
519 } else if (channel
.IsReadyMode()) {
521 LOG(ERROR
) << "Chrome Binaries have \"-readymode\" in channel name, yet "
522 "Chrome Frame is not in ready mode: \"" << channel
.value()
526 // ap must have -applauncher iff Chrome App Launcher is installed multi
527 const ProductState
* app_host_state
= machine_state
.GetProductState(
528 system_install
, BrowserDistribution::CHROME_APP_HOST
);
529 if (app_host_state
!= NULL
) {
530 if (!app_host_state
->is_multi_install()) {
532 LOG(ERROR
) << "Chrome App Launcher is installed in non-multi mode.";
534 if (!channel
.IsAppLauncher()) {
536 LOG(ERROR
) << "Chrome Binaries are missing \"-applauncher\" in channel"
537 " name: \"" << channel
.value() << "\"";
539 } else if (channel
.IsAppLauncher()) {
541 LOG(ERROR
) << "Chrome Binaries have \"-applauncher\" in channel name, yet "
542 "Chrome App Launcher is not installed: \"" << channel
.value()
546 // Chrome, Chrome Frame, or App Host must be present
547 if (chrome_state
== NULL
&& cf_state
== NULL
&& app_host_state
== NULL
) {
549 LOG(ERROR
) << "Chrome Binaries are present with no other products.";
552 // Chrome must be multi-install if present.
553 if (chrome_state
!= NULL
&& !chrome_state
->is_multi_install()) {
556 << "Chrome Binaries are present yet Chrome is not multi-install.";
559 // Chrome Frame must be multi-install if Chrome & App Host are not present.
560 if (cf_state
!= NULL
&& app_host_state
== NULL
&& chrome_state
== NULL
&&
561 !cf_state
->is_multi_install()) {
563 LOG(ERROR
) << "Chrome Binaries are present without Chrome nor App Launcher "
564 << "yet Chrome Frame is not multi-install.";
567 ChromeBinariesRules binaries_rules
;
568 ProductContext
ctx(machine_state
, system_install
, binaries_state
,
571 ValidateBinariesCommands(ctx
, is_valid
);
573 ValidateUsageStats(ctx
, is_valid
);
576 // Validates the path to |setup_exe| for the product described by |ctx|.
577 void InstallationValidator::ValidateSetupPath(const ProductContext
& ctx
,
578 const base::FilePath
& setup_exe
,
579 const string16
& purpose
,
583 BrowserDistribution
* bins_dist
= ctx
.dist
;
584 if (ctx
.state
.is_multi_install()) {
585 bins_dist
= BrowserDistribution::GetSpecificDistribution(
586 BrowserDistribution::CHROME_BINARIES
);
589 base::FilePath expected_path
= installer::GetChromeInstallPath(
590 ctx
.system_install
, bins_dist
);
591 expected_path
= expected_path
592 .AppendASCII(ctx
.state
.version().GetString())
593 .Append(installer::kInstallerDir
)
594 .Append(installer::kSetupExe
);
595 if (!base::FilePath::CompareEqualIgnoreCase(expected_path
.value(),
596 setup_exe
.value())) {
598 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName() << " path to " << purpose
599 << " is not " << expected_path
.value() << ": "
600 << setup_exe
.value();
604 // Validates that |command| meets the expectations described in |expected|.
605 void InstallationValidator::ValidateCommandExpectations(
606 const ProductContext
& ctx
,
607 const CommandLine
& command
,
608 const SwitchExpectations
& expected
,
609 const string16
& source
,
611 for (SwitchExpectations::size_type i
= 0, size
= expected
.size(); i
< size
;
613 const SwitchExpectations::value_type
& expectation
= expected
[i
];
614 if (command
.HasSwitch(expectation
.first
) != expectation
.second
) {
616 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName() << " " << source
617 << (expectation
.second
? " is missing" : " has") << " \""
618 << expectation
.first
<< "\""
619 << (expectation
.second
? "" : " but shouldn't") << ": "
620 << command
.GetCommandLineString();
625 // Validates that |command|, originating from |source|, is formed properly for
626 // the product described by |ctx|
627 void InstallationValidator::ValidateUninstallCommand(const ProductContext
& ctx
,
628 const CommandLine
& command
,
629 const string16
& source
,
633 ValidateSetupPath(ctx
, command
.GetProgram(), ASCIIToUTF16("uninstaller"),
636 const bool is_multi_install
= ctx
.state
.is_multi_install();
637 SwitchExpectations expected
;
639 expected
.push_back(std::make_pair(std::string(switches::kUninstall
), true));
640 expected
.push_back(std::make_pair(std::string(switches::kSystemLevel
),
641 ctx
.system_install
));
642 expected
.push_back(std::make_pair(std::string(switches::kMultiInstall
),
644 ctx
.rules
.AddUninstallSwitchExpectations(ctx
, &expected
);
646 ValidateCommandExpectations(ctx
, command
, expected
, source
, is_valid
);
649 // Validates the rename command for the product described by |ctx|.
650 void InstallationValidator::ValidateRenameCommand(const ProductContext
& ctx
,
653 DCHECK(!ctx
.state
.rename_cmd().empty());
655 CommandLine command
= CommandLine::FromString(ctx
.state
.rename_cmd());
656 string16
name(ASCIIToUTF16("in-use renamer"));
658 ValidateSetupPath(ctx
, command
.GetProgram(), name
, is_valid
);
660 SwitchExpectations expected
;
662 expected
.push_back(std::make_pair(std::string(switches::kRenameChromeExe
),
664 expected
.push_back(std::make_pair(std::string(switches::kSystemLevel
),
665 ctx
.system_install
));
666 expected
.push_back(std::make_pair(std::string(switches::kMultiInstall
),
667 ctx
.state
.is_multi_install()));
668 ctx
.rules
.AddRenameSwitchExpectations(ctx
, &expected
);
670 ValidateCommandExpectations(ctx
, command
, expected
, name
, is_valid
);
673 // Validates the "opv" and "cmd" values for the product described in |ctx|.
674 void InstallationValidator::ValidateOldVersionValues(
675 const ProductContext
& ctx
,
679 // opv and cmd must both be present or both absent
680 if (ctx
.state
.old_version() == NULL
) {
681 if (!ctx
.state
.rename_cmd().empty()) {
683 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName()
684 << " has a rename command but no opv: "
685 << ctx
.state
.rename_cmd();
688 if (ctx
.state
.rename_cmd().empty()) {
690 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName()
691 << " has an opv but no rename command: "
692 << ctx
.state
.old_version()->GetString();
694 ValidateRenameCommand(ctx
, is_valid
);
699 // Validates the multi-install state of the product described in |ctx|.
700 void InstallationValidator::ValidateMultiInstallProduct(
701 const ProductContext
& ctx
,
705 const ProductState
* binaries
=
706 ctx
.machine_state
.GetProductState(ctx
.system_install
,
707 BrowserDistribution::CHROME_BINARIES
);
709 if (ctx
.dist
->GetType() == BrowserDistribution::CHROME_APP_HOST
) {
710 if (!ctx
.machine_state
.GetProductState(
711 true, // system-level
712 BrowserDistribution::CHROME_BINARIES
) &&
713 !ctx
.machine_state
.GetProductState(
714 true, // system-level
715 BrowserDistribution::CHROME_BROWSER
)) {
717 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName()
718 << " (" << ctx
.state
.version().GetString() << ") is "
719 << "installed without Chrome Binaries or a system-level "
724 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName()
725 << " (" << ctx
.state
.version().GetString() << ") is installed "
726 << "without Chrome Binaries.";
729 // Version must match that of binaries.
730 if (ctx
.state
.version().CompareTo(binaries
->version()) != 0) {
732 LOG(ERROR
) << "Version of " << ctx
.dist
->GetAppShortCutName()
733 << " (" << ctx
.state
.version().GetString() << ") does not "
734 "match that of Chrome Binaries ("
735 << binaries
->version().GetString() << ").";
738 // Channel value must match that of binaries.
739 if (!ctx
.state
.channel().Equals(binaries
->channel())) {
741 LOG(ERROR
) << "Channel name of " << ctx
.dist
->GetAppShortCutName()
742 << " (" << ctx
.state
.channel().value()
743 << ") does not match that of Chrome Binaries ("
744 << binaries
->channel().value() << ").";
749 // Validates the Google Update commands for the product described in |ctx|.
750 void InstallationValidator::ValidateAppCommands(
751 const ProductContext
& ctx
,
755 CommandExpectations expectations
;
757 if (ctx
.dist
->GetType() == BrowserDistribution::CHROME_APP_HOST
) {
758 expectations
[kCmdInstallApp
] = &ValidateInstallAppCommand
;
760 if (ctx
.dist
->GetType() == BrowserDistribution::CHROME_BROWSER
) {
761 expectations
[kCmdInstallExtension
] = &ValidateInstallExtensionCommand
;
762 expectations
[kCmdOnOsUpgrade
] = &ValidateOnOsUpgradeCommand
;
765 ValidateAppCommandExpectations(ctx
, expectations
, is_valid
);
768 // Validates usagestats for the product or binaries in |ctx|.
769 void InstallationValidator::ValidateUsageStats(const ProductContext
& ctx
,
771 DWORD usagestats
= 0;
772 if (ctx
.state
.GetUsageStats(&usagestats
)) {
773 if (!ctx
.rules
.UsageStatsAllowed(ctx
)) {
775 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName()
776 << " has a usagestats value (" << usagestats
777 << "), yet should not.";
778 } else if (usagestats
!= 0 && usagestats
!= 1) {
780 LOG(ERROR
) << ctx
.dist
->GetAppShortCutName()
781 << " has an unsupported usagestats value (" << usagestats
787 // Validates the product described in |product_state| according to |rules|.
788 void InstallationValidator::ValidateProduct(
789 const InstallationState
& machine_state
,
791 const ProductState
& product_state
,
792 const ProductRules
& rules
,
796 ProductContext
ctx(machine_state
, system_install
, product_state
, rules
);
798 ValidateUninstallCommand(ctx
, ctx
.state
.uninstall_command(),
799 ASCIIToUTF16("Google Update uninstall command"),
802 ValidateOldVersionValues(ctx
, is_valid
);
804 if (ctx
.state
.is_multi_install())
805 ValidateMultiInstallProduct(ctx
, is_valid
);
807 ValidateAppCommands(ctx
, is_valid
);
809 ValidateUsageStats(ctx
, is_valid
);
813 bool InstallationValidator::ValidateInstallationTypeForState(
814 const InstallationState
& machine_state
,
816 InstallationType
* type
) {
821 // Does the system have any multi-installed products?
822 const ProductState
* multi_state
=
823 machine_state
.GetProductState(system_level
,
824 BrowserDistribution::CHROME_BINARIES
);
825 if (multi_state
!= NULL
)
826 ValidateBinaries(machine_state
, system_level
, *multi_state
, &rock_on
);
828 // Is Chrome installed?
829 const ProductState
* product_state
=
830 machine_state
.GetProductState(system_level
,
831 BrowserDistribution::CHROME_BROWSER
);
832 if (product_state
!= NULL
) {
833 ChromeRules chrome_rules
;
834 ValidateProduct(machine_state
, system_level
, *product_state
,
835 chrome_rules
, &rock_on
);
836 *type
= static_cast<InstallationType
>(
837 *type
| (product_state
->is_multi_install() ?
838 ProductBits::CHROME_MULTI
:
839 ProductBits::CHROME_SINGLE
));
842 // Is Chrome Frame installed?
844 machine_state
.GetProductState(system_level
,
845 BrowserDistribution::CHROME_FRAME
);
846 if (product_state
!= NULL
) {
847 ChromeFrameRules chrome_frame_rules
;
848 ValidateProduct(machine_state
, system_level
, *product_state
,
849 chrome_frame_rules
, &rock_on
);
850 int cf_bit
= !product_state
->is_multi_install() ?
851 ProductBits::CHROME_FRAME_SINGLE
:
852 (product_state
->uninstall_command().HasSwitch(
853 switches::kChromeFrameReadyMode
) ?
854 ProductBits::CHROME_FRAME_READY_MODE
:
855 ProductBits::CHROME_FRAME_MULTI
);
856 *type
= static_cast<InstallationType
>(*type
| cf_bit
);
859 // Is Chrome App Host installed?
861 machine_state
.GetProductState(system_level
,
862 BrowserDistribution::CHROME_APP_HOST
);
863 if (product_state
!= NULL
) {
864 ChromeAppHostRules chrome_app_host_rules
;
865 ValidateProduct(machine_state
, system_level
, *product_state
,
866 chrome_app_host_rules
, &rock_on
);
867 *type
= static_cast<InstallationType
>(*type
| ProductBits::CHROME_APP_HOST
);
868 if (!product_state
->is_multi_install()) {
869 LOG(ERROR
) << "Chrome App Launcher must always be multi-install.";
874 DCHECK_NE(std::find(&kInstallationTypes
[0],
875 &kInstallationTypes
[arraysize(kInstallationTypes
)],
877 &kInstallationTypes
[arraysize(kInstallationTypes
)])
878 << "Invalid combination of products found on system (" << *type
<< ")";
884 bool InstallationValidator::ValidateInstallationType(bool system_level
,
885 InstallationType
* type
) {
887 InstallationState machine_state
;
889 machine_state
.Initialize();
891 return ValidateInstallationTypeForState(machine_state
, system_level
, type
);
894 } // namespace installer