// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/test/chromedriver/chrome/web_view_impl.h"

#include <stddef.h>
#include <utility>

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/test/chromedriver/chrome/browser_info.h"
#include "chrome/test/chromedriver/chrome/debugger_tracker.h"
#include "chrome/test/chromedriver/chrome/devtools_client_impl.h"
#include "chrome/test/chromedriver/chrome/dom_tracker.h"
#include "chrome/test/chromedriver/chrome/frame_tracker.h"
#include "chrome/test/chromedriver/chrome/geolocation_override_manager.h"
#include "chrome/test/chromedriver/chrome/heap_snapshot_taker.h"
#include "chrome/test/chromedriver/chrome/javascript_dialog_manager.h"
#include "chrome/test/chromedriver/chrome/js.h"
#include "chrome/test/chromedriver/chrome/mobile_emulation_override_manager.h"
#include "chrome/test/chromedriver/chrome/navigation_tracker.h"
#include "chrome/test/chromedriver/chrome/network_conditions_override_manager.h"
#include "chrome/test/chromedriver/chrome/non_blocking_navigation_tracker.h"
#include "chrome/test/chromedriver/chrome/page_load_strategy.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome/ui_events.h"
#include "chrome/test/chromedriver/net/timeout.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"

namespace {

const int kWaitForNavigationStopSeconds = 10;

Status GetContextIdForFrame(WebViewImpl* web_view,
                            const std::string& frame,
                            int* context_id) {
  if (frame.empty() || frame == web_view->GetId()) {
    *context_id = 0;
    return Status(kOk);
  }
  Status status =
      web_view->GetFrameTracker()->GetContextIdForFrame(frame, context_id);
  if (status.IsError())
    return status;
  return Status(kOk);
}

WebViewImpl* GetTargetForFrame(WebViewImpl* web_view,
                               const std::string& frame) {
  return frame.empty()
             ? web_view
             : static_cast<WebViewImpl*>(
                   web_view->GetFrameTracker()->GetTargetForFrame(frame));
}

const char* GetAsString(MouseEventType type) {
  switch (type) {
    case kPressedMouseEventType:
      return "mousePressed";
    case kReleasedMouseEventType:
      return "mouseReleased";
    case kMovedMouseEventType:
      return "mouseMoved";
    default:
      return "";
  }
}

const char* GetAsString(TouchEventType type) {
  switch (type) {
    case kTouchStart:
      return "touchstart";
    case kTouchEnd:
      return "touchend";
    case kTouchMove:
      return "touchmove";
    default:
      return "";
  }
}

const char* GetAsString(MouseButton button) {
  switch (button) {
    case kLeftMouseButton:
      return "left";
    case kMiddleMouseButton:
      return "middle";
    case kRightMouseButton:
      return "right";
    case kBackMouseButton:
      return "back";
    case kForwardMouseButton:
      return "forward";
    case kNoneMouseButton:
      return "none";
    default:
      return "";
  }
}

const char* GetAsString(KeyEventType type) {
  switch (type) {
    case kKeyDownEventType:
      return "keyDown";
    case kKeyUpEventType:
      return "keyUp";
    case kRawKeyDownEventType:
      return "rawKeyDown";
    case kCharEventType:
      return "char";
    default:
      return "";
  }
}

const char* GetAsString(PointerType type) {
  switch (type) {
    case kMouse:
      return "mouse";
    case kPen:
      return "pen";
    default:
      NOTREACHED();
      return "";
  }
}

}  // namespace

WebViewImpl::WebViewImpl(const std::string& id,
                         const bool w3c_compliant,
                         const BrowserInfo* browser_info,
                         std::unique_ptr<DevToolsClient> client,
                         const DeviceMetrics* device_metrics,
                         std::string page_load_strategy)
    : id_(id),
      w3c_compliant_(w3c_compliant),
      browser_info_(browser_info),
      is_locked_(false),
      is_detached_(false),
      parent_(nullptr),
      client_(std::move(client)),
      dom_tracker_(new DomTracker(client_.get())),
      frame_tracker_(new FrameTracker(client_.get(), this, browser_info)),
      dialog_manager_(new JavaScriptDialogManager(client_.get(), browser_info)),
      navigation_tracker_(PageLoadStrategy::Create(page_load_strategy,
                                                   client_.get(),
                                                   browser_info,
                                                   dialog_manager_.get())),
      mobile_emulation_override_manager_(
          new MobileEmulationOverrideManager(client_.get(), device_metrics)),
      geolocation_override_manager_(
          new GeolocationOverrideManager(client_.get())),
      network_conditions_override_manager_(
          new NetworkConditionsOverrideManager(client_.get())),
      heap_snapshot_taker_(new HeapSnapshotTaker(client_.get())),
      debugger_(new DebuggerTracker(client_.get())) {
  client_->SetOwner(this);
}

WebViewImpl::~WebViewImpl() {}

