- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / installer / tools / validate_installation_main.cc
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 // 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.
8
9 #include <cstdio>
10 #include <cstdlib>
11
12 #include "base/at_exit.h"
13 #include "base/command_line.h"
14 #include "base/file_util.h"
15 #include "base/logging.h"
16 #include "base/path_service.h"
17 #include "chrome/installer/util/installation_validator.h"
18
19 using installer::InstallationValidator;
20
21 namespace {
22
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();
30
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);
38
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_;
44 };
45
46 // static
47 const wchar_t ConsoleLogHelper::kLogFileName_[] = L"validate_installation.log";
48
49 // Dump violations to stderr.
50 // static
51 FILE* const ConsoleLogHelper::kOutputStream_ = stderr;
52
53 // InstallationValidator logs all violations at ERROR level.
54 // static
55 const logging::LogSeverity
56     ConsoleLogHelper::kViolationSeverity_ = logging::LOG_ERROR;
57
58 // static
59 logging::LogMessageHandlerFunction
60     ConsoleLogHelper::old_message_handler_ = NULL;
61
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);
70
71   old_message_handler_ = logging::GetLogMessageHandler();
72   logging::SetLogMessageHandler(&DumpLogMessage);
73 }
74
75 ConsoleLogHelper::~ConsoleLogHelper() {
76   logging::SetLogMessageHandler(old_message_handler_);
77   old_message_handler_ = NULL;
78
79   logging::CloseLogFile();
80
81   // Delete the log file if it wasn't written to (this is expected).
82   int64 file_size = 0;
83   if (file_util::GetFileSize(log_file_path_, &file_size) && file_size == 0)
84     base::DeleteFile(log_file_path_, false);
85 }
86
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;
92
93   if (PathService::Get(base::DIR_TEMP, &log_path))
94     return log_path.Append(kLogFileName_);
95   else
96     return base::FilePath(kLogFileName_);
97 }
98
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;
111   }
112
113   if (old_message_handler_ != NULL)
114     return (old_message_handler_)(severity, file, line, message_start, str);
115
116   return false;
117 }
118
119 const char* LevelToString(bool system_level) {
120   return system_level ? "System-level" : "User-level";
121 }
122
123 std::string InstallationTypeToString(
124     InstallationValidator::InstallationType type) {
125   std::string result;
126
127   static const struct ProductData {
128     int bit;
129     const char* name;
130   } kProdBitToName[] = {
131     {
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"
146     },
147   };
148
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);
155     }
156   }
157
158   return result;
159 }
160
161 }  // namespace
162
163 // The main program.
164 int wmain(int argc, wchar_t *argv[]) {
165   int result = EXIT_SUCCESS;
166   base::AtExitManager exit_manager;
167
168   CommandLine::Init(0, NULL);
169   ConsoleLogHelper log_helper;
170
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());
183     }
184     if (!is_valid)
185       result = EXIT_FAILURE;
186   }
187
188   return result;
189 }