普通文本  |  339行  |  8.7 KB

// Copyright (c) 2012 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/automation/browser_proxy.h"

#include <algorithm>

#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "chrome/common/automation_constants.h"
#include "chrome/common/automation_messages.h"
#include "chrome/test/automation/automation_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/automation/window_proxy.h"
#include "ui/gfx/point.h"

using base::TimeDelta;
using base::TimeTicks;

bool BrowserProxy::ActivateTab(int tab_index) {
  if (!is_valid())
    return false;

  int activate_tab_response = -1;

  if (!sender_->Send(new AutomationMsg_ActivateTab(
                         handle_, tab_index, &activate_tab_response))) {
    return false;
  }

  if (activate_tab_response >= 0)
    return true;

  return false;
}

bool BrowserProxy::BringToFront() {
  if (!is_valid())
    return false;

  bool succeeded = false;

  if (!sender_->Send(new AutomationMsg_BringBrowserToFront(
                         handle_, &succeeded))) {
    return false;
  }

  return succeeded;
}

bool BrowserProxy::AppendTab(const GURL& tab_url) {
  if (!is_valid())
    return false;

  int append_tab_response = -1;

  sender_->Send(new AutomationMsg_AppendTab(handle_, tab_url,
                                            &append_tab_response));
  return append_tab_response >= 0;
}

bool BrowserProxy::GetActiveTabIndex(int* active_tab_index) const {
  if (!is_valid())
    return false;

  if (!active_tab_index) {
    NOTREACHED();
    return false;
  }

  int active_tab_index_response = -1;

  if (!sender_->Send(new AutomationMsg_ActiveTabIndex(
                         handle_, &active_tab_index_response))) {
    return false;
  }

  if (active_tab_index_response >= 0) {
    *active_tab_index = active_tab_index_response;
    return true;
  }

  return false;
}

scoped_refptr<TabProxy> BrowserProxy::GetTab(int tab_index) const {
  if (!is_valid())
    return NULL;

  int tab_handle = 0;

  sender_->Send(new AutomationMsg_Tab(handle_, tab_index, &tab_handle));
  if (!tab_handle)
    return NULL;

  TabProxy* tab = static_cast<TabProxy*>(tracker_->GetResource(tab_handle));
  if (!tab) {
    tab = new TabProxy(sender_, tracker_, tab_handle);
    tab->AddRef();
  }

  // Since there is no scoped_refptr::attach.
  scoped_refptr<TabProxy> result;
  result.swap(&tab);
  return result;
}

scoped_refptr<TabProxy> BrowserProxy::GetActiveTab() const {
  int active_tab_index;
  if (!GetActiveTabIndex(&active_tab_index))
    return NULL;
  return GetTab(active_tab_index);
}

bool BrowserProxy::GetTabCount(int* num_tabs) const {
  if (!is_valid())
    return false;

  if (!num_tabs) {
    NOTREACHED();
    return false;
  }

  int tab_count_response = -1;

  if (!sender_->Send(new AutomationMsg_TabCount(
                         handle_, &tab_count_response))) {
    return false;
  }

  if (tab_count_response >= 0) {
    *num_tabs = tab_count_response;
    return true;
  }

  return false;
}

bool BrowserProxy::GetType(Browser::Type* type) const {
  if (!is_valid())
    return false;

  if (!type) {
    NOTREACHED();
    return false;
  }

  int type_as_int;
  if (!sender_->Send(new AutomationMsg_Type(handle_, &type_as_int)))
    return false;

  *type = static_cast<Browser::Type>(type_as_int);
  return true;
}

bool BrowserProxy::ApplyAccelerator(int id) {
  return RunCommandAsync(id);
}

bool BrowserProxy::WaitForTabCountToBecome(int count) {
  bool success = false;
  if (!sender_->Send(new AutomationMsg_WaitForTabCountToBecome(
                         handle_, count, &success))) {
    return false;
  }

  return success;
}

bool BrowserProxy::WaitForTabToBecomeActive(int tab,
                                            base::TimeDelta wait_timeout) {
  const TimeTicks start = TimeTicks::Now();
  while (TimeTicks::Now() - start < wait_timeout) {
    base::PlatformThread::Sleep(
        base::TimeDelta::FromMilliseconds(automation::kSleepTime));
    int active_tab;
    if (GetActiveTabIndex(&active_tab) && active_tab == tab)
      return true;
  }
  // If we get here, the active tab hasn't changed.
  return false;
}