WebViewImpl* WebViewImpl::CreateChild(const std::string& session_id,
                                      const std::string& target_id) const {
  DevToolsClientImpl* parent_client =
      static_cast<DevToolsClientImpl*>(client_.get());
  std::unique_ptr<DevToolsClient> child_client(
      std::make_unique<DevToolsClientImpl>(parent_client, session_id));
  WebViewImpl* child = new WebViewImpl(target_id, w3c_compliant_, browser_info_,
                                       std::move(child_client), nullptr,
                                       navigation_tracker_->IsNonBlocking()
                                           ? PageLoadStrategy::kNone
                                           : PageLoadStrategy::kNormal);
  child->parent_ = this;
  return child;
}

std::string WebViewImpl::GetId() {
  return id_;
}

bool WebViewImpl::WasCrashed() {
  return client_->WasCrashed();
}

Status WebViewImpl::ConnectIfNecessary() {
  return client_->ConnectIfNecessary();
}

Status WebViewImpl::HandleReceivedEvents() {
  return client_->HandleReceivedEvents();
}

Status WebViewImpl::GetUrl(std::string* url) {
  base::DictionaryValue params;
  std::unique_ptr<base::DictionaryValue> result;
  Status status = client_->SendCommandAndGetResult(
      "Page.getNavigationHistory", params, &result);
  if (status.IsError())
    return status;
  int current_index = 0;
  if (!result->GetInteger("currentIndex", &current_index))
    return Status(kUnknownError, "navigation history missing currentIndex");
  base::ListValue* entries = nullptr;
  if (!result->GetList("entries", &entries))
    return Status(kUnknownError, "navigation history missing entries");
  base::DictionaryValue* entry = nullptr;
  if (!entries->GetDictionary(current_index, &entry))
    return Status(kUnknownError, "navigation history missing entry");
  if (!entry->GetString("url", url))
    return Status(kUnknownError, "navigation history entry is missing url");
  return Status(kOk);
}

Status WebViewImpl::Load(const std::string& url, const Timeout* timeout) {
  // Javascript URLs will cause a hang while waiting for the page to stop
  // loading, so just disallow.
  if (base::StartsWith(url, "javascript:",
                       base::CompareCase::INSENSITIVE_ASCII))
    return Status(kUnknownError, "unsupported protocol");
  base::DictionaryValue params;
  params.SetString("url", url);
  if (navigation_tracker_->IsNonBlocking()) {
    // With non-bloakcing navigation tracker, the previous navigation might
    // still be in progress, and this can cause the new navigate command to be
    // ignored on Chrome v63 and above. Stop previous navigation first.
    client_->SendCommand("Page.stopLoading", base::DictionaryValue());
    // Use SendCommandAndIgnoreResponse to ensure no blocking occurs.
    return client_->SendCommandAndIgnoreResponse("Page.navigate", params);
  }
  return client_->SendCommandWithTimeout("Page.navigate", params, timeout);
}

Status WebViewImpl::Reload(const Timeout* timeout) {
  base::DictionaryValue params;
  params.SetBoolean("ignoreCache", false);
  return client_->SendCommandWithTimeout("Page.reload", params, timeout);
}

Status WebViewImpl::Freeze(const Timeout* timeout) {
  base::DictionaryValue params;
  params.SetString("state", "frozen");
  return client_->SendCommandWithTimeout("Page.setWebLifecycleState", params,
                                         timeout);
}

Status WebViewImpl::Resume(const Timeout* timeout) {
  base::DictionaryValue params;
  params.SetString("state", "active");
  return client_->SendCommandWithTimeout("Page.setWebLifecycleState", params,
                                         timeout);
}

Status WebViewImpl::SendCommand(const std::string& cmd,
                                const base::DictionaryValue& params) {
  return client_->SendCommand(cmd, params);
}

Status WebViewImpl::SendCommandAndGetResult(
        const std::string& cmd,
        const base::DictionaryValue& params,
        std::unique_ptr<base::Value>* value) {
  std::unique_ptr<base::DictionaryValue> result;
  Status status = client_->SendCommandAndGetResult(cmd, params, &result);
  if (status.IsError())
    return status;
  *value = std::move(result);
  return Status(kOk);
}

