web_view_impl.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/devtools_client_impl.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/dom_tracker.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/frame_tracker.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/geolocation_override_manager.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/javascript_dialog_manager.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/js.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/log.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/navigation_tracker.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/ui_events.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetContextIdForFrame(FrameTracker* tracker,
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            const std::string& frame,
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            int* context_id) {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (frame.empty()) {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *context_id = 0;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kOk);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = tracker->GetContextIdForFrame(frame, context_id);
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetAsString(MouseEventType type) {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kPressedMouseEventType:
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "mousePressed";
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kReleasedMouseEventType:
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "mouseReleased";
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kMovedMouseEventType:
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "mouseMoved";
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "";
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetAsString(MouseButton button) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (button) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kLeftMouseButton:
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "left";
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kMiddleMouseButton:
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "middle";
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kRightMouseButton:
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "right";
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kNoneMouseButton:
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "none";
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "";
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* GetAsString(KeyEventType type) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (type) {
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kKeyDownEventType:
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "keyDown";
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kKeyUpEventType:
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "keyUp";
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kRawKeyDownEventType:
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "rawKeyDown";
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case kCharEventType:
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "char";
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "";
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebViewImpl::WebViewImpl(const std::string& id,
88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                         int build_no,
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         scoped_ptr<DevToolsClient> client,
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         Log* log)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : id_(id),
92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      build_no_(build_no),
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dom_tracker_(new DomTracker(client.get())),
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame_tracker_(new FrameTracker(client.get())),
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      navigation_tracker_(new NavigationTracker(client.get())),
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dialog_manager_(new JavaScriptDialogManager(client.get())),
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      geolocation_override_manager_(
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          new GeolocationOverrideManager(client.get())),
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      client_(client.release()),
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      log_(log) {}
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebViewImpl::~WebViewImpl() {}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string WebViewImpl::GetId() {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id_;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::ConnectIfNecessary() {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->ConnectIfNecessary();
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status WebViewImpl::HandleReceivedEvents() {
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return client_->HandleReceivedEvents();
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::Load(const std::string& url) {
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Javascript URLs will cause a hang while waiting for the page to stop
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // loading, so just disallow.
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (StartsWithASCII(url, "javascript:", false))
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kUnknownError, "unsupported protocol");
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("url", url);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.navigate", params);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::Reload() {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetBoolean("ignoreCache", false);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.reload", params);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::EvaluateScript(const std::string& frame,
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& expression,
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   scoped_ptr<base::Value>* result) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int context_id;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &context_id);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return internal::EvaluateScriptAndGetValue(
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_.get(), context_id, expression, result);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::CallFunction(const std::string& frame,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& function,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const base::ListValue& args,
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 scoped_ptr<base::Value>* result) {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string json;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::JSONWriter::Write(&args, &json);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expression = base::StringPrintf(
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "(%s).apply(null, [%s, %s])",
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kCallFunctionScript,
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      function.c_str(),
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json.c_str());
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> temp_result;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(frame, expression, &temp_result);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return internal::ParseCallFunctionResult(*temp_result, result);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallAsyncFunction(const std::string& frame,
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const std::string& function,
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::ListValue& args,
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::TimeDelta& timeout,
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      scoped_ptr<base::Value>* result) {
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return CallAsyncFunctionInternal(
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, function, args, false, timeout, result);
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallUserAsyncFunction(const std::string& frame,
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const std::string& function,
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::ListValue& args,
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::TimeDelta& timeout,
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          scoped_ptr<base::Value>* result) {
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return CallAsyncFunctionInternal(
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, function, args, true, timeout, result);
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::GetFrameByFunction(const std::string& frame,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& function,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const base::ListValue& args,
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       std::string* out_frame) {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int context_id;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &context_id);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool found_node;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int node_id;
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  status = internal::GetNodeIdFromFunction(
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_.get(), context_id, function, args, &found_node, &node_id);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!found_node)
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kNoSuchFrame);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dom_tracker_->GetFrameIdForNode(node_id, out_frame);
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochStatus WebViewImpl::DispatchMouseEvents(const std::list<MouseEvent>& events,
202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                        const std::string& frame) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::list<MouseEvent>::const_iterator it = events.begin();
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != events.end(); ++it) {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("type", GetAsString(it->type));
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("x", it->x);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("y", it->y);
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    params.SetInteger("modifiers", it->modifiers);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("button", GetAsString(it->button));
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("clickCount", it->click_count);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = client_->SendCommand("Input.dispatchMouseEvent", params);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (build_no_ < 1569 && it->button == kRightMouseButton &&
216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        it->type == kReleasedMouseEventType) {
217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      base::ListValue args;
218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      args.AppendInteger(it->x);
219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      args.AppendInteger(it->y);
220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      args.AppendInteger(it->modifiers);
221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      scoped_ptr<base::Value> result;
222ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      status = CallFunction(
223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          frame, kDispatchContextMenuEventScript, args, &result);
224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      if (status.IsError())
225ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        return status;
226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::DispatchKeyEvents(const std::list<KeyEvent>& events) {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::list<KeyEvent>::const_iterator it = events.begin();
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != events.end(); ++it) {
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("type", GetAsString(it->type));
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it->modifiers & kNumLockKeyModifierMask) {
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetBoolean("isKeypad", true);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetInteger("modifiers",
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        it->modifiers & ~kNumLockKeyModifierMask);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetInteger("modifiers", it->modifiers);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("text", it->modified_text);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("unmodifiedText", it->unmodified_text);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("nativeVirtualKeyCode", it->key_code);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("windowsVirtualKeyCode", it->key_code);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = client_->SendCommand("Input.dispatchKeyEvent", params);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::GetCookies(scoped_ptr<base::ListValue>* cookies) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client_->SendCommandAndGetResult(
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Page.getCookies", params, &result);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* cookies_tmp;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetList("cookies", &cookies_tmp))
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "DevTools didn't return cookies");
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cookies->reset(cookies_tmp->DeepCopy());
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::DeleteCookie(const std::string& name,
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& url) {
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("cookieName", name);
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("url", url);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.deleteCookie", params);
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status WebViewImpl::WaitForPendingNavigations(const std::string& frame_id,
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                              int timeout) {
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  log_->AddEntry(Log::kLog, "waiting for pending navigations...");
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Status status = client_->HandleEventsUntil(
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&WebViewImpl::IsNotPendingNavigation, base::Unretained(this),
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 frame_id),
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(timeout));
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (status.code() == kTimeout) {
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    log_->AddEntry(Log::kLog, "timed out. stopping navigations...");
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<base::Value> unused_value;
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EvaluateScript(std::string(), "window.stop();", &unused_value);
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Status new_status = client_->HandleEventsUntil(
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::Bind(&WebViewImpl::IsNotPendingNavigation, base::Unretained(this),
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   frame_id),
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        base::TimeDelta::FromSeconds(10));
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (new_status.IsError())
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      status = new_status;
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  log_->AddEntry(Log::kLog, "done waiting for pending navigations");
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return status;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::IsPendingNavigation(const std::string& frame_id,
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        bool* is_pending) {
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return navigation_tracker_->IsPendingNavigation(frame_id, is_pending);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)JavaScriptDialogManager* WebViewImpl::GetJavaScriptDialogManager() {
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dialog_manager_.get();
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::OverrideGeolocation(const Geoposition& geoposition) {
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return geolocation_override_manager_->OverrideGeolocation(geoposition);
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::CaptureScreenshot(std::string* screenshot) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client_->SendCommandAndGetResult(
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Page.captureScreenshot", params, &result);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetString("data", screenshot))
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "expected string 'data' in response");
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::SetFileInputFiles(
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& frame,
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& element,
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<base::FilePath>& files) {
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue file_list;
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < files.size(); ++i) {
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!files[i].IsAbsolute()) {
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError,
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    "path is not absolute: " + files[i].AsUTF8Unsafe());
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (files[i].ReferencesParent()) {
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError,
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    "path is not canonical: " + files[i].AsUTF8Unsafe());
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    file_list.AppendString(files[i].value());
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int context_id;
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       &context_id);
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue args;
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  args.Append(element.DeepCopy());
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool found_node;
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int node_id;
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  status = internal::GetNodeIdFromFunction(
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_.get(), context_id, "function(element) { return element; }",
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      args, &found_node, &node_id);
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!found_node)
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "no node ID for file input");
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue params;
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.SetInteger("nodeId", node_id);
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.Set("files", file_list.DeepCopy());
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return client_->SendCommand("DOM.setFileInputFiles", params);
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallAsyncFunctionInternal(const std::string& frame,
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const std::string& function,
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const base::ListValue& args,
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              bool is_user_supplied,
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const base::TimeDelta& timeout,
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              scoped_ptr<base::Value>* result) {
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue async_args;
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendString("return (" + function + ").apply(null, arguments);");
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.Append(args.DeepCopy());
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendBoolean(is_user_supplied);
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendInteger(timeout.InMilliseconds());
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::Value> tmp;
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = CallFunction(
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, kExecuteAsyncScriptScript, async_args, &tmp);
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char* kDocUnloadError = "document unloaded while waiting for result";
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string kQueryResult = base::StringPrintf(
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "function() {"
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  var info = document.$chrome_asyncScriptInfo;"
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  if (!info)"
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "    return {status: %d, value: '%s'};"
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  var result = info.result;"
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  if (!result)"
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "    return {status: 0};"
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  delete info.result;"
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  return result;"
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "}",
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kJavaScriptError,
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kDocUnloadError);
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (true) {
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::ListValue no_args;
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::Value> query_value;
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Status status = CallFunction(frame, kQueryResult, no_args, &query_value);
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (status.IsError()) {
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (status.code() == kNoSuchFrame)
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return Status(kJavaScriptError, kDocUnloadError);
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return status;
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::DictionaryValue* result_info = NULL;
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!query_value->GetAsDictionary(&result_info))
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError, "async result info is not a dictionary");
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int status_code;
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!result_info->GetInteger("status", &status_code))
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError, "async result info has no int 'status'");
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (status_code != kOk) {
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string message;
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result_info->GetString("value", &message);
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(static_cast<StatusCode>(status_code), message);
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::Value* value = NULL;
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (result_info->Get("value", &value)) {
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result->reset(value->DeepCopy());
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kOk);
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Status WebViewImpl::IsNotPendingNavigation(const std::string& frame_id,
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                           bool* is_not_pending) {
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool is_pending;
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Status status =
43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      navigation_tracker_->IsPendingNavigation(frame_id, &is_pending);
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (status.IsError())
43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return status;
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // An alert may block the pending navigation.
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (is_pending && dialog_manager_->IsDialogOpen())
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kUnexpectedAlertOpen);
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *is_not_pending = !is_pending;
43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return Status(kOk);
43990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
44090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace internal {
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScript(DevToolsClient* client,
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      int context_id,
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      const std::string& expression,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      EvaluateScriptReturnType return_type,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      scoped_ptr<base::DictionaryValue>* result) {
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("expression", expression);
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (context_id)
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("contextId", context_id);
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetBoolean("returnByValue", return_type == ReturnByValue);
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> cmd_result;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client->SendCommandAndGetResult(
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Runtime.evaluate", params, &cmd_result);
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool was_thrown;
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetBoolean("wasThrown", &was_thrown))
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "Runtime.evaluate missing 'wasThrown'");
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (was_thrown) {
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string description = "unknown";
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cmd_result->GetString("result.description", &description);
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "Runtime.evaluate threw exception: " + description);
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* unscoped_result;
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetDictionary("result", &unscoped_result))
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "evaluate missing dictionary 'result'");
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->reset(unscoped_result->DeepCopy());
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScriptAndGetObject(DevToolsClient* client,
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int context_id,
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const std::string& expression,
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  bool* got_object,
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  std::string* object_id) {
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(client, context_id, expression, ReturnByObject,
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &result);
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!result->HasKey("objectId")) {
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *got_object = false;
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kOk);
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetString("objectId", object_id))
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "evaluate has invalid 'objectId'");
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *got_object = true;
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScriptAndGetValue(DevToolsClient* client,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 int context_id,
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& expression,
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 scoped_ptr<base::Value>* result) {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> temp_result;
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(client, context_id, expression, ReturnByValue,
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &temp_result);
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string type;
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!temp_result->GetString("type", &type))
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "Runtime.evaluate missing string 'type'");
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (type == "undefined") {
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->reset(base::Value::CreateNullValue());
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Value* value;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!temp_result->Get("value", &value))
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return Status(kUnknownError, "Runtime.evaluate missing 'value'");
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->reset(value->DeepCopy());
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ParseCallFunctionResult(const base::Value& temp_result,
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               scoped_ptr<base::Value>* result) {
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* dict;
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!temp_result.GetAsDictionary(&dict))
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "call function result must be a dictionary");
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int status_code;
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->GetInteger("status", &status_code)) {
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "call function result missing int 'status'");
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status_code != kOk) {
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string message;
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->GetString("value", &message);
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(static_cast<StatusCode>(status_code), message);
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Value* unscoped_value;
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->Get("value", &unscoped_value)) {
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "call function result missing 'value'");
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->reset(unscoped_value->DeepCopy());
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetNodeIdFromFunction(DevToolsClient* client,
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int context_id,
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const std::string& function,
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const base::ListValue& args,
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             bool* found_node,
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int* node_id) {
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string json;
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::JSONWriter::Write(&args, &json);
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expression = base::StringPrintf(
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "(%s).apply(null, [%s, %s, true])",
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kCallFunctionScript,
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      function.c_str(),
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json.c_str());
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool got_object;
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string element_id;
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = internal::EvaluateScriptAndGetObject(
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client, context_id, expression, &got_object, &element_id);
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!got_object) {
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *found_node = false;
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kOk);
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> cmd_result;
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("objectId", element_id);
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = client->SendCommandAndGetResult(
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "DOM.requestNode", params, &cmd_result);
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Release the remote object before doing anything else.
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("objectId", element_id);
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status release_status =
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        client->SendCommand("Runtime.releaseObject", params);
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (release_status.IsError()) {
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Failed to release remote object: "
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << release_status.message();
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetInteger("nodeId", node_id))
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "DOM.requestNode missing int 'nodeId'");
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *found_node = true;
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace internal
598