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"
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.
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();
61 // Wrapper for the windows console operating in high-level IO mode.
62 class WinConsole
: public SimpleConsole
{
64 // The ctor allocates a console. This avoids having to ask the user to start
65 // chrome from a command prompt.
67 : std_out_(INVALID_HANDLE_VALUE
),
68 std_in_(INVALID_HANDLE_VALUE
) {
72 virtual ~WinConsole() {
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
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");
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
|
102 color_combo
= FOREGROUND_RED
| FOREGROUND_INTENSITY
;
105 color_combo
= FOREGROUND_GREEN
| FOREGROUND_INTENSITY
;
112 return (TRUE
== ::SetConsoleTextAttribute(std_out_
, color_combo
));
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.
128 DISALLOW_COPY_AND_ASSIGN(WinConsole
);
133 SimpleConsole
* SimpleConsole::Create() { return new WinConsole(); }
135 #elif defined(OS_POSIX)
138 class PosixConsole
: public SimpleConsole
{
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
);
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());
155 virtual void OnQuit() OVERRIDE
{
156 // The "press enter to continue" prompt isn't very unixy, so only do that on
160 virtual bool SetColor(Color color
) OVERRIDE
{
164 const char* code
= "\033[m";
184 DISALLOW_COPY_AND_ASSIGN(PosixConsole
);
189 SimpleConsole
* SimpleConsole::Create() { return new PosixConsole(); }
191 #else // !defined(OS_WIN) && !defined(OS_POSIX)
192 SimpleConsole
* SimpleConsole::Create() { return NULL
; }
195 ///////////////////////////////////////////////////////////
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());
207 DiagnosticsWriter::~DiagnosticsWriter() {
212 bool DiagnosticsWriter::WriteInfoLine(const std::string
& info_text
) {
213 if (format_
== LOG
) {
214 LOG(WARNING
) << info_text
;
217 if (console_
.get()) {
218 console_
->SetColor(SimpleConsole::DEFAULT
);
219 console_
->Write(base::UTF8ToUTF16(info_text
+ "\n"));
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());
230 test_info
.GetTitle(),
231 test_info
.GetOutcomeCode(),
232 test_info
.GetAdditionalInfo());
235 void DiagnosticsWriter::OnAllTestsDone(DiagnosticsModel
* model
) {
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
,
253 const std::string
& extra
) {
255 SimpleConsole::Color color
;
259 color
= SimpleConsole::GREEN
;
261 color
= SimpleConsole::RED
;
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()));
275 return WriteInfoLine(name
+ "\n " + extra
+ "\n");
279 // For log output, we only care about the tests that failed.
280 return WriteInfoLine(base::StringPrintf("%s%03d %s (%s)",
290 } // namespace diagnostics