Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/test/chromedriver/capabilities.h" | 5 #include "chrome/test/chromedriver/capabilities.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/json/string_escape.h" | |
| 11 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
| 13 #include "base/strings/string_tokenizer.h" | 14 #include "base/strings/string_tokenizer.h" |
| 14 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 15 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 17 #include "base/strings/utf_string_conversions.h" | |
| 16 #include "base/values.h" | 18 #include "base/values.h" |
| 17 #include "chrome/test/chromedriver/chrome/log.h" | 19 #include "chrome/test/chromedriver/chrome/log.h" |
| 18 #include "chrome/test/chromedriver/chrome/status.h" | 20 #include "chrome/test/chromedriver/chrome/status.h" |
| 19 #include "net/base/net_util.h" | 21 #include "net/base/net_util.h" |
| 20 | 22 |
| 21 namespace { | 23 namespace { |
| 22 | 24 |
| 23 typedef base::Callback<Status(const base::Value&, Capabilities*)> Parser; | 25 typedef base::Callback<Status(const base::Value&, Capabilities*)> Parser; |
| 24 | 26 |
| 25 Status ParseBoolean( | 27 Status ParseBoolean( |
| 26 bool* to_set, | 28 bool* to_set, |
| 27 const base::Value& option, | 29 const base::Value& option, |
| 28 Capabilities* capabilities) { | 30 Capabilities* capabilities) { |
| 29 if (!option.GetAsBoolean(to_set)) | 31 if (!option.GetAsBoolean(to_set)) |
| 30 return Status(kUnknownError, "value must be a boolean"); | 32 return Status(kUnknownError, "must be a boolean"); |
| 31 return Status(kOk); | 33 return Status(kOk); |
| 32 } | 34 } |
| 33 | 35 |
| 34 Status ParseString(std::string* to_set, | 36 Status ParseString(std::string* to_set, |
| 35 const base::Value& option, | 37 const base::Value& option, |
| 36 Capabilities* capabilities) { | 38 Capabilities* capabilities) { |
| 37 std::string str; | 39 std::string str; |
| 38 if (!option.GetAsString(&str)) | 40 if (!option.GetAsString(&str)) |
| 39 return Status(kUnknownError, "value must be a string"); | 41 return Status(kUnknownError, "must be a string"); |
| 40 if (str.empty()) | 42 if (str.empty()) |
| 41 return Status(kUnknownError, "value cannot be empty"); | 43 return Status(kUnknownError, "cannot be empty"); |
| 42 *to_set = str; | 44 *to_set = str; |
| 43 return Status(kOk); | 45 return Status(kOk); |
| 44 } | 46 } |
| 45 | 47 |
| 48 Status ParseFilePath(base::FilePath* to_set, | |
| 49 const base::Value& option, | |
| 50 Capabilities* capabilities) { | |
| 51 base::FilePath::StringType str; | |
| 52 if (!option.GetAsString(&str)) | |
| 53 return Status(kUnknownError, "must be a string"); | |
| 54 if (str.empty()) | |
| 55 return Status(kUnknownError, "cannot be empty"); | |
| 56 *to_set = base::FilePath(str); | |
| 57 return Status(kOk); | |
| 58 } | |
| 59 | |
| 60 Status ParseDict(scoped_ptr<base::DictionaryValue>* to_set, | |
| 61 const base::Value& option, | |
| 62 Capabilities* capabilities) { | |
| 63 const base::DictionaryValue* dict = NULL; | |
| 64 if (!option.GetAsDictionary(&dict)) | |
| 65 return Status(kUnknownError, "must be a dictionary"); | |
| 66 to_set->reset(dict->DeepCopy()); | |
| 67 return Status(kOk); | |
| 68 } | |
| 69 | |
| 46 Status IgnoreDeprecatedOption( | 70 Status IgnoreDeprecatedOption( |
| 47 Log* log, | 71 Log* log, |
| 48 const char* option_name, | 72 const char* option_name, |
| 49 const base::Value& option, | 73 const base::Value& option, |
| 50 Capabilities* capabilities) { | 74 Capabilities* capabilities) { |
| 51 log->AddEntry(Log::kWarning, | 75 log->AddEntry(Log::kWarning, |
| 52 base::StringPrintf("deprecated chrome option is ignored: '%s'", | 76 base::StringPrintf("deprecated chrome option is ignored: '%s'", |
| 53 option_name)); | 77 option_name)); |
| 54 return Status(kOk); | 78 return Status(kOk); |
| 55 } | 79 } |
| 56 | 80 |
| 57 Status IgnoreCapability(const base::Value& option, Capabilities* capabilities) { | 81 Status IgnoreCapability(const base::Value& option, Capabilities* capabilities) { |
| 58 return Status(kOk); | 82 return Status(kOk); |
| 59 } | 83 } |
| 60 | 84 |
| 61 Status ParseChromeBinary( | |
| 62 const base::Value& option, | |
| 63 Capabilities* capabilities) { | |
| 64 base::FilePath::StringType path_str; | |
| 65 if (!option.GetAsString(&path_str)) | |
| 66 return Status(kUnknownError, "'binary' must be a string"); | |
| 67 base::FilePath chrome_exe(path_str); | |
| 68 capabilities->command.SetProgram(chrome_exe); | |
| 69 return Status(kOk); | |
| 70 } | |
| 71 | |
| 72 Status ParseLogPath(const base::Value& option, Capabilities* capabilities) { | 85 Status ParseLogPath(const base::Value& option, Capabilities* capabilities) { |
| 73 if (!option.GetAsString(&capabilities->log_path)) | 86 if (!option.GetAsString(&capabilities->log_path)) |
| 74 return Status(kUnknownError, "'logPath' must be a string"); | 87 return Status(kUnknownError, "must be a string"); |
| 75 return Status(kOk); | 88 return Status(kOk); |
| 76 } | 89 } |
| 77 | 90 |
| 78 Status ParseArgs(bool is_android, | 91 Status ParseSwitches(const base::Value& option, |
| 79 const base::Value& option, | 92 Capabilities* capabilities) { |
| 80 Capabilities* capabilities) { | 93 const base::ListValue* switches_list = NULL; |
| 81 const base::ListValue* args_list = NULL; | 94 if (!option.GetAsList(&switches_list)) |
| 82 if (!option.GetAsList(&args_list)) | 95 return Status(kUnknownError, "must be a list"); |
| 83 return Status(kUnknownError, "'args' must be a list"); | 96 for (size_t i = 0; i < switches_list->GetSize(); ++i) { |
| 84 for (size_t i = 0; i < args_list->GetSize(); ++i) { | |
| 85 std::string arg_string; | 97 std::string arg_string; |
| 86 if (!args_list->GetString(i, &arg_string)) | 98 if (!switches_list->GetString(i, &arg_string)) |
| 87 return Status(kUnknownError, "each argument must be a string"); | 99 return Status(kUnknownError, "each argument must be a string"); |
| 88 if (is_android) { | 100 capabilities->switches.SetUnparsedSwitch(arg_string); |
| 89 capabilities->android_args += "--" + arg_string + " "; | |
| 90 } else { | |
| 91 size_t separator_index = arg_string.find("="); | |
| 92 if (separator_index != std::string::npos) { | |
| 93 CommandLine::StringType arg_string_native; | |
| 94 if (!args_list->GetString(i, &arg_string_native)) | |
| 95 return Status(kUnknownError, "each argument must be a string"); | |
| 96 capabilities->command.AppendSwitchNative( | |
| 97 arg_string.substr(0, separator_index), | |
| 98 arg_string_native.substr(separator_index + 1)); | |
| 99 } else { | |
| 100 capabilities->command.AppendSwitch(arg_string); | |
| 101 } | |
| 102 } | |
| 103 } | 101 } |
| 104 return Status(kOk); | 102 return Status(kOk); |
| 105 } | 103 } |
| 106 | 104 |
| 107 Status ParsePrefs(const base::Value& option, Capabilities* capabilities) { | |
| 108 const base::DictionaryValue* prefs = NULL; | |
| 109 if (!option.GetAsDictionary(&prefs)) | |
| 110 return Status(kUnknownError, "'prefs' must be a dictionary"); | |
| 111 capabilities->prefs.reset(prefs->DeepCopy()); | |
| 112 return Status(kOk); | |
| 113 } | |
| 114 | |
| 115 Status ParseLocalState(const base::Value& option, Capabilities* capabilities) { | |
| 116 const base::DictionaryValue* local_state = NULL; | |
| 117 if (!option.GetAsDictionary(&local_state)) | |
| 118 return Status(kUnknownError, "'localState' must be a dictionary"); | |
| 119 capabilities->local_state.reset(local_state->DeepCopy()); | |
| 120 return Status(kOk); | |
| 121 } | |
| 122 | |
| 123 Status ParseExtensions(const base::Value& option, Capabilities* capabilities) { | 105 Status ParseExtensions(const base::Value& option, Capabilities* capabilities) { |
| 124 const base::ListValue* extensions = NULL; | 106 const base::ListValue* extensions = NULL; |
| 125 if (!option.GetAsList(&extensions)) | 107 if (!option.GetAsList(&extensions)) |
| 126 return Status(kUnknownError, "'extensions' must be a list"); | 108 return Status(kUnknownError, "must be a list"); |
| 127 for (size_t i = 0; i < extensions->GetSize(); ++i) { | 109 for (size_t i = 0; i < extensions->GetSize(); ++i) { |
| 128 std::string extension; | 110 std::string extension; |
| 129 if (!extensions->GetString(i, &extension)) { | 111 if (!extensions->GetString(i, &extension)) { |
| 130 return Status(kUnknownError, | 112 return Status(kUnknownError, |
| 131 "each extension must be a base64 encoded string"); | 113 "each extension must be a base64 encoded string"); |
| 132 } | 114 } |
| 133 capabilities->extensions.push_back(extension); | 115 capabilities->extensions.push_back(extension); |
| 134 } | 116 } |
| 135 return Status(kOk); | 117 return Status(kOk); |
| 136 } | 118 } |
| 137 | 119 |
| 138 Status ParseProxy(const base::Value& option, Capabilities* capabilities) { | 120 Status ParseProxy(const base::Value& option, Capabilities* capabilities) { |
| 139 const base::DictionaryValue* proxy_dict; | 121 const base::DictionaryValue* proxy_dict; |
| 140 if (!option.GetAsDictionary(&proxy_dict)) | 122 if (!option.GetAsDictionary(&proxy_dict)) |
| 141 return Status(kUnknownError, "'proxy' must be a dictionary"); | 123 return Status(kUnknownError, "must be a dictionary"); |
| 142 std::string proxy_type; | 124 std::string proxy_type; |
| 143 if (!proxy_dict->GetString("proxyType", &proxy_type)) | 125 if (!proxy_dict->GetString("proxyType", &proxy_type)) |
| 144 return Status(kUnknownError, "'proxyType' must be a string"); | 126 return Status(kUnknownError, "'proxyType' must be a string"); |
| 145 proxy_type = StringToLowerASCII(proxy_type); | 127 proxy_type = StringToLowerASCII(proxy_type); |
| 146 if (proxy_type == "direct") { | 128 if (proxy_type == "direct") { |
| 147 capabilities->command.AppendSwitch("no-proxy-server"); | 129 capabilities->switches.SetSwitch("no-proxy-server"); |
| 148 } else if (proxy_type == "system") { | 130 } else if (proxy_type == "system") { |
| 149 // Chrome default. | 131 // Chrome default. |
| 150 } else if (proxy_type == "pac") { | 132 } else if (proxy_type == "pac") { |
| 151 CommandLine::StringType proxy_pac_url; | 133 CommandLine::StringType proxy_pac_url; |
|
kkania
2013/08/30 03:14:57
string
| |
| 152 if (!proxy_dict->GetString("proxyAutoconfigUrl", &proxy_pac_url)) | 134 if (!proxy_dict->GetString("proxyAutoconfigUrl", &proxy_pac_url)) |
| 153 return Status(kUnknownError, "'proxyAutoconfigUrl' must be a string"); | 135 return Status(kUnknownError, "'proxyAutoconfigUrl' must be a string"); |
| 154 capabilities->command.AppendSwitchNative("proxy-pac-url", proxy_pac_url); | 136 capabilities->switches.SetSwitch("proxy-pac-url", proxy_pac_url); |
| 155 } else if (proxy_type == "autodetect") { | 137 } else if (proxy_type == "autodetect") { |
| 156 capabilities->command.AppendSwitch("proxy-auto-detect"); | 138 capabilities->switches.SetSwitch("proxy-auto-detect"); |
| 157 } else if (proxy_type == "manual") { | 139 } else if (proxy_type == "manual") { |
| 158 const char* proxy_servers_options[][2] = { | 140 const char* proxy_servers_options[][2] = { |
| 159 {"ftpProxy", "ftp"}, {"httpProxy", "http"}, {"sslProxy", "https"}}; | 141 {"ftpProxy", "ftp"}, {"httpProxy", "http"}, {"sslProxy", "https"}}; |
| 160 const base::Value* option_value = NULL; | 142 const base::Value* option_value = NULL; |
| 161 std::string proxy_servers; | 143 std::string proxy_servers; |
| 162 for (size_t i = 0; i < arraysize(proxy_servers_options); ++i) { | 144 for (size_t i = 0; i < arraysize(proxy_servers_options); ++i) { |
| 163 if (!proxy_dict->Get(proxy_servers_options[i][0], &option_value) || | 145 if (!proxy_dict->Get(proxy_servers_options[i][0], &option_value) || |
| 164 option_value->IsType(base::Value::TYPE_NULL)) { | 146 option_value->IsType(base::Value::TYPE_NULL)) { |
| 165 continue; | 147 continue; |
| 166 } | 148 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 185 if (!option_value->GetAsString(&proxy_bypass_list)) | 167 if (!option_value->GetAsString(&proxy_bypass_list)) |
| 186 return Status(kUnknownError, "'noProxy' must be a string"); | 168 return Status(kUnknownError, "'noProxy' must be a string"); |
| 187 } | 169 } |
| 188 | 170 |
| 189 if (proxy_servers.empty() && proxy_bypass_list.empty()) { | 171 if (proxy_servers.empty() && proxy_bypass_list.empty()) { |
| 190 return Status(kUnknownError, | 172 return Status(kUnknownError, |
| 191 "proxyType is 'manual' but no manual " | 173 "proxyType is 'manual' but no manual " |
| 192 "proxy capabilities were found"); | 174 "proxy capabilities were found"); |
| 193 } | 175 } |
| 194 if (!proxy_servers.empty()) | 176 if (!proxy_servers.empty()) |
| 195 capabilities->command.AppendSwitchASCII("proxy-server", proxy_servers); | 177 capabilities->switches.SetSwitch("proxy-server", proxy_servers); |
| 196 if (!proxy_bypass_list.empty()) { | 178 if (!proxy_bypass_list.empty()) { |
| 197 capabilities->command.AppendSwitchASCII("proxy-bypass-list", | 179 capabilities->switches.SetSwitch("proxy-bypass-list", |
| 198 proxy_bypass_list); | 180 proxy_bypass_list); |
| 199 } | 181 } |
| 200 } else { | 182 } else { |
| 201 return Status(kUnknownError, "unrecognized proxy type:" + proxy_type); | 183 return Status(kUnknownError, "unrecognized proxy type:" + proxy_type); |
| 202 } | 184 } |
| 203 return Status(kOk); | 185 return Status(kOk); |
| 204 } | 186 } |
| 205 | 187 |
| 206 Status ParseExcludeSwitches(const base::Value& option, | 188 Status ParseExcludeSwitches(const base::Value& option, |
| 207 Capabilities* capabilities) { | 189 Capabilities* capabilities) { |
| 208 const base::ListValue* switches = NULL; | 190 const base::ListValue* switches = NULL; |
| 209 if (!option.GetAsList(&switches)) | 191 if (!option.GetAsList(&switches)) |
| 210 return Status(kUnknownError, "'excludeSwitches' must be a list"); | 192 return Status(kUnknownError, "must be a list"); |
| 211 for (size_t i = 0; i < switches->GetSize(); ++i) { | 193 for (size_t i = 0; i < switches->GetSize(); ++i) { |
| 212 std::string switch_name; | 194 std::string switch_name; |
| 213 if (!switches->GetString(i, &switch_name)) { | 195 if (!switches->GetString(i, &switch_name)) { |
| 214 return Status(kUnknownError, | 196 return Status(kUnknownError, |
| 215 "each switch to be removed must be a string"); | 197 "each switch to be removed must be a string"); |
| 216 } | 198 } |
| 217 capabilities->exclude_switches.insert(switch_name); | 199 capabilities->exclude_switches.insert(switch_name); |
| 218 } | 200 } |
| 219 return Status(kOk); | 201 return Status(kOk); |
| 220 } | 202 } |
| 221 | 203 |
| 222 Status ParseUseExistingBrowser(const base::Value& option, | 204 Status ParseUseExistingBrowser(const base::Value& option, |
| 223 Capabilities* capabilities) { | 205 Capabilities* capabilities) { |
| 224 std::string server_addr; | 206 std::string server_addr; |
| 225 if (!option.GetAsString(&server_addr)) | 207 if (!option.GetAsString(&server_addr)) |
| 226 return Status(kUnknownError, "must be 'host:port'"); | 208 return Status(kUnknownError, "must be 'host:port'"); |
| 227 | 209 |
| 228 std::vector<std::string> values; | 210 std::vector<std::string> values; |
| 229 base::SplitString(server_addr, ':', &values); | 211 base::SplitString(server_addr, ':', &values); |
| 230 if (values.size() != 2) | 212 if (values.size() != 2) |
| 231 return Status(kUnknownError, "must be 'host:port'"); | 213 return Status(kUnknownError, "must be 'host:port'"); |
| 232 | 214 |
| 233 int port = 0; | 215 int port = 0; |
| 234 base::StringToInt(values[1], &port); | 216 base::StringToInt(values[1], &port); |
| 235 if (port <= 0) | 217 if (port <= 0) |
| 236 return Status(kUnknownError, "port must be >= 0"); | 218 return Status(kUnknownError, "port must be > 0"); |
| 237 | 219 |
| 238 capabilities->use_existing_browser = NetAddress(values[0], port); | 220 capabilities->debugger_address = NetAddress(values[0], port); |
| 239 return Status(kOk); | 221 return Status(kOk); |
| 240 } | 222 } |
| 241 | 223 |
| 242 Status ParseLoggingPrefs(const base::Value& option, | 224 Status ParseLoggingPrefs(const base::Value& option, |
| 243 Capabilities* capabilities) { | 225 Capabilities* capabilities) { |
| 244 const base::DictionaryValue* logging_prefs_dict = NULL; | 226 const base::DictionaryValue* logging_prefs_dict = NULL; |
| 245 if (!option.GetAsDictionary(&logging_prefs_dict)) | 227 if (!option.GetAsDictionary(&logging_prefs_dict)) |
| 246 return Status(kUnknownError, "'loggingPrefs' must be a dictionary"); | 228 return Status(kUnknownError, "must be a dictionary"); |
| 247 | 229 |
| 248 // TODO(klm): verify log types. | 230 // TODO(klm): verify log types. |
| 249 // TODO(klm): verify log levels. | 231 // TODO(klm): verify log levels. |
| 250 capabilities->logging_prefs.reset(logging_prefs_dict->DeepCopy()); | 232 capabilities->logging_prefs.reset(logging_prefs_dict->DeepCopy()); |
| 251 return Status(kOk); | 233 return Status(kOk); |
| 252 } | 234 } |
| 253 | 235 |
| 254 Status ParseChromeOptions( | 236 Status ParseChromeOptions( |
| 255 Log* log, | 237 Log* log, |
| 256 const base::Value& capability, | 238 const base::Value& capability, |
| 257 Capabilities* capabilities) { | 239 Capabilities* capabilities) { |
| 258 const base::DictionaryValue* chrome_options = NULL; | 240 const base::DictionaryValue* chrome_options = NULL; |
| 259 if (!capability.GetAsDictionary(&chrome_options)) | 241 if (!capability.GetAsDictionary(&chrome_options)) |
| 260 return Status(kUnknownError, "'chromeOptions' must be a dictionary"); | 242 return Status(kUnknownError, "must be a dictionary"); |
| 261 | 243 |
| 262 bool is_android = chrome_options->HasKey("androidPackage"); | 244 bool is_android = chrome_options->HasKey("androidPackage"); |
| 263 bool is_existing = chrome_options->HasKey("useExistingBrowser"); | 245 bool is_existing = chrome_options->HasKey("debuggerAddress"); |
| 264 | 246 |
| 265 std::map<std::string, Parser> parser_map; | 247 std::map<std::string, Parser> parser_map; |
| 266 // Ignore 'binary' and 'extensions' capability, since the Java client | 248 // Ignore 'args', 'binary' and 'extensions' capabilities by default, since the |
| 267 // always passes them. | 249 // Java client always passes them. |
| 250 parser_map["args"] = base::Bind(&IgnoreCapability); | |
| 268 parser_map["binary"] = base::Bind(&IgnoreCapability); | 251 parser_map["binary"] = base::Bind(&IgnoreCapability); |
| 269 parser_map["extensions"] = base::Bind(&IgnoreCapability); | 252 parser_map["extensions"] = base::Bind(&IgnoreCapability); |
| 270 if (is_android) { | 253 if (is_android) { |
| 271 parser_map["androidActivity"] = | 254 parser_map["androidActivity"] = |
| 272 base::Bind(&ParseString, &capabilities->android_activity); | 255 base::Bind(&ParseString, &capabilities->android_activity); |
| 273 parser_map["androidDeviceSerial"] = | 256 parser_map["androidDeviceSerial"] = |
| 274 base::Bind(&ParseString, &capabilities->android_device_serial); | 257 base::Bind(&ParseString, &capabilities->android_device_serial); |
| 275 parser_map["androidPackage"] = | 258 parser_map["androidPackage"] = |
| 276 base::Bind(&ParseString, &capabilities->android_package); | 259 base::Bind(&ParseString, &capabilities->android_package); |
| 277 parser_map["androidProcess"] = | 260 parser_map["androidProcess"] = |
| 278 base::Bind(&ParseString, &capabilities->android_process); | 261 base::Bind(&ParseString, &capabilities->android_process); |
| 279 parser_map["args"] = base::Bind(&ParseArgs, true); | 262 parser_map["args"] = base::Bind(&ParseSwitches); |
| 280 } else if (is_existing) { | 263 } else if (is_existing) { |
| 281 parser_map["args"] = base::Bind(&IgnoreCapability); | 264 parser_map["debuggerAddress"] = base::Bind(&ParseUseExistingBrowser); |
| 282 parser_map["useExistingBrowser"] = base::Bind(&ParseUseExistingBrowser); | |
| 283 } else { | 265 } else { |
| 284 parser_map["forceDevToolsScreenshot"] = base::Bind( | 266 parser_map["args"] = base::Bind(&ParseSwitches); |
| 285 &ParseBoolean, &capabilities->force_devtools_screenshot); | 267 parser_map["binary"] = base::Bind(&ParseFilePath, &capabilities->binary); |
| 286 parser_map["args"] = base::Bind(&ParseArgs, false); | |
| 287 parser_map["binary"] = base::Bind(&ParseChromeBinary); | |
| 288 parser_map["detach"] = base::Bind(&ParseBoolean, &capabilities->detach); | 268 parser_map["detach"] = base::Bind(&ParseBoolean, &capabilities->detach); |
| 289 parser_map["excludeSwitches"] = base::Bind(&ParseExcludeSwitches); | 269 parser_map["excludeSwitches"] = base::Bind(&ParseExcludeSwitches); |
| 290 parser_map["extensions"] = base::Bind(&ParseExtensions); | 270 parser_map["extensions"] = base::Bind(&ParseExtensions); |
| 271 parser_map["forceDevToolsScreenshot"] = base::Bind( | |
| 272 &ParseBoolean, &capabilities->force_devtools_screenshot); | |
| 291 parser_map["loadAsync"] = | 273 parser_map["loadAsync"] = |
| 292 base::Bind(&IgnoreDeprecatedOption, log, "loadAsync"); | 274 base::Bind(&IgnoreDeprecatedOption, log, "loadAsync"); |
| 293 parser_map["localState"] = base::Bind(&ParseLocalState); | 275 parser_map["localState"] = |
| 276 base::Bind(&ParseDict, &capabilities->local_state); | |
| 294 parser_map["logPath"] = base::Bind(&ParseLogPath); | 277 parser_map["logPath"] = base::Bind(&ParseLogPath); |
| 295 parser_map["prefs"] = base::Bind(&ParsePrefs); | 278 parser_map["prefs"] = base::Bind(&ParseDict, &capabilities->prefs); |
| 296 } | 279 } |
| 297 | 280 |
| 298 for (base::DictionaryValue::Iterator it(*chrome_options); !it.IsAtEnd(); | 281 for (base::DictionaryValue::Iterator it(*chrome_options); !it.IsAtEnd(); |
| 299 it.Advance()) { | 282 it.Advance()) { |
| 300 if (parser_map.find(it.key()) == parser_map.end()) { | 283 if (parser_map.find(it.key()) == parser_map.end()) { |
| 301 return Status(kUnknownError, | 284 return Status(kUnknownError, |
| 302 "unrecognized chrome option: " + it.key()); | 285 "unrecognized chrome option: " + it.key()); |
| 303 } | 286 } |
| 304 Status status = parser_map[it.key()].Run(it.value(), capabilities); | 287 Status status = parser_map[it.key()].Run(it.value(), capabilities); |
| 305 if (status.IsError()) | 288 if (status.IsError()) |
| 306 return Status(kUnknownError, "cannot parse " + it.key(), status); | 289 return Status(kUnknownError, "cannot parse " + it.key(), status); |
| 307 } | 290 } |
| 308 return Status(kOk); | 291 return Status(kOk); |
| 309 } | 292 } |
| 310 | 293 |
| 311 } // namespace | 294 } // namespace |
| 312 | 295 |
| 296 Switches::Switches() {} | |
| 297 | |
| 298 Switches::~Switches() {} | |
| 299 | |
| 300 void Switches::SetSwitch(const std::string& name) { | |
| 301 SetSwitch(name, NativeString()); | |
| 302 } | |
| 303 | |
| 304 void Switches::SetSwitch(const std::string& name, const std::string& value) { | |
| 305 #if defined(OS_WIN) | |
| 306 SetSwitch(name, UTF8ToUTF16(value)); | |
| 307 #else | |
| 308 switch_map_[name] = value; | |
| 309 #endif | |
| 310 } | |
| 311 | |
| 312 void Switches::SetSwitch(const std::string& name, const string16& value) { | |
| 313 #if defined(OS_WIN) | |
| 314 switch_map_[name] = value; | |
| 315 #else | |
| 316 SetSwitch(name, UTF16ToUTF8(value)); | |
| 317 #endif | |
| 318 } | |
| 319 | |
| 320 void Switches::SetSwitch(const std::string& name, const base::FilePath& value) { | |
| 321 SetSwitch(name, value.value()); | |
| 322 } | |
| 323 | |
| 324 void Switches::SetFromSwitches(const Switches& switches) { | |
| 325 for (SwitchMap::const_iterator iter = switches.switch_map_.begin(); | |
| 326 iter != switches.switch_map_.end(); | |
| 327 ++iter) { | |
| 328 switch_map_[iter->first] = iter->second; | |
| 329 } | |
| 330 } | |
| 331 | |
| 332 void Switches::SetUnparsedSwitch(const std::string& unparsed_switch) { | |
| 333 std::string value; | |
| 334 size_t equals_index = unparsed_switch.find('='); | |
| 335 if (equals_index != std::string::npos) | |
| 336 value = unparsed_switch.substr(equals_index + 1); | |
| 337 | |
| 338 std::string name; | |
| 339 size_t start_index = 0; | |
| 340 if (unparsed_switch.substr(0, 2) == "--") | |
| 341 start_index = 2; | |
| 342 name = unparsed_switch.substr(start_index, equals_index - start_index); | |
| 343 | |
| 344 SetSwitch(name, value); | |
| 345 } | |
| 346 | |
| 347 void Switches::RemoveSwitch(const std::string& name) { | |
| 348 switch_map_.erase(name); | |
| 349 } | |
| 350 | |
| 351 bool Switches::HasSwitch(const std::string& name) const { | |
| 352 return switch_map_.count(name) > 0; | |
| 353 } | |
| 354 | |
| 355 std::string Switches::GetSwitchValue(const std::string& name) const { | |
| 356 NativeString value = GetSwitchValueNative(name); | |
| 357 #if defined(OS_WIN) | |
| 358 return UTF16ToUTF8(value); | |
| 359 #else | |
| 360 return value; | |
| 361 #endif | |
| 362 } | |
| 363 | |
| 364 Switches::NativeString Switches::GetSwitchValueNative( | |
| 365 const std::string& name) const { | |
| 366 SwitchMap::const_iterator iter = switch_map_.find(name); | |
| 367 if (iter == switch_map_.end()) | |
| 368 return NativeString(); | |
| 369 return iter->second; | |
| 370 } | |
| 371 | |
| 372 size_t Switches::GetSize() const { | |
| 373 return switch_map_.size(); | |
| 374 } | |
| 375 | |
| 376 void Switches::AppendToCommandLine(CommandLine* command) const { | |
| 377 for (SwitchMap::const_iterator iter = switch_map_.begin(); | |
| 378 iter != switch_map_.end(); | |
| 379 ++iter) { | |
| 380 command->AppendSwitchNative(iter->first, iter->second); | |
| 381 } | |
| 382 } | |
| 383 | |
| 384 std::string Switches::ToString() const { | |
| 385 std::string str; | |
| 386 SwitchMap::const_iterator iter = switch_map_.begin(); | |
| 387 while (iter != switch_map_.end()) { | |
| 388 str += "--" + iter->first; | |
| 389 std::string value = GetSwitchValue(iter->first); | |
| 390 if (value.length()) { | |
| 391 if (value.find(' ') != std::string::npos) | |
| 392 value = base::GetDoubleQuotedJson(value); | |
|
kkania
2013/08/30 03:14:57
will this work with adb_impl?
| |
| 393 str += "=" + value; | |
| 394 } | |
| 395 ++iter; | |
| 396 if (iter == switch_map_.end()) | |
| 397 break; | |
| 398 str += " "; | |
| 399 } | |
| 400 return str; | |
| 401 } | |
| 402 | |
| 313 Capabilities::Capabilities() | 403 Capabilities::Capabilities() |
| 314 : force_devtools_screenshot(false), | 404 : detach(false), |
| 315 detach(false), | 405 force_devtools_screenshot(false) {} |
| 316 command(CommandLine::NO_PROGRAM) {} | |
| 317 | 406 |
| 318 Capabilities::~Capabilities() {} | 407 Capabilities::~Capabilities() {} |
| 319 | 408 |
| 320 bool Capabilities::IsAndroid() const { | 409 bool Capabilities::IsAndroid() const { |
| 321 return !android_package.empty(); | 410 return !android_package.empty(); |
| 322 } | 411 } |
| 323 | 412 |
| 324 bool Capabilities::IsExistingBrowser() const { | 413 bool Capabilities::IsExistingBrowser() const { |
| 325 return use_existing_browser.IsValid(); | 414 return debugger_address.IsValid(); |
| 326 } | 415 } |
| 327 | 416 |
| 328 Status Capabilities::Parse( | 417 Status Capabilities::Parse( |
| 329 const base::DictionaryValue& desired_caps, | 418 const base::DictionaryValue& desired_caps, |
| 330 Log* log) { | 419 Log* log) { |
| 331 std::map<std::string, Parser> parser_map; | 420 std::map<std::string, Parser> parser_map; |
| 332 parser_map["chromeOptions"] = base::Bind(&ParseChromeOptions, log); | 421 parser_map["chromeOptions"] = base::Bind(&ParseChromeOptions, log); |
| 333 parser_map["loggingPrefs"] = base::Bind(&ParseLoggingPrefs); | 422 parser_map["loggingPrefs"] = base::Bind(&ParseLoggingPrefs); |
| 334 parser_map["proxy"] = base::Bind(&ParseProxy); | 423 parser_map["proxy"] = base::Bind(&ParseProxy); |
| 335 for (std::map<std::string, Parser>::iterator it = parser_map.begin(); | 424 for (std::map<std::string, Parser>::iterator it = parser_map.begin(); |
| 336 it != parser_map.end(); ++it) { | 425 it != parser_map.end(); ++it) { |
| 337 const base::Value* capability = NULL; | 426 const base::Value* capability = NULL; |
| 338 if (desired_caps.Get(it->first, &capability)) { | 427 if (desired_caps.Get(it->first, &capability)) { |
| 339 Status status = it->second.Run(*capability, this); | 428 Status status = it->second.Run(*capability, this); |
| 340 if (status.IsError()) { | 429 if (status.IsError()) { |
| 341 return Status( | 430 return Status( |
| 342 kUnknownError, "cannot parse capability: " + it->first, status); | 431 kUnknownError, "cannot parse capability: " + it->first, status); |
| 343 } | 432 } |
| 344 } | 433 } |
| 345 } | 434 } |
| 346 return Status(kOk); | 435 return Status(kOk); |
| 347 } | 436 } |
| OLD | NEW |