bool BrowserProxy::IsFindWindowFullyVisible(bool* is_visible) {
  if (!is_valid())
    return false;

  if (!is_visible) {
    NOTREACHED();
    return false;
  }

  return sender_->Send(
      new AutomationMsg_FindWindowVisibility(handle_, is_visible));
}

bool BrowserProxy::RunCommandAsync(int browser_command) const {
  if (!is_valid())
    return false;

  bool result = false;

  sender_->Send(new AutomationMsg_WindowExecuteCommandAsync(handle_,
                                                            browser_command,
                                                            &result));

  return result;
}

bool BrowserProxy::RunCommand(int browser_command) const {
  if (!is_valid())
    return false;

  bool result = false;

  sender_->Send(new AutomationMsg_WindowExecuteCommand(handle_,
                                                       browser_command,
                                                       &result));

  return result;
}

bool BrowserProxy::TerminateSession() {
  if (!is_valid())
    return false;

  bool result = false;

  sender_->Send(new AutomationMsg_TerminateSession(handle_, &result));

  return result;
}

scoped_refptr<WindowProxy> BrowserProxy::GetWindow() const {
  if (!is_valid())
    return NULL;

  bool handle_ok = false;
  int window_handle = 0;

  sender_->Send(new AutomationMsg_WindowForBrowser(handle_, &handle_ok,
                                                   &window_handle));
  if (!handle_ok)
    return NULL;

  WindowProxy* window =
      static_cast<WindowProxy*>(tracker_->GetResource(window_handle));
  if (!window) {
    window = new WindowProxy(sender_, tracker_, window_handle);
    window->AddRef();
  }

  // Since there is no scoped_refptr::attach.
  scoped_refptr<WindowProxy> result;
  result.swap(&window);
  return result;
}

bool BrowserProxy::SendJSONRequest(const std::string& request,
                                   int timeout_ms,
                                   std::string* response) {
  if (!is_valid())
    return false;

  bool result = false;
  if (!sender_->Send(
      new AutomationMsg_SendJSONRequestWithBrowserHandle(handle_,
                                                         request,
                                                         response,
                                                         &result),
                                                         timeout_ms))
    return false;
  return result;
}

bool BrowserProxy::GetInitialLoadTimes(base::TimeDelta timeout,
                                       float* min_start_time,
                                       float* max_stop_time,
                                       std::vector<float>* stop_times) {
  std::string json_response;
  const char* kJSONCommand = "{\"command\": \"GetInitialLoadTimes\"}";

  *max_stop_time = 0;
  *min_start_time = -1;
  if (!SendJSONRequest(
          kJSONCommand, timeout.InMilliseconds(), &json_response)) {
    // Older browser versions do not support GetInitialLoadTimes.
    // Fail gracefully and do not record them in this case.
    return false;
  }
  std::string error;
  scoped_ptr<Value> values(base::JSONReader::ReadAndReturnError(
      json_response, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error));
  if (!error.empty() || values->GetType() != Value::TYPE_DICTIONARY)
    return false;

  DictionaryValue* values_dict = static_cast<DictionaryValue*>(values.get());

  Value* tabs_value;
  if (!values_dict->Get("tabs", &tabs_value) ||
      tabs_value->GetType() != Value::TYPE_LIST)
    return false;

  ListValue* tabs_list = static_cast<ListValue*>(tabs_value);

  for (size_t i = 0; i < tabs_list->GetSize(); i++) {
    float stop_ms = 0;
    float start_ms = 0;
    Value* tab_value;
    DictionaryValue* tab_dict;

    if (!tabs_list->Get(i, &tab_value) ||
        tab_value->GetType() != Value::TYPE_DICTIONARY)
      return false;
    tab_dict = static_cast<DictionaryValue*>(tab_value);

    double temp;
    if (!tab_dict->GetDouble("load_start_ms", &temp))
      return false;
    start_ms = static_cast<float>(temp);
    // load_stop_ms can only be null if WaitForInitialLoads did not run.
    if (!tab_dict->GetDouble("load_stop_ms", &temp))
      return false;
    stop_ms = static_cast<float>(temp);

    if (i == 0)
      *min_start_time = start_ms;

    *min_start_time = std::min(start_ms, *min_start_time);
    *max_stop_time = std::max(stop_ms, *max_stop_time);
    stop_times->push_back(stop_ms);
  }
  std::sort(stop_times->begin(), stop_times->end());
  return true;
}