web_view_impl.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/string_util.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stringprintf.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/platform_thread.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/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,
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         scoped_ptr<DevToolsClient> client,
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         Log* log)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : id_(id),
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dom_tracker_(new DomTracker(client.get())),
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame_tracker_(new FrameTracker(client.get())),
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      navigation_tracker_(new NavigationTracker(client.get())),
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dialog_manager_(new JavaScriptDialogManager(client.get())),
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      geolocation_override_manager_(
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          new GeolocationOverrideManager(client.get())),
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      client_(client.release()),
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      log_(log) {}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebViewImpl::~WebViewImpl() {}
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string WebViewImpl::GetId() {
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id_;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::ConnectIfNecessary() {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->ConnectIfNecessary();
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)DevToolsClient* WebViewImpl::GetDevToolsClient() {
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return client_.get();
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::Load(const std::string& url) {
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Javascript URLs will cause a hang while waiting for the page to stop
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // loading, so just disallow.
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (StartsWithASCII(url, "javascript:", false))
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kUnknownError, "unsupported protocol");
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("url", url);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.navigate", params);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::Reload() {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetBoolean("ignoreCache", false);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.reload", params);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::EvaluateScript(const std::string& frame,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   const std::string& expression,
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   scoped_ptr<base::Value>* result) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int context_id;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &context_id);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return internal::EvaluateScriptAndGetValue(
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      client_.get(), context_id, expression, result);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::CallFunction(const std::string& frame,
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& function,
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const base::ListValue& args,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 scoped_ptr<base::Value>* result) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string json;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::JSONWriter::Write(&args, &json);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expression = base::StringPrintf(
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "(%s).apply(null, [%s, %s])",
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kCallFunctionScript,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      function.c_str(),
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json.c_str());
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::Value> temp_result;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(frame, expression, &temp_result);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return internal::ParseCallFunctionResult(*temp_result, result);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallAsyncFunction(const std::string& frame,
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const std::string& function,
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::ListValue& args,
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      const base::TimeDelta& timeout,
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      scoped_ptr<base::Value>* result) {
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return CallAsyncFunctionInternal(
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, function, args, false, timeout, result);
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallUserAsyncFunction(const std::string& frame,
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const std::string& function,
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::ListValue& args,
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::TimeDelta& timeout,
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          scoped_ptr<base::Value>* result) {
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return CallAsyncFunctionInternal(
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, function, args, true, timeout, result);
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::GetFrameByFunction(const std::string& frame,
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& function,
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const base::ListValue& args,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       std::string* out_frame) {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int context_id;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       &context_id);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool found_node;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int node_id;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  status = internal::GetNodeIdFromFunction(
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_.get(), context_id, function, args, &found_node, &node_id);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!found_node)
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kNoSuchFrame);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dom_tracker_->GetFrameIdForNode(node_id, out_frame);
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::DispatchMouseEvents(const std::list<MouseEvent>& events) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::list<MouseEvent>::const_iterator it = events.begin();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != events.end(); ++it) {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("type", GetAsString(it->type));
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("x", it->x);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("y", it->y);
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    params.SetInteger("modifiers", it->modifiers);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("button", GetAsString(it->button));
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("clickCount", it->click_count);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = client_->SendCommand("Input.dispatchMouseEvent", params);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::DispatchKeyEvents(const std::list<KeyEvent>& events) {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (std::list<KeyEvent>::const_iterator it = events.begin();
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != events.end(); ++it) {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("type", GetAsString(it->type));
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it->modifiers & kNumLockKeyModifierMask) {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetBoolean("isKeypad", true);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetInteger("modifiers",
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        it->modifiers & ~kNumLockKeyModifierMask);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      params.SetInteger("modifiers", it->modifiers);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("text", it->modified_text);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("unmodifiedText", it->unmodified_text);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("nativeVirtualKeyCode", it->key_code);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("windowsVirtualKeyCode", it->key_code);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status status = client_->SendCommand("Input.dispatchKeyEvent", params);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (status.IsError())
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return status;
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::GetCookies(scoped_ptr<base::ListValue>* cookies) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client_->SendCommandAndGetResult(
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Page.getCookies", params, &result);
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* cookies_tmp;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetList("cookies", &cookies_tmp))
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "DevTools didn't return cookies");
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cookies->reset(cookies_tmp->DeepCopy());
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::DeleteCookie(const std::string& name,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& url) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("cookieName", name);
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("url", url);
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_->SendCommand("Page.deleteCookie", params);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::WaitForPendingNavigations(const std::string& frame_id) {
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  log_->AddEntry(Log::kLog, "waiting for pending navigations");
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Status status = client_->HandleEventsUntil(
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&WebViewImpl::IsNotPendingNavigation, base::Unretained(this),
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 frame_id));
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  log_->AddEntry(Log::kLog, "done waiting for pending navigations");
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return status;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::IsPendingNavigation(const std::string& frame_id,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        bool* is_pending) {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return navigation_tracker_->IsPendingNavigation(frame_id, is_pending);
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)JavaScriptDialogManager* WebViewImpl::GetJavaScriptDialogManager() {
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dialog_manager_.get();
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::OverrideGeolocation(const Geoposition& geoposition) {
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return geolocation_override_manager_->OverrideGeolocation(geoposition);
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status WebViewImpl::CaptureScreenshot(std::string* screenshot) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client_->SendCommandAndGetResult(
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Page.captureScreenshot", params, &result);
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetString("data", screenshot))
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "expected string 'data' in response");
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::SetFileInputFiles(
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& frame,
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& element,
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<base::FilePath>& files) {
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue file_list;
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < files.size(); ++i) {
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!files[i].IsAbsolute()) {
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError,
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    "path is not absolute: " + files[i].AsUTF8Unsafe());
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (files[i].ReferencesParent()) {
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError,
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    "path is not canonical: " + files[i].AsUTF8Unsafe());
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    file_list.AppendString(files[i].value());
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int context_id;
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = GetContextIdForFrame(frame_tracker_.get(), frame,
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       &context_id);
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue args;
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  args.Append(element.DeepCopy());
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool found_node;
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int node_id;
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  status = internal::GetNodeIdFromFunction(
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_.get(), context_id, "function(element) { return element; }",
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      args, &found_node, &node_id);
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!found_node)
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "no node ID for file input");
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::DictionaryValue params;
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.SetInteger("nodeId", node_id);
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.Set("files", file_list.DeepCopy());
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return client_->SendCommand("DOM.setFileInputFiles", params);
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Status WebViewImpl::CallAsyncFunctionInternal(const std::string& frame,
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const std::string& function,
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const base::ListValue& args,
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              bool is_user_supplied,
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              const base::TimeDelta& timeout,
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              scoped_ptr<base::Value>* result) {
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ListValue async_args;
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendString("return (" + function + ").apply(null, arguments);");
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.Append(args.DeepCopy());
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendBoolean(is_user_supplied);
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  async_args.AppendInteger(timeout.InMilliseconds());
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<base::Value> tmp;
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Status status = CallFunction(
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      frame, kExecuteAsyncScriptScript, async_args, &tmp);
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (status.IsError())
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return status;
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char* kDocUnloadError = "document unloaded while waiting for result";
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string kQueryResult = base::StringPrintf(
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "function() {"
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  var info = document.$chrome_asyncScriptInfo;"
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  if (!info)"
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "    return {status: %d, value: '%s'};"
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  var result = info.result;"
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  if (!result)"
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "    return {status: 0};"
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  delete info.result;"
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "  return result;"
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "}",
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kJavaScriptError,
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kDocUnloadError);
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (true) {
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::ListValue no_args;
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<base::Value> query_value;
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Status status = CallFunction(frame, kQueryResult, no_args, &query_value);
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (status.IsError()) {
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (status.code() == kNoSuchFrame)
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return Status(kJavaScriptError, kDocUnloadError);
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return status;
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::DictionaryValue* result_info = NULL;
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!query_value->GetAsDictionary(&result_info))
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError, "async result info is not a dictionary");
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int status_code;
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!result_info->GetInteger("status", &status_code))
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kUnknownError, "async result info has no int 'status'");
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (status_code != kOk) {
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string message;
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result_info->GetString("value", &message);
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(static_cast<StatusCode>(status_code), message);
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::Value* value = NULL;
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (result_info->Get("value", &value)) {
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result->reset(value->DeepCopy());
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status(kOk);
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Status WebViewImpl::IsNotPendingNavigation(const std::string& frame_id,
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                           bool* is_not_pending) {
40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool is_pending;
40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Status status =
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      navigation_tracker_->IsPendingNavigation(frame_id, &is_pending);
40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (status.IsError())
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return status;
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // An alert may block the pending navigation.
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (is_pending && dialog_manager_->IsDialogOpen())
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return Status(kUnexpectedAlertOpen);
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *is_not_pending = !is_pending;
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return Status(kOk);
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace internal {
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScript(DevToolsClient* client,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      int context_id,
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      const std::string& expression,
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      EvaluateScriptReturnType return_type,
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      scoped_ptr<base::DictionaryValue>* result) {
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue params;
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetString("expression", expression);
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (context_id)
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetInteger("contextId", context_id);
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.SetBoolean("returnByValue", return_type == ReturnByValue);
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> cmd_result;
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = client->SendCommandAndGetResult(
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "Runtime.evaluate", params, &cmd_result);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool was_thrown;
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetBoolean("wasThrown", &was_thrown))
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "Runtime.evaluate missing 'wasThrown'");
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (was_thrown) {
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string description = "unknown";
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cmd_result->GetString("result.description", &description);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "Runtime.evaluate threw exception: " + description);
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* unscoped_result;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetDictionary("result", &unscoped_result))
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "evaluate missing dictionary 'result'");
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->reset(unscoped_result->DeepCopy());
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScriptAndGetObject(DevToolsClient* client,
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  int context_id,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const std::string& expression,
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  bool* got_object,
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  std::string* object_id) {
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> result;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(client, context_id, expression, ReturnByObject,
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &result);
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!result->HasKey("objectId")) {
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *got_object = false;
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kOk);
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result->GetString("objectId", object_id))
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kUnknownError, "evaluate has invalid 'objectId'");
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *got_object = true;
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status EvaluateScriptAndGetValue(DevToolsClient* client,
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 int context_id,
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const std::string& expression,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 scoped_ptr<base::Value>* result) {
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> temp_result;
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = EvaluateScript(client, context_id, expression, ReturnByValue,
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 &temp_result);
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string type;
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!temp_result->GetString("type", &type))
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "Runtime.evaluate missing string 'type'");
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (type == "undefined") {
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->reset(base::Value::CreateNullValue());
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Value* value;
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!temp_result->Get("value", &value))
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return Status(kUnknownError, "Runtime.evaluate missing 'value'");
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    result->reset(value->DeepCopy());
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status ParseCallFunctionResult(const base::Value& temp_result,
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               scoped_ptr<base::Value>* result) {
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::DictionaryValue* dict;
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!temp_result.GetAsDictionary(&dict))
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "call function result must be a dictionary");
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int status_code;
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->GetInteger("status", &status_code)) {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "call function result missing int 'status'");
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status_code != kOk) {
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string message;
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->GetString("value", &message);
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(static_cast<StatusCode>(status_code), message);
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::Value* unscoped_value;
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->Get("value", &unscoped_value)) {
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError,
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  "call function result missing 'value'");
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result->reset(unscoped_value->DeepCopy());
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Status GetNodeIdFromFunction(DevToolsClient* client,
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int context_id,
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const std::string& function,
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             const base::ListValue& args,
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             bool* found_node,
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             int* node_id) {
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string json;
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::JSONWriter::Write(&args, &json);
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string expression = base::StringPrintf(
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "(%s).apply(null, [%s, %s, true])",
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kCallFunctionScript,
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      function.c_str(),
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      json.c_str());
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool got_object;
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string element_id;
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Status status = internal::EvaluateScriptAndGetObject(
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client, context_id, expression, &got_object, &element_id);
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!got_object) {
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *found_node = false;
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status(kOk);
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> cmd_result;
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("objectId", element_id);
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    status = client->SendCommandAndGetResult(
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "DOM.requestNode", params, &cmd_result);
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Release the remote object before doing anything else.
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::DictionaryValue params;
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    params.SetString("objectId", element_id);
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Status release_status =
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        client->SendCommand("Runtime.releaseObject", params);
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (release_status.IsError()) {
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << "Failed to release remote object: "
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 << release_status.message();
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status.IsError())
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return status;
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cmd_result->GetInteger("nodeId", node_id))
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Status(kUnknownError, "DOM.requestNode missing int 'nodeId'");
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *found_node = true;
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Status(kOk);
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace internal
570