[Android] Added UMA for search by image context menu.
[chromium-blink-merge.git] / chrome / installer / util / installation_validator.cc
blobf5fb140cba80b9cf8330c02c565f78ebf33b4670
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.
39 // --chrome-frame --ready-mode should be present for uninstall iff CF in ready
40 // mode.
41 const ProductState* cf_state =
42 ctx.machine_state.GetProductState(ctx.system_install,
43 BrowserDistribution::CHROME_FRAME);
44 const bool ready_mode =
45 cf_state != NULL &&
46 cf_state->uninstall_command().HasSwitch(switches::kChromeFrameReadyMode);
47 expectations->push_back(std::make_pair(std::string(switches::kChromeFrame),
48 ready_mode));
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),
86 true));
87 // --chrome must not be present.
88 expectations->push_back(std::make_pair(std::string(switches::kChrome),
89 false));
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),
100 false));
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),
124 false));
125 // --chrome-frame must not be present.
126 expectations->push_back(std::make_pair(std::string(switches::kChromeFrame),
127 false));
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.
139 return false;
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 {
150 NOTREACHED();
153 void InstallationValidator::ChromeBinariesRules::AddRenameSwitchExpectations(
154 const ProductContext& ctx,
155 SwitchExpectations* expectations) const {
156 NOTREACHED();
159 bool InstallationValidator::ChromeBinariesRules::UsageStatsAllowed(
160 const ProductContext& ctx) const {
161 // UsageStats consent values are always allowed on the binaries.
162 return true;
165 // static
166 const InstallationValidator::InstallationType
167 InstallationValidator::kInstallationTypes[] = {
168 NO_PRODUCTS,
169 CHROME_SINGLE,
170 CHROME_MULTI,
171 CHROME_FRAME_SINGLE,
172 CHROME_FRAME_SINGLE_CHROME_SINGLE,
173 CHROME_FRAME_SINGLE_CHROME_MULTI,
174 CHROME_FRAME_MULTI,
175 CHROME_FRAME_MULTI_CHROME_MULTI,
176 CHROME_FRAME_READY_MODE_CHROME_MULTI,
177 CHROME_APP_HOST,
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,
191 bool* is_valid) {
192 const struct {
193 const string16 exp_key;
194 bool val;
195 const char* msg;
196 } check_list[] = {
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) {
213 *is_valid = false;
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,
229 bool* is_valid) {
230 DCHECK(is_valid);
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())) {
241 *is_valid = false;
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,
263 bool* is_valid) {
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,
273 bool* is_valid) {
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,
283 bool* is_valid) {
284 DCHECK(is_valid);
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,
312 bool* is_valid) {
313 DCHECK(is_valid);
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),
322 true));
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,
338 bool* is_valid) {
339 DCHECK(is_valid);
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;
348 expected.push_back(
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,
367 bool* is_valid) {
368 DCHECK(is_valid);
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,
400 bool* is_valid) {
401 DCHECK(is_valid);
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);
416 } else {
417 *is_valid = false;
418 LOG(ERROR) << ctx.dist->GetAppShortCutName()
419 << " has an unexpected Google Update product command named \""
420 << cmd_id << "\".";
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) {
428 *is_valid = false;
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,
438 bool* is_valid) {
439 DCHECK(is_valid);
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,
467 bool system_install,
468 const ProductState& binaries_state,
469 bool* is_valid) {
470 const ChannelInfo& channel = binaries_state.channel();
472 // ap must have -multi
473 if (!channel.IsMultiInstall()) {
474 *is_valid = false;
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()) {
484 *is_valid = false;
485 LOG(ERROR) << "Chrome Binaries are missing \"chrome\" in channel name:"
486 << " \"" << channel.value() << "\"";
488 } else if (channel.IsChrome()) {
489 *is_valid = false;
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()) {
499 *is_valid = false;
500 LOG(ERROR) << "Chrome Binaries are missing \"-chromeframe\" in channel"
501 " name: \"" << channel.value() << "\"";
503 } else if (channel.IsChromeFrame()) {
504 *is_valid = false;
505 LOG(ERROR) << "Chrome Binaries have \"-chromeframe\" in channel name, yet "
506 "Chrome Frame is not installed multi: \"" << channel.value()
507 << "\"";
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()) {
515 *is_valid = false;
516 LOG(ERROR) << "Chrome Binaries are missing \"-readymode\" in channel"
517 " name: \"" << channel.value() << "\"";
519 } else if (channel.IsReadyMode()) {
520 *is_valid = false;
521 LOG(ERROR) << "Chrome Binaries have \"-readymode\" in channel name, yet "
522 "Chrome Frame is not in ready mode: \"" << channel.value()
523 << "\"";
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()) {
531 *is_valid = false;
532 LOG(ERROR) << "Chrome App Launcher is installed in non-multi mode.";
534 if (!channel.IsAppLauncher()) {
535 *is_valid = false;
536 LOG(ERROR) << "Chrome Binaries are missing \"-applauncher\" in channel"
537 " name: \"" << channel.value() << "\"";
539 } else if (channel.IsAppLauncher()) {
540 *is_valid = false;
541 LOG(ERROR) << "Chrome Binaries have \"-applauncher\" in channel name, yet "
542 "Chrome App Launcher is not installed: \"" << channel.value()
543 << "\"";
546 // Chrome, Chrome Frame, or App Host must be present
547 if (chrome_state == NULL && cf_state == NULL && app_host_state == NULL) {
548 *is_valid = false;
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()) {
554 *is_valid = false;
555 LOG(ERROR)
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()) {
562 *is_valid = false;
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,
569 binaries_rules);
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,
580 bool* is_valid) {
581 DCHECK(is_valid);
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())) {
597 *is_valid = false;
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,
610 bool* is_valid) {
611 for (SwitchExpectations::size_type i = 0, size = expected.size(); i < size;
612 ++i) {
613 const SwitchExpectations::value_type& expectation = expected[i];
614 if (command.HasSwitch(expectation.first) != expectation.second) {
615 *is_valid = false;
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,
630 bool* is_valid) {
631 DCHECK(is_valid);
633 ValidateSetupPath(ctx, command.GetProgram(), ASCIIToUTF16("uninstaller"),
634 is_valid);
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),
643 is_multi_install));
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,
651 bool* is_valid) {
652 DCHECK(is_valid);
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),
663 true));
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,
676 bool* is_valid) {
677 DCHECK(is_valid);
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()) {
682 *is_valid = false;
683 LOG(ERROR) << ctx.dist->GetAppShortCutName()
684 << " has a rename command but no opv: "
685 << ctx.state.rename_cmd();
687 } else {
688 if (ctx.state.rename_cmd().empty()) {
689 *is_valid = false;
690 LOG(ERROR) << ctx.dist->GetAppShortCutName()
691 << " has an opv but no rename command: "
692 << ctx.state.old_version()->GetString();
693 } else {
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,
702 bool* is_valid) {
703 DCHECK(is_valid);
705 const ProductState* binaries =
706 ctx.machine_state.GetProductState(ctx.system_install,
707 BrowserDistribution::CHROME_BINARIES);
708 if (!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)) {
716 *is_valid = false;
717 LOG(ERROR) << ctx.dist->GetAppShortCutName()
718 << " (" << ctx.state.version().GetString() << ") is "
719 << "installed without Chrome Binaries or a system-level "
720 << "Chrome.";
722 } else {
723 *is_valid = false;
724 LOG(ERROR) << ctx.dist->GetAppShortCutName()
725 << " (" << ctx.state.version().GetString() << ") is installed "
726 << "without Chrome Binaries.";
728 } else {
729 // Version must match that of binaries.
730 if (ctx.state.version().CompareTo(binaries->version()) != 0) {
731 *is_valid = false;
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())) {
740 *is_valid = false;
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,
752 bool* is_valid) {
753 DCHECK(is_valid);
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,
770 bool* is_valid) {
771 DWORD usagestats = 0;
772 if (ctx.state.GetUsageStats(&usagestats)) {
773 if (!ctx.rules.UsageStatsAllowed(ctx)) {
774 *is_valid = false;
775 LOG(ERROR) << ctx.dist->GetAppShortCutName()
776 << " has a usagestats value (" << usagestats
777 << "), yet should not.";
778 } else if (usagestats != 0 && usagestats != 1) {
779 *is_valid = false;
780 LOG(ERROR) << ctx.dist->GetAppShortCutName()
781 << " has an unsupported usagestats value (" << usagestats
782 << ").";
787 // Validates the product described in |product_state| according to |rules|.
788 void InstallationValidator::ValidateProduct(
789 const InstallationState& machine_state,
790 bool system_install,
791 const ProductState& product_state,
792 const ProductRules& rules,
793 bool* is_valid) {
794 DCHECK(is_valid);
796 ProductContext ctx(machine_state, system_install, product_state, rules);
798 ValidateUninstallCommand(ctx, ctx.state.uninstall_command(),
799 ASCIIToUTF16("Google Update uninstall command"),
800 is_valid);
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);
812 // static
813 bool InstallationValidator::ValidateInstallationTypeForState(
814 const InstallationState& machine_state,
815 bool system_level,
816 InstallationType* type) {
817 DCHECK(type);
818 bool rock_on = true;
819 *type = NO_PRODUCTS;
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?
843 product_state =
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?
860 product_state =
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.";
870 rock_on = false;
874 DCHECK_NE(std::find(&kInstallationTypes[0],
875 &kInstallationTypes[arraysize(kInstallationTypes)],
876 *type),
877 &kInstallationTypes[arraysize(kInstallationTypes)])
878 << "Invalid combination of products found on system (" << *type << ")";
880 return rock_on;
883 // static
884 bool InstallationValidator::ValidateInstallationType(bool system_level,
885 InstallationType* type) {
886 DCHECK(type);
887 InstallationState machine_state;
889 machine_state.Initialize();
891 return ValidateInstallationTypeForState(machine_state, system_level, type);
894 } // namespace installer