summaryrefslogtreecommitdiffstats
path: root/chrome/test/chromedriver/capabilities.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/test/chromedriver/capabilities.cc')
-rw-r--r--chrome/test/chromedriver/capabilities.cc255
1 files changed, 172 insertions, 83 deletions
diff --git a/chrome/test/chromedriver/capabilities.cc b/chrome/test/chromedriver/capabilities.cc
index 7444641..188074c 100644
--- a/chrome/test/chromedriver/capabilities.cc
+++ b/chrome/test/chromedriver/capabilities.cc
@@ -8,11 +8,13 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/json/string_escape.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/test/chromedriver/chrome/log.h"
#include "chrome/test/chromedriver/chrome/status.h"
@@ -27,7 +29,7 @@ Status ParseBoolean(
const base::Value& option,
Capabilities* capabilities) {
if (!option.GetAsBoolean(to_set))
- return Status(kUnknownError, "value must be a boolean");
+ return Status(kUnknownError, "must be a boolean");
return Status(kOk);
}
@@ -36,13 +38,35 @@ Status ParseString(std::string* to_set,
Capabilities* capabilities) {
std::string str;
if (!option.GetAsString(&str))
- return Status(kUnknownError, "value must be a string");
+ return Status(kUnknownError, "must be a string");
if (str.empty())
- return Status(kUnknownError, "value cannot be empty");
+ return Status(kUnknownError, "cannot be empty");
*to_set = str;
return Status(kOk);
}
+Status ParseFilePath(base::FilePath* to_set,
+ const base::Value& option,
+ Capabilities* capabilities) {
+ base::FilePath::StringType str;
+ if (!option.GetAsString(&str))
+ return Status(kUnknownError, "must be a string");
+ if (str.empty())
+ return Status(kUnknownError, "cannot be empty");
+ *to_set = base::FilePath(str);
+ return Status(kOk);
+}
+
+Status ParseDict(scoped_ptr<base::DictionaryValue>* to_set,
+ const base::Value& option,
+ Capabilities* capabilities) {
+ const base::DictionaryValue* dict = NULL;
+ if (!option.GetAsDictionary(&dict))
+ return Status(kUnknownError, "must be a dictionary");
+ to_set->reset(dict->DeepCopy());
+ return Status(kOk);
+}
+
Status IgnoreDeprecatedOption(
Log* log,
const char* option_name,
@@ -58,72 +82,30 @@ Status IgnoreCapability(const base::Value& option, Capabilities* capabilities) {
return Status(kOk);
}
-Status ParseChromeBinary(
- const base::Value& option,
- Capabilities* capabilities) {
- base::FilePath::StringType path_str;
- if (!option.GetAsString(&path_str))
- return Status(kUnknownError, "'binary' must be a string");
- base::FilePath chrome_exe(path_str);
- capabilities->command.SetProgram(chrome_exe);
- return Status(kOk);
-}
-
Status ParseLogPath(const base::Value& option, Capabilities* capabilities) {
if (!option.GetAsString(&capabilities->log_path))
- return Status(kUnknownError, "'logPath' must be a string");
+ return Status(kUnknownError, "must be a string");
return Status(kOk);
}
-Status ParseArgs(bool is_android,
- const base::Value& option,
- Capabilities* capabilities) {
- const base::ListValue* args_list = NULL;
- if (!option.GetAsList(&args_list))
- return Status(kUnknownError, "'args' must be a list");
- for (size_t i = 0; i < args_list->GetSize(); ++i) {
+Status ParseSwitches(const base::Value& option,
+ Capabilities* capabilities) {
+ const base::ListValue* switches_list = NULL;
+ if (!option.GetAsList(&switches_list))
+ return Status(kUnknownError, "must be a list");
+ for (size_t i = 0; i < switches_list->GetSize(); ++i) {
std::string arg_string;
- if (!args_list->GetString(i, &arg_string))
+ if (!switches_list->GetString(i, &arg_string))
return Status(kUnknownError, "each argument must be a string");
- if (is_android) {
- capabilities->android_args += "--" + arg_string + " ";
- } else {
- size_t separator_index = arg_string.find("=");
- if (separator_index != std::string::npos) {
- CommandLine::StringType arg_string_native;
- if (!args_list->GetString(i, &arg_string_native))
- return Status(kUnknownError, "each argument must be a string");
- capabilities->command.AppendSwitchNative(
- arg_string.substr(0, separator_index),
- arg_string_native.substr(separator_index + 1));
- } else {
- capabilities->command.AppendSwitch(arg_string);
- }
- }
+ capabilities->switches.SetUnparsedSwitch(arg_string);
}
return Status(kOk);
}
-Status ParsePrefs(const base::Value& option, Capabilities* capabilities) {
- const base::DictionaryValue* prefs = NULL;
- if (!option.GetAsDictionary(&prefs))
- return Status(kUnknownError, "'prefs' must be a dictionary");
- capabilities->prefs.reset(prefs->DeepCopy());
- return Status(kOk);
-}
-
-Status ParseLocalState(const base::Value& option, Capabilities* capabilities) {
- const base::DictionaryValue* local_state = NULL;
- if (!option.GetAsDictionary(&local_state))
- return Status(kUnknownError, "'localState' must be a dictionary");
- capabilities->local_state.reset(local_state->DeepCopy());
- return Status(kOk);
-}
-
Status ParseExtensions(const base::Value& option, Capabilities* capabilities) {
const base::ListValue* extensions = NULL;
if (!option.GetAsList(&extensions))
- return Status(kUnknownError, "'extensions' must be a list");
+ return Status(kUnknownError, "must be a list");
for (size_t i = 0; i < extensions->GetSize(); ++i) {
std::string extension;
if (!extensions->GetString(i, &extension)) {
@@ -138,22 +120,22 @@ Status ParseExtensions(const base::Value& option, Capabilities* capabilities) {
Status ParseProxy(const base::Value& option, Capabilities* capabilities) {
const base::DictionaryValue* proxy_dict;
if (!option.GetAsDictionary(&proxy_dict))
- return Status(kUnknownError, "'proxy' must be a dictionary");
+ return Status(kUnknownError, "must be a dictionary");
std::string proxy_type;
if (!proxy_dict->GetString("proxyType", &proxy_type))
return Status(kUnknownError, "'proxyType' must be a string");
proxy_type = StringToLowerASCII(proxy_type);
if (proxy_type == "direct") {
- capabilities->command.AppendSwitch("no-proxy-server");
+ capabilities->switches.SetSwitch("no-proxy-server");
} else if (proxy_type == "system") {
// Chrome default.
} else if (proxy_type == "pac") {
CommandLine::StringType proxy_pac_url;
if (!proxy_dict->GetString("proxyAutoconfigUrl", &proxy_pac_url))
return Status(kUnknownError, "'proxyAutoconfigUrl' must be a string");
- capabilities->command.AppendSwitchNative("proxy-pac-url", proxy_pac_url);
+ capabilities->switches.SetSwitch("proxy-pac-url", proxy_pac_url);
} else if (proxy_type == "autodetect") {
- capabilities->command.AppendSwitch("proxy-auto-detect");
+ capabilities->switches.SetSwitch("proxy-auto-detect");
} else if (proxy_type == "manual") {
const char* proxy_servers_options[][2] = {
{"ftpProxy", "ftp"}, {"httpProxy", "http"}, {"sslProxy", "https"}};
@@ -192,10 +174,10 @@ Status ParseProxy(const base::Value& option, Capabilities* capabilities) {
"proxy capabilities were found");
}
if (!proxy_servers.empty())
- capabilities->command.AppendSwitchASCII("proxy-server", proxy_servers);
+ capabilities->switches.SetSwitch("proxy-server", proxy_servers);
if (!proxy_bypass_list.empty()) {
- capabilities->command.AppendSwitchASCII("proxy-bypass-list",
- proxy_bypass_list);
+ capabilities->switches.SetSwitch("proxy-bypass-list",
+ proxy_bypass_list);
}
} else {
return Status(kUnknownError, "unrecognized proxy type:" + proxy_type);
@@ -207,7 +189,7 @@ Status ParseExcludeSwitches(const base::Value& option,
Capabilities* capabilities) {
const base::ListValue* switches = NULL;
if (!option.GetAsList(&switches))
- return Status(kUnknownError, "'excludeSwitches' must be a list");
+ return Status(kUnknownError, "must be a list");
for (size_t i = 0; i < switches->GetSize(); ++i) {
std::string switch_name;
if (!switches->GetString(i, &switch_name)) {
@@ -233,9 +215,9 @@ Status ParseUseExistingBrowser(const base::Value& option,
int port = 0;
base::StringToInt(values[1], &port);
if (port <= 0)
- return Status(kUnknownError, "port must be >= 0");
+ return Status(kUnknownError, "port must be > 0");
- capabilities->use_existing_browser = NetAddress(values[0], port);
+ capabilities->debugger_address = NetAddress(values[0], port);
return Status(kOk);
}
@@ -243,7 +225,7 @@ Status ParseLoggingPrefs(const base::Value& option,
Capabilities* capabilities) {
const base::DictionaryValue* logging_prefs_dict = NULL;
if (!option.GetAsDictionary(&logging_prefs_dict))
- return Status(kUnknownError, "'loggingPrefs' must be a dictionary");
+ return Status(kUnknownError, "must be a dictionary");
// TODO(klm): verify log types.
// TODO(klm): verify log levels.
@@ -257,14 +239,15 @@ Status ParseChromeOptions(
Capabilities* capabilities) {
const base::DictionaryValue* chrome_options = NULL;
if (!capability.GetAsDictionary(&chrome_options))
- return Status(kUnknownError, "'chromeOptions' must be a dictionary");
+ return Status(kUnknownError, "must be a dictionary");
bool is_android = chrome_options->HasKey("androidPackage");
- bool is_existing = chrome_options->HasKey("useExistingBrowser");
+ bool is_existing = chrome_options->HasKey("debuggerAddress");
std::map<std::string, Parser> parser_map;
- // Ignore 'binary' and 'extensions' capability, since the Java client
- // always passes them.
+ // Ignore 'args', 'binary' and 'extensions' capabilities by default, since the
+ // Java client always passes them.
+ parser_map["args"] = base::Bind(&IgnoreCapability);
parser_map["binary"] = base::Bind(&IgnoreCapability);
parser_map["extensions"] = base::Bind(&IgnoreCapability);
if (is_android) {
@@ -276,23 +259,23 @@ Status ParseChromeOptions(
base::Bind(&ParseString, &capabilities->android_package);
parser_map["androidProcess"] =
base::Bind(&ParseString, &capabilities->android_process);
- parser_map["args"] = base::Bind(&ParseArgs, true);
+ parser_map["args"] = base::Bind(&ParseSwitches);
} else if (is_existing) {
- parser_map["args"] = base::Bind(&IgnoreCapability);
- parser_map["useExistingBrowser"] = base::Bind(&ParseUseExistingBrowser);
+ parser_map["debuggerAddress"] = base::Bind(&ParseUseExistingBrowser);
} else {
- parser_map["forceDevToolsScreenshot"] = base::Bind(
- &ParseBoolean, &capabilities->force_devtools_screenshot);
- parser_map["args"] = base::Bind(&ParseArgs, false);
- parser_map["binary"] = base::Bind(&ParseChromeBinary);
+ parser_map["args"] = base::Bind(&ParseSwitches);
+ parser_map["binary"] = base::Bind(&ParseFilePath, &capabilities->binary);
parser_map["detach"] = base::Bind(&ParseBoolean, &capabilities->detach);
parser_map["excludeSwitches"] = base::Bind(&ParseExcludeSwitches);
parser_map["extensions"] = base::Bind(&ParseExtensions);
+ parser_map["forceDevToolsScreenshot"] = base::Bind(
+ &ParseBoolean, &capabilities->force_devtools_screenshot);
parser_map["loadAsync"] =
base::Bind(&IgnoreDeprecatedOption, log, "loadAsync");
- parser_map["localState"] = base::Bind(&ParseLocalState);
+ parser_map["localState"] =
+ base::Bind(&ParseDict, &capabilities->local_state);
parser_map["logPath"] = base::Bind(&ParseLogPath);
- parser_map["prefs"] = base::Bind(&ParsePrefs);
+ parser_map["prefs"] = base::Bind(&ParseDict, &capabilities->prefs);
}
for (base::DictionaryValue::Iterator it(*chrome_options); !it.IsAtEnd();
@@ -310,10 +293,116 @@ Status ParseChromeOptions(
} // namespace
+Switches::Switches() {}
+
+Switches::~Switches() {}
+
+void Switches::SetSwitch(const std::string& name) {
+ SetSwitch(name, NativeString());
+}
+
+void Switches::SetSwitch(const std::string& name, const std::string& value) {
+#if defined(OS_WIN)
+ SetSwitch(name, UTF8ToUTF16(value));
+#else
+ switch_map_[name] = value;
+#endif
+}
+
+void Switches::SetSwitch(const std::string& name, const string16& value) {
+#if defined(OS_WIN)
+ switch_map_[name] = value;
+#else
+ SetSwitch(name, UTF16ToUTF8(value));
+#endif
+}
+
+void Switches::SetSwitch(const std::string& name, const base::FilePath& value) {
+ SetSwitch(name, value.value());
+}
+
+void Switches::SetFromSwitches(const Switches& switches) {
+ for (SwitchMap::const_iterator iter = switches.switch_map_.begin();
+ iter != switches.switch_map_.end();
+ ++iter) {
+ switch_map_[iter->first] = iter->second;
+ }
+}
+
+void Switches::SetUnparsedSwitch(const std::string& unparsed_switch) {
+ std::string value;
+ size_t equals_index = unparsed_switch.find('=');
+ if (equals_index != std::string::npos)
+ value = unparsed_switch.substr(equals_index + 1);
+
+ std::string name;
+ size_t start_index = 0;
+ if (unparsed_switch.substr(0, 2) == "--")
+ start_index = 2;
+ name = unparsed_switch.substr(start_index, equals_index - start_index);
+
+ SetSwitch(name, value);
+}
+
+void Switches::RemoveSwitch(const std::string& name) {
+ switch_map_.erase(name);
+}
+
+bool Switches::HasSwitch(const std::string& name) const {
+ return switch_map_.count(name) > 0;
+}
+
+std::string Switches::GetSwitchValue(const std::string& name) const {
+ NativeString value = GetSwitchValueNative(name);
+#if defined(OS_WIN)
+ return UTF16ToUTF8(value);
+#else
+ return value;
+#endif
+}
+
+Switches::NativeString Switches::GetSwitchValueNative(
+ const std::string& name) const {
+ SwitchMap::const_iterator iter = switch_map_.find(name);
+ if (iter == switch_map_.end())
+ return NativeString();
+ return iter->second;
+}
+
+size_t Switches::GetSize() const {
+ return switch_map_.size();
+}
+
+void Switches::AppendToCommandLine(CommandLine* command) const {
+ for (SwitchMap::const_iterator iter = switch_map_.begin();
+ iter != switch_map_.end();
+ ++iter) {
+ command->AppendSwitchNative(iter->first, iter->second);
+ }
+}
+
+std::string Switches::ToString() const {
+ std::string str;
+ SwitchMap::const_iterator iter = switch_map_.begin();
+ while (iter != switch_map_.end()) {
+ str += "--" + iter->first;
+ std::string value = GetSwitchValue(iter->first);
+ if (value.length()) {
+ if (value.find(' ') != std::string::npos)
+ value = base::GetDoubleQuotedJson(value);
+ str += "=" + value;
+ }
+ ++iter;
+ if (iter == switch_map_.end())
+ break;
+ str += " ";
+ }
+ return str;
+}
+
Capabilities::Capabilities()
- : force_devtools_screenshot(false),
- detach(false),
- command(CommandLine::NO_PROGRAM) {}
+ : detach(false),
+ force_devtools_screenshot(false) {}
Capabilities::~Capabilities() {}
@@ -322,7 +411,7 @@ bool Capabilities::IsAndroid() const {
}
bool Capabilities::IsExistingBrowser() const {
- return use_existing_browser.IsValid();
+ return debugger_address.IsValid();
}
Status Capabilities::Parse(