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/window_commands.h"
10 #include "base/callback.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/time/time.h"
15 #include "base/values.h"
16 #include "chrome/test/chromedriver/basic_types.h"
17 #include "chrome/test/chromedriver/chrome/automation_extension.h"
18 #include "chrome/test/chromedriver/chrome/chrome.h"
19 #include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h"
20 #include "chrome/test/chromedriver/chrome/devtools_client.h"
21 #include "chrome/test/chromedriver/chrome/geoposition.h"
22 #include "chrome/test/chromedriver/chrome/javascript_dialog_manager.h"
23 #include "chrome/test/chromedriver/chrome/js.h"
24 #include "chrome/test/chromedriver/chrome/status.h"
25 #include "chrome/test/chromedriver/chrome/ui_events.h"
26 #include "chrome/test/chromedriver/chrome/web_view.h"
27 #include "chrome/test/chromedriver/element_util.h"
28 #include "chrome/test/chromedriver/session.h"
29 #include "chrome/test/chromedriver/util.h"
33 Status
GetMouseButton(const base::DictionaryValue
& params
,
34 MouseButton
* button
) {
36 if (!params
.GetInteger("button", &button_num
)) {
37 button_num
= 0; // Default to left mouse button.
38 } else if (button_num
< 0 || button_num
> 2) {
39 return Status(kUnknownError
,
40 base::StringPrintf("invalid button: %d", button_num
));
42 *button
= static_cast<MouseButton
>(button_num
);
46 Status
GetUrl(WebView
* web_view
, const std::string
& frame
, std::string
* url
) {
47 scoped_ptr
<base::Value
> value
;
49 Status status
= web_view
->CallFunction(
50 frame
, "function() { return document.URL; }", args
, &value
);
53 if (!value
->GetAsString(url
))
54 return Status(kUnknownError
, "javascript failed to return the url");
59 Cookie(const std::string
& name
,
60 const std::string
& value
,
61 const std::string
& domain
,
62 const std::string
& path
,
66 : name(name
), value(value
), domain(domain
), path(path
), expiry(expiry
),
67 secure(secure
), session(session
) {}
78 base::DictionaryValue
* CreateDictionaryFrom(const Cookie
& cookie
) {
79 base::DictionaryValue
* dict
= new base::DictionaryValue();
80 dict
->SetString("name", cookie
.name
);
81 dict
->SetString("value", cookie
.value
);
82 if (!cookie
.domain
.empty())
83 dict
->SetString("domain", cookie
.domain
);
84 if (!cookie
.path
.empty())
85 dict
->SetString("path", cookie
.path
);
87 dict
->SetDouble("expiry", cookie
.expiry
);
88 dict
->SetBoolean("secure", cookie
.secure
);
92 Status
GetVisibleCookies(WebView
* web_view
,
93 std::list
<Cookie
>* cookies
) {
94 scoped_ptr
<base::ListValue
> internal_cookies
;
95 Status status
= web_view
->GetCookies(&internal_cookies
);
98 std::list
<Cookie
> cookies_tmp
;
99 for (size_t i
= 0; i
< internal_cookies
->GetSize(); ++i
) {
100 base::DictionaryValue
* cookie_dict
;
101 if (!internal_cookies
->GetDictionary(i
, &cookie_dict
))
102 return Status(kUnknownError
, "DevTools returns a non-dictionary cookie");
105 cookie_dict
->GetString("name", &name
);
107 cookie_dict
->GetString("value", &value
);
109 cookie_dict
->GetString("domain", &domain
);
111 cookie_dict
->GetString("path", &path
);
113 cookie_dict
->GetDouble("expires", &expiry
);
114 expiry
/= 1000; // Convert from millisecond to second.
115 bool session
= false;
116 cookie_dict
->GetBoolean("session", &session
);
118 cookie_dict
->GetBoolean("secure", &secure
);
120 cookies_tmp
.push_back(
121 Cookie(name
, value
, domain
, path
, expiry
, secure
, session
));
123 cookies
->swap(cookies_tmp
);
127 Status
ScrollCoordinateInToView(
128 Session
* session
, WebView
* web_view
, int x
, int y
, int* offset_x
,
130 scoped_ptr
<base::Value
> value
;
131 base::ListValue args
;
132 args
.AppendInteger(x
);
133 args
.AppendInteger(y
);
134 Status status
= web_view
->CallFunction(
137 " if (x < window.pageXOffset ||"
138 " x >= window.pageXOffset + window.innerWidth ||"
139 " y < window.pageYOffset ||"
140 " y >= window.pageYOffset + window.innerHeight) {"
141 " window.scrollTo(x - window.innerWidth/2, y - window.innerHeight/2);"
144 " view_x: Math.floor(window.pageXOffset),"
145 " view_y: Math.floor(window.pageYOffset),"
146 " view_width: Math.floor(window.innerWidth),"
147 " view_height: Math.floor(window.innerHeight)};"
153 base::DictionaryValue
* view_attrib
;
154 value
->GetAsDictionary(&view_attrib
);
155 int view_x
, view_y
, view_width
, view_height
;
156 view_attrib
->GetInteger("view_x", &view_x
);
157 view_attrib
->GetInteger("view_y", &view_y
);
158 view_attrib
->GetInteger("view_width", &view_width
);
159 view_attrib
->GetInteger("view_height", &view_height
);
160 *offset_x
= x
- view_x
;
161 *offset_y
= y
- view_y
;
162 if (*offset_x
< 0 || *offset_x
>= view_width
|| *offset_y
< 0 ||
163 *offset_y
>= view_height
)
164 return Status(kUnknownError
, "Failed to scroll coordinate into view");
168 Status
ExecuteTouchEvent(
169 Session
* session
, WebView
* web_view
, TouchEventType type
,
170 const base::DictionaryValue
& params
) {
172 if (!params
.GetInteger("x", &x
))
173 return Status(kUnknownError
, "'x' must be an integer");
174 if (!params
.GetInteger("y", &y
))
175 return Status(kUnknownError
, "'y' must be an integer");
178 Status status
= ScrollCoordinateInToView(
179 session
, web_view
, x
, y
, &relative_x
, &relative_y
);
182 std::list
<TouchEvent
> events
;
184 TouchEvent(type
, relative_x
, relative_y
));
185 return web_view
->DispatchTouchEvents(events
);
190 Status
ExecuteWindowCommand(
191 const WindowCommand
& command
,
193 const base::DictionaryValue
& params
,
194 scoped_ptr
<base::Value
>* value
) {
195 WebView
* web_view
= NULL
;
196 Status status
= session
->GetTargetWindow(&web_view
);
197 if (status
.IsError())
200 status
= web_view
->ConnectIfNecessary();
201 if (status
.IsError())
204 status
= web_view
->HandleReceivedEvents();
205 if (status
.IsError())
208 if (web_view
->GetJavaScriptDialogManager()->IsDialogOpen())
209 return Status(kUnexpectedAlertOpen
);
211 Status
nav_status(kOk
);
212 for (int attempt
= 0; attempt
< 2; attempt
++) {
214 if (status
.code() == kNoSuchExecutionContext
)
215 // Switch to main frame and retry command if subframe no longer exists.
216 session
->SwitchToTopFrame();
220 nav_status
= web_view
->WaitForPendingNavigations(
221 session
->GetCurrentFrameId(), session
->page_load_timeout
, true);
222 if (nav_status
.IsError())
225 status
= command
.Run(session
, web_view
, params
, value
);
228 nav_status
= web_view
->WaitForPendingNavigations(
229 session
->GetCurrentFrameId(), session
->page_load_timeout
, true);
231 if (status
.IsOk() && nav_status
.IsError() &&
232 nav_status
.code() != kUnexpectedAlertOpen
)
234 if (status
.code() == kUnexpectedAlertOpen
)
242 const base::DictionaryValue
& params
,
243 scoped_ptr
<base::Value
>* value
) {
245 if (!params
.GetString("url", &url
))
246 return Status(kUnknownError
, "'url' must be a string");
247 return web_view
->Load(url
);
250 Status
ExecuteExecuteScript(
253 const base::DictionaryValue
& params
,
254 scoped_ptr
<base::Value
>* value
) {
256 if (!params
.GetString("script", &script
))
257 return Status(kUnknownError
, "'script' must be a string");
258 if (script
== ":takeHeapSnapshot") {
259 return web_view
->TakeHeapSnapshot(value
);
260 } else if (script
== ":startProfile") {
261 return web_view
->StartProfile();
262 } else if (script
== ":endProfile") {
263 return web_view
->EndProfile(value
);
265 const base::ListValue
* args
;
266 if (!params
.GetList("args", &args
))
267 return Status(kUnknownError
, "'args' must be a list");
269 return web_view
->CallFunction(session
->GetCurrentFrameId(),
270 "function(){" + script
+ "}", *args
, value
);
274 Status
ExecuteExecuteAsyncScript(
277 const base::DictionaryValue
& params
,
278 scoped_ptr
<base::Value
>* value
) {
280 if (!params
.GetString("script", &script
))
281 return Status(kUnknownError
, "'script' must be a string");
282 const base::ListValue
* args
;
283 if (!params
.GetList("args", &args
))
284 return Status(kUnknownError
, "'args' must be a list");
286 return web_view
->CallUserAsyncFunction(
287 session
->GetCurrentFrameId(), "function(){" + script
+ "}", *args
,
288 session
->script_timeout
, value
);
291 Status
ExecuteSwitchToFrame(
294 const base::DictionaryValue
& params
,
295 scoped_ptr
<base::Value
>* value
) {
296 const base::Value
* id
;
297 if (!params
.Get("id", &id
))
298 return Status(kUnknownError
, "missing 'id'");
300 if (id
->IsType(base::Value::TYPE_NULL
)) {
301 session
->SwitchToTopFrame();
306 base::ListValue args
;
307 const base::DictionaryValue
* id_dict
;
308 if (id
->GetAsDictionary(&id_dict
)) {
309 script
= "function(elem) { return elem; }";
310 args
.Append(id_dict
->DeepCopy());
314 " return document.evaluate(xpath, document, null, "
315 " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
317 std::string xpath
= "(/html/body//iframe|/html/frameset/frame)";
318 std::string id_string
;
320 if (id
->GetAsString(&id_string
)) {
321 xpath
+= base::StringPrintf(
322 "[@name=\"%s\" or @id=\"%s\"]", id_string
.c_str(), id_string
.c_str());
323 } else if (id
->GetAsInteger(&id_int
)) {
324 xpath
+= base::StringPrintf("[%d]", id_int
+ 1);
326 return Status(kUnknownError
, "invalid 'id'");
328 args
.Append(new base::StringValue(xpath
));
331 Status status
= web_view
->GetFrameByFunction(
332 session
->GetCurrentFrameId(), script
, args
, &frame
);
333 if (status
.IsError())
336 scoped_ptr
<base::Value
> result
;
337 status
= web_view
->CallFunction(
338 session
->GetCurrentFrameId(), script
, args
, &result
);
339 if (status
.IsError())
341 const base::DictionaryValue
* element
;
342 if (!result
->GetAsDictionary(&element
))
343 return Status(kUnknownError
, "fail to locate the sub frame element");
345 std::string chrome_driver_id
= GenerateId();
346 const char kSetFrameIdentifier
[] =
347 "function(frame, id) {"
348 " frame.setAttribute('cd_frame_id_', id);"
350 base::ListValue new_args
;
351 new_args
.Append(element
->DeepCopy());
352 new_args
.AppendString(chrome_driver_id
);
354 status
= web_view
->CallFunction(
355 session
->GetCurrentFrameId(), kSetFrameIdentifier
, new_args
, &result
);
356 if (status
.IsError())
358 session
->SwitchToSubFrame(frame
, chrome_driver_id
);
362 Status
ExecuteSwitchToParentFrame(
365 const base::DictionaryValue
& params
,
366 scoped_ptr
<base::Value
>* value
) {
367 session
->SwitchToParentFrame();
371 Status
ExecuteGetTitle(
374 const base::DictionaryValue
& params
,
375 scoped_ptr
<base::Value
>* value
) {
376 const char kGetTitleScript
[] =
378 " if (document.title)"
379 " return document.title;"
381 " return document.URL;"
383 base::ListValue args
;
384 return web_view
->CallFunction(std::string(), kGetTitleScript
, args
, value
);
387 Status
ExecuteGetPageSource(
390 const base::DictionaryValue
& params
,
391 scoped_ptr
<base::Value
>* value
) {
392 const char kGetPageSource
[] =
394 " return new XMLSerializer().serializeToString(document);"
396 base::ListValue args
;
397 return web_view
->CallFunction(
398 session
->GetCurrentFrameId(), kGetPageSource
, args
, value
);
401 Status
ExecuteFindElement(
405 const base::DictionaryValue
& params
,
406 scoped_ptr
<base::Value
>* value
) {
407 return FindElement(interval_ms
, true, NULL
, session
, web_view
, params
, value
);
410 Status
ExecuteFindElements(
414 const base::DictionaryValue
& params
,
415 scoped_ptr
<base::Value
>* value
) {
417 interval_ms
, false, NULL
, session
, web_view
, params
, value
);
420 Status
ExecuteGetCurrentUrl(
423 const base::DictionaryValue
& params
,
424 scoped_ptr
<base::Value
>* value
) {
426 Status status
= GetUrl(web_view
, session
->GetCurrentFrameId(), &url
);
427 if (status
.IsError())
429 value
->reset(new base::StringValue(url
));
433 Status
ExecuteGoBack(
436 const base::DictionaryValue
& params
,
437 scoped_ptr
<base::Value
>* value
) {
438 return web_view
->EvaluateScript(
439 std::string(), "window.history.back();", value
);
442 Status
ExecuteGoForward(
445 const base::DictionaryValue
& params
,
446 scoped_ptr
<base::Value
>* value
) {
447 return web_view
->EvaluateScript(
448 std::string(), "window.history.forward();", value
);
451 Status
ExecuteRefresh(
454 const base::DictionaryValue
& params
,
455 scoped_ptr
<base::Value
>* value
) {
456 return web_view
->Reload();
459 Status
ExecuteMouseMoveTo(
462 const base::DictionaryValue
& params
,
463 scoped_ptr
<base::Value
>* value
) {
464 std::string element_id
;
465 bool has_element
= params
.GetString("element", &element_id
);
468 bool has_offset
= params
.GetInteger("xoffset", &x_offset
) &&
469 params
.GetInteger("yoffset", &y_offset
);
470 if (!has_element
&& !has_offset
)
471 return Status(kUnknownError
, "at least an element or offset should be set");
475 Status status
= ScrollElementIntoView(
476 session
, web_view
, element_id
, &location
);
477 if (status
.IsError())
480 location
= session
->mouse_position
;
484 location
.Offset(x_offset
, y_offset
);
487 Status status
= GetElementSize(session
, web_view
, element_id
, &size
);
488 if (status
.IsError())
490 location
.Offset(size
.width
/ 2, size
.height
/ 2);
493 std::list
<MouseEvent
> events
;
495 MouseEvent(kMovedMouseEventType
, kNoneMouseButton
,
496 location
.x
, location
.y
, session
->sticky_modifiers
, 0));
498 web_view
->DispatchMouseEvents(events
, session
->GetCurrentFrameId());
500 session
->mouse_position
= location
;
504 Status
ExecuteMouseClick(
507 const base::DictionaryValue
& params
,
508 scoped_ptr
<base::Value
>* value
) {
510 Status status
= GetMouseButton(params
, &button
);
511 if (status
.IsError())
513 std::list
<MouseEvent
> events
;
515 MouseEvent(kPressedMouseEventType
, button
,
516 session
->mouse_position
.x
, session
->mouse_position
.y
,
517 session
->sticky_modifiers
, 1));
519 MouseEvent(kReleasedMouseEventType
, button
,
520 session
->mouse_position
.x
, session
->mouse_position
.y
,
521 session
->sticky_modifiers
, 1));
522 return web_view
->DispatchMouseEvents(events
, session
->GetCurrentFrameId());
525 Status
ExecuteMouseButtonDown(
528 const base::DictionaryValue
& params
,
529 scoped_ptr
<base::Value
>* value
) {
531 Status status
= GetMouseButton(params
, &button
);
532 if (status
.IsError())
534 std::list
<MouseEvent
> events
;
536 MouseEvent(kPressedMouseEventType
, button
,
537 session
->mouse_position
.x
, session
->mouse_position
.y
,
538 session
->sticky_modifiers
, 1));
539 return web_view
->DispatchMouseEvents(events
, session
->GetCurrentFrameId());
542 Status
ExecuteMouseButtonUp(
545 const base::DictionaryValue
& params
,
546 scoped_ptr
<base::Value
>* value
) {
548 Status status
= GetMouseButton(params
, &button
);
549 if (status
.IsError())
551 std::list
<MouseEvent
> events
;
553 MouseEvent(kReleasedMouseEventType
, button
,
554 session
->mouse_position
.x
, session
->mouse_position
.y
,
555 session
->sticky_modifiers
, 1));
556 return web_view
->DispatchMouseEvents(events
, session
->GetCurrentFrameId());
559 Status
ExecuteMouseDoubleClick(
562 const base::DictionaryValue
& params
,
563 scoped_ptr
<base::Value
>* value
) {
565 Status status
= GetMouseButton(params
, &button
);
566 if (status
.IsError())
568 std::list
<MouseEvent
> events
;
570 MouseEvent(kPressedMouseEventType
, button
,
571 session
->mouse_position
.x
, session
->mouse_position
.y
,
572 session
->sticky_modifiers
, 2));
574 MouseEvent(kReleasedMouseEventType
, button
,
575 session
->mouse_position
.x
, session
->mouse_position
.y
,
576 session
->sticky_modifiers
, 2));
577 return web_view
->DispatchMouseEvents(events
, session
->GetCurrentFrameId());
580 Status
ExecuteTouchDown(
583 const base::DictionaryValue
& params
,
584 scoped_ptr
<base::Value
>* value
) {
585 return ExecuteTouchEvent(session
, web_view
, kTouchStart
, params
);
588 Status
ExecuteTouchUp(
591 const base::DictionaryValue
& params
,
592 scoped_ptr
<base::Value
>* value
) {
593 return ExecuteTouchEvent(session
, web_view
, kTouchEnd
, params
);
596 Status
ExecuteTouchMove(
599 const base::DictionaryValue
& params
,
600 scoped_ptr
<base::Value
>* value
) {
601 return ExecuteTouchEvent(session
, web_view
, kTouchMove
, params
);
604 Status
ExecuteGetActiveElement(
607 const base::DictionaryValue
& params
,
608 scoped_ptr
<base::Value
>* value
) {
609 return GetActiveElement(session
, web_view
, value
);
612 Status
ExecuteSendKeysToActiveElement(
615 const base::DictionaryValue
& params
,
616 scoped_ptr
<base::Value
>* value
) {
617 const base::ListValue
* key_list
;
618 if (!params
.GetList("value", &key_list
))
619 return Status(kUnknownError
, "'value' must be a list");
620 return SendKeysOnWindow(
621 web_view
, key_list
, false, &session
->sticky_modifiers
);
624 Status
ExecuteGetAppCacheStatus(
627 const base::DictionaryValue
& params
,
628 scoped_ptr
<base::Value
>* value
) {
629 return web_view
->EvaluateScript(
630 session
->GetCurrentFrameId(),
631 "applicationCache.status",
635 Status
ExecuteIsBrowserOnline(
638 const base::DictionaryValue
& params
,
639 scoped_ptr
<base::Value
>* value
) {
640 return web_view
->EvaluateScript(
641 session
->GetCurrentFrameId(),
646 Status
ExecuteGetStorageItem(
650 const base::DictionaryValue
& params
,
651 scoped_ptr
<base::Value
>* value
) {
653 if (!params
.GetString("key", &key
))
654 return Status(kUnknownError
, "'key' must be a string");
655 base::ListValue args
;
656 args
.Append(new base::StringValue(key
));
657 return web_view
->CallFunction(
658 session
->GetCurrentFrameId(),
659 base::StringPrintf("function(key) { return %s[key]; }", storage
),
664 Status
ExecuteGetStorageKeys(
668 const base::DictionaryValue
& params
,
669 scoped_ptr
<base::Value
>* value
) {
670 const char script
[] =
672 "for (var key in %s) {"
676 return web_view
->EvaluateScript(
677 session
->GetCurrentFrameId(),
678 base::StringPrintf(script
, storage
),
682 Status
ExecuteSetStorageItem(
686 const base::DictionaryValue
& params
,
687 scoped_ptr
<base::Value
>* value
) {
689 if (!params
.GetString("key", &key
))
690 return Status(kUnknownError
, "'key' must be a string");
691 std::string storage_value
;
692 if (!params
.GetString("value", &storage_value
))
693 return Status(kUnknownError
, "'value' must be a string");
694 base::ListValue args
;
695 args
.Append(new base::StringValue(key
));
696 args
.Append(new base::StringValue(storage_value
));
697 return web_view
->CallFunction(
698 session
->GetCurrentFrameId(),
699 base::StringPrintf("function(key, value) { %s[key] = value; }", storage
),
704 Status
ExecuteRemoveStorageItem(
708 const base::DictionaryValue
& params
,
709 scoped_ptr
<base::Value
>* value
) {
711 if (!params
.GetString("key", &key
))
712 return Status(kUnknownError
, "'key' must be a string");
713 base::ListValue args
;
714 args
.Append(new base::StringValue(key
));
715 return web_view
->CallFunction(
716 session
->GetCurrentFrameId(),
717 base::StringPrintf("function(key) { %s.removeItem(key) }", storage
),
722 Status
ExecuteClearStorage(
726 const base::DictionaryValue
& params
,
727 scoped_ptr
<base::Value
>* value
) {
728 return web_view
->EvaluateScript(
729 session
->GetCurrentFrameId(),
730 base::StringPrintf("%s.clear()", storage
),
734 Status
ExecuteGetStorageSize(
738 const base::DictionaryValue
& params
,
739 scoped_ptr
<base::Value
>* value
) {
740 return web_view
->EvaluateScript(
741 session
->GetCurrentFrameId(),
742 base::StringPrintf("%s.length", storage
),
746 Status
ExecuteScreenshot(
749 const base::DictionaryValue
& params
,
750 scoped_ptr
<base::Value
>* value
) {
751 Status status
= session
->chrome
->ActivateWebView(web_view
->GetId());
752 if (status
.IsError())
755 std::string screenshot
;
756 ChromeDesktopImpl
* desktop
= NULL
;
757 status
= session
->chrome
->GetAsDesktop(&desktop
);
758 if (status
.IsOk() && !session
->force_devtools_screenshot
) {
759 AutomationExtension
* extension
= NULL
;
760 status
= desktop
->GetAutomationExtension(&extension
);
761 if (status
.IsError())
763 status
= extension
->CaptureScreenshot(&screenshot
);
764 // If the screenshot was forbidden, fallback to DevTools.
765 if (status
.code() == kForbidden
)
766 status
= web_view
->CaptureScreenshot(&screenshot
);
768 status
= web_view
->CaptureScreenshot(&screenshot
);
770 if (status
.IsError())
773 value
->reset(new base::StringValue(screenshot
));
777 Status
ExecuteGetCookies(
780 const base::DictionaryValue
& params
,
781 scoped_ptr
<base::Value
>* value
) {
782 std::list
<Cookie
> cookies
;
783 Status status
= GetVisibleCookies(web_view
, &cookies
);
784 if (status
.IsError())
786 scoped_ptr
<base::ListValue
> cookie_list(new base::ListValue());
787 for (std::list
<Cookie
>::const_iterator it
= cookies
.begin();
788 it
!= cookies
.end(); ++it
) {
789 cookie_list
->Append(CreateDictionaryFrom(*it
));
791 value
->reset(cookie_list
.release());
795 Status
ExecuteAddCookie(
798 const base::DictionaryValue
& params
,
799 scoped_ptr
<base::Value
>* value
) {
800 const base::DictionaryValue
* cookie
;
801 if (!params
.GetDictionary("cookie", &cookie
))
802 return Status(kUnknownError
, "missing 'cookie'");
803 base::ListValue args
;
804 args
.Append(cookie
->DeepCopy());
805 scoped_ptr
<base::Value
> result
;
806 return web_view
->CallFunction(
807 session
->GetCurrentFrameId(), kAddCookieScript
, args
, &result
);
810 Status
ExecuteDeleteCookie(
813 const base::DictionaryValue
& params
,
814 scoped_ptr
<base::Value
>* value
) {
816 if (!params
.GetString("name", &name
))
817 return Status(kUnknownError
, "missing 'name'");
818 base::DictionaryValue params_url
;
819 scoped_ptr
<base::Value
> value_url
;
821 Status status
= GetUrl(web_view
, session
->GetCurrentFrameId(), &url
);
822 if (status
.IsError())
824 return web_view
->DeleteCookie(name
, url
);
827 Status
ExecuteDeleteAllCookies(
830 const base::DictionaryValue
& params
,
831 scoped_ptr
<base::Value
>* value
) {
832 std::list
<Cookie
> cookies
;
833 Status status
= GetVisibleCookies(web_view
, &cookies
);
834 if (status
.IsError())
837 if (!cookies
.empty()) {
838 base::DictionaryValue params_url
;
839 scoped_ptr
<base::Value
> value_url
;
841 status
= GetUrl(web_view
, session
->GetCurrentFrameId(), &url
);
842 if (status
.IsError())
844 for (std::list
<Cookie
>::const_iterator it
= cookies
.begin();
845 it
!= cookies
.end(); ++it
) {
846 status
= web_view
->DeleteCookie(it
->name
, url
);
847 if (status
.IsError())
855 Status
ExecuteSetLocation(
858 const base::DictionaryValue
& params
,
859 scoped_ptr
<base::Value
>* value
) {
860 const base::DictionaryValue
* location
= NULL
;
861 Geoposition geoposition
;
862 if (!params
.GetDictionary("location", &location
) ||
863 !location
->GetDouble("latitude", &geoposition
.latitude
) ||
864 !location
->GetDouble("longitude", &geoposition
.longitude
))
865 return Status(kUnknownError
, "missing or invalid 'location'");
866 if (location
->HasKey("accuracy") &&
867 !location
->GetDouble("accuracy", &geoposition
.accuracy
)) {
868 return Status(kUnknownError
, "invalid 'accuracy'");
870 // |accuracy| is not part of the WebDriver spec yet, so if it is not given
871 // default to 100 meters accuracy.
872 geoposition
.accuracy
= 100;
875 Status status
= web_view
->OverrideGeolocation(geoposition
);
877 session
->overridden_geoposition
.reset(new Geoposition(geoposition
));
881 Status
ExecuteTakeHeapSnapshot(
884 const base::DictionaryValue
& params
,
885 scoped_ptr
<base::Value
>* value
) {
886 return web_view
->TakeHeapSnapshot(value
);