blob: 63aa36f0083222ead603a89c12ff5b78b8efa609 [file] [log] [blame]
[email protected]fcb247c2011-03-26 02:46:161// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]7cc2c912011-02-13 03:11:212// 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/commands/webelement_commands.h"
6
[email protected]3b63f8f42011-03-28 01:54:157#include "base/memory/scoped_ptr.h"
[email protected]bd6c46eaa2011-02-16 20:58:448#include "base/stringprintf.h"
[email protected]7cc2c912011-02-13 03:11:219#include "base/third_party/icu/icu_utf.h"
10#include "base/values.h"
11#include "chrome/test/webdriver/commands/response.h"
12#include "chrome/test/webdriver/error_codes.h"
13#include "chrome/test/webdriver/session.h"
[email protected]7cc2c912011-02-13 03:11:2114#include "third_party/webdriver/atoms.h"
[email protected]f5aae772011-03-11 22:44:0815#include "ui/gfx/point.h"
16#include "ui/gfx/size.h"
[email protected]7cc2c912011-02-13 03:11:2117
18namespace webdriver {
19
[email protected]d89805322011-02-20 01:20:1720///////////////////// WebElementCommand ////////////////////
21
[email protected]8d167c22011-02-15 22:10:0122WebElementCommand::WebElementCommand(
23 const std::vector<std::string>& path_segments,
24 const DictionaryValue* const parameters)
25 : WebDriverCommand(path_segments, parameters),
26 path_segments_(path_segments) {}
27
28WebElementCommand::~WebElementCommand() {}
29
[email protected]7cc2c912011-02-13 03:11:2130bool WebElementCommand::Init(Response* const response) {
31 if (!WebDriverCommand::Init(response))
32 return false;
33
34 // There should be at least 5 segments to match
35 // "/session/$session/element/$id"
36 if (path_segments_.size() < 5) {
37 SET_WEBDRIVER_ERROR(response, "Path segments is less than 5",
38 kBadRequest);
39 return false;
40 }
41
42 // We cannot verify the ID is valid until we execute the command and
43 // inject the ID into the in-page cache.
[email protected]3aa7b8a2011-02-25 01:55:4144 element = WebElementId(path_segments_.at(4));
[email protected]7cc2c912011-02-13 03:11:2145 return true;
46}
47
[email protected]d89805322011-02-20 01:20:1748///////////////////// ElementAttributeCommand ////////////////////
49
50ElementAttributeCommand::ElementAttributeCommand(
51 const std::vector<std::string>& path_segments,
52 DictionaryValue* parameters)
53 : WebElementCommand(path_segments, parameters) {}
54
55ElementAttributeCommand::~ElementAttributeCommand() {}
56
57bool ElementAttributeCommand::DoesGet() {
58 return true;
59}
60
61void ElementAttributeCommand::ExecuteGet(Response* const response) {
62 // There should be at least 7 segments to match
63 // "/session/$session/element/$id/attribute/$name"
64 if (path_segments_.size() < 7) {
65 SET_WEBDRIVER_ERROR(response, "Path segments is less than 7",
66 kBadRequest);
67 return;
68 }
69
70 std::string script = base::StringPrintf(
71 "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE);
72
73 scoped_ptr<ListValue> args(new ListValue);
[email protected]3aa7b8a2011-02-25 01:55:4174 args->Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:1775 args->Append(Value::CreateStringValue(path_segments_.at(6)));
76
77 Value* result = NULL;
78 ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
79 response->SetStatus(status);
80 response->SetValue(result);
81}
82
83///////////////////// ElementClearCommand ////////////////////
84
85ElementClearCommand::ElementClearCommand(
86 const std::vector<std::string>& path_segments,
87 DictionaryValue* parameters)
88 : WebElementCommand(path_segments, parameters) {}
89
90ElementClearCommand::~ElementClearCommand() {}
91
92bool ElementClearCommand::DoesPost() {
93 return true;
94}
95
96void ElementClearCommand::ExecutePost(Response* const response) {
97 scoped_ptr<ListValue> args(new ListValue);
[email protected]3aa7b8a2011-02-25 01:55:4198 args->Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:1799
100 std::string script = base::StringPrintf(
101 "(%s).apply(null, arguments);", atoms::CLEAR);
102
103 Value* result = NULL;
104 ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
105 response->SetStatus(status);
106 response->SetValue(result);
107}
108
109///////////////////// ElementCssCommand ////////////////////
110
111ElementCssCommand::ElementCssCommand(
112 const std::vector<std::string>& path_segments,
113 DictionaryValue* parameters)
114 : WebElementCommand(path_segments, parameters) {}
115
116ElementCssCommand::~ElementCssCommand() {}
117
118bool ElementCssCommand::DoesGet() {
119 return true;
120}
121
122void ElementCssCommand::ExecuteGet(Response* const response) {
123 // There should be at least 7 segments to match
124 // "/session/$session/element/$id/css/$propertyName"
125 if (path_segments_.size() < 7) {
126 SET_WEBDRIVER_ERROR(response, "Path segments is less than 7",
127 kBadRequest);
128 return;
129 }
130
131 std::string script = base::StringPrintf(
132 "return (%s).apply(null, arguments);", atoms::GET_EFFECTIVE_STYLE);
133
134 scoped_ptr<ListValue> args(new ListValue);
[email protected]3aa7b8a2011-02-25 01:55:41135 args->Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:17136 args->Append(Value::CreateStringValue(path_segments_.at(6)));
137
138 Value* result = NULL;
139 ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
140 response->SetStatus(status);
141 response->SetValue(result);
142}
143
144///////////////////// ElementDisplayedCommand ////////////////////
145
146ElementDisplayedCommand::ElementDisplayedCommand(
147 const std::vector<std::string>& path_segments,
148 DictionaryValue* parameters)
149 : WebElementCommand(path_segments, parameters) {}
150
151ElementDisplayedCommand::~ElementDisplayedCommand() {}
152
153bool ElementDisplayedCommand::DoesGet() {
154 return true;
155}
156
157void ElementDisplayedCommand::ExecuteGet(Response* const response) {
[email protected]fcb247c2011-03-26 02:46:16158 bool is_displayed;
159 ErrorCode status = session_->IsElementDisplayed(
160 session_->current_target(), element, &is_displayed);
161 if (status == kSuccess)
162 response->SetValue(Value::CreateBooleanValue(is_displayed));
[email protected]d89805322011-02-20 01:20:17163 response->SetStatus(status);
[email protected]d89805322011-02-20 01:20:17164}
165
166///////////////////// ElementEnabledCommand ////////////////////
167
168ElementEnabledCommand::ElementEnabledCommand(
169 const std::vector<std::string>& path_segments,
170 DictionaryValue* parameters)
171 : WebElementCommand(path_segments, parameters) {}
172
173ElementEnabledCommand::~ElementEnabledCommand() {}
174
175bool ElementEnabledCommand::DoesGet() {
176 return true;
177}
178
179void ElementEnabledCommand::ExecuteGet(Response* const response) {
180 scoped_ptr<ListValue> args(new ListValue);
[email protected]3aa7b8a2011-02-25 01:55:41181 args->Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:17182
183 std::string script = base::StringPrintf(
184 "return (%s).apply(null, arguments);", atoms::IS_ENABLED);
185
186 Value* result = NULL;
187 ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
188 response->SetStatus(status);
189 response->SetValue(result);
190}
191
192///////////////////// ElementEqualsCommand ////////////////////
193
194ElementEqualsCommand::ElementEqualsCommand(
195 const std::vector<std::string>& path_segments,
196 DictionaryValue* parameters)
197 : WebElementCommand(path_segments, parameters) {}
198
199ElementEqualsCommand::~ElementEqualsCommand() {}
200
201bool ElementEqualsCommand::DoesGet() {
202 return true;
203}
204
205void ElementEqualsCommand::ExecuteGet(Response* const response) {
206 // There should be at least 7 segments to match
207 // "/session/$session/element/$id/equals/$other"
208 if (path_segments_.size() < 7) {
209 SET_WEBDRIVER_ERROR(response, "Path segments is less than 7",
210 kBadRequest);
211 return;
212 }
213
214 std::string script = "return arguments[0] == arguments[1];";
215
216 scoped_ptr<ListValue> args(new ListValue);
[email protected]3aa7b8a2011-02-25 01:55:41217 args->Append(element.ToValue());
[email protected]6c55b1d2011-03-26 15:23:59218
219 WebElementId other_element(path_segments_.at(6));
220 args->Append(other_element.ToValue());
[email protected]d89805322011-02-20 01:20:17221
222 Value* result = NULL;
223 ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
224 response->SetStatus(status);
225 response->SetValue(result);
226}
227
228///////////////////// ElementLocationCommand ////////////////////
229
230ElementLocationCommand::ElementLocationCommand(
231 const std::vector<std::string>& path_segments,
232 DictionaryValue* parameters)
233 : WebElementCommand(path_segments, parameters) {}
234
235ElementLocationCommand::~ElementLocationCommand() {}
236
237bool ElementLocationCommand::DoesGet() {
238 return true;
239}
240
241void ElementLocationCommand::ExecuteGet(Response* const response) {
242 std::string script = base::StringPrintf(
243 "return (%s).apply(null, arguments);", atoms::GET_LOCATION);
244
245 ListValue args;
[email protected]3aa7b8a2011-02-25 01:55:41246 args.Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:17247
248 Value* result = NULL;
249 ErrorCode status = session_->ExecuteScript(script, &args, &result);
250 response->SetStatus(status);
251 response->SetValue(result);
252}
253
254///////////////////// ElementLocationInViewCommand ////////////////////
255
256ElementLocationInViewCommand::ElementLocationInViewCommand(
257 const std::vector<std::string>& path_segments,
258 DictionaryValue* parameters)
259 : WebElementCommand(path_segments, parameters) {}
260
261ElementLocationInViewCommand::~ElementLocationInViewCommand() {}
262
263bool ElementLocationInViewCommand::DoesGet() {
264 return true;
265}
266
267void ElementLocationInViewCommand::ExecuteGet(Response* const response) {
[email protected]f5aae772011-03-11 22:44:08268 gfx::Point location;
269 ErrorCode code = session_->GetElementLocationInView(element, &location);
[email protected]3aa7b8a2011-02-25 01:55:41270 response->SetStatus(code);
271 if (code == kSuccess) {
272 DictionaryValue* coord_dict = new DictionaryValue();
[email protected]f5aae772011-03-11 22:44:08273 coord_dict->SetInteger("x", location.x());
274 coord_dict->SetInteger("y", location.y());
[email protected]3aa7b8a2011-02-25 01:55:41275 response->SetValue(coord_dict);
276 }
[email protected]d89805322011-02-20 01:20:17277}
278
279///////////////////// ElementNameCommand ////////////////////
280
281ElementNameCommand::ElementNameCommand(
282 const std::vector<std::string>& path_segments,
283 DictionaryValue* parameters)
284 : WebElementCommand(path_segments, parameters) {}
285
286ElementNameCommand::~ElementNameCommand() {}
287
288bool ElementNameCommand::DoesGet() {
289 return true;
290}
291
292void ElementNameCommand::ExecuteGet(Response* const response) {
293 scoped_ptr<ListValue> args(new ListValue);
[email protected]3aa7b8a2011-02-25 01:55:41294 args->Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:17295
296 std::string script = "return arguments[0].tagName;";
297
298 Value* result = NULL;
299 ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
300 response->SetStatus(status);
301 response->SetValue(result);
302}
303
304///////////////////// ElementSelectedCommand ////////////////////
305
306ElementSelectedCommand::ElementSelectedCommand(
307 const std::vector<std::string>& path_segments,
308 DictionaryValue* parameters)
309 : WebElementCommand(path_segments, parameters) {}
310
311ElementSelectedCommand::~ElementSelectedCommand() {}
312
313bool ElementSelectedCommand::DoesGet() {
314 return true;
315}
316
317bool ElementSelectedCommand::DoesPost() {
318 return true;
319}
320
321void ElementSelectedCommand::ExecuteGet(Response* const response) {
322 scoped_ptr<ListValue> args(new ListValue);
[email protected]3aa7b8a2011-02-25 01:55:41323 args->Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:17324
325 std::string script = base::StringPrintf(
326 "return (%s).apply(null, arguments);", atoms::IS_SELECTED);
327
328 Value* result = NULL;
329 ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
330 response->SetStatus(status);
331 response->SetValue(result);
332}
333
334void ElementSelectedCommand::ExecutePost(Response* const response) {
335 scoped_ptr<ListValue> args(new ListValue);
[email protected]3aa7b8a2011-02-25 01:55:41336 args->Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:17337 args->Append(Value::CreateBooleanValue(true));
338
339 std::string script = base::StringPrintf(
340 "return (%s).apply(null, arguments);", atoms::SET_SELECTED);
341
342 Value* result = NULL;
343 ErrorCode status = session_->ExecuteScript(script, args.get(), &result);
344 response->SetStatus(status);
345 response->SetValue(result);
346}
347
348///////////////////// ElementSizeCommand ////////////////////
349
350ElementSizeCommand::ElementSizeCommand(
351 const std::vector<std::string>& path_segments,
352 DictionaryValue* parameters)
353 : WebElementCommand(path_segments, parameters) {}
354
355ElementSizeCommand::~ElementSizeCommand() {}
356
357bool ElementSizeCommand::DoesGet() {
358 return true;
359}
360
361void ElementSizeCommand::ExecuteGet(Response* const response) {
[email protected]f5aae772011-03-11 22:44:08362 gfx::Size size;
363 ErrorCode status = session_->GetElementSize(
364 session_->current_target(), element, &size);
365 if (status == kSuccess) {
366 DictionaryValue* dict = new DictionaryValue();
367 dict->SetInteger("width", size.width());
368 dict->SetInteger("height", size.height());
369 response->SetValue(dict);
370 }
[email protected]d89805322011-02-20 01:20:17371 response->SetStatus(status);
[email protected]d89805322011-02-20 01:20:17372}
373
374///////////////////// ElementSubmitCommand ////////////////////
375
376ElementSubmitCommand::ElementSubmitCommand(
377 const std::vector<std::string>& path_segments,
378 DictionaryValue* parameters)
379 : WebElementCommand(path_segments, parameters) {}
380
381ElementSubmitCommand::~ElementSubmitCommand() {}
382
383bool ElementSubmitCommand::DoesPost() {
384 return true;
385}
386
387void ElementSubmitCommand::ExecutePost(Response* const response) {
388 // TODO(jleyba): We need to wait for any post-submit navigation events to
389 // complete before responding to the client.
390 std::string script = base::StringPrintf(
391 "(%s).apply(null, arguments);", atoms::SUBMIT);
392
393 ListValue args;
[email protected]3aa7b8a2011-02-25 01:55:41394 args.Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:17395
396 Value* result = NULL;
397 ErrorCode status = session_->ExecuteScript(script, &args, &result);
398 response->SetStatus(status);
399 response->SetValue(result);
400}
401
402///////////////////// ElementToggleCommand ////////////////////
403
404ElementToggleCommand::ElementToggleCommand(
405 const std::vector<std::string>& path_segments,
406 DictionaryValue* parameters)
407 : WebElementCommand(path_segments, parameters) {}
408
409ElementToggleCommand::~ElementToggleCommand() {}
410
411bool ElementToggleCommand::DoesPost() {
412 return true;
413}
414
415void ElementToggleCommand::ExecutePost(Response* const response) {
416 std::string script = base::StringPrintf(
417 "return (%s).apply(null, arguments);", atoms::TOGGLE);
418
419 ListValue args;
[email protected]3aa7b8a2011-02-25 01:55:41420 args.Append(element.ToValue());
[email protected]d89805322011-02-20 01:20:17421
422 Value* result = NULL;
423 ErrorCode status = session_->ExecuteScript(script, &args, &result);
424 response->SetStatus(status);
425 response->SetValue(result);
426}
427
428///////////////////// ElementValueCommand ////////////////////
429
[email protected]8d167c22011-02-15 22:10:01430ElementValueCommand::ElementValueCommand(
431 const std::vector<std::string>& path_segments,
432 DictionaryValue* parameters)
433 : WebElementCommand(path_segments, parameters) {}
434
435ElementValueCommand::~ElementValueCommand() {}
436
437bool ElementValueCommand::DoesGet() {
438 return true;
439}
440
441bool ElementValueCommand::DoesPost() {
442 return true;
443}
444
[email protected]7cc2c912011-02-13 03:11:21445void ElementValueCommand::ExecuteGet(Response* const response) {
446 Value* unscoped_result = NULL;
447 ListValue args;
448 std::string script = "return arguments[0]['value']";
[email protected]3aa7b8a2011-02-25 01:55:41449 args.Append(element.ToValue());
[email protected]7cc2c912011-02-13 03:11:21450 ErrorCode code =
451 session_->ExecuteScript(script, &args, &unscoped_result);
452 scoped_ptr<Value> result(unscoped_result);
453 if (code != kSuccess) {
454 SET_WEBDRIVER_ERROR(response, "Failed to execute script", code);
455 return;
456 }
457 if (!result->IsType(Value::TYPE_STRING) &&
458 !result->IsType(Value::TYPE_NULL)) {
459 SET_WEBDRIVER_ERROR(response,
460 "Result is not string or null type",
461 kInternalServerError);
462 return;
463 }
[email protected]b7448dc2011-02-19 23:32:55464 response->SetStatus(kSuccess);
465 response->SetValue(result.release());
[email protected]7cc2c912011-02-13 03:11:21466}
467
468void ElementValueCommand::ExecutePost(Response* const response) {
469 ListValue* key_list;
470 if (!GetListParameter("value", &key_list)) {
471 SET_WEBDRIVER_ERROR(response,
472 "Missing or invalid 'value' parameter",
473 kBadRequest);
474 return;
475 }
476 // Flatten the given array of strings into one.
477 string16 keys;
478 for (size_t i = 0; i < key_list->GetSize(); ++i) {
479 string16 keys_list_part;
480 key_list->GetString(i, &keys_list_part);
481 for (size_t j = 0; j < keys_list_part.size(); ++j) {
482 if (CBU16_IS_SURROGATE(keys_list_part[j])) {
483 SET_WEBDRIVER_ERROR(
484 response,
485 "ChromeDriver only supports characters in the BMP",
486 kBadRequest);
487 return;
488 }
489 }
490 keys.append(keys_list_part);
491 }
492
[email protected]3aa7b8a2011-02-25 01:55:41493 ErrorCode code = session_->SendKeys(element, keys);
[email protected]7cc2c912011-02-13 03:11:21494 if (code != kSuccess) {
495 SET_WEBDRIVER_ERROR(response,
496 "Internal SendKeys error",
497 code);
498 return;
499 }
[email protected]b7448dc2011-02-19 23:32:55500 response->SetStatus(kSuccess);
[email protected]7cc2c912011-02-13 03:11:21501}
502
[email protected]d89805322011-02-20 01:20:17503///////////////////// ElementTextCommand ////////////////////
504
[email protected]8d167c22011-02-15 22:10:01505ElementTextCommand::ElementTextCommand(
506 const std::vector<std::string>& path_segments,
507 DictionaryValue* parameters)
508 : WebElementCommand(path_segments, parameters) {}
509
510ElementTextCommand::~ElementTextCommand() {}
511
512bool ElementTextCommand::DoesGet() {
513 return true;
514}
515
[email protected]7cc2c912011-02-13 03:11:21516void ElementTextCommand::ExecuteGet(Response* const response) {
517 Value* unscoped_result = NULL;
518 ListValue args;
[email protected]3aa7b8a2011-02-25 01:55:41519 args.Append(element.ToValue());
[email protected]bd6c46eaa2011-02-16 20:58:44520
521 std::string script = base::StringPrintf(
522 "return (%s).apply(null, arguments);", atoms::GET_TEXT);
523
524 ErrorCode code = session_->ExecuteScript(script, &args,
525 &unscoped_result);
[email protected]7cc2c912011-02-13 03:11:21526 scoped_ptr<Value> result(unscoped_result);
527 if (code != kSuccess) {
528 SET_WEBDRIVER_ERROR(response, "Failed to execute script", code);
529 return;
530 }
531 if (!result->IsType(Value::TYPE_STRING)) {
532 SET_WEBDRIVER_ERROR(response,
533 "Result is not string type",
534 kInternalServerError);
535 return;
536 }
[email protected]b7448dc2011-02-19 23:32:55537 response->SetStatus(kSuccess);
538 response->SetValue(result.release());
[email protected]7cc2c912011-02-13 03:11:21539}
540
541} // namespace webdriver