Status WebViewImpl::TraverseHistory(int delta, const Timeout* timeout) {
  base::DictionaryValue params;
  std::unique_ptr<base::DictionaryValue> result;
  Status status = client_->SendCommandAndGetResult(
      "Page.getNavigationHistory", params, &result);
  if (status.IsError()) {
    // TODO(samuong): remove this once we stop supporting WebView on KitKat.
    // Older versions of WebView on Android (on KitKat and earlier) do not have
    // the Page.getNavigationHistory DevTools command handler, so fall back to
    // using JavaScript to navigate back and forward. WebView reports its build
    // number as 0, so use the error status to detect if we can't use the
    // DevTools command.
    if (browser_info_->browser_name == "webview")
      return TraverseHistoryWithJavaScript(delta);
    else
      return status;
  }

  int current_index;
  if (!result->GetInteger("currentIndex", &current_index))
    return Status(kUnknownError, "DevTools didn't return currentIndex");

  base::ListValue* entries;
  if (!result->GetList("entries", &entries))
    return Status(kUnknownError, "DevTools didn't return entries");

  base::DictionaryValue* entry;
  if (!entries->GetDictionary(current_index + delta, &entry)) {
    // The WebDriver spec says that if there are no pages left in the browser's
    // history (i.e. |current_index + delta| is out of range), then we must not
    // navigate anywhere.
    return Status(kOk);
  }

  int entry_id;
  if (!entry->GetInteger("id", &entry_id))
    return Status(kUnknownError, "history entry does not have an id");
  params.SetInteger("entryId", entry_id);

  return client_->SendCommandWithTimeout("Page.navigateToHistoryEntry", params,
                                         timeout);
}

Status WebViewImpl::TraverseHistoryWithJavaScript(int delta) {
  std::unique_ptr<base::Value> value;
  if (delta == -1)
    return EvaluateScript(std::string(), "window.history.back();", &value);
  else if (delta == 1)
    return EvaluateScript(std::string(), "window.history.forward();", &value);
  else
    return Status(kUnknownError, "expected delta to be 1 or -1");
}

Status WebViewImpl::EvaluateScript(const std::string& frame,
                                   const std::string& expression,
                                   std::unique_ptr<base::Value>* result) {
  WebViewImpl* target = GetTargetForFrame(this, frame);
  if (target != nullptr && target != this) {
    if (target->IsDetached())
      return Status(kTargetDetached);
    WebViewImplHolder target_holder(target);
    return target->EvaluateScript(frame, expression, result);
  }

  int context_id;
  Status status = GetContextIdForFrame(this, frame, &context_id);
  if (status.IsError())
    return status;
  return internal::EvaluateScriptAndGetValue(
      client_.get(), context_id, expression, result);
}

Status WebViewImpl::CallFunction(const std::string& frame,
                                 const std::string& function,
                                 const base::ListValue& args,
                                 std::unique_ptr<base::Value>* result) {
  std::string json;
  base::JSONWriter::Write(args, &json);
  std::string w3c = w3c_compliant_ ? "true" : "false";
  // TODO(zachconrad): Second null should be array of shadow host ids.
  std::string expression = base::StringPrintf(
      "(%s).apply(null, [null, %s, %s, %s])",
      kCallFunctionScript,
      function.c_str(),
      json.c_str(),
      w3c.c_str());
  std::unique_ptr<base::Value> temp_result;
  Status status = EvaluateScript(frame, expression, &temp_result);
  if (status.IsError())
      return status;
  return internal::ParseCallFunctionResult(*temp_result, result);
}

Status WebViewImpl::CallAsyncFunction(const std::string& frame,
                                      const std::string& function,
                                      const base::ListValue& args,
                                      const base::TimeDelta& timeout,
                                      std::unique_ptr<base::Value>* result) {
  return CallAsyncFunctionInternal(
      frame, function, args, false, timeout, result);
}

Status WebViewImpl::CallUserAsyncFunction(
    const std::string& frame,
    const std::string& function,
    const base::ListValue& args,
    const base::TimeDelta& timeout,
    std::unique_ptr<base::Value>* result) {
  return CallAsyncFunctionInternal(
      frame, function, args, true, timeout, result);
}

Status WebViewImpl::GetFrameByFunction(const std::string& frame,
                                       const std::string& function,
                                       const base::ListValue& args,
                                       std::string* out_frame) {
  WebViewImpl* target = GetTargetForFrame(this, frame);
  if (target != nullptr && target != this) {
    if (target->IsDetached())
      return Status(kTargetDetached);
    WebViewImplHolder target_holder(target);
    return target->GetFrameByFunction(frame, function, args, out_frame);
  }

  int context_id;
  Status status = GetContextIdForFrame(this, frame, &context_id);
  if (status.IsError())
    return status;
  bool found_node;
  int node_id;
  status = internal::GetNodeIdFromFunction(
      client_.get(), context_id, function, args,
      &found_node, &node_id, w3c_compliant_);
  if (status.IsError())
    return status;
  if (!found_node)
    return Status(kNoSuchFrame);
  return dom_tracker_->GetFrameIdForNode(node_id, out_frame);
}

