Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: chrome/test/webdriver/webdriver_capabilities_parser.cc

Issue 8341044: Enhance and refactor ChromeDriver's capability handling. Log warning for (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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/webdriver/webdriver_capabilities_parser.h"
6
7 #include "base/base64.h"
8 #include "base/file_util.h"
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/stringprintf.h"
12 #include "base/values.h"
13 #include "chrome/common/zip.h"
14 #include "chrome/test/webdriver/webdriver_error.h"
15 #include "chrome/test/webdriver/webdriver_util.h"
16
17 using base::Value;
18
19 namespace webdriver {
20
21 namespace {
22
23 Error* CreateBadInputError(const std::string& name,
24 Value::Type type,
25 const Value* option) {
26 return new Error(kBadRequest, base::StringPrintf(
27 "%s must be of type %s, not %s. Received: %s",
28 name.c_str(), GetJsonTypeName(type),
29 GetJsonTypeName(option->GetType()),
30 JsonStringifyForDisplay(option).c_str()));
31 }
32
33 } // namespace
34
35 Capabilities::Capabilities()
36 : command(CommandLine::NO_PROGRAM),
37 detach(false),
38 load_async(false),
39 native_events(false),
40 verbose(false) { }
41
42 Capabilities::~Capabilities() { }
43
44 CapabilitiesParser::CapabilitiesParser(
45 const base::DictionaryValue* capabilities_dict,
46 const FilePath& root_path,
47 Capabilities* capabilities)
48 : dict_(capabilities_dict),
49 root_(root_path),
50 caps_(capabilities) {
51 }
52
53 CapabilitiesParser::~CapabilitiesParser() { }
54
55 Error* CapabilitiesParser::Parse() {
56 const char kOptionsKey[] = "chromeOptions";
57 const base::DictionaryValue* options = dict_;
58 bool legacy_options = true;
59 Value* options_value;
60 if (dict_->Get(kOptionsKey, &options_value)) {
61 legacy_options = false;
62 if (options_value->IsType(Value::TYPE_DICTIONARY)) {
63 options = static_cast<DictionaryValue*>(options_value);
64 } else {
65 return CreateBadInputError(
66 kOptionsKey, Value::TYPE_DICTIONARY, options_value);
67 }
68 }
69
70 typedef Error* (CapabilitiesParser::*Parser)(const Value*);
71 std::map<std::string, Parser> parser_map;
72 if (legacy_options) {
73 parser_map["chrome.binary"] = &CapabilitiesParser::ParseBinary;
74 parser_map["chrome.channel"] = &CapabilitiesParser::ParseChannel;
75 parser_map["chrome.detach"] = &CapabilitiesParser::ParseDetach;
76 parser_map["chrome.extensions"] = &CapabilitiesParser::ParseExtensions;
77 parser_map["chrome.loadAsync"] = &CapabilitiesParser::ParseLoadAsync;
78 parser_map["chrome.nativeEvents"] = &CapabilitiesParser::ParseNativeEvents;
79 parser_map["chrome.profile"] = &CapabilitiesParser::ParseProfile;
80 parser_map["chrome.switches"] = &CapabilitiesParser::ParseArgs;
81 parser_map["chrome.verbose"] = &CapabilitiesParser::ParseVerbose;
82 } else {
83 parser_map["args"] = &CapabilitiesParser::ParseArgs;
84 parser_map["binary"] = &CapabilitiesParser::ParseBinary;
85 parser_map["channel"] = &CapabilitiesParser::ParseChannel;
86 parser_map["detach"] = &CapabilitiesParser::ParseDetach;
87 parser_map["extensions"] = &CapabilitiesParser::ParseExtensions;
88 parser_map["loadAsync"] = &CapabilitiesParser::ParseLoadAsync;
89 parser_map["nativeEvents"] = &CapabilitiesParser::ParseNativeEvents;
90 parser_map["profile"] = &CapabilitiesParser::ParseProfile;
91 parser_map["verbose"] = &CapabilitiesParser::ParseVerbose;
92 }
93
94 base::DictionaryValue::key_iterator key_iter = options->begin_keys();
95 for (; key_iter != options->end_keys(); ++key_iter) {
96 if (parser_map.find(*key_iter) == parser_map.end()) {
97 LOG(WARNING) << "Ignoring unrecognized capability: " << *key_iter;
98 continue;
99 }
100 Value* option = NULL;
101 options->GetWithoutPathExpansion(*key_iter, &option);
102 Error* error = (this->*parser_map[*key_iter])(option);
103 if (error) {
104 error->AddDetails(base::StringPrintf(
105 "Error occurred while processing capability '%s'",
106 (*key_iter).c_str()));
107 return error;
108 }
109 }
110 return NULL;
111 }
112
113 Error* CapabilitiesParser::ParseArgs(const Value* option) {
114 const base::ListValue* args;
115 if (!option->GetAsList(&args))
116 return CreateBadInputError("arguments", Value::TYPE_LIST, option);
117 for (size_t i = 0; i < args->GetSize(); ++i) {
118 std::string arg_string;
119 if (!args->GetString(i, &arg_string))
120 return CreateBadInputError("argument", Value::TYPE_STRING, option);
121 size_t separator_index = arg_string.find("=");
122 if (separator_index != std::string::npos) {
123 CommandLine::StringType arg_string_native;
124 if (!args->GetString(i, &arg_string_native))
125 return CreateBadInputError("argument", Value::TYPE_STRING, option);
126 caps_->command.AppendSwitchNative(
127 arg_string.substr(0, separator_index),
128 arg_string_native.substr(separator_index + 1));
129 } else {
130 caps_->command.AppendSwitch(arg_string);
131 }
132 }
133 return NULL;
134 }
135
136 Error* CapabilitiesParser::ParseBinary(const Value* option) {
137 FilePath::StringType path;
138 if (!option->GetAsString(&path)) {
139 return CreateBadInputError("binary path", Value::TYPE_STRING, option);
140 }
141 caps_->command.SetProgram(FilePath(path));
142 return NULL;
143 }
144
145 Error* CapabilitiesParser::ParseChannel(const Value* option) {
146 if (!option->GetAsString(&caps_->channel))
147 return CreateBadInputError("channel", Value::TYPE_STRING, option);
148 return NULL;
149 }
150
151 Error* CapabilitiesParser::ParseDetach(const Value* option) {
152 if (!option->GetAsBoolean(&caps_->detach))
153 return CreateBadInputError("detach", Value::TYPE_BOOLEAN, option);
154 return NULL;
155 }
156
157 Error* CapabilitiesParser::ParseExtensions(const Value* option) {
158 const base::ListValue* extensions;
159 if (!option->GetAsList(&extensions))
160 return CreateBadInputError("extensions", Value::TYPE_LIST, option);
161 for (size_t i = 0; i < extensions->GetSize(); ++i) {
162 std::string extension_base64;
163 if (!extensions->GetString(i, &extension_base64)) {
164 return new Error(kBadRequest,
165 "Each extension must be a base64 encoded string");
166 }
167 FilePath extension = root_.AppendASCII(
168 base::StringPrintf("extension%" PRIuS ".crx", i));
169 std::string error_msg;
170 if (!DecodeAndWriteFile(extension, extension_base64, false /* unzip */,
171 &error_msg)) {
172 return new Error(
173 kUnknownError,
174 "Error occurred while parsing extension: " + error_msg);
175 }
176 caps_->extensions.push_back(extension);
177 }
178 return NULL;
179 }
180
181 Error* CapabilitiesParser::ParseLoadAsync(const Value* option) {
182 if (!option->GetAsBoolean(&caps_->load_async))
183 return CreateBadInputError("loadAsync", Value::TYPE_BOOLEAN, option);
184 return NULL;
185 }
186
187 Error* CapabilitiesParser::ParseNativeEvents(const Value* option) {
188 if (!option->GetAsBoolean(&caps_->native_events))
189 return CreateBadInputError("nativeEvents", Value::TYPE_BOOLEAN, option);
190 return NULL;
191 }
192
193 Error* CapabilitiesParser::ParseProfile(const Value* option) {
194 std::string profile_base64;
195 if (!option->GetAsString(&profile_base64))
196 return CreateBadInputError("profile", Value::TYPE_STRING, option);
197 std::string error_msg;
198 caps_->profile = root_.AppendASCII("profile");
199 if (!DecodeAndWriteFile(caps_->profile, profile_base64, true /* unzip */,
200 &error_msg))
201 return new Error(kUnknownError, "unable to unpack profile: " + error_msg);
202 return NULL;
203 }
204
205 Error* CapabilitiesParser::ParseVerbose(const Value* option) {
206 if (!option->GetAsBoolean(&caps_->verbose))
207 return CreateBadInputError("verbose", Value::TYPE_BOOLEAN, option);
208 return NULL;
209 }
210
211 bool CapabilitiesParser::DecodeAndWriteFile(
212 const FilePath& path,
213 const std::string& base64,
214 bool unzip,
215 std::string* error_msg) {
216 std::string data;
217 if (!base::Base64Decode(base64, &data)) {
218 *error_msg = "Could not decode base64 data";
219 return false;
220 }
221 if (unzip) {
222 FilePath temp_file(root_.AppendASCII(GenerateRandomID()));
223 if (!file_util::WriteFile(temp_file, data.c_str(), data.length())) {
224 *error_msg = "Could not write file";
225 return false;
226 }
227 if (!zip::Unzip(temp_file, path)) {
228 *error_msg = "Could not unzip archive";
229 return false;
230 }
231 } else {
232 if (!file_util::WriteFile(path, data.c_str(), data.length())) {
233 *error_msg = "Could not write file";
234 return false;
235 }
236 }
237 return true;
238 }
239
240 } // namespace webdriver
OLDNEW
« no previous file with comments | « chrome/test/webdriver/webdriver_capabilities_parser.h ('k') | chrome/test/webdriver/webdriver_capabilities_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698