Home | History | Annotate | Download | only in chromedriver
      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/window_commands.h"
      6 
      7 #include <list>
      8 
      9 #include "base/callback.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "base/threading/platform_thread.h"
     13 #include "base/time/time.h"
     14 #include "base/values.h"
     15 #include "chrome/test/chromedriver/basic_types.h"
     16 #include "chrome/test/chromedriver/chrome/chrome.h"
     17 #include "chrome/test/chromedriver/chrome/devtools_client.h"
     18 #include "chrome/test/chromedriver/chrome/geoposition.h"
     19 #include "chrome/test/chromedriver/chrome/javascript_dialog_manager.h"
     20 #include "chrome/test/chromedriver/chrome/js.h"
     21 #include "chrome/test/chromedriver/chrome/status.h"
     22 #include "chrome/test/chromedriver/chrome/ui_events.h"
     23 #include "chrome/test/chromedriver/chrome/web_view.h"
     24 #include "chrome/test/chromedriver/element_util.h"
     25 #include "chrome/test/chromedriver/session.h"
     26 #include "chrome/test/chromedriver/util.h"
     27 
     28 namespace {
     29 
     30 Status GetMouseButton(const base::DictionaryValue& params,
     31                       MouseButton* button) {
     32   int button_num;
     33   if (!params.GetInteger("button", &button_num)) {
     34     button_num = 0;  // Default to left mouse button.
     35   } else if (button_num < 0 || button_num > 2) {
     36     return Status(kUnknownError,
     37                   base::StringPrintf("invalid button: %d", button_num));
     38   }
     39   *button = static_cast<MouseButton>(button_num);
     40   return Status(kOk);
     41 }
     42 
     43 Status GetUrl(WebView* web_view, const std::string& frame, std::string* url) {
     44   scoped_ptr<base::Value> value;
     45   base::ListValue args;
     46   Status status = web_view->CallFunction(
     47       frame, "function() { return document.URL; }", args, &value);
     48   if (status.IsError())
     49     return status;
     50   if (!value->GetAsString(url))
     51     return Status(kUnknownError, "javascript failed to return the url");
     52   return Status(kOk);
     53 }
     54 
     55 struct Cookie {
     56   Cookie(const std::string& name,
     57          const std::string& value,
     58          const std::string& domain,
     59          const std::string& path,
     60          double expiry,
     61          bool secure,
     62          bool session)
     63       : name(name), value(value), domain(domain), path(path), expiry(expiry),
     64         secure(secure), session(session) {}
     65 
     66   std::string name;
     67   std::string value;
     68   std::string domain;
     69   std::string path;
     70   double expiry;
     71   bool secure;
     72   bool session;
     73 };
     74 
     75 base::DictionaryValue* CreateDictionaryFrom(const Cookie& cookie) {
     76   base::DictionaryValue* dict = new base::DictionaryValue();
     77   dict->SetString("name", cookie.name);
     78   dict->SetString("value", cookie.value);
     79   if (!cookie.domain.empty())
     80     dict->SetString("domain", cookie.domain);
     81   if (!cookie.path.empty())
     82     dict->SetString("path", cookie.path);
     83   if (!cookie.session)
     84     dict->SetDouble("expiry", cookie.expiry);
     85   dict->SetBoolean("secure", cookie.secure);
     86   return dict;
     87 }
     88 
     89 Status GetVisibleCookies(WebView* web_view,
     90                          std::list<Cookie>* cookies) {
     91   scoped_ptr<base::ListValue> internal_cookies;
     92   Status status = web_view->GetCookies(&internal_cookies);
     93   if (status.IsError())
     94     return status;
     95   std::list<Cookie> cookies_tmp;
     96   for (size_t i = 0; i < internal_cookies->GetSize(); ++i) {
     97     base::DictionaryValue* cookie_dict;
     98     if (!internal_cookies->GetDictionary(i, &cookie_dict))
     99       return Status(kUnknownError, "DevTools returns a non-dictionary cookie");
    100 
    101     std::string name;
    102     cookie_dict->GetString("name", &name);
    103     std::string value;
    104     cookie_dict->GetString("value", &value);
    105     std::string domain;
    106     cookie_dict->GetString("domain", &domain);
    107     std::string path;
    108     cookie_dict->GetString("path", &path);
    109     double expiry = 0;
    110     cookie_dict->GetDouble("expires", &expiry);
    111     expiry /= 1000;  // Convert from millisecond to second.
    112     bool session = false;
    113     cookie_dict->GetBoolean("session", &session);
    114     bool secure = false;
    115     cookie_dict->GetBoolean("secure", &secure);
    116 
    117     cookies_tmp.push_back(
    118         Cookie(name, value, domain, path, expiry, secure, session));
    119   }
    120   cookies->swap(cookies_tmp);
    121   return Status(kOk);
    122 }
    123 
    124 }  // namespace
    125 
    126 Status ExecuteWindowCommand(
    127     const WindowCommand& command,
    128     Session* session,
    129     const base::DictionaryValue& params,
    130     scoped_ptr<base::Value>* value) {
    131   WebView* web_view = NULL;
    132   Status status = session->GetTargetWindow(&web_view);
    133   if (status.IsError())
    134     return status;
    135 
    136   status = web_view->ConnectIfNecessary();
    137   if (status.IsError())
    138     return status;
    139 
    140   status = web_view->HandleReceivedEvents();
    141   if (status.IsError())
    142     return status;
    143 
    144   if (web_view->GetJavaScriptDialogManager()->IsDialogOpen())
    145     return Status(kUnexpectedAlertOpen);
    146 
    147   Status nav_status(kOk);
    148   for (int attempt = 0; attempt < 2; attempt++) {
    149     if (attempt == 1) {
    150       if (status.code() == kNoSuchExecutionContext)
    151         // Switch to main frame and retry command if subframe no longer exists.
    152         session->SwitchToTopFrame();
    153       else
    154         break;
    155     }
    156     nav_status =
    157         web_view->WaitForPendingNavigations(session->GetCurrentFrameId(),
    158                                             session->page_load_timeout);
    159     if (nav_status.IsError())
    160       return nav_status;
    161 
    162     status = command.Run(session, web_view, params, value);
    163   }
    164 
    165   nav_status =
    166       web_view->WaitForPendingNavigations(session->GetCurrentFrameId(),
    167                                           session->page_load_timeout);
    168 
    169   if (status.IsOk() && nav_status.IsError() &&
    170       nav_status.code() != kDisconnected &&
    171       nav_status.code() != kUnexpectedAlertOpen)
    172     return nav_status;
    173   if (status.code() == kUnexpectedAlertOpen)
    174     return Status(kOk);
    175   return status;
    176 }
    177 
    178 Status ExecuteGet(
    179     Session* session,
    180     WebView* web_view,
    181     const base::DictionaryValue& params,
    182     scoped_ptr<base::Value>* value) {
    183   std::string url;
    184   if (!params.GetString("url", &url))
    185     return Status(kUnknownError, "'url' must be a string");
    186   return web_view->Load(url);
    187 }
    188 
    189 Status ExecuteExecuteScript(
    190     Session* session,
    191     WebView* web_view,
    192     const base::DictionaryValue& params,
    193     scoped_ptr<base::Value>* value) {
    194   std::string script;
    195   if (!params.GetString("script", &script))
    196     return Status(kUnknownError, "'script' must be a string");
    197   const base::ListValue* args;
    198   if (!params.GetList("args", &args))
    199     return Status(kUnknownError, "'args' must be a list");
    200 
    201   return web_view->CallFunction(
    202       session->GetCurrentFrameId(), "function(){" + script + "}", *args, value);
    203 }
    204 
    205 Status ExecuteExecuteAsyncScript(
    206     Session* session,
    207     WebView* web_view,
    208     const base::DictionaryValue& params,
    209     scoped_ptr<base::Value>* value) {
    210   std::string script;
    211   if (!params.GetString("script", &script))
    212     return Status(kUnknownError, "'script' must be a string");
    213   const base::ListValue* args;
    214   if (!params.GetList("args", &args))
    215     return Status(kUnknownError, "'args' must be a list");
    216 
    217   return web_view->CallUserAsyncFunction(
    218       session->GetCurrentFrameId(), "function(){" + script + "}", *args,
    219       base::TimeDelta::FromMilliseconds(session->script_timeout), value);
    220 }
    221 
    222 Status ExecuteSwitchToFrame(
    223     Session* session,
    224     WebView* web_view,
    225     const base::DictionaryValue& params,
    226     scoped_ptr<base::Value>* value) {
    227   const base::Value* id;
    228   if (!params.Get("id", &id))
    229     return Status(kUnknownError, "missing 'id'");
    230 
    231   if (id->IsType(base::Value::TYPE_NULL)) {
    232     session->SwitchToTopFrame();
    233     return Status(kOk);
    234   }
    235 
    236   std::string script;
    237   base::ListValue args;
    238   const base::DictionaryValue* id_dict;
    239   if (id->GetAsDictionary(&id_dict)) {
    240     script = "function(elem) { return elem; }";
    241     args.Append(id_dict->DeepCopy());
    242   } else {
    243     script =
    244         "function(xpath) {"
    245         "  return document.evaluate(xpath, document, null, "
    246         "      XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
    247         "}";
    248     std::string xpath = "(/html/body//iframe|/html/frameset/frame)";
    249     std::string id_string;
    250     int id_int;
    251     if (id->GetAsString(&id_string)) {
    252       xpath += base::StringPrintf(
    253           "[@name=\"%s\" or @id=\"%s\"]", id_string.c_str(), id_string.c_str());
    254     } else if (id->GetAsInteger(&id_int)) {
    255       xpath += base::StringPrintf("[%d]", id_int + 1);
    256     } else {
    257       return Status(kUnknownError, "invalid 'id'");
    258     }
    259     args.Append(new base::StringValue(xpath));
    260   }
    261   std::string frame;
    262   Status status = web_view->GetFrameByFunction(
    263       session->GetCurrentFrameId(), script, args, &frame);
    264   if (status.IsError())
    265     return status;
    266 
    267   scoped_ptr<base::Value> result;
    268   status = web_view->CallFunction(
    269       session->GetCurrentFrameId(), script, args, &result);
    270   if (status.IsError())
    271     return status;
    272   const base::DictionaryValue* element;
    273   if (!result->GetAsDictionary(&element))
    274     return Status(kUnknownError, "fail to locate the sub frame element");
    275 
    276   std::string chrome_driver_id = GenerateId();
    277   const char* kSetFrameIdentifier =
    278       "function(frame, id) {"
    279       "  frame.setAttribute('cd_frame_id_', id);"
    280       "}";
    281   base::ListValue new_args;
    282   new_args.Append(element->DeepCopy());
    283   new_args.AppendString(chrome_driver_id);
    284   result.reset(NULL);
    285   status = web_view->CallFunction(
    286       session->GetCurrentFrameId(), kSetFrameIdentifier, new_args, &result);
    287   if (status.IsError())
    288     return status;
    289   session->SwitchToSubFrame(frame, chrome_driver_id);
    290   return Status(kOk);
    291 }
    292 
    293 Status ExecuteGetTitle(
    294     Session* session,
    295     WebView* web_view,
    296     const base::DictionaryValue& params,
    297     scoped_ptr<base::Value>* value) {
    298   const char* kGetTitleScript =
    299       "function() {"
    300       "  if (document.title)"
    301       "    return document.title;"
    302       "  else"
    303       "    return document.URL;"
    304       "}";
    305   base::ListValue args;
    306   return web_view->CallFunction(std::string(), kGetTitleScript, args, value);
    307 }
    308 
    309 Status ExecuteGetPageSource(
    310     Session* session,
    311     WebView* web_view,
    312     const base::DictionaryValue& params,
    313     scoped_ptr<base::Value>* value) {
    314   const char* kGetPageSource =
    315       "function() {"
    316       "  return new XMLSerializer().serializeToString(document);"
    317       "}";
    318   base::ListValue args;
    319   return web_view->CallFunction(
    320       session->GetCurrentFrameId(), kGetPageSource, args, value);
    321 }
    322 
    323 Status ExecuteFindElement(
    324     int interval_ms,
    325     Session* session,
    326     WebView* web_view,
    327     const base::DictionaryValue& params,
    328     scoped_ptr<base::Value>* value) {
    329   return FindElement(interval_ms, true, NULL, session, web_view, params, value);
    330 }
    331 
    332 Status ExecuteFindElements(
    333     int interval_ms,
    334     Session* session,
    335     WebView* web_view,
    336     const base::DictionaryValue& params,
    337     scoped_ptr<base::Value>* value) {
    338   return FindElement(
    339       interval_ms, false, NULL, session, web_view, params, value);
    340 }
    341 
    342 Status ExecuteGetCurrentUrl(
    343     Session* session,
    344     WebView* web_view,
    345     const base::DictionaryValue& params,
    346     scoped_ptr<base::Value>* value) {
    347   std::string url;
    348   Status status = GetUrl(web_view, session->GetCurrentFrameId(), &url);
    349   if (status.IsError())
    350     return status;
    351   value->reset(new base::StringValue(url));
    352   return Status(kOk);
    353 }
    354 
    355 Status ExecuteGoBack(
    356     Session* session,
    357     WebView* web_view,
    358     const base::DictionaryValue& params,
    359     scoped_ptr<base::Value>* value) {
    360   return web_view->EvaluateScript(
    361       std::string(), "window.history.back();", value);
    362 }
    363 
    364 Status ExecuteGoForward(
    365     Session* session,
    366     WebView* web_view,
    367     const base::DictionaryValue& params,
    368     scoped_ptr<base::Value>* value) {
    369   return web_view->EvaluateScript(
    370       std::string(), "window.history.forward();", value);
    371 }
    372 
    373 Status ExecuteRefresh(
    374     Session* session,
    375     WebView* web_view,
    376     const base::DictionaryValue& params,
    377     scoped_ptr<base::Value>* value) {
    378   return web_view->Reload();
    379 }
    380 
    381 Status ExecuteMouseMoveTo(
    382     Session* session,
    383     WebView* web_view,
    384     const base::DictionaryValue& params,
    385     scoped_ptr<base::Value>* value) {
    386   std::string element_id;
    387   bool has_element = params.GetString("element", &element_id);
    388   int x_offset = 0;
    389   int y_offset = 0;
    390   bool has_offset = params.GetInteger("xoffset", &x_offset) &&
    391       params.GetInteger("yoffset", &y_offset);
    392   if (!has_element && !has_offset)
    393     return Status(kUnknownError, "at least an element or offset should be set");
    394 
    395   WebPoint location;
    396   if (has_element) {
    397     Status status = ScrollElementIntoView(
    398         session, web_view, element_id, &location);
    399     if (status.IsError())
    400       return status;
    401   } else {
    402     location = session->mouse_position;
    403   }
    404 
    405   if (has_offset) {
    406     location.Offset(x_offset, y_offset);
    407   } else {
    408     WebSize size;
    409     Status status = GetElementSize(session, web_view, element_id, &size);
    410     if (status.IsError())
    411       return status;
    412     location.Offset(size.width / 2, size.height / 2);
    413   }
    414 
    415   std::list<MouseEvent> events;
    416   events.push_back(
    417       MouseEvent(kMovedMouseEventType, kNoneMouseButton,
    418                  location.x, location.y, session->sticky_modifiers, 0));
    419   Status status =
    420       web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
    421   if (status.IsOk())
    422     session->mouse_position = location;
    423   return status;
    424 }
    425 
    426 Status ExecuteMouseClick(
    427     Session* session,
    428     WebView* web_view,
    429     const base::DictionaryValue& params,
    430     scoped_ptr<base::Value>* value) {
    431   MouseButton button;
    432   Status status = GetMouseButton(params, &button);
    433   if (status.IsError())
    434     return status;
    435   std::list<MouseEvent> events;
    436   events.push_back(
    437       MouseEvent(kPressedMouseEventType, button,
    438                  session->mouse_position.x, session->mouse_position.y,
    439                  session->sticky_modifiers, 1));
    440   events.push_back(
    441       MouseEvent(kReleasedMouseEventType, button,
    442                  session->mouse_position.x, session->mouse_position.y,
    443                  session->sticky_modifiers, 1));
    444   return web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
    445 }
    446 
    447 Status ExecuteMouseButtonDown(
    448     Session* session,
    449     WebView* web_view,
    450     const base::DictionaryValue& params,
    451     scoped_ptr<base::Value>* value) {
    452   MouseButton button;
    453   Status status = GetMouseButton(params, &button);
    454   if (status.IsError())
    455     return status;
    456   std::list<MouseEvent> events;
    457   events.push_back(
    458       MouseEvent(kPressedMouseEventType, button,
    459                  session->mouse_position.x, session->mouse_position.y,
    460                  session->sticky_modifiers, 1));
    461   return web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
    462 }
    463 
    464 Status ExecuteMouseButtonUp(
    465     Session* session,
    466     WebView* web_view,
    467     const base::DictionaryValue& params,
    468     scoped_ptr<base::Value>* value) {
    469   MouseButton button;
    470   Status status = GetMouseButton(params, &button);
    471   if (status.IsError())
    472     return status;
    473   std::list<MouseEvent> events;
    474   events.push_back(
    475       MouseEvent(kReleasedMouseEventType, button,
    476                  session->mouse_position.x, session->mouse_position.y,
    477                  session->sticky_modifiers, 1));
    478   return web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
    479 }
    480 
    481 Status ExecuteMouseDoubleClick(
    482     Session* session,
    483     WebView* web_view,
    484     const base::DictionaryValue& params,
    485     scoped_ptr<base::Value>* value) {
    486   MouseButton button;
    487   Status status = GetMouseButton(params, &button);
    488   if (status.IsError())
    489     return status;
    490   std::list<MouseEvent> events;
    491   events.push_back(
    492       MouseEvent(kPressedMouseEventType, button,
    493                  session->mouse_position.x, session->mouse_position.y,
    494                  session->sticky_modifiers, 2));
    495   events.push_back(
    496       MouseEvent(kReleasedMouseEventType, button,
    497                  session->mouse_position.x, session->mouse_position.y,
    498                  session->sticky_modifiers, 2));
    499   return web_view->DispatchMouseEvents(events, session->GetCurrentFrameId());
    500 }
    501 
    502 Status ExecuteGetActiveElement(
    503     Session* session,
    504     WebView* web_view,
    505     const base::DictionaryValue& params,
    506     scoped_ptr<base::Value>* value) {
    507   base::ListValue args;
    508   return web_view->CallFunction(
    509       session->GetCurrentFrameId(),
    510       "function() { return document.activeElement || document.body }",
    511       args,
    512       value);
    513 }
    514 
    515 Status ExecuteSendKeysToActiveElement(
    516     Session* session,
    517     WebView* web_view,
    518     const base::DictionaryValue& params,
    519     scoped_ptr<base::Value>* value) {
    520   const base::ListValue* key_list;
    521   if (!params.GetList("value", &key_list))
    522     return Status(kUnknownError, "'value' must be a list");
    523   return SendKeysOnWindow(
    524       web_view, key_list, false, &session->sticky_modifiers);
    525 }
    526 
    527 Status ExecuteGetAppCacheStatus(
    528     Session* session,
    529     WebView* web_view,
    530     const base::DictionaryValue& params,
    531     scoped_ptr<base::Value>* value) {
    532   return web_view->EvaluateScript(
    533       session->GetCurrentFrameId(),
    534       "applicationCache.status",
    535       value);
    536 }
    537 
    538 Status ExecuteIsBrowserOnline(
    539     Session* session,
    540     WebView* web_view,
    541     const base::DictionaryValue& params,
    542     scoped_ptr<base::Value>* value) {
    543   return web_view->EvaluateScript(
    544       session->GetCurrentFrameId(),
    545       "navigator.onLine",
    546       value);
    547 }
    548 
    549 Status ExecuteGetStorageItem(
    550     const char* storage,
    551     Session* session,
    552     WebView* web_view,
    553     const base::DictionaryValue& params,
    554     scoped_ptr<base::Value>* value) {
    555   std::string key;
    556   if (!params.GetString("key", &key))
    557     return Status(kUnknownError, "'key' must be a string");
    558   base::ListValue args;
    559   args.Append(new base::StringValue(key));
    560   return web_view->CallFunction(
    561       session->GetCurrentFrameId(),
    562       base::StringPrintf("function(key) { return %s[key]; }", storage),
    563       args,
    564       value);
    565 }
    566 
    567 Status ExecuteGetStorageKeys(
    568     const char* storage,
    569     Session* session,
    570     WebView* web_view,
    571     const base::DictionaryValue& params,
    572     scoped_ptr<base::Value>* value) {
    573   const char script[] =
    574       "var keys = [];"
    575       "for (var key in %s) {"
    576       "  keys.push(key);"
    577       "}"
    578       "keys";
    579   return web_view->EvaluateScript(
    580       session->GetCurrentFrameId(),
    581       base::StringPrintf(script, storage),
    582       value);
    583 }
    584 
    585 Status ExecuteSetStorageItem(
    586     const char* storage,
    587     Session* session,
    588     WebView* web_view,
    589     const base::DictionaryValue& params,
    590     scoped_ptr<base::Value>* value) {
    591   std::string key;
    592   if (!params.GetString("key", &key))
    593     return Status(kUnknownError, "'key' must be a string");
    594   std::string storage_value;
    595   if (!params.GetString("value", &storage_value))
    596     return Status(kUnknownError, "'value' must be a string");
    597   base::ListValue args;
    598   args.Append(new base::StringValue(key));
    599   args.Append(new base::StringValue(storage_value));
    600   return web_view->CallFunction(
    601       session->GetCurrentFrameId(),
    602       base::StringPrintf("function(key, value) { %s[key] = value; }", storage),
    603       args,
    604       value);
    605 }
    606 
    607 Status ExecuteRemoveStorageItem(
    608     const char* storage,
    609     Session* session,
    610     WebView* web_view,
    611     const base::DictionaryValue& params,
    612     scoped_ptr<base::Value>* value) {
    613   std::string key;
    614   if (!params.GetString("key", &key))
    615     return Status(kUnknownError, "'key' must be a string");
    616   base::ListValue args;
    617   args.Append(new base::StringValue(key));
    618   return web_view->CallFunction(
    619       session->GetCurrentFrameId(),
    620       base::StringPrintf("function(key) { %s.removeItem(key) }", storage),
    621       args,
    622       value);
    623 }
    624 
    625 Status ExecuteClearStorage(
    626     const char* storage,
    627     Session* session,
    628     WebView* web_view,
    629     const base::DictionaryValue& params,
    630     scoped_ptr<base::Value>* value) {
    631   return web_view->EvaluateScript(
    632       session->GetCurrentFrameId(),
    633       base::StringPrintf("%s.clear()", storage),
    634       value);
    635 }
    636 
    637 Status ExecuteGetStorageSize(
    638     const char* storage,
    639     Session* session,
    640     WebView* web_view,
    641     const base::DictionaryValue& params,
    642     scoped_ptr<base::Value>* value) {
    643   return web_view->EvaluateScript(
    644       session->GetCurrentFrameId(),
    645       base::StringPrintf("%s.length", storage),
    646       value);
    647 }
    648 
    649 Status ExecuteScreenshot(
    650     Session* session,
    651     WebView* web_view,
    652     const base::DictionaryValue& params,
    653     scoped_ptr<base::Value>* value) {
    654   std::string screenshot;
    655   Status status = web_view->CaptureScreenshot(&screenshot);
    656   if (status.IsError())
    657     return status;
    658   value->reset(new base::StringValue(screenshot));
    659   return Status(kOk);
    660 }
    661 
    662 Status ExecuteGetCookies(
    663     Session* session,
    664     WebView* web_view,
    665     const base::DictionaryValue& params,
    666     scoped_ptr<base::Value>* value) {
    667   std::list<Cookie> cookies;
    668   Status status = GetVisibleCookies(web_view, &cookies);
    669   if (status.IsError())
    670     return status;
    671   scoped_ptr<base::ListValue> cookie_list(new base::ListValue());
    672   for (std::list<Cookie>::const_iterator it = cookies.begin();
    673        it != cookies.end(); ++it) {
    674     cookie_list->Append(CreateDictionaryFrom(*it));
    675   }
    676   value->reset(cookie_list.release());
    677   return Status(kOk);
    678 }
    679 
    680 Status ExecuteAddCookie(
    681     Session* session,
    682     WebView* web_view,
    683     const base::DictionaryValue& params,
    684     scoped_ptr<base::Value>* value) {
    685   const base::DictionaryValue* cookie;
    686   if (!params.GetDictionary("cookie", &cookie))
    687     return Status(kUnknownError, "missing 'cookie'");
    688   base::ListValue args;
    689   args.Append(cookie->DeepCopy());
    690   scoped_ptr<base::Value> result;
    691   return web_view->CallFunction(
    692       session->GetCurrentFrameId(), kAddCookieScript, args, &result);
    693 }
    694 
    695 Status ExecuteDeleteCookie(
    696     Session* session,
    697     WebView* web_view,
    698     const base::DictionaryValue& params,
    699     scoped_ptr<base::Value>* value) {
    700   std::string name;
    701   if (!params.GetString("name", &name))
    702     return Status(kUnknownError, "missing 'name'");
    703   base::DictionaryValue params_url;
    704   scoped_ptr<base::Value> value_url;
    705   std::string url;
    706   Status status = GetUrl(web_view, session->GetCurrentFrameId(), &url);
    707   if (status.IsError())
    708     return status;
    709   return web_view->DeleteCookie(name, url);
    710 }
    711 
    712 Status ExecuteDeleteAllCookies(
    713     Session* session,
    714     WebView* web_view,
    715     const base::DictionaryValue& params,
    716     scoped_ptr<base::Value>* value) {
    717   std::list<Cookie> cookies;
    718   Status status = GetVisibleCookies(web_view, &cookies);
    719   if (status.IsError())
    720     return status;
    721 
    722   if (!cookies.empty()) {
    723     base::DictionaryValue params_url;
    724     scoped_ptr<base::Value> value_url;
    725     std::string url;
    726     status = GetUrl(web_view, session->GetCurrentFrameId(), &url);
    727     if (status.IsError())
    728       return status;
    729     for (std::list<Cookie>::const_iterator it = cookies.begin();
    730          it != cookies.end(); ++it) {
    731       status = web_view->DeleteCookie(it->name, url);
    732       if (status.IsError())
    733         return status;
    734     }
    735   }
    736 
    737   return Status(kOk);
    738 }
    739 
    740 Status ExecuteSetLocation(
    741     Session* session,
    742     WebView* web_view,
    743     const base::DictionaryValue& params,
    744     scoped_ptr<base::Value>* value) {
    745   const base::DictionaryValue* location = NULL;
    746   Geoposition geoposition;
    747   if (!params.GetDictionary("location", &location) ||
    748       !location->GetDouble("latitude", &geoposition.latitude) ||
    749       !location->GetDouble("longitude", &geoposition.longitude))
    750     return Status(kUnknownError, "missing or invalid 'location'");
    751   if (location->HasKey("accuracy") &&
    752       !location->GetDouble("accuracy", &geoposition.accuracy)) {
    753     return Status(kUnknownError, "invalid 'accuracy'");
    754   } else {
    755     // |accuracy| is not part of the WebDriver spec yet, so if it is not given
    756     // default to 100 meters accuracy.
    757     geoposition.accuracy = 100;
    758   }
    759 
    760   Status status = web_view->OverrideGeolocation(geoposition);
    761   if (status.IsOk())
    762     session->overridden_geoposition.reset(new Geoposition(geoposition));
    763   return status;
    764 }
    765