Status WebViewImpl::DispatchTouchEventsForMouseEvents(
    const std::list<MouseEvent>& events,
    const std::string& frame) {
  // Touch events are filtered by the compositor if there are no touch listeners
  // on the page. Wait two frames for the compositor to sync with the main
  // thread to get consistent behavior.
  base::DictionaryValue params;
  params.SetString("expression",
                   "new Promise(x => setTimeout(() => setTimeout(x, 20), 20))");
  params.SetBoolean("awaitPromise", true);
  client_->SendCommand("Runtime.evaluate", params);
  for (auto it = events.begin(); it != events.end(); ++it) {
    base::DictionaryValue params;

    switch (it->type) {
      case kPressedMouseEventType:
        params.SetString("type", "touchStart");
        break;
      case kReleasedMouseEventType:
        params.SetString("type", "touchEnd");
        break;
      case kMovedMouseEventType:
        if (it->button == kNoneMouseButton)
          continue;
        params.SetString("type", "touchMove");
        break;
      default:
        break;
    }

    std::unique_ptr<base::ListValue> touchPoints(new base::ListValue);
    if (it->type != kReleasedMouseEventType) {
      std::unique_ptr<base::DictionaryValue> touchPoint(
          new base::DictionaryValue);
      touchPoint->SetInteger("x", it->x);
      touchPoint->SetInteger("y", it->y);
      touchPoints->Append(std::move(touchPoint));
    }
    params.SetList("touchPoints", std::move(touchPoints));
    params.SetInteger("modifiers", it->modifiers);
    Status status = client_->SendCommand("Input.dispatchTouchEvent", params);
    if (status.IsError())
      return status;
  }
  return Status(kOk);
}

Status WebViewImpl::DispatchMouseEvents(const std::list<MouseEvent>& events,
                                        const std::string& frame) {
  if (mobile_emulation_override_manager_->IsEmulatingTouch())
    return DispatchTouchEventsForMouseEvents(events, frame);

  double page_scale_factor = 1.0;
  for (auto it = events.begin(); it != events.end(); ++it) {
    base::DictionaryValue params;
    params.SetString("type", GetAsString(it->type));
    params.SetInteger("x", it->x * page_scale_factor);
    params.SetInteger("y", it->y * page_scale_factor);
    params.SetInteger("modifiers", it->modifiers);
    params.SetString("button", GetAsString(it->button));
    params.SetInteger("buttons", it->buttons);
    params.SetInteger("clickCount", it->click_count);
    params.SetString("pointerType", GetAsString(it->pointer_type));
    Status status = client_->SendCommand("Input.dispatchMouseEvent", params);
    if (status.IsError())
      return status;
  }
  return Status(kOk);
}

Status WebViewImpl::DispatchTouchEvent(const TouchEvent& event) {
  base::ListValue args;
  args.Append(std::make_unique<base::Value>(event.x));
  args.Append(std::make_unique<base::Value>(event.y));
  args.Append(std::make_unique<base::Value>(GetAsString(event.type)));
  std::unique_ptr<base::Value> unused;
  return CallFunction(std::string(), kDispatchTouchEventScript, args, &unused);
}

Status WebViewImpl::DispatchTouchEvents(const std::list<TouchEvent>& events) {
  for (auto it = events.begin(); it != events.end(); ++it) {
    Status status = DispatchTouchEvent(*it);
    if (status.IsError())
      return status;
  }
  return Status(kOk);
}

Status WebViewImpl::DispatchKeyEvents(const std::list<KeyEvent>& events) {
  for (auto it = events.begin(); it != events.end(); ++it) {
    base::DictionaryValue params;
    params.SetString("type", GetAsString(it->type));
    if (it->modifiers & kNumLockKeyModifierMask) {
      params.SetBoolean("isKeypad", true);
      params.SetInteger("modifiers",
                        it->modifiers & ~kNumLockKeyModifierMask);
    } else {
      params.SetInteger("modifiers", it->modifiers);
    }
    params.SetString("text", it->modified_text);
    params.SetString("unmodifiedText", it->unmodified_text);
    params.SetInteger("windowsVirtualKeyCode", it->key_code);
    ui::DomCode dom_code = ui::UsLayoutKeyboardCodeToDomCode(it->key_code);
    std::string code = ui::KeycodeConverter::DomCodeToCodeString(dom_code);
    if (!code.empty())
      params.SetString("code", code);
    if (!it->key.empty())
      params.SetString("key", it->key);
    Status status = client_->SendCommand("Input.dispatchKeyEvent", params);
    if (status.IsError())
      return status;
  }
  return Status(kOk);
}

Status WebViewImpl::GetCookies(std::unique_ptr<base::ListValue>* cookies,
                               const std::string& current_page_url) {
  base::DictionaryValue params;
  std::unique_ptr<base::DictionaryValue> result;

  if (browser_info_->browser_name != "webview") {
    base::ListValue url_list;
    url_list.AppendString(current_page_url);
    params.SetKey("urls", url_list.Clone());
    Status status =
        client_->SendCommandAndGetResult("Network.getCookies", params, &result);
    if (status.IsError())
      return status;
  } else {
    Status status =
        client_->SendCommandAndGetResult("Page.getCookies", params, &result);
    if (status.IsError())
      return status;
  }

  base::ListValue* cookies_tmp;
  if (!result->GetList("cookies", &cookies_tmp))
    return Status(kUnknownError, "DevTools didn't return cookies");
  cookies->reset(cookies_tmp->DeepCopy());
  return Status(kOk);
}

