summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-20 17:59:04 +0000
committerkkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-20 17:59:04 +0000
commit64b8c616b3750acc4fd22cb5e6682e389a73c46e (patch)
tree6b7a177e89ef07ea0dba0a3eb8f04a71442d3784
parente62768fec279649b786e1fe6f42a898cdc84914b (diff)
downloadchromium_src-64b8c616b3750acc4fd22cb5e6682e389a73c46e.zip
chromium_src-64b8c616b3750acc4fd22cb5e6682e389a73c46e.tar.gz
chromium_src-64b8c616b3750acc4fd22cb5e6682e389a73c46e.tar.bz2
Implement log command and prefs for chromedriver. Have separate logs per
session. Log every command by default. BUG=none TEST=none Review URL: http://codereview.chromium.org/8997019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@115147 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/chrome_tests.gypi2
-rw-r--r--chrome/test/webdriver/commands/command.cc2
-rw-r--r--chrome/test/webdriver/commands/command.h4
-rw-r--r--chrome/test/webdriver/commands/create_session.cc39
-rw-r--r--chrome/test/webdriver/commands/log_command.cc49
-rw-r--r--chrome/test/webdriver/commands/log_command.h36
-rw-r--r--chrome/test/webdriver/commands/response.cc10
-rw-r--r--chrome/test/webdriver/commands/response.h11
-rw-r--r--chrome/test/webdriver/commands/session_with_id.cc2
-rw-r--r--chrome/test/webdriver/commands/set_timeout_commands_unittest.cc7
-rw-r--r--chrome/test/webdriver/commands/url_command.cc1
-rw-r--r--chrome/test/webdriver/commands/webdriver_command.cc27
-rw-r--r--chrome/test/webdriver/commands/webdriver_command.h2
-rw-r--r--chrome/test/webdriver/webdriver_automation.cc19
-rw-r--r--chrome/test/webdriver/webdriver_automation.h4
-rw-r--r--chrome/test/webdriver/webdriver_capabilities_parser.cc104
-rw-r--r--chrome/test/webdriver/webdriver_capabilities_parser.h15
-rw-r--r--chrome/test/webdriver/webdriver_capabilities_parser_unittest.cc40
-rw-r--r--chrome/test/webdriver/webdriver_dispatch.cc4
-rw-r--r--chrome/test/webdriver/webdriver_dispatch.h4
-rw-r--r--chrome/test/webdriver/webdriver_element_id.cc1
-rw-r--r--chrome/test/webdriver/webdriver_key_converter.cc8
-rw-r--r--chrome/test/webdriver/webdriver_key_converter.h3
-rw-r--r--chrome/test/webdriver/webdriver_key_converter_unittest.cc16
-rw-r--r--chrome/test/webdriver/webdriver_logging.cc194
-rw-r--r--chrome/test/webdriver/webdriver_logging.h125
-rw-r--r--chrome/test/webdriver/webdriver_server.cc43
-rw-r--r--chrome/test/webdriver/webdriver_session.cc87
-rw-r--r--chrome/test/webdriver/webdriver_session.h51
29 files changed, 657 insertions, 253 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 24c5919..9a155b5 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -984,6 +984,8 @@
'test/webdriver/commands/execute_command.h',
'test/webdriver/commands/find_element_commands.cc',
'test/webdriver/commands/find_element_commands.h',
+ 'test/webdriver/commands/log_command.cc',
+ 'test/webdriver/commands/log_command.h',
'test/webdriver/commands/navigate_commands.cc',
'test/webdriver/commands/navigate_commands.h',
'test/webdriver/commands/mouse_commands.cc',
diff --git a/chrome/test/webdriver/commands/command.cc b/chrome/test/webdriver/commands/command.cc
index 3b1ea07..7f4686d 100644
--- a/chrome/test/webdriver/commands/command.cc
+++ b/chrome/test/webdriver/commands/command.cc
@@ -29,7 +29,7 @@ bool Command::Init(Response* const response) {
return true;
}
-void Command::Finish() {}
+void Command::Finish(Response* const response) {}
std::string Command::GetPathVariable(const size_t i) const {
return i < path_segments_.size() ? path_segments_.at(i) : "";
diff --git a/chrome/test/webdriver/commands/command.h b/chrome/test/webdriver/commands/command.h
index 94dee0f..97f0259 100644
--- a/chrome/test/webdriver/commands/command.h
+++ b/chrome/test/webdriver/commands/command.h
@@ -45,7 +45,7 @@ class Command {
// Called after this command is executed. Returns NULL if no error occurs.
// This is only called if |Init| is successful and regardless of whether
// the execution results in a |Error|.
- virtual void Finish();
+ virtual void Finish(Response* const response);
// Executes the corresponding variant of this command URL.
// Always called after |Init()| and called from the Execute function.
@@ -101,10 +101,10 @@ class Command {
// false if there is no such parameter, or if it is not a list.
bool GetListParameter(const std::string& key, ListValue** out) const;
- private:
const std::vector<std::string> path_segments_;
const scoped_ptr<const DictionaryValue> parameters_;
+ private:
#if defined(OS_MACOSX)
// An autorelease pool must exist on any thread where Objective C is used,
// even implicitly. Otherwise the warning:
diff --git a/chrome/test/webdriver/commands/create_session.cc b/chrome/test/webdriver/commands/create_session.cc
index 4f07f3a..7e80ec6 100644
--- a/chrome/test/webdriver/commands/create_session.cc
+++ b/chrome/test/webdriver/commands/create_session.cc
@@ -8,11 +8,9 @@
#include "base/command_line.h"
#include "base/file_path.h"
-#include "base/logging.h"
#include "base/scoped_temp_dir.h"
#include "base/values.h"
#include "chrome/test/webdriver/commands/response.h"
-#include "chrome/test/webdriver/webdriver_capabilities_parser.h"
#include "chrome/test/webdriver/webdriver_error.h"
#include "chrome/test/webdriver/webdriver_session.h"
#include "chrome/test/webdriver/webdriver_session_manager.h"
@@ -34,48 +32,15 @@ void CreateSession::ExecutePost(Response* const response) {
kBadRequest, "Missing or invalid 'desiredCapabilities'"));
return;
}
- ScopedTempDir temp_dir;
- if (!temp_dir.CreateUniqueTempDir()) {
- response->SetError(new Error(
- kUnknownError, "Unable to create temp directory for unpacking"));
- return;
- }
- Capabilities caps;
- CapabilitiesParser parser(dict, temp_dir.path(), &caps);
- Error* error = parser.Parse();
- if (error) {
- response->SetError(error);
- return;
- }
-
- // Since logging is shared among sessions, if any session requests verbose
- // logging, verbose logging will be enabled for all sessions. It is not
- // possible to turn it off.
- if (caps.verbose)
- logging::SetMinLogLevel(logging::LOG_INFO);
-
- Session::Options session_options;
- session_options.load_async = caps.load_async;
- session_options.use_native_events = caps.native_events;
- session_options.no_website_testing_defaults =
- caps.no_website_testing_defaults;
- session_options.extensions = caps.extensions;
-
- Automation::BrowserOptions browser_options;
- browser_options.command = caps.command;
- browser_options.channel_id = caps.channel;
- browser_options.detach_process = caps.detach;
- browser_options.user_data_dir = caps.profile;
// Session manages its own liftime, so do not call delete.
- Session* session = new Session(session_options);
- error = session->Init(browser_options);
+ Session* session = new Session();
+ Error* error = session->Init(dict);
if (error) {
response->SetError(error);
return;
}
- LOG(INFO) << "Created session " << session->id();
// Redirect to a relative URI. Although prohibited by the HTTP standard,
// this is what the IEDriver does. Finding the actual IP address is
// difficult, and returning the hostname causes perf problems with the python
diff --git a/chrome/test/webdriver/commands/log_command.cc b/chrome/test/webdriver/commands/log_command.cc
new file mode 100644
index 0000000..738a585
--- /dev/null
+++ b/chrome/test/webdriver/commands/log_command.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/test/webdriver/commands/log_command.h"
+
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chrome/test/webdriver/commands/response.h"
+#include "chrome/test/webdriver/webdriver_error.h"
+#include "chrome/test/webdriver/webdriver_session.h"
+
+namespace webdriver {
+
+LogCommand::LogCommand(
+ const std::vector<std::string>& path_segments,
+ DictionaryValue* parameters)
+ : WebDriverCommand(path_segments, parameters) {
+}
+
+LogCommand::~LogCommand() {
+}
+
+bool LogCommand::DoesPost() {
+ return true;
+}
+
+void LogCommand::ExecutePost(Response* const response) {
+ std::string type;
+ if (!GetStringParameter("type", &type)) {
+ response->SetError(new Error(kUnknownError, "Missing or invalid 'type'"));
+ return;
+ }
+
+ LogType log_type;
+ if (!LogType::FromString(type, &log_type)) {
+ response->SetError(new Error(kUnknownError, "Unknown log type: " + type));
+ return;
+ }
+
+ if (log_type.type() == LogType::kDriver) {
+ response->SetValue(session_->GetLog());
+ } else {
+ response->SetError(new Error(kUnknownError, "Unrecognized type: " + type));
+ return;
+ }
+}
+
+} // namespace webdriver
diff --git a/chrome/test/webdriver/commands/log_command.h b/chrome/test/webdriver/commands/log_command.h
new file mode 100644
index 0000000..e9ce310
--- /dev/null
+++ b/chrome/test/webdriver/commands/log_command.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_TEST_WEBDRIVER_COMMANDS_LOG_COMMAND_H_
+#define CHROME_TEST_WEBDRIVER_COMMANDS_LOG_COMMAND_H_
+
+#include <string>
+#include <vector>
+
+#include "chrome/test/webdriver/commands/webdriver_command.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace webdriver {
+
+class Response;
+
+class LogCommand : public WebDriverCommand {
+ public:
+ LogCommand(const std::vector<std::string>& path_segments,
+ base::DictionaryValue* parameters);
+ virtual ~LogCommand();
+
+ virtual bool DoesPost() OVERRIDE;
+ virtual void ExecutePost(Response* const response) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LogCommand);
+};
+
+} // namespace webdriver
+
+#endif // CHROME_TEST_WEBDRIVER_COMMANDS_LOG_COMMAND_H_
diff --git a/chrome/test/webdriver/commands/response.cc b/chrome/test/webdriver/commands/response.cc
index 7239f71..bef1386 100644
--- a/chrome/test/webdriver/commands/response.cc
+++ b/chrome/test/webdriver/commands/response.cc
@@ -9,6 +9,9 @@
#include "base/logging.h"
#include "base/values.h"
+using base::DictionaryValue;
+using base::Value;
+
namespace webdriver {
namespace {
@@ -41,8 +44,7 @@ void Response::SetStatus(ErrorCode status) {
const Value* Response::GetValue() const {
Value* out = NULL;
- LOG_IF(WARNING, !data_.Get(kValueKey, &out))
- << "Accessing unset response value."; // Should never happen.
+ data_.Get(kValueKey, &out);
return out;
}
@@ -63,6 +65,10 @@ void Response::SetField(const std::string& key, Value* value) {
data_.Set(key, value);
}
+const Value* Response::GetDictionary() const {
+ return &data_;
+}
+
std::string Response::ToJSON() const {
std::string json;
base::JSONWriter::Write(&data_, false, &json);
diff --git a/chrome/test/webdriver/commands/response.h b/chrome/test/webdriver/commands/response.h
index 9c44e60..3545081 100644
--- a/chrome/test/webdriver/commands/response.h
+++ b/chrome/test/webdriver/commands/response.h
@@ -28,11 +28,11 @@ class Response {
void SetStatus(ErrorCode status);
// Ownership of the returned pointer is kept by this object.
- const Value* GetValue() const;
+ const base::Value* GetValue() const;
// Sets the |value| of this response, assuming ownership of the object in the
// process.
- void SetValue(Value* value);
+ void SetValue(base::Value* value);
// Configures this response to report the given error. Ownership of the error
// is taken from the caller.
@@ -42,13 +42,16 @@ class Response {
// string to indicate the value should be set in a nested object. Any
// previously set value for the |key| will be deleted.
// This object assumes ownership of |value|.
- void SetField(const std::string& key, Value* value);
+ void SetField(const std::string& key, base::Value* value);
+
+ // Returns a pointer to the actual response dictionary.
+ const base::Value* GetDictionary() const;
// Returns this response as a JSON string.
std::string ToJSON() const;
private:
- DictionaryValue data_;
+ base::DictionaryValue data_;
DISALLOW_COPY_AND_ASSIGN(Response);
};
diff --git a/chrome/test/webdriver/commands/session_with_id.cc b/chrome/test/webdriver/commands/session_with_id.cc
index 3148fa0..d14236b 100644
--- a/chrome/test/webdriver/commands/session_with_id.cc
+++ b/chrome/test/webdriver/commands/session_with_id.cc
@@ -70,7 +70,7 @@ void SessionWithID::ExecuteGet(Response* const response) {
Value::CreateStringValue(chrome::kChromeVersion));
temp_value->SetWithoutPathExpansion(
"chrome.nativeEvents",
- Value::CreateBooleanValue(session_->options().use_native_events));
+ Value::CreateBooleanValue(session_->capabilities().native_events));
response->SetValue(temp_value);
}
diff --git a/chrome/test/webdriver/commands/set_timeout_commands_unittest.cc b/chrome/test/webdriver/commands/set_timeout_commands_unittest.cc
index ff8f5ac..748738e 100644
--- a/chrome/test/webdriver/commands/set_timeout_commands_unittest.cc
+++ b/chrome/test/webdriver/commands/set_timeout_commands_unittest.cc
@@ -50,8 +50,7 @@ void AssertTimeoutSet(const Session& test_session, int expected_timeout,
} // namespace
TEST(ImplicitWaitCommandTest, SettingImplicitWaits) {
- Session::Options options = Session::Options();
- Session test_session(options);
+ Session test_session;
ASSERT_EQ(0, test_session.implicit_wait()) << "Sanity check failed";
std::vector<std::string> path_segments;
@@ -75,10 +74,10 @@ TEST(ImplicitWaitCommandTest, SettingImplicitWaits) {
AssertError(kBadRequest, "ms parameter is not a number", &command);
parameters->SetInteger("ms", -1);
- AssertError(kBadRequest, "timeout must be non-negative: -1", &command);
+ AssertError(kBadRequest, "Timeout must be non-negative", &command);
parameters->SetDouble("ms", -3.0);
- AssertError(kBadRequest, "timeout must be non-negative: -3", &command);
+ AssertError(kBadRequest, "Timeout must be non-negative", &command);
parameters->SetInteger("ms", 1);
AssertTimeoutSet(test_session, 1, &command);
diff --git a/chrome/test/webdriver/commands/url_command.cc b/chrome/test/webdriver/commands/url_command.cc
index 05a138a..f66494c 100644
--- a/chrome/test/webdriver/commands/url_command.cc
+++ b/chrome/test/webdriver/commands/url_command.cc
@@ -49,7 +49,6 @@ void URLCommand::ExecutePost(Response* const response) {
response->SetError(error);
return;
}
- response->SetValue(new StringValue(url));
}
diff --git a/chrome/test/webdriver/commands/webdriver_command.cc b/chrome/test/webdriver/commands/webdriver_command.cc
index 7d626f6..3fb9e41 100644
--- a/chrome/test/webdriver/commands/webdriver_command.cc
+++ b/chrome/test/webdriver/commands/webdriver_command.cc
@@ -6,14 +6,17 @@
#include <string>
-#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
#include "base/values.h"
#include "chrome/test/webdriver/commands/response.h"
#include "chrome/test/webdriver/webdriver_error.h"
+#include "chrome/test/webdriver/webdriver_logging.h"
#include "chrome/test/webdriver/webdriver_session.h"
#include "chrome/test/webdriver/webdriver_session_manager.h"
+#include "chrome/test/webdriver/webdriver_util.h"
namespace webdriver {
@@ -41,6 +44,12 @@ bool WebDriverCommand::Init(Response* const response) {
return false;
}
+ std::string message = base::StringPrintf(
+ "Command received (%s)", JoinString(path_segments_, '/').c_str());
+ if (parameters_.get())
+ message += " with params " + JsonStringifyForDisplay(parameters_.get());
+ session_->logger().Log(kFineLogLevel, message);
+
if (ShouldRunPreAndPostCommandHandlers()) {
Error* error = session_->BeforeExecuteCommand();
if (error) {
@@ -52,17 +61,27 @@ bool WebDriverCommand::Init(Response* const response) {
return true;
}
-void WebDriverCommand::Finish() {
+void WebDriverCommand::Finish(Response* const response) {
// The session may have been terminated as a result of the command.
if (!SessionManager::GetInstance()->Has(session_id_))
return;
+
if (ShouldRunPreAndPostCommandHandlers()) {
scoped_ptr<Error> error(session_->AfterExecuteCommand());
if (error.get()) {
- LOG(WARNING) << "Command did not finish successfully: "
- << error->details();
+ session_->logger().Log(kWarningLogLevel,
+ "AfterExecuteCommand failed: " + error->details());
}
}
+
+ LogLevel level = kWarningLogLevel;
+ if (response->GetStatus() == kSuccess)
+ level = kFineLogLevel;
+ session_->logger().Log(
+ level, base::StringPrintf(
+ "Command finished (%s) with response %s",
+ JoinString(path_segments_, '/').c_str(),
+ JsonStringifyForDisplay(response->GetDictionary()).c_str()));
}
bool WebDriverCommand::ShouldRunPreAndPostCommandHandlers() {
diff --git a/chrome/test/webdriver/commands/webdriver_command.h b/chrome/test/webdriver/commands/webdriver_command.h
index bbef57b..56ba60f 100644
--- a/chrome/test/webdriver/commands/webdriver_command.h
+++ b/chrome/test/webdriver/commands/webdriver_command.h
@@ -34,7 +34,7 @@ class WebDriverCommand : public Command {
// Initializes this webdriver command by fetching the command session.
virtual bool Init(Response* const response) OVERRIDE;
- virtual void Finish() OVERRIDE;
+ virtual void Finish(Response* const response) OVERRIDE;
// Returns whether this command should run the session pre and post
// command handlers. These handlers include waiting for the page to load.
diff --git a/chrome/test/webdriver/webdriver_automation.cc b/chrome/test/webdriver/webdriver_automation.cc
index 80e25c5..787c4e6 100644
--- a/chrome/test/webdriver/webdriver_automation.cc
+++ b/chrome/test/webdriver/webdriver_automation.cc
@@ -15,7 +15,6 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/json/json_writer.h"
-#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
@@ -190,7 +189,7 @@ Automation::BrowserOptions::BrowserOptions()
Automation::BrowserOptions::~BrowserOptions() {}
-Automation::Automation() {}
+Automation::Automation(const Logger& logger) : logger_(logger) {}
Automation::~Automation() {}
@@ -229,7 +228,6 @@ void Automation::Init(const BrowserOptions& options, Error** error) {
std::string chrome_details = base::StringPrintf(
"Using Chrome binary at: %" PRFilePath,
command.GetProgram().value().c_str());
- LOG(INFO) << chrome_details;
// Create the ProxyLauncher and launch Chrome.
// In Chrome 13/14, the only way to detach the browser process is to use a
@@ -257,9 +255,16 @@ void Automation::Init(const BrowserOptions& options, Error** error) {
#endif
}
if (channel_id.empty()) {
+ std::string command_line_str;
+#if defined(OS_WIN)
+ command_line_str = WideToUTF8(command.GetCommandLineString());
+#elif defined(OS_POSIX)
+ command_line_str = command.GetCommandLineString();
+#endif
+ logger_.Log(kInfoLogLevel, "Launching chrome: " + command_line_str);
launcher_.reset(new AnonymousProxyLauncher(false));
} else {
- LOG(INFO) << "Using named testing interface";
+ logger_.Log(kInfoLogLevel, "Using named testing interface");
launcher_.reset(new NamedProxyLauncher(channel_id, launch_browser, false));
}
ProxyLauncher::LaunchState launch_props = {
@@ -271,7 +276,7 @@ void Automation::Init(const BrowserOptions& options, Error** error) {
true // show_window
};
if (!launcher_->InitializeConnection(launch_props, true)) {
- LOG(ERROR) << "Failed to initialize connection";
+ logger_.Log(kSevereLogLevel, "Failed to initialize connection");
*error = new Error(
kUnknownError,
"Unable to either launch or connect to Chrome. Please check that "
@@ -280,8 +285,8 @@ void Automation::Init(const BrowserOptions& options, Error** error) {
}
launcher_->automation()->set_action_timeout_ms(base::kNoTimeout);
- LOG(INFO) << "Chrome launched successfully. Version: "
- << automation()->server_version();
+ logger_.Log(kInfoLogLevel, "Connected to Chrome successfully. Version: " +
+ automation()->server_version());
// Check the version of Chrome is compatible with this ChromeDriver.
chrome_details += ", version (" + automation()->server_version() + ")";
diff --git a/chrome/test/webdriver/webdriver_automation.h b/chrome/test/webdriver/webdriver_automation.h
index 0328871..9b2036c 100644
--- a/chrome/test/webdriver/webdriver_automation.h
+++ b/chrome/test/webdriver/webdriver_automation.h
@@ -15,6 +15,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/task.h"
#include "chrome/common/automation_constants.h"
+#include "chrome/test/webdriver/webdriver_logging.h"
#include "ui/base/keycodes/keyboard_codes.h"
class AutomationId;
@@ -65,7 +66,7 @@ class Automation {
bool detach_process;
};
- Automation();
+ explicit Automation(const Logger& logger);
virtual ~Automation();
// Start the system's default Chrome binary.
@@ -232,6 +233,7 @@ class Automation {
Error* CheckAdvancedInteractionsSupported();
Error* CheckNewExtensionInterfaceSupported();
+ const Logger& logger_;
scoped_ptr<ProxyLauncher> launcher_;
DISALLOW_COPY_AND_ASSIGN(Automation);
diff --git a/chrome/test/webdriver/webdriver_capabilities_parser.cc b/chrome/test/webdriver/webdriver_capabilities_parser.cc
index 9ac398a..b9555ab 100644
--- a/chrome/test/webdriver/webdriver_capabilities_parser.cc
+++ b/chrome/test/webdriver/webdriver_capabilities_parser.cc
@@ -7,7 +7,6 @@
#include "base/base64.h"
#include "base/file_util.h"
#include "base/format_macros.h"
-#include "base/logging.h"
#include "base/stringprintf.h"
#include "base/string_util.h"
#include "base/values.h"
@@ -16,6 +15,7 @@
#include "chrome/test/webdriver/webdriver_error.h"
#include "chrome/test/webdriver/webdriver_util.h"
+using base::DictionaryValue;
using base::Value;
namespace webdriver {
@@ -39,39 +39,49 @@ Capabilities::Capabilities()
detach(false),
load_async(false),
native_events(false),
- no_website_testing_defaults(false),
- verbose(false) { }
+ no_website_testing_defaults(false) {
+ log_levels[LogType::kDriver] = kAllLogLevel;
+}
Capabilities::~Capabilities() { }
CapabilitiesParser::CapabilitiesParser(
- const base::DictionaryValue* capabilities_dict,
+ const DictionaryValue* capabilities_dict,
const FilePath& root_path,
+ const Logger& logger,
Capabilities* capabilities)
: dict_(capabilities_dict),
root_(root_path),
+ logger_(logger),
caps_(capabilities) {
}
CapabilitiesParser::~CapabilitiesParser() { }
Error* CapabilitiesParser::Parse() {
- // Parse WebDriver proxy capabilities first.
- const char kProxyKey[] = "proxy";
- Value* proxy_options_value;
- if (dict_->Get(kProxyKey, &proxy_options_value)) {
- const base::DictionaryValue* proxy_options;
- if (!proxy_options_value->GetAsDictionary(&proxy_options)) {
- return CreateBadInputError(
- kProxyKey, Value::TYPE_DICTIONARY, proxy_options_value);
+ // Parse WebDriver standard capabilities.
+ typedef Error* (CapabilitiesParser::*Parser)(const Value*);
+
+ struct NameAndParser {
+ const char* name;
+ Parser parser;
+ };
+ NameAndParser name_and_parser[] = {
+ { "proxy", &CapabilitiesParser::ParseProxy },
+ { "loggingPrefs", &CapabilitiesParser::ParseLoggingPrefs }
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(name_and_parser); ++i) {
+ Value* value;
+ if (dict_->Get(name_and_parser[i].name, &value)) {
+ Error* error = (this->*name_and_parser[i].parser)(value);
+ if (error)
+ return error;
}
- Error* error = ParseProxyCapabilities(proxy_options);
- if (error)
- return error;
}
+ // Parse Chrome custom capabilities (a.k.a., ChromeOptions).
const char kOptionsKey[] = "chromeOptions";
- const base::DictionaryValue* options = dict_;
+ const DictionaryValue* options = dict_;
bool legacy_options = true;
Value* options_value;
if (dict_->Get(kOptionsKey, &options_value)) {
@@ -84,7 +94,6 @@ Error* CapabilitiesParser::Parse() {
}
}
- typedef Error* (CapabilitiesParser::*Parser)(const Value*);
std::map<std::string, Parser> parser_map;
if (legacy_options) {
parser_map["chrome.binary"] = &CapabilitiesParser::ParseBinary;
@@ -97,7 +106,6 @@ Error* CapabilitiesParser::Parse() {
parser_map["chrome.switches"] = &CapabilitiesParser::ParseArgs;
parser_map["chrome.noWebsiteTestingDefaults"] =
&CapabilitiesParser::ParseNoWebsiteTestingDefaults;
- parser_map["chrome.verbose"] = &CapabilitiesParser::ParseVerbose;
} else {
parser_map["args"] = &CapabilitiesParser::ParseArgs;
parser_map["binary"] = &CapabilitiesParser::ParseBinary;
@@ -109,10 +117,9 @@ Error* CapabilitiesParser::Parse() {
parser_map["profile"] = &CapabilitiesParser::ParseProfile;
parser_map["noWebsiteTestingDefaults"] =
&CapabilitiesParser::ParseNoWebsiteTestingDefaults;
- parser_map["verbose"] = &CapabilitiesParser::ParseVerbose;
}
- base::DictionaryValue::key_iterator key_iter = options->begin_keys();
+ DictionaryValue::key_iterator key_iter = options->begin_keys();
for (; key_iter != options->end_keys(); ++key_iter) {
if (parser_map.find(*key_iter) == parser_map.end()) {
if (!legacy_options)
@@ -207,6 +214,31 @@ Error* CapabilitiesParser::ParseLoadAsync(const Value* option) {
return NULL;
}
+Error* CapabilitiesParser::ParseLoggingPrefs(const base::Value* option) {
+ const DictionaryValue* logging_prefs;
+ if (!option->GetAsDictionary(&logging_prefs))
+ return CreateBadInputError("loggingPrefs", Value::TYPE_DICTIONARY, option);
+
+ DictionaryValue::key_iterator key_iter = logging_prefs->begin_keys();
+ for (; key_iter != logging_prefs->end_keys(); ++key_iter) {
+ LogType log_type;
+ if (!LogType::FromString(*key_iter, &log_type))
+ continue;
+
+ Value* level_value;
+ logging_prefs->Get(*key_iter, &level_value);
+ int level;
+ if (!level_value->GetAsInteger(&level)) {
+ return CreateBadInputError(
+ std::string("loggingPrefs.") + *key_iter,
+ Value::TYPE_INTEGER,
+ level_value);
+ }
+ caps_->log_levels[log_type.type()] = static_cast<LogLevel>(level);
+ }
+ return NULL;
+}
+
Error* CapabilitiesParser::ParseNativeEvents(const Value* option) {
if (!option->GetAsBoolean(&caps_->native_events))
return CreateBadInputError("nativeEvents", Value::TYPE_BOOLEAN, option);
@@ -225,8 +257,11 @@ Error* CapabilitiesParser::ParseProfile(const Value* option) {
return NULL;
}
-Error* CapabilitiesParser::ParseProxyCapabilities(
- const base::DictionaryValue* options) {
+Error* CapabilitiesParser::ParseProxy(const base::Value* option) {
+ const DictionaryValue* options;
+ if (!option->GetAsDictionary(&options))
+ return CreateBadInputError("proxy", Value::TYPE_DICTIONARY, option);
+
// Quick check of proxy capabilities.
std::set<std::string> proxy_options;
proxy_options.insert("autodetect");
@@ -238,10 +273,10 @@ Error* CapabilitiesParser::ParseProxyCapabilities(
proxy_options.insert("sslProxy");
proxy_options.insert("class"); // Created by BeanToJSONConverter.
- base::DictionaryValue::key_iterator key_iter = options->begin_keys();
+ DictionaryValue::key_iterator key_iter = options->begin_keys();
for (; key_iter != options->end_keys(); ++key_iter) {
if (proxy_options.find(*key_iter) == proxy_options.end()) {
- LOG(WARNING) << "Unrecognized proxy capability: " << *key_iter;
+ logger_.Log(kInfoLogLevel, "Unrecognized proxy capability: " + *key_iter);
}
}
@@ -255,13 +290,14 @@ Error* CapabilitiesParser::ParseProxyCapabilities(
proxy_type_parser_map["direct"] = NULL;
proxy_type_parser_map["system"] = NULL;
- Value* option;
- if (!options->Get("proxyType", &option))
+ Value* proxy_type_value;
+ if (!options->Get("proxyType", &proxy_type_value))
return new Error(kBadRequest, "Missing 'proxyType' capability.");
std::string proxy_type;
- if (!option->GetAsString(&proxy_type))
- return CreateBadInputError("proxyType", Value::TYPE_STRING, option);
+ if (!proxy_type_value->GetAsString(&proxy_type))
+ return CreateBadInputError("proxyType", Value::TYPE_STRING,
+ proxy_type_value);
proxy_type = StringToLowerASCII(proxy_type);
if (proxy_type_parser_map.find(proxy_type) == proxy_type_parser_map.end())
@@ -283,7 +319,7 @@ Error* CapabilitiesParser::ParseProxyCapabilities(
}
Error* CapabilitiesParser::ParseProxyAutoDetect(
- const base::DictionaryValue* options){
+ const DictionaryValue* options){
const char kProxyAutoDetectKey[] = "autodetect";
bool proxy_auto_detect = false;
if (!options->GetBoolean(kProxyAutoDetectKey, &proxy_auto_detect))
@@ -295,7 +331,7 @@ Error* CapabilitiesParser::ParseProxyAutoDetect(
}
Error* CapabilitiesParser::ParseProxyAutoconfigUrl(
- const base::DictionaryValue* options){
+ const DictionaryValue* options){
const char kProxyAutoconfigUrlKey[] = "proxyAutoconfigUrl";
CommandLine::StringType proxy_pac_url;
if (!options->GetString(kProxyAutoconfigUrlKey, &proxy_pac_url))
@@ -306,7 +342,7 @@ Error* CapabilitiesParser::ParseProxyAutoconfigUrl(
}
Error* CapabilitiesParser::ParseProxyServers(
- const base::DictionaryValue* options) {
+ const DictionaryValue* options) {
const char kNoProxy[] = "noProxy";
const char kFtpProxy[] = "ftpProxy";
const char kHttpProxy[] = "httpProxy";
@@ -374,12 +410,6 @@ Error* CapabilitiesParser::ParseNoWebsiteTestingDefaults(const Value* option) {
return NULL;
}
-Error* CapabilitiesParser::ParseVerbose(const Value* option) {
- if (!option->GetAsBoolean(&caps_->verbose))
- return CreateBadInputError("verbose", Value::TYPE_BOOLEAN, option);
- return NULL;
-}
-
bool CapabilitiesParser::DecodeAndWriteFile(
const FilePath& path,
const std::string& base64,
diff --git a/chrome/test/webdriver/webdriver_capabilities_parser.h b/chrome/test/webdriver/webdriver_capabilities_parser.h
index 861bcdd..c292512 100644
--- a/chrome/test/webdriver/webdriver_capabilities_parser.h
+++ b/chrome/test/webdriver/webdriver_capabilities_parser.h
@@ -12,6 +12,7 @@
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/file_path.h"
+#include "chrome/test/webdriver/webdriver_logging.h"
namespace base {
class DictionaryValue;
@@ -45,6 +46,9 @@ struct Capabilities {
// Whether Chrome should not block when loading.
bool load_async;
+ // The minimum level to log for each log type.
+ LogLevel log_levels[LogType::kNum];
+
// Whether Chrome should simulate input events using OS APIs instead of
// WebKit APIs.
bool native_events;
@@ -58,9 +62,6 @@ struct Capabilities {
// Path to a custom profile to use.
FilePath profile;
-
- // Whether ChromeDriver should log verbosely.
- bool verbose;
};
// Parses the given capabilities dictionary to produce a |Capabilities|
@@ -75,6 +76,7 @@ class CapabilitiesParser {
// this directory.
CapabilitiesParser(const base::DictionaryValue* capabilities_dict,
const FilePath& root_path,
+ const Logger& logger,
Capabilities* capabilities);
~CapabilitiesParser();
@@ -88,15 +90,15 @@ class CapabilitiesParser {
Error* ParseDetach(const base::Value* option);
Error* ParseExtensions(const base::Value* option);
Error* ParseLoadAsync(const base::Value* option);
+ Error* ParseLoggingPrefs(const base::Value* option);
Error* ParseNativeEvents(const base::Value* option);
Error* ParseNoProxy(const base::Value* option);
Error* ParseProfile(const base::Value* option);
+ Error* ParseProxy(const base::Value* option);
Error* ParseProxyAutoDetect(const base::DictionaryValue* options);
Error* ParseProxyAutoconfigUrl(const base::DictionaryValue* options);
- Error* ParseProxyCapabilities(const base::DictionaryValue* options);
Error* ParseProxyServers(const base::DictionaryValue* options);
Error* ParseNoWebsiteTestingDefaults(const base::Value* option);
- Error* ParseVerbose(const base::Value* option);
// Decodes the given base64-encoded string, optionally unzips it, and
// writes the result to |path|.
// On error, false will be returned and |error_msg| will be set.
@@ -111,6 +113,9 @@ class CapabilitiesParser {
// The root directory under which to write all files.
const FilePath root_;
+ // Reference to the logger to use.
+ const Logger& logger_;
+
// A pointer to the capabilities to modify while parsing.
Capabilities* caps_;
diff --git a/chrome/test/webdriver/webdriver_capabilities_parser_unittest.cc b/chrome/test/webdriver/webdriver_capabilities_parser_unittest.cc
index 12ae069..085c0b9 100644
--- a/chrome/test/webdriver/webdriver_capabilities_parser_unittest.cc
+++ b/chrome/test/webdriver/webdriver_capabilities_parser_unittest.cc
@@ -21,7 +21,7 @@ namespace webdriver {
TEST(CapabilitiesParser, NoCaps) {
Capabilities caps;
DictionaryValue dict;
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
}
@@ -35,19 +35,17 @@ TEST(CapabilitiesParser, SimpleCaps) {
options->SetBoolean("detach", true);
options->SetBoolean("loadAsync", true);
options->SetBoolean("nativeEvents", true);
- options->SetBoolean("verbose", true);
Capabilities caps;
ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- CapabilitiesParser parser(&dict, temp_dir.path(), &caps);
+ CapabilitiesParser parser(&dict, temp_dir.path(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
EXPECT_EQ(FILE_PATH_LITERAL("binary"), caps.command.GetProgram().value());
EXPECT_STREQ("channel", caps.channel.c_str());
EXPECT_TRUE(caps.detach);
EXPECT_TRUE(caps.load_async);
EXPECT_TRUE(caps.native_events);
- EXPECT_TRUE(caps.verbose);
}
TEST(CapabilitiesParser, Args) {
@@ -64,7 +62,7 @@ TEST(CapabilitiesParser, Args) {
Capabilities caps;
ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- CapabilitiesParser parser(&dict, temp_dir.path(), &caps);
+ CapabilitiesParser parser(&dict, temp_dir.path(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
EXPECT_TRUE(caps.command.HasSwitch("arg1"));
EXPECT_STREQ("val", caps.command.GetSwitchValueASCII("arg2").c_str());
@@ -84,7 +82,7 @@ TEST(CapabilitiesParser, Extensions) {
Capabilities caps;
ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- CapabilitiesParser parser(&dict, temp_dir.path(), &caps);
+ CapabilitiesParser parser(&dict, temp_dir.path(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
ASSERT_EQ(2u, caps.extensions.size());
std::string contents;
@@ -115,7 +113,7 @@ TEST(CapabilitiesParser, Profile) {
options->SetString("profile", base64);
Capabilities caps;
- CapabilitiesParser parser(&dict, temp_dir.path(), &caps);
+ CapabilitiesParser parser(&dict, temp_dir.path(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
std::string new_contents;
ASSERT_TRUE(file_util::ReadFileToString(
@@ -127,15 +125,7 @@ TEST(CapabilitiesParser, UnknownCap) {
Capabilities caps;
DictionaryValue dict;
dict.SetString("chromeOptions.nosuchcap", "none");
- CapabilitiesParser parser(&dict, FilePath(), &caps);
- ASSERT_TRUE(parser.Parse());
-}
-
-TEST(CapabilitiesParser, BadInput) {
- Capabilities caps;
- DictionaryValue dict;
- dict.SetString("chromeOptions.verbose", "false");
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_TRUE(parser.Parse());
}
@@ -149,7 +139,7 @@ TEST(CapabilitiesParser, ProxyCap) {
options->SetString("proxyType", "PAC");
options->SetString("proxyAutoconfigUrl", kPacUrl);
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
EXPECT_STREQ(kPacUrl,
caps.command.GetSwitchValueASCII(switches::kProxyPacUrl).c_str());
@@ -164,7 +154,7 @@ TEST(CapabilitiesParser, ProxyTypeCapIncompatiblePac) {
options->SetString("proxyType", "pac");
options->SetString("httpProxy", "http://localhost:8001");
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_TRUE(parser.Parse());
}
@@ -176,7 +166,7 @@ TEST(CapabilitiesParser, ProxyTypeCapIncompatibleManual) {
options->SetString("proxyType", "manual");
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_TRUE(parser.Parse());
}
@@ -188,7 +178,7 @@ TEST(CapabilitiesParser, ProxyTypeCapNullValue) {
options->Set("proxyType", Value::CreateNullValue());
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_TRUE(parser.Parse());
}
@@ -203,7 +193,7 @@ TEST(CapabilitiesParser, ProxyTypeManualCap) {
options->SetString("httpProxy", "localhost:8001");
options->SetString("ftpProxy", "localhost:9001");
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
EXPECT_STREQ(kProxyServers,
caps.command.GetSwitchValueASCII(switches::kProxyServer).c_str());
@@ -219,7 +209,7 @@ TEST(CapabilitiesParser, ProxyBypassListCap) {
options->SetString("proxyType", "manual");
options->SetString("noProxy", kBypassList);
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
EXPECT_STREQ(kBypassList,
caps.command.GetSwitchValueASCII(switches::kProxyBypassList).c_str());
@@ -235,7 +225,7 @@ TEST(CapabilitiesParser, ProxyBypassListCapNullValue) {
options->Set("noProxy", Value::CreateNullValue());
options->SetString("httpProxy", "localhost:8001");
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
EXPECT_FALSE(caps.command.HasSwitch(switches::kProxyBypassList));
}
@@ -249,7 +239,7 @@ TEST(CapabilitiesParser, UnknownProxyCap) {
options->SetString("proxyType", "DIRECT");
options->SetString("badProxyCap", "error");
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
}
@@ -263,7 +253,7 @@ TEST(CapabilitiesParser, ProxyFtpServerCapNullValue) {
options->SetString("httpProxy", "localhost:8001");
options->Set("ftpProxy", Value::CreateNullValue());
- CapabilitiesParser parser(&dict, FilePath(), &caps);
+ CapabilitiesParser parser(&dict, FilePath(), Logger(), &caps);
ASSERT_FALSE(parser.Parse());
EXPECT_STREQ("http=localhost:8001",
caps.command.GetSwitchValueASCII(switches::kProxyServer).c_str());
diff --git a/chrome/test/webdriver/webdriver_dispatch.cc b/chrome/test/webdriver/webdriver_dispatch.cc
index 42299a9..aa925ac 100644
--- a/chrome/test/webdriver/webdriver_dispatch.cc
+++ b/chrome/test/webdriver/webdriver_dispatch.cc
@@ -82,7 +82,7 @@ void DispatchCommand(Command* const command,
} else {
NOTREACHED();
}
- command->Finish();
+ command->Finish(response);
}
void SendOkWithBody(struct mg_connection* connection,
@@ -114,7 +114,7 @@ void SendLog(struct mg_connection* connection,
const struct mg_request_info* request_info,
void* user_data) {
std::string content, log;
- if (GetLogContents(&log)) {
+ if (FileLog::Get()->GetLogContents(&log)) {
content = "START ChromeDriver log";
const size_t kMaxSizeWithoutHeaders = kMaxHttpMessageSize - 10000;
if (log.size() > kMaxSizeWithoutHeaders) {
diff --git a/chrome/test/webdriver/webdriver_dispatch.h b/chrome/test/webdriver/webdriver_dispatch.h
index a0cb40a..5480cde 100644
--- a/chrome/test/webdriver/webdriver_dispatch.h
+++ b/chrome/test/webdriver/webdriver_dispatch.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/basictypes.h"
-#include "base/logging.h"
#include "chrome/test/webdriver/commands/response.h"
#include "third_party/mongoose/mongoose.h"
@@ -95,8 +94,6 @@ void Dispatch(struct mg_connection* connection,
&path_segments,
&parameters,
&response)) {
- LOG(INFO) << "Received command, url: " << request_info->uri
- << ", method: " << request_info->request_method;
internal::DispatchHelper(
new CommandType(path_segments, parameters),
method,
@@ -105,7 +102,6 @@ void Dispatch(struct mg_connection* connection,
internal::SendResponse(connection,
request_info->request_method,
response);
- LOG(INFO) << "Sent command response, url: " << request_info->uri;
}
class Dispatcher {
diff --git a/chrome/test/webdriver/webdriver_element_id.cc b/chrome/test/webdriver/webdriver_element_id.cc
index d618c07..db24d1d 100644
--- a/chrome/test/webdriver/webdriver_element_id.cc
+++ b/chrome/test/webdriver/webdriver_element_id.cc
@@ -4,7 +4,6 @@
#include "chrome/test/webdriver/webdriver_element_id.h"
-#include "base/logging.h"
#include "base/values.h"
#include "chrome/test/automation/javascript_message_utils.h"
diff --git a/chrome/test/webdriver/webdriver_key_converter.cc b/chrome/test/webdriver/webdriver_key_converter.cc
index 33f9f390..53ee4ed 100644
--- a/chrome/test/webdriver/webdriver_key_converter.cc
+++ b/chrome/test/webdriver/webdriver_key_converter.cc
@@ -10,6 +10,7 @@
#include "chrome/common/automation_constants.h"
#include "chrome/test/automation/automation_json_requests.h"
#include "chrome/test/webdriver/keycode_text_conversion.h"
+#include "chrome/test/webdriver/webdriver_logging.h"
namespace {
@@ -178,6 +179,7 @@ WebKeyEvent CreateCharEvent(const std::string& unmodified_text,
}
bool ConvertKeysToWebKeyEvents(const string16& client_keys,
+ const Logger& logger,
std::vector<WebKeyEvent>* client_key_events,
std::string* error_msg) {
std::vector<WebKeyEvent> key_events;
@@ -268,8 +270,10 @@ bool ConvertKeysToWebKeyEvents(const string16& client_keys,
}
if (unmodified_text.empty() || modified_text.empty()) {
// Do a best effort and use the raw key we were given.
- LOG(WARNING) << "No translation for key code. Code point: "
- << static_cast<int>(key);
+ logger.Log(
+ kWarningLogLevel,
+ base::StringPrintf("No translation for key code. Code point: %d",
+ static_cast<int>(key)));
if (unmodified_text.empty())
unmodified_text = UTF16ToUTF8(keys.substr(i, 1));
if (modified_text.empty())
diff --git a/chrome/test/webdriver/webdriver_key_converter.h b/chrome/test/webdriver/webdriver_key_converter.h
index 940ec43..410fa96 100644
--- a/chrome/test/webdriver/webdriver_key_converter.h
+++ b/chrome/test/webdriver/webdriver_key_converter.h
@@ -15,6 +15,8 @@
namespace webdriver {
+class Logger;
+
// Convenience functions for creating |WebKeyEvent|s. Used by unittests.
WebKeyEvent CreateKeyDownEvent(ui::KeyboardCode key_code, int modifiers);
WebKeyEvent CreateKeyUpEvent(ui::KeyboardCode key_code, int modifiers);
@@ -26,6 +28,7 @@ WebKeyEvent CreateCharEvent(const std::string& unmodified_text,
// conversion. However, if the input is invalid it will return false and set
// an error message.
bool ConvertKeysToWebKeyEvents(const string16& keys,
+ const Logger& logger,
std::vector<WebKeyEvent>* key_events,
std::string* error_msg);
diff --git a/chrome/test/webdriver/webdriver_key_converter_unittest.cc b/chrome/test/webdriver/webdriver_key_converter_unittest.cc
index 1fe3e5e..b0fdb77 100644
--- a/chrome/test/webdriver/webdriver_key_converter_unittest.cc
+++ b/chrome/test/webdriver/webdriver_key_converter_unittest.cc
@@ -19,7 +19,7 @@ void CheckEvents(const string16& keys,
size_t expected_size) {
std::vector<WebKeyEvent> events;
std::string error_msg;
- EXPECT_TRUE(ConvertKeysToWebKeyEvents(keys, &events, &error_msg));
+ EXPECT_TRUE(ConvertKeysToWebKeyEvents(keys, Logger(), &events, &error_msg));
EXPECT_EQ(expected_size, events.size());
for (size_t i = 0; i < events.size() && i < expected_size; ++i) {
EXPECT_EQ(expected_events[i].type, events[i].type);
@@ -41,8 +41,8 @@ void CheckNonShiftChar(ui::KeyboardCode key_code, char character) {
char_string.push_back(character);
std::vector<WebKeyEvent> events;
std::string error_msg;
- EXPECT_TRUE(ConvertKeysToWebKeyEvents(ASCIIToUTF16(char_string), &events,
- &error_msg));
+ EXPECT_TRUE(ConvertKeysToWebKeyEvents(ASCIIToUTF16(char_string), Logger(),
+ &events, &error_msg));
ASSERT_EQ(3u, events.size()) << "Char: " << character;
EXPECT_EQ(key_code, events[0].key_code) << "Char: " << character;
ASSERT_EQ(1u, events[1].modified_text.length()) << "Char: " << character;
@@ -57,8 +57,8 @@ void CheckShiftChar(ui::KeyboardCode key_code, char character, char lower) {
char_string.push_back(character);
std::vector<WebKeyEvent> events;
std::string error_msg;
- EXPECT_TRUE(ConvertKeysToWebKeyEvents(ASCIIToUTF16(char_string), &events,
- &error_msg));
+ EXPECT_TRUE(ConvertKeysToWebKeyEvents(ASCIIToUTF16(char_string), Logger(),
+ &events, &error_msg));
ASSERT_EQ(5u, events.size()) << "Char: " << character;
EXPECT_EQ(ui::VKEY_SHIFT, events[0].key_code) << "Char: " << character;
EXPECT_EQ(key_code, events[1].key_code) << "Char: " << character;
@@ -281,11 +281,13 @@ TEST(WebDriverKeyConverter, AllSpecialWebDriverKeysOnEnglishKeyboard) {
std::vector<WebKeyEvent> events;
std::string error_msg;
if (i == 1) {
- EXPECT_FALSE(ConvertKeysToWebKeyEvents(keys, &events, &error_msg))
+ EXPECT_FALSE(ConvertKeysToWebKeyEvents(keys, Logger(), &events,
+ &error_msg))
<< "Index: " << i;
EXPECT_EQ(0u, events.size()) << "Index: " << i;
} else {
- EXPECT_TRUE(ConvertKeysToWebKeyEvents(keys, &events, &error_msg))
+ EXPECT_TRUE(ConvertKeysToWebKeyEvents(keys, Logger(),
+ &events, &error_msg))
<< "Index: " << i;
if (i == 0) {
EXPECT_EQ(0u, events.size()) << "Index: " << i;
diff --git a/chrome/test/webdriver/webdriver_logging.cc b/chrome/test/webdriver/webdriver_logging.cc
index 2a0b3c5..e52d1ec 100644
--- a/chrome/test/webdriver/webdriver_logging.cc
+++ b/chrome/test/webdriver/webdriver_logging.cc
@@ -4,24 +4,194 @@
#include "chrome/test/webdriver/webdriver_logging.h"
+#include <cmath>
+
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/stringprintf.h"
+#include "base/time.h"
+
+using base::DictionaryValue;
+using base::ListValue;
+using base::Value;
-namespace {
+namespace webdriver {
-// Path to the WebDriver log file.
-const FilePath::CharType kLogPath[] = FILE_PATH_LITERAL("chromedriver.log");
+FileLog* FileLog::singleton_ = NULL;
-} // namespace
+double start_time = 0;
-namespace webdriver {
+// static
+bool LogType::FromString(const std::string& name, LogType* log_type) {
+ if (name == "driver") {
+ *log_type = LogType(kDriver);
+ } else {
+ return false;
+ }
+ return true;
+}
+
+LogType::LogType() : type_(kInvalid) { }
+
+LogType::LogType(Type type) : type_(type) { }
+
+LogType::~LogType() { }
+
+std::string LogType::ToString() const {
+ switch (type_) {
+ case kDriver:
+ return "driver";
+ default:
+ return "unknown";
+ };
+}
+
+LogType::Type LogType::type() const {
+ return type_;
+}
+
+LogHandler::LogHandler() { }
+
+LogHandler::~LogHandler() { }
+
+// static
+void FileLog::InitGlobalLog(LogLevel level) {
+ singleton_ = new FileLog(FilePath(FILE_PATH_LITERAL("chromedriver.log")),
+ level);
+}
+
+// static
+FileLog* FileLog::Get() {
+ return singleton_;
+}
+
+FileLog::FileLog(const FilePath& path, LogLevel level)
+ : path_(path),
+ min_log_level_(level) {
+ file_.reset(file_util::OpenFile(path, "w"));
+}
+
+FileLog::~FileLog() { }
+
+void FileLog::Log(LogLevel level, const base::Time& time,
+ const std::string& message) {
+ if (level < min_log_level_)
+ return;
+
+ const char* level_name = "UNKNOWN";
+ switch (level) {
+ case kSevereLogLevel:
+ level_name = "SEVERE";
+ break;
+ case kWarningLogLevel:
+ level_name = "WARNING";
+ break;
+ case kInfoLogLevel:
+ level_name = "INFO";
+ break;
+ case kFineLogLevel:
+ level_name = "FINE";
+ break;
+ case kFinerLogLevel:
+ level_name = "FINER";
+ break;
+ default:
+ break;
+ }
+ base::TimeDelta delta(time - base::Time::UnixEpoch());
+ std::string time_utc = base::Int64ToString(delta.InMilliseconds());
+ std::string entry = base::StringPrintf(
+ "[%s][%s]:", time_utc.c_str(), level_name);
-void InitWebDriverLogging(int min_log_level) {
+ int pad_length = 26 - entry.length();
+ if (pad_length < 1)
+ pad_length = 1;
+ std::string padding(pad_length, ' ');
+ entry += base::StringPrintf(
+ "%s%s\n", padding.c_str(), message.c_str());
+
+ base::AutoLock auto_lock(lock_);
+#if defined(OS_WIN)
+ SetFilePointer(file_.get(), 0, 0, SEEK_END);
+ DWORD num_written;
+ WriteFile(file_.get(),
+ static_cast<const void*>(entry.c_str()),
+ static_cast<DWORD>(entry.length()),
+ &num_written,
+ NULL);
+#else
+ fprintf(file_.get(), "%s", entry.c_str());
+ fflush(file_.get());
+#endif
+}
+
+bool FileLog::GetLogContents(std::string* contents) {
+ return file_util::ReadFileToString(path_, contents);
+}
+
+void FileLog::set_min_log_level(LogLevel level) {
+ min_log_level_ = level;
+}
+
+InMemoryLog::InMemoryLog() { }
+
+InMemoryLog::~InMemoryLog() { }
+
+void InMemoryLog::Log(LogLevel level, const base::Time& time,
+ const std::string& message) {
+ // base's JSONWriter doesn't obey the spec, and writes
+ // doubles without a fraction with a '.0' postfix. base's Value class
+ // only includes doubles or int types. Instead of returning the timestamp
+ // in unix epoch time, we return it based on the start of chromedriver so
+ // a 32-bit int doesn't overflow.
+ // TODO(kkania): Add int64_t to base Values or fix the JSONWriter/Reader and
+ // use unix epoch time.
+ base::TimeDelta delta(time - base::Time::FromDoubleT(start_time));
+ DictionaryValue* entry = new DictionaryValue();
+ entry->SetInteger("level", level);
+ entry->SetInteger("timestamp", delta.InMilliseconds());
+ entry->SetString("message", message);
+ base::AutoLock auto_lock(entries_lock_);
+ entries_list_.Append(entry);
+}
+
+const ListValue* InMemoryLog::entries_list() const {
+ return &entries_list_;
+}
+
+Logger::Logger() : min_log_level_(kAllLogLevel) { }
+
+Logger::Logger(LogLevel level) : min_log_level_(level) { }
+
+Logger::~Logger() { }
+
+void Logger::Log(LogLevel level, const std::string& message) const {
+ if (level < min_log_level_)
+ return;
+
+ base::Time time = base::Time::Now();
+ for (size_t i = 0; i < handlers_.size(); ++i) {
+ handlers_[i]->Log(level, time, message);
+ }
+}
+
+void Logger::AddHandler(LogHandler* log_handler) {
+ handlers_.push_back(log_handler);
+}
+
+void Logger::set_min_log_level(LogLevel level) {
+ min_log_level_ = level;
+}
+
+void InitWebDriverLogging(LogLevel min_log_level) {
+ start_time = base::Time::Now().ToDoubleT();
+ // Turn off base/logging.
bool success = InitLogging(
- kLogPath,
- logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
- logging::LOCK_LOG_FILE,
+ NULL,
+ logging::LOG_NONE,
+ logging::DONT_LOCK_LOG_FILE,
logging::DELETE_OLD_LOG_FILE,
logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
if (!success) {
@@ -31,11 +201,9 @@ void InitWebDriverLogging(int min_log_level) {
false, // enable_thread_id
true, // enable_timestamp
false); // enable_tickcount
- logging::SetMinLogLevel(min_log_level);
-}
-bool GetLogContents(std::string* log_contents) {
- return file_util::ReadFileToString(FilePath(kLogPath), log_contents);
+ // Init global file log.
+ FileLog::InitGlobalLog(min_log_level);
}
} // namespace webdriver
diff --git a/chrome/test/webdriver/webdriver_logging.h b/chrome/test/webdriver/webdriver_logging.h
index 2b8ab5e..e10ec1e 100644
--- a/chrome/test/webdriver/webdriver_logging.h
+++ b/chrome/test/webdriver/webdriver_logging.h
@@ -6,16 +6,129 @@
#define CHROME_TEST_WEBDRIVER_WEBDRIVER_LOGGING_H_
#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/values.h"
+
+namespace base {
+class Time;
+}
namespace webdriver {
-// Initializes logging for WebDriver. All logging below the given level
-// will be discarded.
-void InitWebDriverLogging(int min_log_level);
+// WebDriver logging levels.
+enum LogLevel {
+ kSevereLogLevel = 1000,
+ kWarningLogLevel = 900,
+ kInfoLogLevel = 800,
+ kFineLogLevel = 500,
+ kFinerLogLevel = 400,
+ kAllLogLevel = -1000
+};
+
+// Represents a type/source of a WebDriver log.
+class LogType {
+ public:
+ enum Type {
+ kInvalid = -1,
+ kDriver,
+ kNum // must be correct
+ };
+
+ static bool FromString(const std::string& name, LogType* log_type);
+
+ LogType();
+ explicit LogType(Type type);
+ ~LogType();
+
+ std::string ToString() const;
+ Type type() const;
+
+ private:
+ Type type_;
+};
+
+class LogHandler {
+ public:
+ LogHandler();
+ virtual ~LogHandler();
+
+ virtual void Log(LogLevel level, const base::Time& time,
+ const std::string& message) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LogHandler);
+};
+
+class FileLog : public LogHandler {
+ public:
+ static void InitGlobalLog(LogLevel level);
+ static FileLog* Get();
+
+ FileLog(const FilePath& path, LogLevel level);
+ virtual ~FileLog();
+
+ virtual void Log(LogLevel level, const base::Time& time,
+ const std::string& message) OVERRIDE;
+
+ bool GetLogContents(std::string* contents);
-// Retrieves the current contents of the WebDriver log file.
-// Returns true on success.
-bool GetLogContents(std::string* log_contents);
+ void set_min_log_level(LogLevel level);
+
+ private:
+ static FileLog* singleton_;
+
+ FilePath path_;
+ file_util::ScopedFILE file_;
+ base::Lock lock_;
+
+ LogLevel min_log_level_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileLog);
+};
+
+class InMemoryLog : public LogHandler {
+ public:
+ InMemoryLog();
+ virtual ~InMemoryLog();
+
+ virtual void Log(LogLevel level, const base::Time& time,
+ const std::string& message) OVERRIDE;
+
+ const base::ListValue* entries_list() const;
+
+ private:
+ base::ListValue entries_list_;
+ base::Lock entries_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(InMemoryLog);
+};
+
+// Forwards logging messages to added logs.
+class Logger {
+ public:
+ Logger();
+ explicit Logger(LogLevel level);
+ ~Logger();
+
+ void Log(LogLevel level, const std::string& message) const;
+ void AddHandler(LogHandler* log_handler);
+
+ void set_min_log_level(LogLevel level);
+
+ private:
+ std::vector<LogHandler*> handlers_;
+ LogLevel min_log_level_;
+};
+
+// Initializes logging for WebDriver. All logging below the given level
+// will be discarded in the global file log.
+void InitWebDriverLogging(LogLevel min_log_level);
} // namespace webdriver
diff --git a/chrome/test/webdriver/webdriver_server.cc b/chrome/test/webdriver/webdriver_server.cc
index 22e6cf2..b5c692d 100644
--- a/chrome/test/webdriver/webdriver_server.cc
+++ b/chrome/test/webdriver/webdriver_server.cc
@@ -16,7 +16,6 @@
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
-#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_number_conversions.h"
#include "base/string_split.h"
@@ -24,6 +23,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
+#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
@@ -37,6 +37,7 @@
#include "chrome/test/webdriver/commands/execute_async_script_command.h"
#include "chrome/test/webdriver/commands/execute_command.h"
#include "chrome/test/webdriver/commands/find_element_commands.h"
+#include "chrome/test/webdriver/commands/log_command.h"
#include "chrome/test/webdriver/commands/navigate_commands.h"
#include "chrome/test/webdriver/commands/mouse_commands.h"
#include "chrome/test/webdriver/commands/screenshot_command.h"
@@ -64,6 +65,8 @@
namespace webdriver {
+namespace {
+
void InitCallbacks(Dispatcher* dispatcher,
base::WaitableEvent* shutdown_event,
bool forbid_other_requests) {
@@ -134,6 +137,7 @@ void InitCallbacks(Dispatcher* dispatcher,
dispatcher->Add<SetAsyncScriptTimeoutCommand>(
"/session/*/timeouts/async_script");
dispatcher->Add<ImplicitWaitCommand>( "/session/*/timeouts/implicit_wait");
+ dispatcher->Add<LogCommand>( "/session/*/log");
// Cookie functions.
dispatcher->Add<CookieCommand>( "/session/*/cookie");
@@ -155,17 +159,13 @@ void InitCallbacks(Dispatcher* dispatcher,
dispatcher->ForbidAllOtherRequests();
}
-} // namespace webdriver
-
-namespace {
-
void* ProcessHttpRequest(mg_event event_raised,
struct mg_connection* connection,
const struct mg_request_info* request_info) {
bool handler_result_code = false;
if (event_raised == MG_NEW_REQUEST) {
handler_result_code =
- reinterpret_cast<webdriver::Dispatcher*>(request_info->user_data)->
+ reinterpret_cast<Dispatcher*>(request_info->user_data)->
ProcessHttpRequest(connection, request_info);
}
@@ -191,13 +191,9 @@ void MakeMongooseOptions(const std::string& port,
} // namespace
-// Sets up and runs the Mongoose HTTP server for the JSON over HTTP
-// protcol of webdriver. The spec is located at:
-// http://code.google.com/p/selenium/wiki/JsonWireProtocol.
-int main(int argc, char *argv[]) {
+int RunChromeDriver() {
base::AtExitManager exit;
base::WaitableEvent shutdown_event(false, false);
- CommandLine::Init(argc, argv);
CommandLine* cmd_line = CommandLine::ForCurrentProcess();
#if defined(OS_POSIX)
@@ -210,11 +206,15 @@ int main(int argc, char *argv[]) {
chrome::RegisterPathProvider();
TestTimeouts::Initialize();
+ InitWebDriverLogging(kAllLogLevel);
+ FileLog::Get()->Log(kInfoLogLevel,
+ base::Time::Now(),
+ std::string("ChromeDriver ") + chrome::kChromeVersion);
+
// Parse command line flags.
std::string port = "9515";
std::string root;
std::string url_base;
- bool verbose = false;
int http_threads = 4;
bool enable_keep_alive = true;
if (cmd_line->HasSwitch("port"))
@@ -226,9 +226,6 @@ int main(int argc, char *argv[]) {
root = cmd_line->GetSwitchValueASCII("root");
if (cmd_line->HasSwitch("url-base"))
url_base = cmd_line->GetSwitchValueASCII("url-base");
- // Whether or not to do verbose logging.
- if (cmd_line->HasSwitch("verbose"))
- verbose = true;
if (cmd_line->HasSwitch("http-threads")) {
if (!base::StringToInt(cmd_line->GetSwitchValueASCII("http-threads"),
&http_threads)) {
@@ -239,15 +236,12 @@ int main(int argc, char *argv[]) {
if (cmd_line->HasSwitch("disable-keep-alive"))
enable_keep_alive = false;
- webdriver::InitWebDriverLogging(
- verbose ? logging::LOG_INFO : logging::LOG_WARNING);
-
- webdriver::SessionManager* manager = webdriver::SessionManager::GetInstance();
+ SessionManager* manager = SessionManager::GetInstance();
manager->set_port(port);
manager->set_url_base(url_base);
- webdriver::Dispatcher dispatcher(url_base);
- webdriver::InitCallbacks(&dispatcher, &shutdown_event, root.empty());
+ Dispatcher dispatcher(url_base);
+ InitCallbacks(&dispatcher, &shutdown_event, root.empty());
std::vector<std::string> args;
MakeMongooseOptions(port, root, http_threads, enable_keep_alive, &args);
@@ -284,3 +278,10 @@ int main(int argc, char *argv[]) {
return (EXIT_SUCCESS);
}
+
+} // namespace webdriver
+
+int main(int argc, char *argv[]) {
+ CommandLine::Init(argc, argv);
+ webdriver::RunChromeDriver();
+}
diff --git a/chrome/test/webdriver/webdriver_session.cc b/chrome/test/webdriver/webdriver_session.cc
index fd02cf7..92c3a08 100644
--- a/chrome/test/webdriver/webdriver_session.cc
+++ b/chrome/test/webdriver/webdriver_session.cc
@@ -14,7 +14,6 @@
#include "base/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
-#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop_proxy.h"
#include "base/process.h"
@@ -35,8 +34,10 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/automation_json_requests.h"
#include "chrome/test/automation/value_conversion_util.h"
+#include "chrome/test/webdriver/webdriver_capabilities_parser.h"
#include "chrome/test/webdriver/webdriver_error.h"
#include "chrome/test/webdriver/webdriver_key_converter.h"
+#include "chrome/test/webdriver/webdriver_logging.h"
#include "chrome/test/webdriver/webdriver_session_manager.h"
#include "chrome/test/webdriver/webdriver_util.h"
#include "third_party/webdriver/atoms.h"
@@ -50,43 +51,58 @@ FrameId::FrameId(const WebViewId& view_id, const FramePath& frame_path)
frame_path(frame_path) {
}
-Session::Options::Options()
- : use_native_events(false),
- load_async(false),
- no_website_testing_defaults(false) {
-}
-
-Session::Options::~Options() {
-}
-
-Session::Session(const Options& options)
- : id_(GenerateRandomID()),
+Session::Session()
+ : session_log_(new InMemoryLog()),
+ logger_(kAllLogLevel),
+ id_(GenerateRandomID()),
current_target_(FrameId(WebViewId(), FramePath())),
thread_(id_.c_str()),
async_script_timeout_(0),
implicit_wait_(0),
- has_alert_prompt_text_(false),
- options_(options) {
+ has_alert_prompt_text_(false) {
SessionManager::GetInstance()->Add(this);
+ logger_.AddHandler(session_log_.get());
+ if (FileLog::Get())
+ logger_.AddHandler(FileLog::Get());
}
Session::~Session() {
SessionManager::GetInstance()->Remove(id_);
}
-Error* Session::Init(const Automation::BrowserOptions& options) {
+Error* Session::Init(const DictionaryValue* capabilities_dict) {
if (!thread_.Start()) {
delete this;
return new Error(kUnknownError, "Cannot start session thread");
}
+ ScopedTempDir temp_dir;
+ if (!temp_dir.CreateUniqueTempDir()) {
+ delete this;
+ return new Error(
+ kUnknownError, "Unable to create temp directory for unpacking");
+ }
+ logger_.Log(kFineLogLevel,
+ "Initializing session with capabilities " +
+ JsonStringifyForDisplay(capabilities_dict));
+ CapabilitiesParser parser(
+ capabilities_dict, temp_dir.path(), logger_, &capabilities_);
+ Error* error = parser.Parse();
+ if (error) {
+ delete this;
+ return error;
+ }
+ logger_.set_min_log_level(capabilities_.log_levels[LogType::kDriver]);
- Error* error = NULL;
+ Automation::BrowserOptions browser_options;
+ browser_options.command = capabilities_.command;
+ browser_options.channel_id = capabilities_.channel;
+ browser_options.detach_process = capabilities_.detach;
+ browser_options.user_data_dir = capabilities_.profile;
RunSessionTask(base::Bind(
&Session::InitOnSessionThread,
base::Unretained(this),
- options,
+ browser_options,
&error));
-
if (!error)
error = PostBrowserStartInit();
@@ -114,10 +130,8 @@ Error* Session::BeforeExecuteCommand() {
Error* Session::AfterExecuteCommand() {
Error* error = NULL;
- if (!options_.load_async) {
- LOG(INFO) << "Waiting for the page to stop loading";
+ if (!capabilities_.load_async) {
error = WaitForAllViewsToStopLoading();
- LOG(INFO) << "Done waiting for the page to stop loading";
}
return error;
}
@@ -291,7 +305,7 @@ Error* Session::NavigateToURL(const std::string& url) {
"The current target does not support navigation");
}
Error* error = NULL;
- if (options_.load_async) {
+ if (capabilities_.load_async) {
RunSessionTask(base::Bind(
&Automation::NavigateToURLAsync,
base::Unretained(automation_.get()),
@@ -1020,11 +1034,14 @@ Error* Session::GetAttribute(const ElementId& element,
Error* Session::WaitForAllViewsToStopLoading() {
if (!automation_.get())
return NULL;
+
+ logger_.Log(kFinerLogLevel, "Waiting for all views to stop loading...");
Error* error = NULL;
RunSessionTask(base::Bind(
&Automation::WaitForAllViewsToStopLoading,
base::Unretained(automation_.get()),
&error));
+ logger_.Log(kFinerLogLevel, "Done waiting for all views to stop loading");
return error;
}
@@ -1137,6 +1154,10 @@ Error* Session::SetPreference(
return error;
}
+base::ListValue* Session::GetLog() const {
+ return session_log_->entries_list()->DeepCopy();
+}
+
const std::string& Session::id() const {
return id_;
}
@@ -1165,8 +1186,12 @@ const Point& Session::get_mouse_position() const {
return mouse_position_;
}
-const Session::Options& Session::options() const {
- return options_;
+const Logger& Session::logger() const {
+ return logger_;
+}
+
+const Capabilities& Session::capabilities() const {
+ return capabilities_;
}
void Session::RunSessionTask(Task* task) {
@@ -1204,7 +1229,7 @@ void Session::RunClosureOnSessionThread(const base::Closure& task,
void Session::InitOnSessionThread(const Automation::BrowserOptions& options,
Error** error) {
- automation_.reset(new Automation());
+ automation_.reset(new Automation(logger_));
automation_->Init(options, error);
if (*error)
return;
@@ -1279,12 +1304,12 @@ Error* Session::ExecuteScriptAndParseValue(const FrameId& frame_id,
void Session::SendKeysOnSessionThread(const string16& keys, Error** error) {
std::vector<WebKeyEvent> key_events;
std::string error_msg;
- if (!ConvertKeysToWebKeyEvents(keys, &key_events, &error_msg)) {
+ if (!ConvertKeysToWebKeyEvents(keys, logger_, &key_events, &error_msg)) {
*error = new Error(kUnknownError, error_msg);
return;
}
for (size_t i = 0; i < key_events.size(); ++i) {
- if (options_.use_native_events) {
+ if (capabilities_.native_events) {
// The automation provider will generate up/down events for us, we
// only need to call it once as compared to the WebKeyEvent method.
// Hence we filter events by their types, keeping only rawkeydown.
@@ -1511,7 +1536,7 @@ Error* Session::VerifyElementIsClickable(
return new Error(kUnknownError, message);
}
if (message.length()) {
- LOG(WARNING) << message;
+ logger_.Log(kWarningLogLevel, message);
}
return NULL;
}
@@ -1588,14 +1613,14 @@ Error* Session::GetAppCacheStatus(int* status) {
Error* Session::PostBrowserStartInit() {
Error* error = NULL;
- if (!options_.no_website_testing_defaults)
+ if (!capabilities_.no_website_testing_defaults)
error = InitForWebsiteTesting();
if (error)
return error;
// Install extensions.
- for (size_t i = 0; i < options_.extensions.size(); ++i) {
- error = InstallExtensionDeprecated(options_.extensions[i]);
+ for (size_t i = 0; i < capabilities_.extensions.size(); ++i) {
+ error = InstallExtensionDeprecated(capabilities_.extensions[i]);
if (error)
return error;
}
diff --git a/chrome/test/webdriver/webdriver_session.h b/chrome/test/webdriver/webdriver_session.h
index d2ea02f..834d2f4 100644
--- a/chrome/test/webdriver/webdriver_session.h
+++ b/chrome/test/webdriver/webdriver_session.h
@@ -19,7 +19,9 @@
#include "chrome/test/webdriver/frame_path.h"
#include "chrome/test/webdriver/webdriver_automation.h"
#include "chrome/test/webdriver/webdriver_basic_types.h"
+#include "chrome/test/webdriver/webdriver_capabilities_parser.h"
#include "chrome/test/webdriver/webdriver_element_id.h"
+#include "chrome/test/webdriver/webdriver_logging.h"
class FilePath;
@@ -51,43 +53,15 @@ struct FrameId {
// A session manages its own lifetime.
class Session {
public:
- struct Options {
- Options();
- ~Options();
-
- // True if the session should simulate OS-level input. Currently only
- // applies to keyboard input.
- bool use_native_events;
-
- // True if the session should not wait for page loads and navigate
- // asynchronously.
- bool load_async;
-
- // By default, ChromeDriver configures Chrome in such a way as convenient
- // for website testing. E.g., it configures Chrome so that sites are allowed
- // to use the geolocation API without requesting the user's consent.
- // If this is set to true, ChromeDriver will not modify Chrome's default
- // behavior.
- bool no_website_testing_defaults;
-
- // A list of extensions to install on startup.
- std::vector<FilePath> extensions;
- };
-
// Adds this |Session| to the |SessionManager|. The session manages its own
- // lifetime. Do not call delete.
- explicit Session(const Options& options);
+ // lifetime. Call |Terminate|, not delete, if you need to quit.
+ Session();
// Removes this |Session| from the |SessionManager|.
~Session();
- // Starts the session thread and a new browser, using the exe found at
- // |browser_exe| and duplicating the provided |user_data_dir|.
- // If |browser_exe| is empty, it will search in all the default locations.
- // It |user_data_dir| is empty, it will use a temporary dir.
- // Returns true on success. On failure, the session will delete
- // itself and return an error code.
- Error* Init(const Automation::BrowserOptions& options);
+ // Initializes the session with the given capabilities.
+ Error* Init(const base::DictionaryValue* capabilities_dict);
// Should be called before executing a command.
Error* BeforeExecuteCommand();
@@ -347,6 +321,10 @@ class Session {
bool is_user_pref,
base::Value* value);
+ // Returns a copy of the current log entries. Caller is responsible for
+ // returned value.
+ base::ListValue* GetLog() const;
+
const std::string& id() const;
const FrameId& current_target() const;
@@ -359,7 +337,9 @@ class Session {
const Point& get_mouse_position() const;
- const Options& options() const;
+ const Logger& logger() const;
+
+ const Capabilities& capabilities() const;
// Gets the browser connection state.
Error* GetBrowserConnectionState(bool* online);
@@ -418,6 +398,9 @@ class Session {
Error* PostBrowserStartInit();
Error* InitForWebsiteTesting();
+ scoped_ptr<InMemoryLog> session_log_;
+ Logger logger_;
+
const std::string id_;
FrameId current_target_;
@@ -446,7 +429,7 @@ class Session {
std::string alert_prompt_text_;
bool has_alert_prompt_text_;
- Options options_;
+ Capabilities capabilities_;
DISALLOW_COPY_AND_ASSIGN(Session);
};