web_view_impl.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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"
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/test/chromedriver/chrome/mobile_emulation_override_manager.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/navigation_tracker.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/ui_events.h"
280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/test/chromedriver/chrome/version.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetContextIdForFrame(FrameTracker* tracker,
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            const std::string& frame,
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            int* context_id) {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (frame.empty()) {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *context_id = 0;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kOk);
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = tracker->GetContextIdForFrame(frame, context_id);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetAsString(MouseEventType type) {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kPressedMouseEventType:
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "mousePressed";
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kReleasedMouseEventType:
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "mouseReleased";
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kMovedMouseEventType:
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "mouseMoved";
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "";
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char* GetAsString(TouchEventType type) {
59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  switch (type) {
60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchStart:
61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchStart";
62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchEnd:
63d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchEnd";
64d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchMove:
65d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchMove";
66d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    default:
67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "";
68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst char* GetPointStateString(TouchEventType type) {
72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  switch (type) {
73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchStart:
74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchPressed";
75d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchEnd:
76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchReleased";
77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    case kTouchMove:
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "touchMoved";
79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    default:
80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return "";
81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetAsString(MouseButton button) {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (button) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kLeftMouseButton:
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "left";
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kMiddleMouseButton:
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "middle";
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kRightMouseButton:
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "right";
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kNoneMouseButton:
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "none";
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "";
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetAsString(KeyEventType type) {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kKeyDownEventType:
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "keyDown";
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kKeyUpEventType:
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "keyUp";
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kRawKeyDownEventType:
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "rawKeyDown";
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kCharEventType:
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "char";
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "";
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebViewImpl::WebViewImpl(const std::string& id,
1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                         const BrowserInfo* browser_info,
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         scoped_ptr<DevToolsClient> client,
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         const DeviceMetrics* device_metrics)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : id_(id),
1210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      browser_info_(browser_info),
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dom_tracker_(new DomTracker(client.get())),
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame_tracker_(new FrameTracker(client.get())),
1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      navigation_tracker_(new NavigationTracker(client.get(), browser_info)),
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dialog_manager_(new JavaScriptDialogManager(client.get())),
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      mobile_emulation_override_manager_(
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          new MobileEmulationOverrideManager(client.get(), device_metrics)),
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      geolocation_override_manager_(
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          new GeolocationOverrideManager(client.get())),
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      heap_snapshot_taker_(new HeapSnapshotTaker(client.get())),
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      debugger_(new DebuggerTracker(client.get())),
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      client_(client.release()) {}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebViewImpl::~WebViewImpl() {}
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string WebViewImpl::GetId() {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id_;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool WebViewImpl::WasCrashed() {
14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return client_->WasCrashed();
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::ConnectIfNecessary() {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->ConnectIfNecessary();
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status WebViewImpl::HandleReceivedEvents() {
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return client_->HandleReceivedEvents();
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::Load(const std::string& url) {
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Javascript URLs will cause a hang while waiting for the page to stop
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // loading, so just disallow.
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (StartsWithASCII(url, "javascript:", false))
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kUnknownError, "unsupported protocol");
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("url", url);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.navigate", params);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::Reload() {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetBoolean("ignoreCache", false);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.reload", params);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::EvaluateScript(const std::string& frame,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& expression,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   scoped_ptr<base::Value>* result) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int context_id;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &context_id);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return internal::EvaluateScriptAndGetValue(
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_.get(), context_id, expression, result);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::CallFunction(const std::string& frame,
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& function,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const base::ListValue& args,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 scoped_ptr<base::Value>* result) {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string json;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::JSONWriter::Write(&args, &json);
186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // TODO(zachconrad): Second null should be array of shadow host ids.
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expression = base::StringPrintf(
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "(%s).apply(null, [null, %s, %s])",
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kCallFunctionScript,
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      function.c_str(),
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json.c_str());
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> temp_result;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(frame, expression, &temp_result);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return internal::ParseCallFunctionResult(*temp_result, result);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallAsyncFunction(const std::string& frame,
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const std::string& function,
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::ListValue& args,
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::TimeDelta& timeout,
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      scoped_ptr<base::Value>* result) {
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return CallAsyncFunctionInternal(
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, function, args, false, timeout, result);
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallUserAsyncFunction(const std::string& frame,
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const std::string& function,
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::ListValue& args,
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::TimeDelta& timeout,
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          scoped_ptr<base::Value>* result) {
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return CallAsyncFunctionInternal(
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, function, args, true, timeout, result);
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::GetFrameByFunction(const std::string& frame,
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& function,
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const base::ListValue& args,
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       std::string* out_frame) {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int context_id;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &context_id);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool found_node;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int node_id;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  status = internal::GetNodeIdFromFunction(
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_.get(), context_id, function, args, &found_node, &node_id);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!found_node)
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kNoSuchFrame);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dom_tracker_->GetFrameIdForNode(node_id, out_frame);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochStatus WebViewImpl::DispatchMouseEvents(const std::list<MouseEvent>& events,
239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                        const std::string& frame) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::list<MouseEvent>::const_iterator it = events.begin();
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != events.end(); ++it) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("type", GetAsString(it->type));
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("x", it->x);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("y", it->y);
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    params.SetInteger("modifiers", it->modifiers);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("button", GetAsString(it->button));
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("clickCount", it->click_count);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = client_->SendCommand("Input.dispatchMouseEvent", params);
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (browser_info_->build_no < 1569 && it->button == kRightMouseButton &&
253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        it->type == kReleasedMouseEventType) {
254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      base::ListValue args;
255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      args.AppendInteger(it->x);
256ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      args.AppendInteger(it->y);
257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      args.AppendInteger(it->modifiers);
258ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      scoped_ptr<base::Value> result;
259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      status = CallFunction(
260ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          frame, kDispatchContextMenuEventScript, args, &result);
261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (status.IsError())
262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        return status;
263ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
266d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
267d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Status WebViewImpl::DispatchTouchEvent(const TouchEvent& event) {
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue params;
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.SetString("type", GetAsString(event.type));
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> point_list(new base::ListValue);
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> point(new base::DictionaryValue);
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  point->SetString("state", GetPointStateString(event.type));
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  point->SetInteger("x", event.x);
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  point->SetInteger("y", event.y);
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  point_list->Set(0, point.release());
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  params.Set("touchPoints", point_list.release());
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return client_->SendCommand("Input.dispatchTouchEvent", params);
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
281d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochStatus WebViewImpl::DispatchTouchEvents(const std::list<TouchEvent>& events) {
282d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  for (std::list<TouchEvent>::const_iterator it = events.begin();
283d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch       it != events.end(); ++it) {
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Status status = DispatchTouchEvent(*it);
285d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (status.IsError())
286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return status;
287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
288d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return Status(kOk);
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::DispatchKeyEvents(const std::list<KeyEvent>& events) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::list<KeyEvent>::const_iterator it = events.begin();
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != events.end(); ++it) {
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("type", GetAsString(it->type));
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it->modifiers & kNumLockKeyModifierMask) {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetBoolean("isKeypad", true);
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetInteger("modifiers",
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        it->modifiers & ~kNumLockKeyModifierMask);
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetInteger("modifiers", it->modifiers);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("text", it->modified_text);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("unmodifiedText", it->unmodified_text);
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("nativeVirtualKeyCode", it->key_code);
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("windowsVirtualKeyCode", it->key_code);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = client_->SendCommand("Input.dispatchKeyEvent", params);
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::GetCookies(scoped_ptr<base::ListValue>* cookies) {
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client_->SendCommandAndGetResult(
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Page.getCookies", params, &result);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* cookies_tmp;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetList("cookies", &cookies_tmp))
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "DevTools didn't return cookies");
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cookies->reset(cookies_tmp->DeepCopy());
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::DeleteCookie(const std::string& name,
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& url) {
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("cookieName", name);
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("url", url);
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.deleteCookie", params);
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status WebViewImpl::WaitForPendingNavigations(const std::string& frame_id,
337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                              const base::TimeDelta& timeout,
338424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                              bool stop_load_on_timeout) {
33958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  VLOG(0) << "Waiting for pending navigations...";
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Status status = client_->HandleEventsUntil(
341424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&WebViewImpl::IsNotPendingNavigation,
342424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 base::Unretained(this),
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 frame_id),
344424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      timeout);
345424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (status.code() == kTimeout && stop_load_on_timeout) {
34658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    VLOG(0) << "Timed out. Stopping navigation...";
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<base::Value> unused_value;
348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EvaluateScript(std::string(), "window.stop();", &unused_value);
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Status new_status = client_->HandleEventsUntil(
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&WebViewImpl::IsNotPendingNavigation, base::Unretained(this),
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   frame_id),
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::TimeDelta::FromSeconds(10));
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (new_status.IsError())
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      status = new_status;
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  VLOG(0) << "Done waiting for pending navigations";
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return status;
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::IsPendingNavigation(const std::string& frame_id,
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        bool* is_pending) {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return navigation_tracker_->IsPendingNavigation(frame_id, is_pending);
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)JavaScriptDialogManager* WebViewImpl::GetJavaScriptDialogManager() {
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dialog_manager_.get();
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::OverrideGeolocation(const Geoposition& geoposition) {
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return geolocation_override_manager_->OverrideGeolocation(geoposition);
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::CaptureScreenshot(std::string* screenshot) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client_->SendCommandAndGetResult(
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Page.captureScreenshot", params, &result);
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetString("data", screenshot))
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "expected string 'data' in response");
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::SetFileInputFiles(
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& frame,
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& element,
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<base::FilePath>& files) {
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue file_list;
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < files.size(); ++i) {
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!files[i].IsAbsolute()) {
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError,
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    "path is not absolute: " + files[i].AsUTF8Unsafe());
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (files[i].ReferencesParent()) {
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError,
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    "path is not canonical: " + files[i].AsUTF8Unsafe());
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    file_list.AppendString(files[i].value());
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int context_id;
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       &context_id);
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue args;
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  args.Append(element.DeepCopy());
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool found_node;
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int node_id;
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  status = internal::GetNodeIdFromFunction(
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_.get(), context_id, "function(element) { return element; }",
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      args, &found_node, &node_id);
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!found_node)
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "no node ID for file input");
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue params;
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.SetInteger("nodeId", node_id);
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.Set("files", file_list.DeepCopy());
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return client_->SendCommand("DOM.setFileInputFiles", params);
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
424d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)Status WebViewImpl::TakeHeapSnapshot(scoped_ptr<base::Value>* snapshot) {
425d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return heap_snapshot_taker_->TakeSnapshot(snapshot);
426d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
427d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Status WebViewImpl::InitProfileInternal() {
429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::DictionaryValue params;
430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO: Remove Debugger.enable after Chrome 36 stable is released.
432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Status status_debug = client_->SendCommand("Debugger.enable", params);
433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status_debug.IsError())
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return status_debug;
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Status status_profiler = client_->SendCommand("Profiler.enable", params);
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status_profiler.IsError()) {
440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Status status_debugger = client_->SendCommand("Debugger.disable", params);
441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (status_debugger.IsError())
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return status_debugger;
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return status_profiler;
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return Status(kOk);
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Status WebViewImpl::StopProfileInternal() {
451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::DictionaryValue params;
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Status status_debug = client_->SendCommand("Debugger.disable", params);
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Status status_profiler = client_->SendCommand("Profiler.disable", params);
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
45546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (status_debug.IsError()) {
456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return status_debug;
45746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (status_profiler.IsError()) {
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return status_profiler;
45946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return Status(kOk);
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
464cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Status WebViewImpl::StartProfile() {
465cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Status status_init = InitProfileInternal();
466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status_init.IsError())
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return status_init;
469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::DictionaryValue params;
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return client_->SendCommand("Profiler.start", params);
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Status WebViewImpl::EndProfile(scoped_ptr<base::Value>* profile_data) {
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::DictionaryValue params;
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> profile_result;
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Status status = client_->SendCommandAndGetResult(
479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "Profiler.stop", params, &profile_result);
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (status.IsError()) {
482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Status disable_profile_status = StopProfileInternal();
48346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (disable_profile_status.IsError()) {
48446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return disable_profile_status;
48546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    } else {
48646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return status;
48746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *profile_data = profile_result.PassAs<base::Value>();
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return status;
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallAsyncFunctionInternal(const std::string& frame,
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const std::string& function,
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const base::ListValue& args,
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              bool is_user_supplied,
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const base::TimeDelta& timeout,
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              scoped_ptr<base::Value>* result) {
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue async_args;
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendString("return (" + function + ").apply(null, arguments);");
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.Append(args.DeepCopy());
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendBoolean(is_user_supplied);
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendInteger(timeout.InMilliseconds());
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::Value> tmp;
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = CallFunction(
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, kExecuteAsyncScriptScript, async_args, &tmp);
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char* kDocUnloadError = "document unloaded while waiting for result";
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string kQueryResult = base::StringPrintf(
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "function() {"
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  var info = document.$chrome_asyncScriptInfo;"
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  if (!info)"
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "    return {status: %d, value: '%s'};"
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  var result = info.result;"
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  if (!result)"
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "    return {status: 0};"
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  delete info.result;"
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  return result;"
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "}",
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kJavaScriptError,
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kDocUnloadError);
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (true) {
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::ListValue no_args;
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::Value> query_value;
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Status status = CallFunction(frame, kQueryResult, no_args, &query_value);
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (status.IsError()) {
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (status.code() == kNoSuchFrame)
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return Status(kJavaScriptError, kDocUnloadError);
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return status;
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::DictionaryValue* result_info = NULL;
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!query_value->GetAsDictionary(&result_info))
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError, "async result info is not a dictionary");
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int status_code;
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!result_info->GetInteger("status", &status_code))
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError, "async result info has no int 'status'");
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (status_code != kOk) {
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string message;
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result_info->GetString("value", &message);
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(static_cast<StatusCode>(status_code), message);
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::Value* value = NULL;
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (result_info->Get("value", &value)) {
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result->reset(value->DeepCopy());
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kOk);
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Status WebViewImpl::IsNotPendingNavigation(const std::string& frame_id,
55990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                           bool* is_not_pending) {
56090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool is_pending;
56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Status status =
56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      navigation_tracker_->IsPendingNavigation(frame_id, &is_pending);
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (status.IsError())
56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return status;
56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // An alert may block the pending navigation.
56690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (is_pending && dialog_manager_->IsDialogOpen())
56790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kUnexpectedAlertOpen);
56890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
56990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *is_not_pending = !is_pending;
57090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return Status(kOk);
57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace internal {
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScript(DevToolsClient* client,
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      int context_id,
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      const std::string& expression,
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      EvaluateScriptReturnType return_type,
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      scoped_ptr<base::DictionaryValue>* result) {
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("expression", expression);
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (context_id)
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("contextId", context_id);
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetBoolean("returnByValue", return_type == ReturnByValue);
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> cmd_result;
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client->SendCommandAndGetResult(
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Runtime.evaluate", params, &cmd_result);
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool was_thrown;
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetBoolean("wasThrown", &was_thrown))
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "Runtime.evaluate missing 'wasThrown'");
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (was_thrown) {
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string description = "unknown";
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cmd_result->GetString("result.description", &description);
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "Runtime.evaluate threw exception: " + description);
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* unscoped_result;
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetDictionary("result", &unscoped_result))
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "evaluate missing dictionary 'result'");
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->reset(unscoped_result->DeepCopy());
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScriptAndGetObject(DevToolsClient* client,
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int context_id,
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const std::string& expression,
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  bool* got_object,
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  std::string* object_id) {
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(client, context_id, expression, ReturnByObject,
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &result);
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!result->HasKey("objectId")) {
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *got_object = false;
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kOk);
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetString("objectId", object_id))
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "evaluate has invalid 'objectId'");
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *got_object = true;
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScriptAndGetValue(DevToolsClient* client,
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 int context_id,
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& expression,
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 scoped_ptr<base::Value>* result) {
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> temp_result;
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(client, context_id, expression, ReturnByValue,
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &temp_result);
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string type;
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!temp_result->GetString("type", &type))
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "Runtime.evaluate missing string 'type'");
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (type == "undefined") {
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->reset(base::Value::CreateNullValue());
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Value* value;
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!temp_result->Get("value", &value))
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return Status(kUnknownError, "Runtime.evaluate missing 'value'");
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->reset(value->DeepCopy());
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ParseCallFunctionResult(const base::Value& temp_result,
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               scoped_ptr<base::Value>* result) {
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* dict;
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!temp_result.GetAsDictionary(&dict))
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "call function result must be a dictionary");
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int status_code;
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->GetInteger("status", &status_code)) {
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "call function result missing int 'status'");
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status_code != kOk) {
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string message;
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->GetString("value", &message);
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(static_cast<StatusCode>(status_code), message);
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Value* unscoped_value;
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->Get("value", &unscoped_value)) {
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "call function result missing 'value'");
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->reset(unscoped_value->DeepCopy());
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetNodeIdFromFunction(DevToolsClient* client,
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int context_id,
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const std::string& function,
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const base::ListValue& args,
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             bool* found_node,
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int* node_id) {
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string json;
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::JSONWriter::Write(&args, &json);
685ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // TODO(zachconrad): Second null should be array of shadow host ids.
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expression = base::StringPrintf(
687ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      "(%s).apply(null, [null, %s, %s, true])",
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kCallFunctionScript,
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      function.c_str(),
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json.c_str());
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool got_object;
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string element_id;
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = internal::EvaluateScriptAndGetObject(
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client, context_id, expression, &got_object, &element_id);
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!got_object) {
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *found_node = false;
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kOk);
701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> cmd_result;
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("objectId", element_id);
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = client->SendCommandAndGetResult(
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "DOM.requestNode", params, &cmd_result);
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Release the remote object before doing anything else.
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("objectId", element_id);
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status release_status =
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        client->SendCommand("Runtime.releaseObject", params);
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (release_status.IsError()) {
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Failed to release remote object: "
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << release_status.message();
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetInteger("nodeId", node_id))
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "DOM.requestNode missing int 'nodeId'");
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *found_node = true;
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace internal
731