Status WebViewImpl::DeleteCookie(const std::string& name,
                                 const std::string& url,
                                 const std::string& domain,
                                 const std::string& path) {
  base::DictionaryValue params;
  params.SetString("url", url);
  std::string command;
  params.SetString("name", name);
  params.SetString("domain", domain);
  params.SetString("path", path);
  command = "Network.deleteCookies";
  return client_->SendCommand(command, params);
}

Status WebViewImpl::AddCookie(const std::string& name,
                              const std::string& url,
                              const std::string& value,
                              const std::string& domain,
                              const std::string& path,
                              bool secure,
                              bool httpOnly,
                              double expiry) {
  base::DictionaryValue params;
  params.SetString("name", name);
  params.SetString("url", url);
  params.SetString("value", value);
  params.SetString("domain", domain);
  params.SetString("path", path);
  params.SetBoolean("secure", secure);
  params.SetBoolean("httpOnly", httpOnly);
  if (expiry >= 0)
    params.SetDouble("expires", expiry);

  std::unique_ptr<base::DictionaryValue> result;
  Status status =
      client_->SendCommandAndGetResult("Network.setCookie", params, &result);
  bool success;
  if (!result->GetBoolean("success", &success) || !success)
    return Status(kUnableToSetCookie);
  return Status(kOk);
}

Status WebViewImpl::WaitForPendingNavigations(const std::string& frame_id,
                                              const Timeout& timeout,
                                              bool stop_load_on_timeout) {
  VLOG(0) << "Waiting for pending navigations...";
  const auto not_pending_navigation =
      base::Bind(&WebViewImpl::IsNotPendingNavigation, base::Unretained(this),
                 frame_id, base::Unretained(&timeout));
  Status status = client_->HandleEventsUntil(not_pending_navigation, timeout);
  if (status.code() == kTimeout && stop_load_on_timeout) {
    VLOG(0) << "Timed out. Stopping navigation...";
    navigation_tracker_->set_timed_out(true);
    client_->SendCommand("Page.stopLoading", base::DictionaryValue());
    // We don't consider |timeout| here to make sure the navigation actually
    // stops and we cleanup properly after a command that caused a navigation
    // that timed out.  Otherwise we might have to wait for that before
    // executing the next command, and it will be counted towards its timeout.
    Status new_status = client_->HandleEventsUntil(
        not_pending_navigation,
        Timeout(base::TimeDelta::FromSeconds(kWaitForNavigationStopSeconds)));
    navigation_tracker_->set_timed_out(false);
    if (new_status.IsError())
      status = new_status;
  }
  VLOG(0) << "Done waiting for pending navigations. Status: "
          << status.message();
  return status;
}

Status WebViewImpl::IsPendingNavigation(const std::string& frame_id,
                                        const Timeout* timeout,
                                        bool* is_pending) {
  return
      navigation_tracker_->IsPendingNavigation(frame_id, timeout, is_pending);
}

JavaScriptDialogManager* WebViewImpl::GetJavaScriptDialogManager() {
  return dialog_manager_.get();
}

Status WebViewImpl::OverrideGeolocation(const Geoposition& geoposition) {
  return geolocation_override_manager_->OverrideGeolocation(geoposition);
}

Status WebViewImpl::OverrideNetworkConditions(
    const NetworkConditions& network_conditions) {
  return network_conditions_override_manager_->OverrideNetworkConditions(
      network_conditions);
}

Status WebViewImpl::CaptureScreenshot(
    std::string* screenshot,
    const base::DictionaryValue& params) {
  std::unique_ptr<base::DictionaryValue> result;
  Timeout timeout(base::TimeDelta::FromSeconds(10));
  Status status = client_->SendCommandAndGetResultWithTimeout(
      "Page.captureScreenshot", params, &timeout, &result);
  if (status.IsError())
    return status;
  if (!result->GetString("data", screenshot))
    return Status(kUnknownError, "expected string 'data' in response");
  return Status(kOk);
}

Status WebViewImpl::SetFileInputFiles(
    const std::string& frame,
    const base::DictionaryValue& element,
    const std::vector<base::FilePath>& files) {
  WebViewImpl* target = GetTargetForFrame(this, frame);
  if (target != nullptr && target != this) {
    if (target->IsDetached())
      return Status(kTargetDetached);
    WebViewImplHolder target_holder(target);
    return target->SetFileInputFiles(frame, element, files);
  }

  base::ListValue file_list;
  for (size_t i = 0; i < files.size(); ++i) {
    if (!files[i].IsAbsolute()) {
      return Status(kUnknownError,
                    "path is not absolute: " + files[i].AsUTF8Unsafe());
    }
    if (files[i].ReferencesParent()) {
      return Status(kUnknownError,
                    "path is not canonical: " + files[i].AsUTF8Unsafe());
    }
    file_list.AppendString(files[i].value());
  }

  int context_id;
  Status status = GetContextIdForFrame(this, frame, &context_id);
  if (status.IsError())
    return status;
  base::ListValue args;
  args.Append(element.CreateDeepCopy());
  bool found_node;
  int node_id;
  status = internal::GetNodeIdFromFunction(
      client_.get(), context_id, "function(element) { return element; }",
      args, &found_node, &node_id, w3c_compliant_);
  if (status.IsError())
    return status;
  if (!found_node)
    return Status(kUnknownError, "no node ID for file input");
  base::DictionaryValue params;
  params.SetInteger("nodeId", node_id);
  params.SetKey("files", file_list.Clone());
  return client_->SendCommand("DOM.setFileInputFiles", params);
}

