Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / diagnostics / diagnostics_writer.cc
blob7e75d10e42e13f8c667903f2f54862bddbc9d870
1 // Copyright 2013 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 #include "chrome/browser/diagnostics/diagnostics_writer.h"
7 #include "build/build_config.h"
9 #if defined(OS_POSIX)
10 #include <stdio.h>
11 #include <unistd.h>
12 #endif
14 #include <string>
16 #include "base/basictypes.h"
17 #include "base/command_line.h"
18 #include "base/logging.h"
19 #include "base/logging.h"
20 #include "base/strings/string16.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/base/ui_base_paths.h"
27 namespace diagnostics {
29 // This is a minimalistic interface to wrap the platform console.
30 class SimpleConsole {
31 public:
32 enum Color {
33 DEFAULT,
34 RED,
35 GREEN,
38 virtual ~SimpleConsole() {}
40 // Init must be called before using any other method. If it returns
41 // false there will be no console output.
42 virtual bool Init() = 0;
44 // Writes a string to the console with the current color.
45 virtual bool Write(const base::string16& text) = 0;
47 // Called when the program is about to exit.
48 virtual void OnQuit() = 0;
50 // Sets the foreground text color.
51 virtual bool SetColor(Color color) = 0;
53 // Create an appropriate SimpleConsole instance. May return NULL if there is
54 // no implementation for the current platform.
55 static SimpleConsole* Create();
58 #if defined(OS_WIN)
59 namespace {
61 // Wrapper for the windows console operating in high-level IO mode.
62 class WinConsole : public SimpleConsole {
63 public:
64 // The ctor allocates a console. This avoids having to ask the user to start
65 // chrome from a command prompt.
66 WinConsole()
67 : std_out_(INVALID_HANDLE_VALUE),
68 std_in_(INVALID_HANDLE_VALUE) {
69 ::AllocConsole();
72 virtual ~WinConsole() {
73 ::FreeConsole();
76 virtual bool Init() {
77 return SetIOHandles();
80 virtual bool Write(const base::string16& txt) {
81 DWORD sz = txt.size();
82 return (TRUE == ::WriteConsoleW(std_out_, txt.c_str(), sz, &sz, NULL));
85 // Reads a string from the console. Internally it is limited to 256
86 // characters.
87 virtual void OnQuit() {
88 // Block here so the user can see the results.
89 SetColor(SimpleConsole::DEFAULT);
90 Write(L"Press [enter] to continue\n");
91 wchar_t buf[256];
92 DWORD read = arraysize(buf);
93 ::ReadConsoleW(std_in_, buf, read, &read, NULL);
96 // Sets the foreground and background color.
97 virtual bool SetColor(Color color) {
98 uint16 color_combo = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE |
99 FOREGROUND_INTENSITY;
100 switch (color) {
101 case RED:
102 color_combo = FOREGROUND_RED | FOREGROUND_INTENSITY;
103 break;
104 case GREEN:
105 color_combo = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
106 break;
107 case DEFAULT:
108 break;
109 default:
110 NOTREACHED();
112 return (TRUE == ::SetConsoleTextAttribute(std_out_, color_combo));
115 private:
116 bool SetIOHandles() {
117 std_out_ = ::GetStdHandle(STD_OUTPUT_HANDLE);
118 std_in_ = ::GetStdHandle(STD_INPUT_HANDLE);
119 return ((std_out_ != INVALID_HANDLE_VALUE) &&
120 (std_in_ != INVALID_HANDLE_VALUE));
123 // The input and output handles to the screen. They seem to be
124 // implemented as pipes but they have non-documented protocol.
125 HANDLE std_out_;
126 HANDLE std_in_;
128 DISALLOW_COPY_AND_ASSIGN(WinConsole);
131 } // namespace
133 SimpleConsole* SimpleConsole::Create() { return new WinConsole(); }
135 #elif defined(OS_POSIX)
136 namespace {
138 class PosixConsole : public SimpleConsole {
139 public:
140 PosixConsole() : use_color_(false) {}
142 virtual bool Init() OVERRIDE {
143 // Technically, we should also check the terminal capabilities before using
144 // color, but in practice this is unlikely to be an issue.
145 use_color_ = isatty(STDOUT_FILENO);
146 return true;
149 virtual bool Write(const base::string16& text) OVERRIDE {
150 // We're assuming that the terminal is using UTF-8 encoding.
151 printf("%s", base::UTF16ToUTF8(text).c_str());
152 return true;
155 virtual void OnQuit() OVERRIDE {
156 // The "press enter to continue" prompt isn't very unixy, so only do that on
157 // Windows.
160 virtual bool SetColor(Color color) OVERRIDE {
161 if (!use_color_)
162 return false;
164 const char* code = "\033[m";
165 switch (color) {
166 case RED:
167 code = "\033[1;31m";
168 break;
169 case GREEN:
170 code = "\033[1;32m";
171 break;
172 case DEFAULT:
173 break;
174 default:
175 NOTREACHED();
177 printf("%s", code);
178 return true;
181 private:
182 bool use_color_;
184 DISALLOW_COPY_AND_ASSIGN(PosixConsole);
187 } // namespace
189 SimpleConsole* SimpleConsole::Create() { return new PosixConsole(); }
191 #else // !defined(OS_WIN) && !defined(OS_POSIX)
192 SimpleConsole* SimpleConsole::Create() { return NULL; }
193 #endif
195 ///////////////////////////////////////////////////////////
196 // DiagnosticsWriter
198 DiagnosticsWriter::DiagnosticsWriter(FormatType format)
199 : failures_(0), format_(format) {
200 // Only create consoles for non-log output.
201 if (format_ != LOG) {
202 console_.reset(SimpleConsole::Create());
203 console_->Init();
207 DiagnosticsWriter::~DiagnosticsWriter() {
208 if (console_.get())
209 console_->OnQuit();
212 bool DiagnosticsWriter::WriteInfoLine(const std::string& info_text) {
213 if (format_ == LOG) {
214 LOG(WARNING) << info_text;
215 return true;
216 } else {
217 if (console_.get()) {
218 console_->SetColor(SimpleConsole::DEFAULT);
219 console_->Write(base::UTF8ToUTF16(info_text + "\n"));
222 return true;
225 void DiagnosticsWriter::OnTestFinished(int index, DiagnosticsModel* model) {
226 const DiagnosticsModel::TestInfo& test_info = model->GetTest(index);
227 bool success = (DiagnosticsModel::TEST_OK == test_info.GetResult());
228 WriteResult(success,
229 test_info.GetName(),
230 test_info.GetTitle(),
231 test_info.GetOutcomeCode(),
232 test_info.GetAdditionalInfo());
235 void DiagnosticsWriter::OnAllTestsDone(DiagnosticsModel* model) {
236 WriteInfoLine(
237 base::StringPrintf("Finished %d tests.", model->GetTestRunCount()));
240 void DiagnosticsWriter::OnRecoveryFinished(int index, DiagnosticsModel* model) {
241 const DiagnosticsModel::TestInfo& test_info = model->GetTest(index);
242 WriteInfoLine("Finished Recovery for: " + test_info.GetTitle());
245 void DiagnosticsWriter::OnAllRecoveryDone(DiagnosticsModel* model) {
246 WriteInfoLine("Finished All Recovery operations.");
249 bool DiagnosticsWriter::WriteResult(bool success,
250 const std::string& id,
251 const std::string& name,
252 int outcome_code,
253 const std::string& extra) {
254 std::string result;
255 SimpleConsole::Color color;
257 if (success) {
258 result = "[PASS] ";
259 color = SimpleConsole::GREEN;
260 } else {
261 color = SimpleConsole::RED;
262 result = "[FAIL] ";
263 failures_++;
266 if (format_ != LOG) {
267 if (console_.get()) {
268 console_->SetColor(color);
269 console_->Write(base::ASCIIToUTF16(result));
271 if (format_ == MACHINE) {
272 return WriteInfoLine(base::StringPrintf(
273 "%03d %s (%s)", outcome_code, id.c_str(), extra.c_str()));
274 } else {
275 return WriteInfoLine(name + "\n " + extra + "\n");
277 } else {
278 if (!success) {
279 // For log output, we only care about the tests that failed.
280 return WriteInfoLine(base::StringPrintf("%s%03d %s (%s)",
281 result.c_str(),
282 outcome_code,
283 id.c_str(),
284 extra.c_str()));
287 return true;
290 } // namespace diagnostics