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 15namespace { 16 17// Translates Console.messageAdded.message.level into Log::Level. 18bool 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 35ConsoleLogger::ConsoleLogger(Log* log) 36 : log_(log) {} 37 38Status ConsoleLogger::OnConnected(DevToolsClient* client) { 39 base::DictionaryValue params; 40 return client->SendCommand("Console.enable", params); 41} 42 43Status 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(¶ms, &message_json); 97 log_->AddEntry(Log::kWarning, message_json); 98 return Status(kOk); 99} 100