Status WebViewImpl::TakeHeapSnapshot(std::unique_ptr<base::Value>* snapshot) {
  return heap_snapshot_taker_->TakeSnapshot(snapshot);
}

Status WebViewImpl::InitProfileInternal() {
  base::DictionaryValue params;

  // TODO: Remove Debugger.enable after Chrome 36 stable is released.
  Status status_debug = client_->SendCommand("Debugger.enable", params);

  if (status_debug.IsError())
    return status_debug;

  Status status_profiler = client_->SendCommand("Profiler.enable", params);

  if (status_profiler.IsError()) {
    Status status_debugger = client_->SendCommand("Debugger.disable", params);
    if (status_debugger.IsError())
      return status_debugger;

    return status_profiler;
  }

  return Status(kOk);
}

Status WebViewImpl::StopProfileInternal() {
  base::DictionaryValue params;
  Status status_debug = client_->SendCommand("Debugger.disable", params);
  Status status_profiler = client_->SendCommand("Profiler.disable", params);

  if (status_debug.IsError()) {
    return status_debug;
  } else if (status_profiler.IsError()) {
    return status_profiler;
  }

  return Status(kOk);
}

Status WebViewImpl::StartProfile() {
  Status status_init = InitProfileInternal();

  if (status_init.IsError())
    return status_init;

  base::DictionaryValue params;
  return client_->SendCommand("Profiler.start", params);
}

Status WebViewImpl::EndProfile(std::unique_ptr<base::Value>* profile_data) {
  base::DictionaryValue params;
  std::unique_ptr<base::DictionaryValue> profile_result;

  Status status = client_->SendCommandAndGetResult(
      "Profiler.stop", params, &profile_result);

  if (status.IsError()) {
    Status disable_profile_status = StopProfileInternal();
    if (disable_profile_status.IsError()) {
      return disable_profile_status;
    } else {
      return status;
    }
  }

  *profile_data = std::move(profile_result);
  return status;
}

Status WebViewImpl::SynthesizeTapGesture(int x,
                                         int y,
                                         int tap_count,
                                         bool is_long_press) {
  base::DictionaryValue params;
  params.SetInteger("x", x);
  params.SetInteger("y", y);
  params.SetInteger("tapCount", tap_count);
  if (is_long_press)
    params.SetInteger("duration", 1500);
  return client_->SendCommand("Input.synthesizeTapGesture", params);
}

Status WebViewImpl::SynthesizeScrollGesture(int x,
                                            int y,
                                            int xoffset,
                                            int yoffset) {
  base::DictionaryValue params;
  params.SetInteger("x", x);
  params.SetInteger("y", y);
  // Chrome's synthetic scroll gesture is actually a "swipe" gesture, so the
  // direction of the swipe is opposite to the scroll (i.e. a swipe up scrolls
  // down, and a swipe left scrolls right).
  params.SetInteger("xDistance", -xoffset);
  params.SetInteger("yDistance", -yoffset);
  return client_->SendCommand("Input.synthesizeScrollGesture", params);
}

Status WebViewImpl::SynthesizePinchGesture(int x, int y, double scale_factor) {
  base::DictionaryValue params;
  params.SetInteger("x", x);
  params.SetInteger("y", y);
  params.SetDouble("scaleFactor", scale_factor);
  return client_->SendCommand("Input.synthesizePinchGesture", params);
}

Status WebViewImpl::GetScreenOrientation(std::string* orientation) {
  base::DictionaryValue empty_params;
  std::unique_ptr<base::DictionaryValue> result;
  Status status =
    client_->SendCommandAndGetResult("Emulation.getScreenOrientation",
                                      empty_params,
                                      &result);
  if (status.IsError() || !result->GetString("orientation", orientation))
    return status;
  return Status(kOk);
}

Status WebViewImpl::SetScreenOrientation(std::string orientation) {
  base::DictionaryValue params;
  params.SetString("screenOrientation", orientation);
  Status status =
    client_->SendCommand("Emulation.lockScreenOrientation", params);
  if (status.IsError())
    return status;
  return Status(kOk);
}

Status WebViewImpl::DeleteScreenOrientation() {
  base::DictionaryValue params;
  Status status =
    client_->SendCommand("Emulation.unlockScreenOrientation", params);
  if (status.IsError())
    return status;
  return Status(kOk);
}

