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