Home | History | Annotate | Download | only in chromedriver
      1 // Copyright (c) 2012 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/logging.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/logging.h"
      9 #include "base/time/time.h"
     10 #include "chrome/test/chromedriver/capabilities.h"
     11 #include "chrome/test/chromedriver/chrome/console_logger.h"
     12 #include "chrome/test/chromedriver/chrome/performance_logger.h"
     13 #include "chrome/test/chromedriver/chrome/status.h"
     14 
     15 
     16 namespace {
     17 
     18 // Map between WebDriverLog::WebDriverLevel and its name in WD wire protocol.
     19 // Array indices are the WebDriverLog::WebDriverLevel enum values.
     20 const char* const kWebDriverLevelNames[] = {
     21   "ALL", "DEBUG", "INFO", "WARNING", "SEVERE", "OFF"
     22 };
     23 
     24 // Map between Log::Level and WebDriverLog::WebDriverLevel.
     25 // Array indices are the Log::Level enum values.
     26 WebDriverLog::WebDriverLevel kLogLevelToWebDriverLevels[] = {
     27   WebDriverLog::kWdDebug,  // kDebug
     28   WebDriverLog::kWdInfo,  // kLog
     29   WebDriverLog::kWdWarning,  // kWarning
     30   WebDriverLog::kWdSevere  // kError
     31 };
     32 
     33 // Translates Log::Level to WebDriverLog::WebDriverLevel.
     34 WebDriverLog::WebDriverLevel LogLevelToWebDriverLevel(Log::Level level) {
     35   const int index = level - Log::kDebug;
     36   CHECK_GE(index, 0);
     37   CHECK_LT(static_cast<size_t>(index), arraysize(kLogLevelToWebDriverLevels));
     38   return kLogLevelToWebDriverLevels[index];
     39 }
     40 
     41 // Returns WD wire protocol level name for a WebDriverLog::WebDriverLevel.
     42 std::string GetWebDriverLevelName(
     43     const WebDriverLog::WebDriverLevel level) {
     44   const int index = level - WebDriverLog::kWdAll;
     45   CHECK_GE(index, 0);
     46   CHECK_LT(static_cast<size_t>(index), arraysize(kWebDriverLevelNames));
     47   return kWebDriverLevelNames[index];
     48 }
     49 
     50 }  // namespace
     51 
     52 bool WebDriverLog::NameToLevel(
     53     const std::string& name, WebDriverLog::WebDriverLevel* out_level) {
     54   for (size_t i = 0; i < arraysize(kWebDriverLevelNames); ++i) {
     55     if (name == kWebDriverLevelNames[i]) {
     56       CHECK_LE(WebDriverLog::kWdAll + i,
     57                static_cast<size_t>(WebDriverLog::kWdOff));
     58       *out_level =
     59           static_cast<WebDriverLog::WebDriverLevel>(WebDriverLog::kWdAll + i);
     60       return true;
     61     }
     62   }
     63   return false;
     64 }
     65 
     66 WebDriverLog::WebDriverLog(
     67     const std::string& type, WebDriverLog::WebDriverLevel min_wd_level)
     68     : type_(type),
     69       min_wd_level_(min_wd_level),
     70       entries_(new base::ListValue()) {
     71   VLOG(1) << "Log(" << type_ << ", " << min_wd_level_ << ")";
     72 }
     73 
     74 WebDriverLog::~WebDriverLog() {
     75   VLOG(1) << "Log type '" << type_ << "' lost "
     76           << entries_->GetSize() << " entries on destruction";
     77 }
     78 
     79 const std::string& WebDriverLog::GetType() {
     80   return type_;
     81 }
     82 
     83 void WebDriverLog::AddEntryTimestamped(const base::Time& timestamp,
     84                                        Log::Level level,
     85                                        const std::string& message) {
     86   const WebDriverLog::WebDriverLevel wd_level = LogLevelToWebDriverLevel(level);
     87   if (wd_level < min_wd_level_)
     88     return;
     89   scoped_ptr<base::DictionaryValue> log_entry_dict(new base::DictionaryValue());
     90   log_entry_dict->SetDouble("timestamp",
     91                             static_cast<int64>(timestamp.ToJsTime()));
     92   log_entry_dict->SetString("level", GetWebDriverLevelName(wd_level));
     93   log_entry_dict->SetString("message", message);
     94   entries_->Append(log_entry_dict.release());
     95 }
     96 
     97 scoped_ptr<base::ListValue> WebDriverLog::GetAndClearEntries() {
     98   scoped_ptr<base::ListValue> ret(entries_.release());
     99   entries_.reset(new base::ListValue());
    100   return ret.Pass();
    101 }
    102 
    103 Status CreateLogs(const Capabilities& capabilities,
    104                   ScopedVector<WebDriverLog>* out_devtools_logs,
    105                   ScopedVector<DevToolsEventListener>* out_listeners) {
    106   ScopedVector<WebDriverLog> devtools_logs;
    107   ScopedVector<DevToolsEventListener> listeners;
    108   WebDriverLog::WebDriverLevel browser_log_level = WebDriverLog::kWdInfo;
    109 
    110   if (capabilities.logging_prefs) {
    111     for (DictionaryValue::Iterator pref(*capabilities.logging_prefs);
    112          !pref.IsAtEnd(); pref.Advance()) {
    113       const std::string type = pref.key();
    114       std::string level_name;
    115       if (!pref.value().GetAsString(&level_name)) {
    116         return Status(kUnknownError,
    117                       "logging level must be a string for log type: " + type);
    118       }
    119       WebDriverLog::WebDriverLevel level = WebDriverLog::kWdOff;
    120       if (!WebDriverLog::NameToLevel(level_name, &level)) {
    121         return Status(kUnknownError,
    122                       "invalid log level \"" + level_name +
    123                       "\" for type: " + type);
    124       }
    125       if ("performance" == type) {
    126         if (WebDriverLog::kWdOff != level) {
    127           WebDriverLog* log = new WebDriverLog(type, WebDriverLog::kWdAll);
    128           devtools_logs.push_back(log);
    129           listeners.push_back(new PerformanceLogger(log));
    130         }
    131       } else if ("browser" == type) {
    132         browser_log_level = level;
    133       } else {
    134         // Driver "should" ignore unrecognized log types, per Selenium tests.
    135         // For example the Java client passes the "client" log type in the caps,
    136         // which the server should never provide.
    137         LOG(WARNING) << "Ignoring unrecognized log type: LoggingPrefs." << type;
    138       }
    139     }
    140   }
    141   // Create "browser" log -- should always exist.
    142   WebDriverLog* browser_log = new WebDriverLog("browser", browser_log_level);
    143   devtools_logs.push_back(browser_log);
    144   // If the level is OFF, don't even bother listening for DevTools events.
    145   if (browser_log_level != WebDriverLog::kWdOff)
    146     listeners.push_back(new ConsoleLogger(browser_log));
    147 
    148   out_devtools_logs->swap(devtools_logs);
    149   out_listeners->swap(listeners);
    150   return Status(kOk);
    151 }
    152