Status WebViewImpl::CallAsyncFunctionInternal(
    const std::string& frame,
    const std::string& function,
    const base::ListValue& args,
    bool is_user_supplied,
    const base::TimeDelta& timeout,
    std::unique_ptr<base::Value>* result) {
  base::ListValue async_args;
  async_args.AppendString("return (" + function + ").apply(null, arguments);");
  async_args.Append(args.CreateDeepCopy());
  async_args.AppendBoolean(is_user_supplied);
  async_args.AppendInteger(timeout.InMilliseconds());
  std::unique_ptr<base::Value> tmp;
  Status status = CallFunction(
      frame, kExecuteAsyncScriptScript, async_args, &tmp);
  if (status.IsError())
    return status;

  const char kDocUnloadError[] = "document unloaded while waiting for result";
  std::string kQueryResult = base::StringPrintf(
      "function() {"
      "  var info = document.$chrome_asyncScriptInfo;"
      "  if (!info)"
      "    return {status: %d, value: '%s'};"
      "  var result = info.result;"
      "  if (!result)"
      "    return {status: 0};"
      "  delete info.result;"
      "  return result;"
      "}",
      kJavaScriptError,
      kDocUnloadError);

  while (true) {
    base::ListValue no_args;
    std::unique_ptr<base::Value> query_value;
    Status status = CallFunction(frame, kQueryResult, no_args, &query_value);
    if (status.IsError()) {
      if (status.code() == kNoSuchFrame)
        return Status(kJavaScriptError, kDocUnloadError);
      return status;
    }

    base::DictionaryValue* result_info = NULL;
    if (!query_value->GetAsDictionary(&result_info))
      return Status(kUnknownError, "async result info is not a dictionary");
    int status_code;
    if (!result_info->GetInteger("status", &status_code))
      return Status(kUnknownError, "async result info has no int 'status'");
    if (status_code != kOk) {
      std::string message;
      result_info->GetString("value", &message);
      return Status(static_cast<StatusCode>(status_code), message);
    }

    base::Value* value = NULL;
    if (result_info->Get("value", &value)) {
      result->reset(value->DeepCopy());
      return Status(kOk);
    }

    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
  }
}

Status WebViewImpl::IsNotPendingNavigation(const std::string& frame_id,
                                           const Timeout* timeout,
                                           bool* is_not_pending) {
  bool is_pending;
  Status status =
      navigation_tracker_->IsPendingNavigation(frame_id, timeout, &is_pending);
  if (status.IsError())
    return status;
  // An alert may block the pending navigation.
  if (dialog_manager_->IsDialogOpen())
    return Status(kUnexpectedAlertOpen);

  *is_not_pending = !is_pending;
  return Status(kOk);
}

bool WebViewImpl::IsOOPIF(const std::string& frame_id) {
  WebView* target = GetTargetForFrame(this, frame_id);
  return target != nullptr && frame_id == target->GetId();
}

FrameTracker* WebViewImpl::GetFrameTracker() const {
  return frame_tracker_.get();
}

const WebViewImpl* WebViewImpl::GetParent() const {
  return parent_;
}

bool WebViewImpl::Lock() {
  bool was_locked = is_locked_;
  is_locked_ = true;
  return was_locked;
}

void WebViewImpl::Unlock() {
  is_locked_ = false;
}

bool WebViewImpl::IsLocked() const {
  return is_locked_;
}

void WebViewImpl::SetDetached() {
  is_detached_ = true;
  client_->SetDetached();
}

bool WebViewImpl::IsDetached() const {
  return is_detached_;
}

WebViewImplHolder::WebViewImplHolder(WebViewImpl* web_view)
    : web_view_(web_view), was_locked_(web_view->Lock()) {}

WebViewImplHolder::~WebViewImplHolder() {
  if (web_view_ != nullptr && !was_locked_) {
    if (!web_view_->IsDetached())
      web_view_->Unlock();
    else if (web_view_->GetParent() != nullptr)
      web_view_->GetParent()->GetFrameTracker()->DeleteTargetForFrame(
          web_view_->GetId());
  }
}

