OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/test/chromedriver/capabilities_parser.h" | |
6 | |
7 #include <map> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/callback.h" | |
11 #include "base/string_util.h" | |
12 #include "base/stringprintf.h" | |
13 #include "chrome/test/chromedriver/chrome/status.h" | |
14 | |
15 namespace { | |
16 | |
17 Status ParseChromeBinary( | |
18 const base::Callback<bool(const base::FilePath&)>& file_checker, | |
19 const base::Value& option, | |
20 Capabilities* capabilities) { | |
21 base::FilePath::StringType path_str; | |
22 if (!option.GetAsString(&path_str)) | |
23 return Status(kUnknownError, "'binary' must be a string"); | |
24 base::FilePath chrome_exe(path_str); | |
25 if (!file_checker.Run(chrome_exe)) { | |
26 return Status(kUnknownError, | |
27 base::StringPrintf("no chrome binary at %" PRFilePath, | |
28 path_str.c_str())); | |
29 } | |
30 capabilities->chrome_exe = chrome_exe; | |
31 return Status(kOk); | |
32 } | |
33 | |
34 Status ParseLogPath(const base::Value& option, Capabilities* capabilities) { | |
35 if (!option.GetAsString(&capabilities->log_path)) | |
36 return Status(kUnknownError, "'logPath' must be a string"); | |
37 return Status(kOk); | |
38 } | |
39 | |
40 Status ParseArgs(const base::Value& option, Capabilities* capabilities) { | |
41 const base::ListValue* args_list = NULL; | |
42 if (!option.GetAsList(&args_list)) | |
43 return Status(kUnknownError, "'args' must be a list"); | |
44 for (size_t i = 0; i < args_list->GetSize(); ++i) { | |
45 const base::Value* value = NULL; | |
46 args_list->Get(i, &value); | |
47 capabilities->args.Append(value->DeepCopy()); | |
48 } | |
49 return Status(kOk); | |
50 } | |
51 | |
52 Status ParsePrefs(const base::Value& option, Capabilities* capabilities) { | |
53 if (!option.GetAsDictionary(&capabilities->prefs)) | |
54 return Status(kUnknownError, "'prefs' must be a dictionary"); | |
55 return Status(kOk); | |
56 } | |
57 | |
58 Status ParseLocalState(const base::Value& option, Capabilities* capabilities) { | |
59 if (!option.GetAsDictionary(&capabilities->local_state)) | |
60 return Status(kUnknownError, "'localState' must be a dictionary"); | |
61 return Status(kOk); | |
62 } | |
63 | |
64 Status ParseExtensions(const base::Value& option, Capabilities* capabilities) { | |
65 if (!option.GetAsList(&capabilities->extensions)) | |
66 return Status(kUnknownError, "'extensions' must be a list"); | |
67 return Status(kOk); | |
68 } | |
69 | |
70 Status ParseProxy(const base::Value& option, Capabilities* capabilities) { | |
71 const base::DictionaryValue* proxy_dict; | |
72 if (!option.GetAsDictionary(&proxy_dict)) | |
73 return Status(kUnknownError, "'proxy' must be a dictionary"); | |
74 std::string proxy_type; | |
75 if (!proxy_dict->GetString("proxyType", &proxy_type)) | |
76 return Status(kUnknownError, "'proxyType' must be a string"); | |
77 proxy_type = StringToLowerASCII(proxy_type); | |
78 if (proxy_type == "direct") { | |
79 capabilities->args.AppendString("no-proxy-server"); | |
80 } else if (proxy_type == "system") { | |
81 // Chrome default. | |
82 } else if (proxy_type == "pac") { | |
83 std::string proxy_pac_url; | |
84 if (!proxy_dict->GetString("proxyAutoconfigUrl", &proxy_pac_url)) | |
85 return Status(kUnknownError, "'proxyAutoconfigUrl' must be a string"); | |
86 capabilities->args.AppendString("proxy-pac-url=" + proxy_pac_url); | |
87 } else if (proxy_type == "autodetect") { | |
88 capabilities->args.AppendString("proxy-auto-detect"); | |
89 } else if (proxy_type == "manual") { | |
90 const char* proxy_servers_options[][2] = { | |
91 {"ftpProxy", "ftp"}, {"httpProxy", "http"}, {"sslProxy", "https"}}; | |
92 std::string proxy_servers; | |
93 for (size_t i = 0; i < arraysize(proxy_servers_options); ++i) { | |
94 if (!proxy_dict->HasKey(proxy_servers_options[i][0])) | |
95 continue; | |
96 std::string value; | |
97 if (!proxy_dict->GetString(proxy_servers_options[i][0], &value)) { | |
98 return Status( | |
99 kUnknownError, | |
100 base::StringPrintf("'%s' must be a string", | |
101 proxy_servers_options[i][0])); | |
102 } | |
103 // Converts into Chrome proxy scheme. | |
104 // Example: "http=localhost:9000;ftp=localhost:8000". | |
105 if (!proxy_servers.empty()) | |
106 proxy_servers += ";"; | |
107 proxy_servers += base::StringPrintf( | |
108 "%s=%s", proxy_servers_options[i][1], value.c_str()); | |
109 } | |
110 | |
111 std::string proxy_bypass_list; | |
112 if (proxy_dict->HasKey("noProxy")) { | |
113 if (!proxy_dict->GetString("noProxy", & proxy_bypass_list)) | |
114 return Status(kUnknownError, "'noProxy' must be a string"); | |
115 } | |
116 | |
117 if (proxy_servers.empty() && proxy_bypass_list.empty()) { | |
118 return Status(kUnknownError, "proxyType is 'manual' but no manual " | |
119 "proxy capabilities were found"); | |
120 } | |
121 if (!proxy_servers.empty()) | |
122 capabilities->args.AppendString("proxy-server=" + proxy_servers); | |
123 if (!proxy_bypass_list.empty()) | |
124 capabilities->args.AppendString("proxy-bypass-list=" + proxy_bypass_list); | |
125 } else { | |
126 return Status(kUnknownError, "unrecognized proxy type:" + proxy_type); | |
127 } | |
128 return Status(kOk); | |
129 } | |
130 | |
131 } // namespace | |
132 | |
133 Capabilities::Capabilities() | |
134 : prefs(NULL), local_state(NULL), extensions(NULL) {} | |
135 | |
136 Capabilities::~Capabilities() {} | |
137 | |
138 bool Capabilities::HasAndroidPackage() const { | |
139 return !android_package.empty(); | |
140 } | |
141 | |
142 Status Capabilities::Parse( | |
143 const base::DictionaryValue& chrome_options, | |
144 const base::Callback<bool(const base::FilePath&)>& file_checker) { | |
145 const base::Value* android_package_value; | |
146 if (chrome_options.Get("android_package", &android_package_value)) { | |
147 if (!android_package_value->GetAsString(&android_package) || | |
148 android_package.empty()) { | |
149 return Status(kUnknownError, | |
150 "'android_package' must be a non-empty string"); | |
151 } else if (chrome_options.size() > 1u) { | |
152 return Status(kUnknownError, | |
153 "Android only supports option 'android_package'"); | |
154 } | |
155 } else { | |
156 typedef base::Callback<Status(const base::Value&, Capabilities*)> Parser; | |
157 std::map<std::string, Parser> parser_map; | |
158 | |
159 parser_map["binary"] = base::Bind(&ParseChromeBinary, file_checker); | |
160 parser_map["logPath"] = base::Bind(&ParseLogPath); | |
161 parser_map["args"] = base::Bind(&ParseArgs); | |
162 parser_map["prefs"] = base::Bind(&ParsePrefs); | |
163 parser_map["localState"] = base::Bind(&ParseLocalState); | |
164 parser_map["extensions"] = base::Bind(&ParseExtensions); | |
165 parser_map["proxy"] = base::Bind(&ParseProxy); | |
kkania
2013/04/03 19:09:35
this isn't part of chromeOptions. It's a cross-bro
chrisgao (Use stgao instead)
2013/04/06 01:12:01
Done.
| |
166 | |
167 for (base::DictionaryValue::Iterator it(chrome_options); !it.IsAtEnd(); | |
168 it.Advance()) { | |
169 if (parser_map.find(it.key()) == parser_map.end()) { | |
170 return Status(kUnknownError, | |
171 "unrecognized chrome capability: " + it.key()); | |
172 } | |
173 Status status = parser_map[it.key()].Run(it.value(), this); | |
174 if (status.IsError()) | |
175 return status; | |
176 } | |
177 } | |
178 return Status(kOk); | |
179 } | |
OLD | NEW |