• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 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.
4 
5 #include "chrome/test/chromedriver/chrome/console_logger.h"
6 
7 #include "base/json/json_writer.h"
8 #include "base/logging.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/values.h"
11 #include "chrome/test/chromedriver/chrome/devtools_client.h"
12 #include "chrome/test/chromedriver/chrome/log.h"
13 #include "chrome/test/chromedriver/chrome/status.h"
14 
15 namespace {
16 
17 // Translates Console.messageAdded.message.level into Log::Level.
ConsoleLevelToLogLevel(const std::string & name,Log::Level * out_level)18 bool ConsoleLevelToLogLevel(const std::string& name, Log::Level *out_level) {
19   const char* const kConsoleLevelNames[] = {
20     "debug", "log", "warning", "error"
21   };
22 
23   for (size_t i = 0; i < arraysize(kConsoleLevelNames); ++i) {
24     if (name == kConsoleLevelNames[i]) {
25       CHECK_LE(Log::kDebug + i, static_cast<size_t>(Log::kError));
26       *out_level = static_cast<Log::Level>(Log::kDebug + i);
27       return true;
28     }
29   }
30   return false;
31 }
32 
33 }  // namespace
34 
ConsoleLogger(Log * log)35 ConsoleLogger::ConsoleLogger(Log* log)
36     : log_(log) {}
37 
OnConnected(DevToolsClient * client)38 Status ConsoleLogger::OnConnected(DevToolsClient* client) {
39   base::DictionaryValue params;
40   return client->SendCommand("Console.enable", params);
41 }
42 
OnEvent(DevToolsClient * client,const std::string & method,const base::DictionaryValue & params)43 Status ConsoleLogger::OnEvent(
44     DevToolsClient* client,
45     const std::string& method,
46     const base::DictionaryValue& params) {
47   if (method != "Console.messageAdded")
48     return Status(kOk);
49 
50   // If the event has proper structure and fields, log formatted.
51   // Else it's a weird message that we don't know how to format, log full JSON.
52   const base::DictionaryValue *message_dict = NULL;
53   if (params.GetDictionary("message", &message_dict)) {
54     std::string text;
55     std::string level_name;
56     Log::Level level = Log::kInfo;
57     if (message_dict->GetString("text", &text) && !text.empty() &&
58         message_dict->GetString("level", &level_name) &&
59         ConsoleLevelToLogLevel(level_name, &level)) {
60 
61       const char* origin_cstr = "unknown";
62       std::string origin;
63       if ((message_dict->GetString("url", &origin) && !origin.empty()) ||
64           (message_dict->GetString("source", &origin) && !origin.empty())) {
65         origin_cstr = origin.c_str();
66       }
67 
68       std::string line_column;
69       int line = -1;
70       if (message_dict->GetInteger("line", &line)) {
71         int column = -1;
72         if (message_dict->GetInteger("column", &column)) {
73           base::SStringPrintf(&line_column, "%d:%d", line, column);
74         } else {
75           base::SStringPrintf(&line_column, "%d", line);
76         }
77       } else {
78         // No line number, but print anyway, just to maintain the number of
79         // fields in the formatted message in case someone wants to parse it.
80         line_column = "-";
81       }
82 
83       std::string source;
84       message_dict->GetString("source", &source);
85       log_->AddEntry(level, source, base::StringPrintf("%s %s %s",
86                                                        origin_cstr,
87                                                        line_column.c_str(),
88                                                        text.c_str()));
89 
90       return Status(kOk);
91     }
92   }
93 
94   // Don't know how to format, log full JSON.
95   std::string message_json;
96   base::JSONWriter::Write(&params, &message_json);
97   log_->AddEntry(Log::kWarning, message_json);
98   return Status(kOk);
99 }
100