namespace internal {

Status EvaluateScript(DevToolsClient* client,
                      int context_id,
                      const std::string& expression,
                      EvaluateScriptReturnType return_type,
                      std::unique_ptr<base::DictionaryValue>* result) {
  base::DictionaryValue params;
  params.SetString("expression", expression);
  if (context_id)
    params.SetInteger("contextId", context_id);
  params.SetBoolean("returnByValue", return_type == ReturnByValue);
  std::unique_ptr<base::DictionaryValue> cmd_result;
  Status status = client->SendCommandAndGetResult(
      "Runtime.evaluate", params, &cmd_result);
  if (status.IsError())
    return status;

  bool was_thrown;
  if (!cmd_result->GetBoolean("wasThrown", &was_thrown)) {
    // As of crrev.com/411814, Runtime.evaluate no longer returns a 'wasThrown'
    // property in the response, so check 'exceptionDetails' instead.
    // TODO(samuong): Ignore 'wasThrown' when we stop supporting Chrome 54.
    was_thrown = cmd_result->HasKey("exceptionDetails");
  }
  if (was_thrown) {
    std::string description = "unknown";
    cmd_result->GetString("result.description", &description);
    return Status(kUnknownError,
                  "Runtime.evaluate threw exception: " + description);
  }

  base::DictionaryValue* unscoped_result;
  if (!cmd_result->GetDictionary("result", &unscoped_result))
    return Status(kUnknownError, "evaluate missing dictionary 'result'");
  result->reset(unscoped_result->DeepCopy());
  return Status(kOk);
}

Status EvaluateScriptAndGetObject(DevToolsClient* client,
                                  int context_id,
                                  const std::string& expression,
                                  bool* got_object,
                                  std::string* object_id) {
  std::unique_ptr<base::DictionaryValue> result;
  Status status = EvaluateScript(client, context_id, expression, ReturnByObject,
                                 &result);
  if (status.IsError())
    return status;
  if (!result->HasKey("objectId")) {
    *got_object = false;
    return Status(kOk);
  }
  if (!result->GetString("objectId", object_id))
    return Status(kUnknownError, "evaluate has invalid 'objectId'");
  *got_object = true;
  return Status(kOk);
}

Status EvaluateScriptAndGetValue(DevToolsClient* client,
                                 int context_id,
                                 const std::string& expression,
                                 std::unique_ptr<base::Value>* result) {
  std::unique_ptr<base::DictionaryValue> temp_result;
  Status status = EvaluateScript(client, context_id, expression, ReturnByValue,
                                 &temp_result);
  if (status.IsError())
    return status;

  std::string type;
  if (!temp_result->GetString("type", &type))
    return Status(kUnknownError, "Runtime.evaluate missing string 'type'");

  if (type == "undefined") {
    *result = std::make_unique<base::Value>();
  } else {
    base::Value* value;
    if (!temp_result->Get("value", &value))
      return Status(kUnknownError, "Runtime.evaluate missing 'value'");
    result->reset(value->DeepCopy());
  }
  return Status(kOk);
}

Status ParseCallFunctionResult(const base::Value& temp_result,
                               std::unique_ptr<base::Value>* result) {
  const base::DictionaryValue* dict;
  if (!temp_result.GetAsDictionary(&dict))
    return Status(kUnknownError, "call function result must be a dictionary");
  int status_code;
  if (!dict->GetInteger("status", &status_code)) {
    return Status(kUnknownError,
                  "call function result missing int 'status'");
  }
  if (status_code != kOk) {
    std::string message;
    dict->GetString("value", &message);
    return Status(static_cast<StatusCode>(status_code), message);
  }
  const base::Value* unscoped_value;
  if (!dict->Get("value", &unscoped_value)) {
    // Missing 'value' indicates the JavaScript code didn't return a value.
    return Status(kOk);
  }
  result->reset(unscoped_value->DeepCopy());
  return Status(kOk);
}

Status GetNodeIdFromFunction(DevToolsClient* client,
                             int context_id,
                             const std::string& function,
                             const base::ListValue& args,
                             bool* found_node,
                             int* node_id,
                             bool w3c_compliant) {
  std::string json;
  base::JSONWriter::Write(args, &json);
  std::string w3c = w3c_compliant ? "true" : "false";
  // TODO(zachconrad): Second null should be array of shadow host ids.
  std::string expression = base::StringPrintf(
      "(%s).apply(null, [null, %s, %s, %s, true])",
      kCallFunctionScript,
      function.c_str(),
      json.c_str(),
      w3c.c_str());

  bool got_object;
  std::string element_id;
  Status status = internal::EvaluateScriptAndGetObject(
      client, context_id, expression, &got_object, &element_id);
  if (status.IsError())
    return status;
  if (!got_object) {
    *found_node = false;
    return Status(kOk);
  }

  std::unique_ptr<base::DictionaryValue> cmd_result;
  {
    base::DictionaryValue params;
    params.SetString("objectId", element_id);
    status = client->SendCommandAndGetResult(
        "DOM.requestNode", params, &cmd_result);
  }
  {
    // Release the remote object before doing anything else.
    base::DictionaryValue params;
    params.SetString("objectId", element_id);
    Status release_status =
        client->SendCommand("Runtime.releaseObject", params);
    if (release_status.IsError()) {
      LOG(ERROR) << "Failed to release remote object: "
                 << release_status.message();
    }
  }
  if (status.IsError())
    return status;

  if (!cmd_result->GetInteger("nodeId", node_id))
    return Status(kUnknownError, "DOM.requestNode missing int 'nodeId'");
  *found_node = true;
  return Status(kOk);
}



}  // namespace internal
