Implement nacl_irt_memory for non-sfi mode.
[chromium-blink-merge.git] / chrome / test / chromedriver / element_commands.cc
blob7595a05aaf2dd1a34b8041508638d32ec9cea647
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.
5 #include "chrome/test/chromedriver/element_commands.h"
7 #include <list>
8 #include <vector>
10 #include "base/callback.h"
11 #include "base/files/file_path.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/threading/platform_thread.h"
15 #include "base/time/time.h"
16 #include "base/values.h"
17 #include "chrome/test/chromedriver/basic_types.h"
18 #include "chrome/test/chromedriver/chrome/chrome.h"
19 #include "chrome/test/chromedriver/chrome/js.h"
20 #include "chrome/test/chromedriver/chrome/status.h"
21 #include "chrome/test/chromedriver/chrome/ui_events.h"
22 #include "chrome/test/chromedriver/chrome/web_view.h"
23 #include "chrome/test/chromedriver/element_util.h"
24 #include "chrome/test/chromedriver/session.h"
25 #include "chrome/test/chromedriver/util.h"
26 #include "third_party/webdriver/atoms.h"
28 namespace {
30 Status SendKeysToElement(
31 Session* session,
32 WebView* web_view,
33 const std::string& element_id,
34 const base::ListValue* key_list) {
35 bool is_displayed = false;
36 bool is_focused = false;
37 base::TimeTicks start_time = base::TimeTicks::Now();
38 while (true) {
39 Status status = IsElementDisplayed(
40 session, web_view, element_id, true, &is_displayed);
41 if (status.IsError())
42 return status;
43 if (is_displayed)
44 break;
45 status = IsElementFocused(session, web_view, element_id, &is_focused);
46 if (status.IsError())
47 return status;
48 if (is_focused)
49 break;
50 if (base::TimeTicks::Now() - start_time >= session->implicit_wait) {
51 return Status(kElementNotVisible);
53 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
56 bool is_enabled = false;
57 Status status = IsElementEnabled(session, web_view, element_id, &is_enabled);
58 if (status.IsError())
59 return status;
60 if (!is_enabled)
61 return Status(kInvalidElementState);
63 if (!is_focused) {
64 base::ListValue args;
65 args.Append(CreateElement(element_id));
66 scoped_ptr<base::Value> result;
67 status = web_view->CallFunction(
68 session->GetCurrentFrameId(), kFocusScript, args, &result);
69 if (status.IsError())
70 return status;
73 return SendKeysOnWindow(web_view, key_list, true, &session->sticky_modifiers);
76 Status ExecuteTouchSingleTapAtom(
77 Session* session,
78 WebView* web_view,
79 const std::string& element_id,
80 const base::DictionaryValue& params,
81 scoped_ptr<base::Value>* value) {
82 base::ListValue args;
83 args.Append(CreateElement(element_id));
84 return web_view->CallFunction(
85 session->GetCurrentFrameId(),
86 webdriver::atoms::asString(webdriver::atoms::TOUCH_SINGLE_TAP),
87 args,
88 value);
91 } // namespace
93 Status ExecuteElementCommand(
94 const ElementCommand& command,
95 Session* session,
96 WebView* web_view,
97 const base::DictionaryValue& params,
98 scoped_ptr<base::Value>* value) {
99 std::string id;
100 if (params.GetString("id", &id) || params.GetString("element", &id))
101 return command.Run(session, web_view, id, params, value);
102 return Status(kUnknownError, "element identifier must be a string");
105 Status ExecuteFindChildElement(
106 int interval_ms,
107 Session* session,
108 WebView* web_view,
109 const std::string& element_id,
110 const base::DictionaryValue& params,
111 scoped_ptr<base::Value>* value) {
112 return FindElement(
113 interval_ms, true, &element_id, session, web_view, params, value);
116 Status ExecuteFindChildElements(
117 int interval_ms,
118 Session* session,
119 WebView* web_view,
120 const std::string& element_id,
121 const base::DictionaryValue& params,
122 scoped_ptr<base::Value>* value) {
123 return FindElement(
124 interval_ms, false, &element_id, session, web_view, params, value);
127 Status ExecuteHoverOverElement(
128 Session* session,
129 WebView* web_view,
130 const std::string& element_id,
131 const base::DictionaryValue& params,
132 scoped_ptr<base::Value>* value) {
133 WebPoint location;
134 Status status = GetElementClickableLocation(
135 session, web_view, element_id, &location);
136 if (status.IsError())
137 return status;
139 MouseEvent move_event(
140 kMovedMouseEventType, kNoneMouseButton, location.x, location.y,
141 session->sticky_modifiers, 0);
142 std::list<MouseEvent> events;
143 events.push_back(move_event);
144 status = web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
145 if (status.IsOk())
146 session->mouse_position = location;
147 return status;
150 Status ExecuteClickElement(
151 Session* session,
152 WebView* web_view,
153 const std::string& element_id,
154 const base::DictionaryValue& params,
155 scoped_ptr<base::Value>* value) {
156 std::string tag_name;
157 Status status = GetElementTagName(session, web_view, element_id, &tag_name);
158 if (status.IsError())
159 return status;
160 if (tag_name == "option") {
161 bool is_toggleable;
162 status = IsOptionElementTogglable(
163 session, web_view, element_id, &is_toggleable);
164 if (status.IsError())
165 return status;
166 if (is_toggleable)
167 return ToggleOptionElement(session, web_view, element_id);
168 else
169 return SetOptionElementSelected(session, web_view, element_id, true);
170 } else {
171 WebPoint location;
172 status = GetElementClickableLocation(
173 session, web_view, element_id, &location);
174 if (status.IsError())
175 return status;
177 std::list<MouseEvent> events;
178 events.push_back(
179 MouseEvent(kMovedMouseEventType, kNoneMouseButton,
180 location.x, location.y, session->sticky_modifiers, 0));
181 events.push_back(
182 MouseEvent(kPressedMouseEventType, kLeftMouseButton,
183 location.x, location.y, session->sticky_modifiers, 1));
184 events.push_back(
185 MouseEvent(kReleasedMouseEventType, kLeftMouseButton,
186 location.x, location.y, session->sticky_modifiers, 1));
187 status =
188 web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
189 if (status.IsOk())
190 session->mouse_position = location;
191 return status;
195 Status ExecuteTouchSingleTap(
196 Session* session,
197 WebView* web_view,
198 const std::string& element_id,
199 const base::DictionaryValue& params,
200 scoped_ptr<base::Value>* value) {
201 // Fall back to javascript atom for pre-m30 Chrome.
202 if (session->chrome->GetBuildNo() < 1576)
203 return ExecuteTouchSingleTapAtom(
204 session, web_view, element_id, params, value);
206 WebPoint location;
207 Status status = GetElementClickableLocation(
208 session, web_view, element_id, &location);
209 if (status.IsError())
210 return status;
212 std::list<TouchEvent> events;
213 events.push_back(
214 TouchEvent(kTouchStart, location.x, location.y));
215 events.push_back(
216 TouchEvent(kTouchEnd, location.x, location.y));
217 return web_view->DispatchTouchEvents(events);
220 Status ExecuteClearElement(
221 Session* session,
222 WebView* web_view,
223 const std::string& element_id,
224 const base::DictionaryValue& params,
225 scoped_ptr<base::Value>* value) {
226 base::ListValue args;
227 args.Append(CreateElement(element_id));
228 scoped_ptr<base::Value> result;
229 return web_view->CallFunction(
230 session->GetCurrentFrameId(),
231 webdriver::atoms::asString(webdriver::atoms::CLEAR),
232 args, &result);
235 Status ExecuteSendKeysToElement(
236 Session* session,
237 WebView* web_view,
238 const std::string& element_id,
239 const base::DictionaryValue& params,
240 scoped_ptr<base::Value>* value) {
241 const base::ListValue* key_list;
242 if (!params.GetList("value", &key_list))
243 return Status(kUnknownError, "'value' must be a list");
245 bool is_input = false;
246 Status status = IsElementAttributeEqualToIgnoreCase(
247 session, web_view, element_id, "tagName", "input", &is_input);
248 if (status.IsError())
249 return status;
250 bool is_file = false;
251 status = IsElementAttributeEqualToIgnoreCase(
252 session, web_view, element_id, "type", "file", &is_file);
253 if (status.IsError())
254 return status;
255 if (is_input && is_file) {
256 // Compress array into a single string.
257 base::FilePath::StringType paths_string;
258 for (size_t i = 0; i < key_list->GetSize(); ++i) {
259 base::FilePath::StringType path_part;
260 if (!key_list->GetString(i, &path_part))
261 return Status(kUnknownError, "'value' is invalid");
262 paths_string.append(path_part);
265 // Separate the string into separate paths, delimited by '\n'.
266 std::vector<base::FilePath::StringType> path_strings;
267 base::SplitString(paths_string, '\n', &path_strings);
268 std::vector<base::FilePath> paths;
269 for (size_t i = 0; i < path_strings.size(); ++i)
270 paths.push_back(base::FilePath(path_strings[i]));
272 bool multiple = false;
273 status = IsElementAttributeEqualToIgnoreCase(
274 session, web_view, element_id, "multiple", "true", &multiple);
275 if (status.IsError())
276 return status;
277 if (!multiple && paths.size() > 1)
278 return Status(kUnknownError, "the element can not hold multiple files");
280 scoped_ptr<base::DictionaryValue> element(CreateElement(element_id));
281 return web_view->SetFileInputFiles(
282 session->GetCurrentFrameId(), *element, paths);
283 } else {
284 return SendKeysToElement(session, web_view, element_id, key_list);
288 Status ExecuteSubmitElement(
289 Session* session,
290 WebView* web_view,
291 const std::string& element_id,
292 const base::DictionaryValue& params,
293 scoped_ptr<base::Value>* value) {
294 base::ListValue args;
295 args.Append(CreateElement(element_id));
296 return web_view->CallFunction(
297 session->GetCurrentFrameId(),
298 webdriver::atoms::asString(webdriver::atoms::SUBMIT),
299 args,
300 value);
303 Status ExecuteGetElementText(
304 Session* session,
305 WebView* web_view,
306 const std::string& element_id,
307 const base::DictionaryValue& params,
308 scoped_ptr<base::Value>* value) {
309 base::ListValue args;
310 args.Append(CreateElement(element_id));
311 return web_view->CallFunction(
312 session->GetCurrentFrameId(),
313 webdriver::atoms::asString(webdriver::atoms::GET_TEXT),
314 args,
315 value);
318 Status ExecuteGetElementValue(
319 Session* session,
320 WebView* web_view,
321 const std::string& element_id,
322 const base::DictionaryValue& params,
323 scoped_ptr<base::Value>* value) {
324 base::ListValue args;
325 args.Append(CreateElement(element_id));
326 return web_view->CallFunction(
327 session->GetCurrentFrameId(),
328 "function(elem) { return elem['value'] }",
329 args,
330 value);
333 Status ExecuteGetElementTagName(
334 Session* session,
335 WebView* web_view,
336 const std::string& element_id,
337 const base::DictionaryValue& params,
338 scoped_ptr<base::Value>* value) {
339 base::ListValue args;
340 args.Append(CreateElement(element_id));
341 return web_view->CallFunction(
342 session->GetCurrentFrameId(),
343 "function(elem) { return elem.tagName.toLowerCase() }",
344 args,
345 value);
348 Status ExecuteIsElementSelected(
349 Session* session,
350 WebView* web_view,
351 const std::string& element_id,
352 const base::DictionaryValue& params,
353 scoped_ptr<base::Value>* value) {
354 base::ListValue args;
355 args.Append(CreateElement(element_id));
356 return web_view->CallFunction(
357 session->GetCurrentFrameId(),
358 webdriver::atoms::asString(webdriver::atoms::IS_SELECTED),
359 args,
360 value);
363 Status ExecuteIsElementEnabled(
364 Session* session,
365 WebView* web_view,
366 const std::string& element_id,
367 const base::DictionaryValue& params,
368 scoped_ptr<base::Value>* value) {
369 base::ListValue args;
370 args.Append(CreateElement(element_id));
371 return web_view->CallFunction(
372 session->GetCurrentFrameId(),
373 webdriver::atoms::asString(webdriver::atoms::IS_ENABLED),
374 args,
375 value);
378 Status ExecuteIsElementDisplayed(
379 Session* session,
380 WebView* web_view,
381 const std::string& element_id,
382 const base::DictionaryValue& params,
383 scoped_ptr<base::Value>* value) {
384 base::ListValue args;
385 args.Append(CreateElement(element_id));
386 return web_view->CallFunction(
387 session->GetCurrentFrameId(),
388 webdriver::atoms::asString(webdriver::atoms::IS_DISPLAYED),
389 args,
390 value);
393 Status ExecuteGetElementLocation(
394 Session* session,
395 WebView* web_view,
396 const std::string& element_id,
397 const base::DictionaryValue& params,
398 scoped_ptr<base::Value>* value) {
399 base::ListValue args;
400 args.Append(CreateElement(element_id));
401 return web_view->CallFunction(
402 session->GetCurrentFrameId(),
403 webdriver::atoms::asString(webdriver::atoms::GET_LOCATION),
404 args,
405 value);
408 Status ExecuteGetElementLocationOnceScrolledIntoView(
409 Session* session,
410 WebView* web_view,
411 const std::string& element_id,
412 const base::DictionaryValue& params,
413 scoped_ptr<base::Value>* value) {
414 WebPoint location;
415 Status status = ScrollElementIntoView(
416 session, web_view, element_id, &location);
417 if (status.IsError())
418 return status;
419 value->reset(CreateValueFrom(location));
420 return Status(kOk);
423 Status ExecuteGetElementSize(
424 Session* session,
425 WebView* web_view,
426 const std::string& element_id,
427 const base::DictionaryValue& params,
428 scoped_ptr<base::Value>* value) {
429 base::ListValue args;
430 args.Append(CreateElement(element_id));
431 return web_view->CallFunction(
432 session->GetCurrentFrameId(),
433 webdriver::atoms::asString(webdriver::atoms::GET_SIZE),
434 args,
435 value);
438 Status ExecuteGetElementAttribute(
439 Session* session,
440 WebView* web_view,
441 const std::string& element_id,
442 const base::DictionaryValue& params,
443 scoped_ptr<base::Value>* value) {
444 std::string name;
445 if (!params.GetString("name", &name))
446 return Status(kUnknownError, "missing 'name'");
447 return GetElementAttribute(session, web_view, element_id, name, value);
450 Status ExecuteGetElementValueOfCSSProperty(
451 Session* session,
452 WebView* web_view,
453 const std::string& element_id,
454 const base::DictionaryValue& params,
455 scoped_ptr<base::Value>* value) {
456 std::string property_name;
457 if (!params.GetString("propertyName", &property_name))
458 return Status(kUnknownError, "missing 'propertyName'");
459 std::string property_value;
460 Status status = GetElementEffectiveStyle(
461 session, web_view, element_id, property_name, &property_value);
462 if (status.IsError())
463 return status;
464 value->reset(new base::StringValue(property_value));
465 return Status(kOk);
468 Status ExecuteElementEquals(
469 Session* session,
470 WebView* web_view,
471 const std::string& element_id,
472 const base::DictionaryValue& params,
473 scoped_ptr<base::Value>* value) {
474 std::string other_element_id;
475 if (!params.GetString("other", &other_element_id))
476 return Status(kUnknownError, "'other' must be a string");
477 value->reset(new base::FundamentalValue(element_id == other_element_id));
478 return Status(kOk);