web_view_impl.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/web_view_impl.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/json/json_writer.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/platform_thread.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/debugger_tracker.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_client_impl.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/dom_tracker.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/frame_tracker.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/geolocation_override_manager.h"
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/heap_snapshot_taker.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/javascript_dialog_manager.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/js.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/navigation_tracker.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/ui_events.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetContextIdForFrame(FrameTracker* tracker,
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            const std::string& frame,
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            int* context_id) {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (frame.empty()) {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *context_id = 0;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kOk);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = tracker->GetContextIdForFrame(frame, context_id);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetAsString(MouseEventType type) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kPressedMouseEventType:
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "mousePressed";
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kReleasedMouseEventType:
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "mouseReleased";
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kMovedMouseEventType:
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "mouseMoved";
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "";
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char* GetAsString(TouchEventType type) {
57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  switch (type) {
58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchStart:
59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchStart";
60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchEnd:
61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchEnd";
62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchMove:
63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchMove";
64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    default:
65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "";
66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char* GetPointStateString(TouchEventType type) {
70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  switch (type) {
71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchStart:
72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchPressed";
73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchEnd:
74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchReleased";
75d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchMove:
76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchMoved";
77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    default:
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "";
79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetAsString(MouseButton button) {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (button) {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kLeftMouseButton:
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "left";
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kMiddleMouseButton:
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "middle";
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kRightMouseButton:
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "right";
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kNoneMouseButton:
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "none";
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "";
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetAsString(KeyEventType type) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kKeyDownEventType:
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "keyDown";
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kKeyUpEventType:
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "keyUp";
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kRawKeyDownEventType:
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "rawKeyDown";
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kCharEventType:
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "char";
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "";
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebViewImpl::WebViewImpl(const std::string& id,
115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                         int build_no,
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                         scoped_ptr<DevToolsClient> client)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : id_(id),
118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      build_no_(build_no),
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dom_tracker_(new DomTracker(client.get())),
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame_tracker_(new FrameTracker(client.get())),
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      navigation_tracker_(new NavigationTracker(client.get())),
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dialog_manager_(new JavaScriptDialogManager(client.get())),
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      geolocation_override_manager_(
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          new GeolocationOverrideManager(client.get())),
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      heap_snapshot_taker_(new HeapSnapshotTaker(client.get())),
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      debugger_(new DebuggerTracker(client.get())),
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      client_(client.release()) {}
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebViewImpl::~WebViewImpl() {}
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string WebViewImpl::GetId() {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id_;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WebViewImpl::WasCrashed() {
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return client_->WasCrashed();
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::ConnectIfNecessary() {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->ConnectIfNecessary();
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status WebViewImpl::HandleReceivedEvents() {
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return client_->HandleReceivedEvents();
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::Load(const std::string& url) {
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Javascript URLs will cause a hang while waiting for the page to stop
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // loading, so just disallow.
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (StartsWithASCII(url, "javascript:", false))
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kUnknownError, "unsupported protocol");
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("url", url);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.navigate", params);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::Reload() {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetBoolean("ignoreCache", false);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.reload", params);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::EvaluateScript(const std::string& frame,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& expression,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   scoped_ptr<base::Value>* result) {
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int context_id;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &context_id);
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return internal::EvaluateScriptAndGetValue(
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_.get(), context_id, expression, result);
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::CallFunction(const std::string& frame,
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& function,
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const base::ListValue& args,
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 scoped_ptr<base::Value>* result) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string json;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::JSONWriter::Write(&args, &json);
181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // TODO(zachconrad): Second null should be array of shadow host ids.
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expression = base::StringPrintf(
183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "(%s).apply(null, [null, %s, %s])",
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kCallFunctionScript,
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      function.c_str(),
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json.c_str());
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> temp_result;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(frame, expression, &temp_result);
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return internal::ParseCallFunctionResult(*temp_result, result);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallAsyncFunction(const std::string& frame,
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const std::string& function,
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::ListValue& args,
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::TimeDelta& timeout,
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      scoped_ptr<base::Value>* result) {
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return CallAsyncFunctionInternal(
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, function, args, false, timeout, result);
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallUserAsyncFunction(const std::string& frame,
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const std::string& function,
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::ListValue& args,
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::TimeDelta& timeout,
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          scoped_ptr<base::Value>* result) {
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return CallAsyncFunctionInternal(
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, function, args, true, timeout, result);
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::GetFrameByFunction(const std::string& frame,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& function,
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const base::ListValue& args,
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       std::string* out_frame) {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int context_id;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &context_id);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool found_node;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int node_id;
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  status = internal::GetNodeIdFromFunction(
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_.get(), context_id, function, args, &found_node, &node_id);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!found_node)
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kNoSuchFrame);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dom_tracker_->GetFrameIdForNode(node_id, out_frame);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochStatus WebViewImpl::DispatchMouseEvents(const std::list<MouseEvent>& events,
234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                        const std::string& frame) {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::list<MouseEvent>::const_iterator it = events.begin();
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != events.end(); ++it) {
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("type", GetAsString(it->type));
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("x", it->x);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("y", it->y);
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    params.SetInteger("modifiers", it->modifiers);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("button", GetAsString(it->button));
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("clickCount", it->click_count);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = client_->SendCommand("Input.dispatchMouseEvent", params);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (build_no_ < 1569 && it->button == kRightMouseButton &&
248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        it->type == kReleasedMouseEventType) {
249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      base::ListValue args;
250ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      args.AppendInteger(it->x);
251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      args.AppendInteger(it->y);
252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      args.AppendInteger(it->modifiers);
253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      scoped_ptr<base::Value> result;
254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      status = CallFunction(
255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          frame, kDispatchContextMenuEventScript, args, &result);
256ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (status.IsError())
257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        return status;
258ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Status WebViewImpl::DispatchTouchEvent(const TouchEvent& event) {
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue params;
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.SetString("type", GetAsString(event.type));
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> point_list(new base::ListValue);
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> point(new base::DictionaryValue);
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  point->SetString("state", GetPointStateString(event.type));
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  point->SetInteger("x", event.x);
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  point->SetInteger("y", event.y);
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  point_list->Set(0, point.release());
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.Set("touchPoints", point_list.release());
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return client_->SendCommand("Input.dispatchTouchEvent", params);
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
276d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochStatus WebViewImpl::DispatchTouchEvents(const std::list<TouchEvent>& events) {
277d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  for (std::list<TouchEvent>::const_iterator it = events.begin();
278d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch       it != events.end(); ++it) {
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Status status = DispatchTouchEvent(*it);
280d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (status.IsError())
281d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return status;
282d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
283d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Status(kOk);
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::DispatchKeyEvents(const std::list<KeyEvent>& events) {
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::list<KeyEvent>::const_iterator it = events.begin();
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != events.end(); ++it) {
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("type", GetAsString(it->type));
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it->modifiers & kNumLockKeyModifierMask) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetBoolean("isKeypad", true);
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetInteger("modifiers",
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        it->modifiers & ~kNumLockKeyModifierMask);
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetInteger("modifiers", it->modifiers);
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("text", it->modified_text);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("unmodifiedText", it->unmodified_text);
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("nativeVirtualKeyCode", it->key_code);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("windowsVirtualKeyCode", it->key_code);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = client_->SendCommand("Input.dispatchKeyEvent", params);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::GetCookies(scoped_ptr<base::ListValue>* cookies) {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client_->SendCommandAndGetResult(
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Page.getCookies", params, &result);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* cookies_tmp;
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetList("cookies", &cookies_tmp))
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "DevTools didn't return cookies");
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cookies->reset(cookies_tmp->DeepCopy());
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::DeleteCookie(const std::string& name,
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& url) {
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("cookieName", name);
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("url", url);
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.deleteCookie", params);
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status WebViewImpl::WaitForPendingNavigations(const std::string& frame_id,
332424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                              const base::TimeDelta& timeout,
333424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                              bool stop_load_on_timeout) {
33458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  VLOG(0) << "Waiting for pending navigations...";
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Status status = client_->HandleEventsUntil(
336424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&WebViewImpl::IsNotPendingNavigation,
337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 base::Unretained(this),
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 frame_id),
339424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      timeout);
340424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (status.code() == kTimeout && stop_load_on_timeout) {
34158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    VLOG(0) << "Timed out. Stopping navigation...";
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<base::Value> unused_value;
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EvaluateScript(std::string(), "window.stop();", &unused_value);
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Status new_status = client_->HandleEventsUntil(
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&WebViewImpl::IsNotPendingNavigation, base::Unretained(this),
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   frame_id),
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::TimeDelta::FromSeconds(10));
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (new_status.IsError())
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      status = new_status;
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  VLOG(0) << "Done waiting for pending navigations";
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return status;
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::IsPendingNavigation(const std::string& frame_id,
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        bool* is_pending) {
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return navigation_tracker_->IsPendingNavigation(frame_id, is_pending);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)JavaScriptDialogManager* WebViewImpl::GetJavaScriptDialogManager() {
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dialog_manager_.get();
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::OverrideGeolocation(const Geoposition& geoposition) {
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return geolocation_override_manager_->OverrideGeolocation(geoposition);
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::CaptureScreenshot(std::string* screenshot) {
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client_->SendCommandAndGetResult(
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Page.captureScreenshot", params, &result);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetString("data", screenshot))
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "expected string 'data' in response");
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::SetFileInputFiles(
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& frame,
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& element,
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<base::FilePath>& files) {
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue file_list;
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < files.size(); ++i) {
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!files[i].IsAbsolute()) {
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError,
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    "path is not absolute: " + files[i].AsUTF8Unsafe());
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (files[i].ReferencesParent()) {
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError,
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    "path is not canonical: " + files[i].AsUTF8Unsafe());
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    file_list.AppendString(files[i].value());
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int context_id;
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       &context_id);
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue args;
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  args.Append(element.DeepCopy());
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool found_node;
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int node_id;
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  status = internal::GetNodeIdFromFunction(
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_.get(), context_id, "function(element) { return element; }",
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      args, &found_node, &node_id);
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!found_node)
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "no node ID for file input");
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue params;
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.SetInteger("nodeId", node_id);
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.Set("files", file_list.DeepCopy());
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return client_->SendCommand("DOM.setFileInputFiles", params);
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)Status WebViewImpl::TakeHeapSnapshot(scoped_ptr<base::Value>* snapshot) {
420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return heap_snapshot_taker_->TakeSnapshot(snapshot);
421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallAsyncFunctionInternal(const std::string& frame,
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const std::string& function,
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const base::ListValue& args,
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              bool is_user_supplied,
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const base::TimeDelta& timeout,
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              scoped_ptr<base::Value>* result) {
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue async_args;
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendString("return (" + function + ").apply(null, arguments);");
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.Append(args.DeepCopy());
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendBoolean(is_user_supplied);
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendInteger(timeout.InMilliseconds());
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::Value> tmp;
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = CallFunction(
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, kExecuteAsyncScriptScript, async_args, &tmp);
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char* kDocUnloadError = "document unloaded while waiting for result";
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string kQueryResult = base::StringPrintf(
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "function() {"
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  var info = document.$chrome_asyncScriptInfo;"
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  if (!info)"
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "    return {status: %d, value: '%s'};"
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  var result = info.result;"
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  if (!result)"
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "    return {status: 0};"
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  delete info.result;"
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  return result;"
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "}",
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kJavaScriptError,
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kDocUnloadError);
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (true) {
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::ListValue no_args;
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::Value> query_value;
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Status status = CallFunction(frame, kQueryResult, no_args, &query_value);
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (status.IsError()) {
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (status.code() == kNoSuchFrame)
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return Status(kJavaScriptError, kDocUnloadError);
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return status;
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::DictionaryValue* result_info = NULL;
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!query_value->GetAsDictionary(&result_info))
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError, "async result info is not a dictionary");
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int status_code;
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!result_info->GetInteger("status", &status_code))
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError, "async result info has no int 'status'");
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (status_code != kOk) {
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string message;
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result_info->GetString("value", &message);
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(static_cast<StatusCode>(status_code), message);
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::Value* value = NULL;
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (result_info->Get("value", &value)) {
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result->reset(value->DeepCopy());
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kOk);
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Status WebViewImpl::IsNotPendingNavigation(const std::string& frame_id,
48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                           bool* is_not_pending) {
48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool is_pending;
49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Status status =
49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      navigation_tracker_->IsPendingNavigation(frame_id, &is_pending);
49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (status.IsError())
49390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return status;
49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // An alert may block the pending navigation.
49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (is_pending && dialog_manager_->IsDialogOpen())
49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kUnexpectedAlertOpen);
49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *is_not_pending = !is_pending;
49990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return Status(kOk);
50090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace internal {
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScript(DevToolsClient* client,
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      int context_id,
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      const std::string& expression,
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      EvaluateScriptReturnType return_type,
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      scoped_ptr<base::DictionaryValue>* result) {
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("expression", expression);
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (context_id)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("contextId", context_id);
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetBoolean("returnByValue", return_type == ReturnByValue);
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> cmd_result;
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client->SendCommandAndGetResult(
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Runtime.evaluate", params, &cmd_result);
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool was_thrown;
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetBoolean("wasThrown", &was_thrown))
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "Runtime.evaluate missing 'wasThrown'");
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (was_thrown) {
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string description = "unknown";
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cmd_result->GetString("result.description", &description);
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "Runtime.evaluate threw exception: " + description);
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* unscoped_result;
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetDictionary("result", &unscoped_result))
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "evaluate missing dictionary 'result'");
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->reset(unscoped_result->DeepCopy());
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScriptAndGetObject(DevToolsClient* client,
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int context_id,
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const std::string& expression,
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  bool* got_object,
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  std::string* object_id) {
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(client, context_id, expression, ReturnByObject,
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &result);
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!result->HasKey("objectId")) {
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *got_object = false;
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kOk);
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetString("objectId", object_id))
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "evaluate has invalid 'objectId'");
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *got_object = true;
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScriptAndGetValue(DevToolsClient* client,
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 int context_id,
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& expression,
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 scoped_ptr<base::Value>* result) {
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> temp_result;
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(client, context_id, expression, ReturnByValue,
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &temp_result);
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string type;
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!temp_result->GetString("type", &type))
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "Runtime.evaluate missing string 'type'");
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (type == "undefined") {
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->reset(base::Value::CreateNullValue());
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Value* value;
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!temp_result->Get("value", &value))
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return Status(kUnknownError, "Runtime.evaluate missing 'value'");
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->reset(value->DeepCopy());
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ParseCallFunctionResult(const base::Value& temp_result,
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               scoped_ptr<base::Value>* result) {
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* dict;
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!temp_result.GetAsDictionary(&dict))
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "call function result must be a dictionary");
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int status_code;
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->GetInteger("status", &status_code)) {
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "call function result missing int 'status'");
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status_code != kOk) {
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string message;
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->GetString("value", &message);
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(static_cast<StatusCode>(status_code), message);
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Value* unscoped_value;
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->Get("value", &unscoped_value)) {
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "call function result missing 'value'");
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->reset(unscoped_value->DeepCopy());
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetNodeIdFromFunction(DevToolsClient* client,
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int context_id,
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const std::string& function,
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const base::ListValue& args,
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             bool* found_node,
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int* node_id) {
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string json;
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::JSONWriter::Write(&args, &json);
614ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // TODO(zachconrad): Second null should be array of shadow host ids.
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expression = base::StringPrintf(
616ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "(%s).apply(null, [null, %s, %s, true])",
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kCallFunctionScript,
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      function.c_str(),
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json.c_str());
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool got_object;
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string element_id;
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = internal::EvaluateScriptAndGetObject(
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client, context_id, expression, &got_object, &element_id);
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!got_object) {
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *found_node = false;
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kOk);
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> cmd_result;
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("objectId", element_id);
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = client->SendCommandAndGetResult(
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "DOM.requestNode", params, &cmd_result);
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Release the remote object before doing anything else.
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("objectId", element_id);
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status release_status =
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        client->SendCommand("Runtime.releaseObject", params);
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (release_status.IsError()) {
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Failed to release remote object: "
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << release_status.message();
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetInteger("nodeId", node_id))
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "DOM.requestNode missing int 'nodeId'");
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *found_node = true;
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace internal
660