Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / installer / tools / validate_installation_main.cc
blob74f860c5c40b4fcce181e3e1d55444d239b38c92
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.
5 // A command-line tool that inspects the current system, displaying information
6 // about installed products. Violations are dumped to stderr. The process
7 // exit code is 0 if there are no violations, or 1 otherwise.
9 #include <cstdio>
10 #include <cstdlib>
12 #include "base/at_exit.h"
13 #include "base/command_line.h"
14 #include "base/files/file_util.h"
15 #include "base/logging.h"
16 #include "base/path_service.h"
17 #include "chrome/installer/util/installation_validator.h"
19 using installer::InstallationValidator;
21 namespace {
23 // A helper class that initializes logging and installs a log message handler to
24 // direct ERROR messages to stderr. Only one instance of this class may be live
25 // at a time.
26 class ConsoleLogHelper {
27 public:
28 ConsoleLogHelper();
29 ~ConsoleLogHelper();
31 private:
32 static base::FilePath GetLogFilePath();
33 static bool DumpLogMessage(int severity,
34 const char* file,
35 int line,
36 size_t message_start,
37 const std::string& str);
39 static const wchar_t kLogFileName_[];
40 static FILE* const kOutputStream_;
41 static const logging::LogSeverity kViolationSeverity_;
42 static logging::LogMessageHandlerFunction old_message_handler_;
43 base::FilePath log_file_path_;
46 // static
47 const wchar_t ConsoleLogHelper::kLogFileName_[] = L"validate_installation.log";
49 // Dump violations to stderr.
50 // static
51 FILE* const ConsoleLogHelper::kOutputStream_ = stderr;
53 // InstallationValidator logs all violations at ERROR level.
54 // static
55 const logging::LogSeverity
56 ConsoleLogHelper::kViolationSeverity_ = logging::LOG_ERROR;
58 // static
59 logging::LogMessageHandlerFunction
60 ConsoleLogHelper::old_message_handler_ = NULL;
62 ConsoleLogHelper::ConsoleLogHelper() : log_file_path_(GetLogFilePath()) {
63 LOG_ASSERT(old_message_handler_ == NULL);
64 logging::LoggingSettings settings;
65 settings.logging_dest = logging::LOG_TO_FILE;
66 settings.log_file = log_file_path_.value().c_str();
67 settings.lock_log = logging::DONT_LOCK_LOG_FILE;
68 settings.delete_old = logging::DELETE_OLD_LOG_FILE;
69 logging::InitLogging(settings);
71 old_message_handler_ = logging::GetLogMessageHandler();
72 logging::SetLogMessageHandler(&DumpLogMessage);
75 ConsoleLogHelper::~ConsoleLogHelper() {
76 logging::SetLogMessageHandler(old_message_handler_);
77 old_message_handler_ = NULL;
79 logging::CloseLogFile();
81 // Delete the log file if it wasn't written to (this is expected).
82 int64 file_size = 0;
83 if (base::GetFileSize(log_file_path_, &file_size) && file_size == 0)
84 base::DeleteFile(log_file_path_, false);
87 // Returns the path to the log file to create. The file should be empty at
88 // process exit since we redirect log messages to stderr.
89 // static
90 base::FilePath ConsoleLogHelper::GetLogFilePath() {
91 base::FilePath log_path;
93 if (PathService::Get(base::DIR_TEMP, &log_path))
94 return log_path.Append(kLogFileName_);
95 else
96 return base::FilePath(kLogFileName_);
99 // A logging::LogMessageHandlerFunction that sends the body of messages logged
100 // at the severity of validation violations to stderr. All other messages are
101 // sent through the default logging pipeline.
102 // static
103 bool ConsoleLogHelper::DumpLogMessage(int severity,
104 const char* file,
105 int line,
106 size_t message_start,
107 const std::string& str) {
108 if (severity == kViolationSeverity_) {
109 fprintf(kOutputStream_, "%s", str.c_str() + message_start);
110 return true;
113 if (old_message_handler_ != NULL)
114 return (old_message_handler_)(severity, file, line, message_start, str);
116 return false;
119 const char* LevelToString(bool system_level) {
120 return system_level ? "System-level" : "User-level";
123 std::string InstallationTypeToString(
124 InstallationValidator::InstallationType type) {
125 std::string result;
127 static const struct ProductData {
128 int bit;
129 const char* name;
130 } kProdBitToName[] = {
132 InstallationValidator::ProductBits::CHROME_SINGLE,
133 "Chrome"
134 }, {
135 InstallationValidator::ProductBits::CHROME_MULTI,
136 "Chrome (multi)"
137 }, {
138 InstallationValidator::ProductBits::CHROME_FRAME_SINGLE,
139 "Chrome Frame"
140 }, {
141 InstallationValidator::ProductBits::CHROME_FRAME_MULTI,
142 "Chrome Frame (multi)"
143 }, {
144 InstallationValidator::ProductBits::CHROME_FRAME_READY_MODE,
145 "Ready-mode Chrome Frame"
149 for (size_t i = 0; i < arraysize(kProdBitToName); ++i) {
150 const ProductData& product_data = kProdBitToName[i];
151 if ((type & product_data.bit) != 0) {
152 if (!result.empty())
153 result.append(", ");
154 result.append(product_data.name);
158 return result;
161 } // namespace
163 // The main program.
164 int wmain(int argc, wchar_t *argv[]) {
165 int result = EXIT_SUCCESS;
166 base::AtExitManager exit_manager;
168 base::CommandLine::Init(0, NULL);
169 ConsoleLogHelper log_helper;
171 // Check user-level and system-level for products.
172 for (int i = 0; i < 2; ++i) {
173 const bool system_level = (i != 0);
174 InstallationValidator::InstallationType type =
175 InstallationValidator::NO_PRODUCTS;
176 bool is_valid =
177 InstallationValidator::ValidateInstallationType(system_level, &type);
178 if (type != InstallationValidator::NO_PRODUCTS) {
179 FILE* stream = is_valid ? stdout : stderr;
180 fprintf(stream, "%s installations%s: %s\n", LevelToString(system_level),
181 (is_valid ? "" : " (with errors)"),
182 InstallationTypeToString(type).c_str());
184 if (!is_valid)
185 result = EXIT_FAILURE;
188 return result;