Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(622)

Side by Side Diff: chrome/installer/util/installation_validator.cc

Issue 6490024: New installation validator machinery to check the machine state.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 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.
4
5 // Implementation of the installation validator.
6
7 #include "chrome/installer/util/installation_validator.h"
8
9 #include <algorithm>
10
11 #include "base/logging.h"
12 #include "base/version.h"
13 #include "chrome/installer/util/browser_distribution.h"
14 #include "chrome/installer/util/helper.h"
15 #include "chrome/installer/util/installation_state.h"
16
17 namespace installer {
18
19 BrowserDistribution::Type
20 InstallationValidator::ChromeRules::distribution_type() const {
21 return BrowserDistribution::CHROME_BROWSER;
22 }
23
24 void InstallationValidator::ChromeRules::AddUninstallSwitchExpectations(
25 const InstallationState& machine_state,
26 bool system_install,
27 const ProductState& product_state,
28 SwitchExpectations* expectations) const {
29 const bool is_multi_install =
30 product_state.uninstall_command().HasSwitch(switches::kMultiInstall);
31
32 // --chrome should be present iff --multi-install.
33 expectations->push_back(std::make_pair(std::string(switches::kChrome),
34 is_multi_install));
35 // --chrome-frame --ready-mode should be present iff CF in ready mode.
36 const ProductState* cf_state =
37 machine_state.GetProductState(system_install,
38 BrowserDistribution::CHROME_FRAME);
39 const bool ready_mode =
40 cf_state != NULL &&
41 cf_state->uninstall_command().HasSwitch(switches::kChromeFrameReadyMode);
42 expectations->push_back(std::make_pair(std::string(switches::kChromeFrame),
43 ready_mode));
44 expectations->push_back(
45 std::make_pair(std::string(switches::kChromeFrameReadyMode), ready_mode));
46 }
47
48 BrowserDistribution::Type
49 InstallationValidator::ChromeFrameRules::distribution_type() const {
50 return BrowserDistribution::CHROME_FRAME;
51 }
52
53 void InstallationValidator::ChromeFrameRules::AddUninstallSwitchExpectations(
54 const InstallationState& machine_state,
55 bool system_install,
56 const ProductState& product_state,
57 SwitchExpectations* expectations) const {
58 // --chrome-frame must be present.
59 expectations->push_back(std::make_pair(std::string(switches::kChromeFrame),
60 true));
61 // --chrome must not be present.
62 expectations->push_back(std::make_pair(std::string(switches::kChrome),
63 false));
64 }
65
66 // static
67 const InstallationValidator::InstallationType
68 InstallationValidator::kInstallationTypes[] = {
69 NO_PRODUCTS,
70 CHROME_SINGLE,
71 CHROME_MULTI,
72 CHROME_FRAME_SINGLE,
73 CHROME_FRAME_SINGLE_CHROME_SINGLE,
74 CHROME_FRAME_SINGLE_CHROME_MULTI,
75 CHROME_FRAME_MULTI,
76 CHROME_FRAME_MULTI_CHROME_MULTI,
77 CHROME_FRAME_READY_MODE_CHROME_MULTI
78 };
79
80 // Validates the multi-install binaries at level |system_level|.
81 void InstallationValidator::ValidateBinaries(
82 const InstallationState& machine_state,
83 bool system_install,
84 const ProductState& binaries_state,
85 bool* is_valid) {
86 const ChannelInfo& channel = binaries_state.channel();
87
88 // ap must have -multi
89 if (!channel.IsMultiInstall()) {
90 *is_valid = false;
91 LOG(ERROR) << "Chrome Binaries are missing \"-multi\" in channel name: \""
92 << channel.value() << "\"";
93 }
94
95 // ap must have -chrome iff Chrome is installed
96 const ProductState* chrome_state = machine_state.GetProductState(
97 system_install, BrowserDistribution::CHROME_BROWSER);
98 if (chrome_state != NULL) {
99 if (!channel.IsChrome()) {
100 *is_valid = false;
101 LOG(ERROR) << "Chrome Binaries are missing \"chrome\" in channel name:"
102 << " \"" << channel.value() << "\"";
103 }
104 } else if (channel.IsChrome()) {
105 *is_valid = false;
106 LOG(ERROR) << "Chrome Binaries have \"-chrome\" in channel name, yet Chrome"
107 " is not installed: \"" << channel.value() << "\"";
108 }
109
110 // ap must have -chromeframe iff Chrome Frame is installed multi
111 const ProductState* cf_state = machine_state.GetProductState(
112 system_install, BrowserDistribution::CHROME_FRAME);
113 if (cf_state != NULL && cf_state->is_multi_install()) {
114 if (!channel.IsChromeFrame()) {
115 *is_valid = false;
116 LOG(ERROR) << "Chrome Binaries are missing \"-chromeframe\" in channel"
117 " name: \"" << channel.value() << "\"";
118 }
119 } else if (channel.IsChromeFrame()) {
120 *is_valid = false;
121 LOG(ERROR) << "Chrome Binaries have \"-chromeframe\" in channel name, yet "
122 "Chrome Frame is not installed multi: \"" << channel.value()
123 << "\"";
124 }
125
126 // ap must have -readymode iff Chrome Frame is installed in ready-mode
127 if (cf_state != NULL &&
128 cf_state->uninstall_command().HasSwitch(
129 installer::switches::kChromeFrameReadyMode)) {
130 if (!channel.IsReadyMode()) {
131 *is_valid = false;
132 LOG(ERROR) << "Chrome Binaries are missing \"-readymode\" in channel"
133 " name: \"" << channel.value() << "\"";
134 }
135 } else if (channel.IsReadyMode()) {
136 *is_valid = false;
137 LOG(ERROR) << "Chrome Binaries have \"-readymode\" in channel name, yet "
138 "Chrome Frame is not in ready mode: \"" << channel.value()
139 << "\"";
140 }
141
142 // Chrome or Chrome Frame must be present
143 if (chrome_state == NULL && cf_state == NULL) {
144 *is_valid = false;
145 LOG(ERROR) << "Chrome Binaries are present with no other products.";
146 }
147
148 // Chrome must be multi-install if present.
149 if (chrome_state != NULL && !chrome_state->is_multi_install()) {
150 *is_valid = false;
151 LOG(ERROR)
152 << "Chrome Binaries are present yet Chrome is not multi-install.";
153 }
154
155 // Chrome Frame must be multi-install if Chrome is not present.
156 if (cf_state != NULL && chrome_state == NULL &&
157 !cf_state->is_multi_install()) {
158 *is_valid = false;
159 LOG(ERROR) << "Chrome Binaries are present without Chrome yet Chrome Frame "
160 "is not multi-install.";
161 }
162 }
163
164 // Validates the path to |setup_exe| for the product described by |ctx|.
165 void InstallationValidator::ValidateSetupPath(const ProductContext& ctx,
166 const FilePath& setup_exe,
167 const char* purpose,
168 bool* is_valid) {
169 DCHECK(is_valid);
170
171 BrowserDistribution* bins_dist = ctx.dist;
172 if (ctx.state.is_multi_install()) {
173 bins_dist = BrowserDistribution::GetSpecificDistribution(
174 BrowserDistribution::CHROME_BINARIES);
175 }
176
177 FilePath expected_path = installer::GetChromeInstallPath(ctx.system_install,
178 bins_dist);
179 expected_path = expected_path
180 .AppendASCII(ctx.state.version().GetString())
181 .Append(installer::kInstallerDir)
182 .Append(installer::kSetupExe);
183 if (!FilePath::CompareEqualIgnoreCase(expected_path.value(),
184 setup_exe.value())) {
185 *is_valid = false;
186 LOG(ERROR) << ctx.dist->GetApplicationName() << " path to " << purpose
187 << " is not " << expected_path.value() << ": "
188 << setup_exe.value();
189 }
190 }
191
192 // Validates that |command| meets the expectations described in |expected|.
193 void InstallationValidator::ValidateCommandExpectations(
194 const ProductContext& ctx,
195 const CommandLine& command,
196 const SwitchExpectations& expected,
197 const char* source,
198 bool* is_valid) {
199 for (SwitchExpectations::size_type i = 0, size = expected.size(); i < size;
200 ++i) {
201 const SwitchExpectations::value_type& expectation = expected[i];
202 if (command.HasSwitch(expectation.first) != expectation.second) {
203 *is_valid = false;
204 LOG(ERROR) << ctx.dist->GetApplicationName() << " " << source
205 << (expectation.second ? " is missing" : " has") << " \""
206 << expectation.first << "\""
207 << (expectation.second ? "" : " but shouldn't") << ": "
208 << command.command_line_string();
209 }
210 }
211 }
212
213 // Validates that |command|, originating from |source|, is formed properly for
214 // the product described by |ctx|
215 void InstallationValidator::ValidateUninstallCommand(const ProductContext& ctx,
216 const CommandLine& command,
217 const char* source,
218 bool* is_valid) {
219 DCHECK(is_valid);
220
221 ValidateSetupPath(ctx, command.GetProgram(), "uninstaller", is_valid);
222
223 const bool is_multi_install = ctx.state.is_multi_install();
224 SwitchExpectations expected;
225
226 expected.push_back(std::make_pair(std::string(switches::kUninstall), true));
227 expected.push_back(std::make_pair(std::string(switches::kSystemLevel),
228 ctx.system_install));
229 expected.push_back(std::make_pair(std::string(switches::kMultiInstall),
230 is_multi_install));
231 ctx.rules.AddUninstallSwitchExpectations(ctx.machine_state,
232 ctx.system_install,
233 ctx.state, &expected);
234
235 ValidateCommandExpectations(ctx, command, expected, source, is_valid);
236 }
237
238 // Validates the rename command for the product described by |ctx|.
239 void InstallationValidator::ValidateRenameCommand(const ProductContext& ctx,
240 bool* is_valid) {
241 DCHECK(is_valid);
242 DCHECK(!ctx.state.rename_cmd().empty());
243
244 CommandLine command = CommandLine::FromString(ctx.state.rename_cmd());
245
246 ValidateSetupPath(ctx, command.GetProgram(), "in-use renamer", is_valid);
247
248 SwitchExpectations expected;
249
250 expected.push_back(std::make_pair(std::string(switches::kRenameChromeExe),
251 true));
252 expected.push_back(std::make_pair(std::string(switches::kSystemLevel),
253 ctx.system_install));
254 expected.push_back(std::make_pair(std::string(switches::kMultiInstall),
255 ctx.state.is_multi_install()));
256
257 ValidateCommandExpectations(ctx, command, expected, "in-use renamer",
258 is_valid);
259 }
260
261 // Validates the "opv" and "cmd" values for the product described in |ctx|.
262 void InstallationValidator::ValidateOldVersionValues(
263 const ProductContext& ctx,
264 bool* is_valid) {
265 DCHECK(is_valid);
266
267 // opv and cmd must both be present or both absent
268 if (ctx.state.old_version() == NULL) {
269 if (!ctx.state.rename_cmd().empty()) {
270 *is_valid = false;
271 LOG(ERROR) << ctx.dist->GetApplicationName()
272 << " has a rename command but no opv: "
273 << ctx.state.rename_cmd();
274 }
275 } else {
276 if (ctx.state.rename_cmd().empty()) {
277 *is_valid = false;
278 LOG(ERROR) << ctx.dist->GetApplicationName()
279 << " has an opv but no rename command: "
280 << ctx.state.old_version()->GetString();
281 } else {
282 ValidateRenameCommand(ctx, is_valid);
283 }
284 }
285 }
286
287 // Validates the multi-install state of the product described in |ctx|.
288 void InstallationValidator::ValidateMultiInstallProduct(
289 const ProductContext& ctx,
290 bool* is_valid) {
291 DCHECK(is_valid);
292
293 const ProductState* binaries =
294 ctx.machine_state.GetProductState(ctx.system_install,
295 BrowserDistribution::CHROME_BINARIES);
296 DCHECK(binaries);
297
298 // Version must match that of binaries.
299 if (ctx.state.version().CompareTo(binaries->version()) != 0) {
300 *is_valid = false;
301 LOG(ERROR) << "Version of " << ctx.dist->GetApplicationName()
302 << " (" << ctx.state.version().GetString() << ") does not "
303 "match that of Chrome Binaries ("
304 << binaries->version().GetString() << ").";
305 }
306
307 // Channel value must match that of binaries.
308 if (!ctx.state.channel().Equals(binaries->channel())) {
309 *is_valid = false;
310 LOG(ERROR) << "Channel name of " << ctx.dist->GetApplicationName()
311 << " (" << ctx.state.channel().value()
312 << ") does not match that of Chrome Binaries ("
313 << binaries->channel().value() << ").";
314 }
315 }
316
317 // Validates the product described in |product_state| according to |rules|.
318 void InstallationValidator::ValidateProduct(
319 const InstallationState& machine_state,
320 bool system_install,
321 const ProductState& product_state,
322 const ProductRules& rules,
323 bool* is_valid) {
324 DCHECK(is_valid);
325 ProductContext ctx = {
326 machine_state,
327 system_install,
328 BrowserDistribution::GetSpecificDistribution(rules.distribution_type()),
329 product_state,
330 rules
331 };
332
333 ValidateUninstallCommand(ctx, product_state.uninstall_command(),
334 "Google Update uninstall command", is_valid);
335
336 ValidateOldVersionValues(ctx, is_valid);
337
338 if (product_state.is_multi_install())
339 ValidateMultiInstallProduct(ctx, is_valid);
340 }
341
342 // static
343 bool InstallationValidator::ValidateInstallationTypeForState(
344 const InstallationState& machine_state,
345 bool system_level,
346 InstallationType* type) {
347 DCHECK(type);
348 bool rock_on = true;
349 *type = NO_PRODUCTS;
350
351 // Does the system have any multi-installed products?
352 const ProductState* multi_state =
353 machine_state.GetProductState(system_level,
354 BrowserDistribution::CHROME_BINARIES);
355 if (multi_state != NULL)
356 ValidateBinaries(machine_state, system_level, *multi_state, &rock_on);
357
358 // Is Chrome installed?
359 const ProductState* product_state =
360 machine_state.GetProductState(system_level,
361 BrowserDistribution::CHROME_BROWSER);
362 if (product_state != NULL) {
363 ChromeRules chrome_rules;
364 ValidateProduct(machine_state, system_level, *product_state,
365 chrome_rules, &rock_on);
366 *type = static_cast<InstallationType>(
367 *type | (product_state->is_multi_install() ?
368 ProductBits::CHROME_MULTI :
369 ProductBits::CHROME_SINGLE));
370 }
371
372 // Is Chrome Frame installed?
373 product_state =
374 machine_state.GetProductState(system_level,
375 BrowserDistribution::CHROME_FRAME);
376 if (product_state != NULL) {
377 ChromeFrameRules chrome_frame_rules;
378 ValidateProduct(machine_state, system_level, *product_state,
379 chrome_frame_rules, &rock_on);
380 int cf_bit = !product_state->is_multi_install() ?
381 ProductBits::CHROME_FRAME_SINGLE :
382 (product_state->uninstall_command().HasSwitch(
383 switches::kChromeFrameReadyMode) ?
384 ProductBits::CHROME_FRAME_READY_MODE :
385 ProductBits::CHROME_FRAME_MULTI);
386 *type = static_cast<InstallationType>(*type | cf_bit);
387 }
388
389 DCHECK_NE(std::find(&kInstallationTypes[0],
390 &kInstallationTypes[arraysize(kInstallationTypes)],
391 *type),
392 &kInstallationTypes[arraysize(kInstallationTypes)])
393 << "Invalid combination of products found on system (" << *type << ")";
394
395 return rock_on;
396 }
397
398 // static
399 bool InstallationValidator::ValidateInstallationType(bool system_level,
400 InstallationType* type) {
401 DCHECK(type);
402 InstallationState machine_state;
403
404 machine_state.Initialize();
405
406 return ValidateInstallationTypeForState(machine_state, system_level, type);
407 }
408
409 } // namespace installer
OLDNEW
« no previous file with comments | « chrome/installer/util/installation_validator.h ('k') | chrome/installer/util/installation_validator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698