blob: 78de5bdd5dba4b86b0841e02924a9af186e901f1 [file] [log] [blame]
// Copyright (c) 2011 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/automation_json_requests.h"
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/format_macros.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/stringprintf.h"
#include "base/test/test_timeouts.h"
#include "base/time.h"
#include "base/values.h"
#include "chrome/common/automation_messages.h"
#include "chrome/test/automation/automation_proxy.h"
#include "content/common/json_value_serializer.h"
namespace {
bool SendAutomationJSONRequest(AutomationMessageSender* sender,
const DictionaryValue& request_dict,
DictionaryValue* reply_dict,
std::string* error_msg) {
std::string request, reply;
base::JSONWriter::Write(&request_dict, false, &request);
std::string command;
request_dict.GetString("command", &command);
LOG(INFO) << "Sending '" << command << "' command.";
base::Time before_sending = base::Time::Now();
bool success = false;
if (!SendAutomationJSONRequestWithDefaultTimeout(
sender, request, &reply, &success)) {
*error_msg = base::StringPrintf(
"Chrome did not respond to '%s'. Elapsed time was %" PRId64 " ms. "
"Request details: (%s).",
command.c_str(),
(base::Time::Now() - before_sending).InMilliseconds(),
request.c_str());
return false;
}
scoped_ptr<Value> value(base::JSONReader::Read(reply, true));
if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) {
LOG(ERROR) << "JSON request did not return dict: " << command << "\n";
return false;
}
DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
if (!success) {
std::string error;
dict->GetString("error", &error);
*error_msg = base::StringPrintf(
"Internal Chrome error during '%s': (%s). Request details: (%s).",
command.c_str(),
error.c_str(),
request.c_str());
LOG(ERROR) << "JSON request failed: " << command << "\n"
<< " with error: " << error;
return false;
}
reply_dict->MergeDictionary(dict);
return true;
}
} // namespace
WebKeyEvent::WebKeyEvent(automation::KeyEventTypes type,
ui::KeyboardCode key_code,
const std::string& unmodified_text,
const std::string& modified_text,
int modifiers)
: type(type),
key_code(key_code),
unmodified_text(unmodified_text),
modified_text(modified_text),
modifiers(modifiers) {}
bool SendAutomationJSONRequest(AutomationMessageSender* sender,
const std::string& request,
int timeout_ms,
std::string* reply,
bool* success) {
return sender->Send(new AutomationMsg_SendJSONRequest(
-1, request, reply, success), timeout_ms);
}
bool SendAutomationJSONRequestWithDefaultTimeout(
AutomationMessageSender* sender,
const std::string& request,
std::string* reply,
bool* success) {
return sender->Send(new AutomationMsg_SendJSONRequest(
-1, request, reply, success));
}
bool SendGetIndicesFromTabIdJSONRequest(
AutomationMessageSender* sender,
int tab_id,
int* browser_index,
int* tab_index,
std::string* error_msg) {
DictionaryValue request_dict;
request_dict.SetString("command", "GetIndicesFromTab");
request_dict.SetInteger("tab_id", tab_id);
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict, error_msg))
return false;
if (!reply_dict.GetInteger("windex", browser_index))
return false;
if (!reply_dict.GetInteger("tab_index", tab_index))
return false;
return true;
}
bool SendGetIndicesFromTabHandleJSONRequest(
AutomationMessageSender* sender,
int tab_handle,
int* browser_index,
int* tab_index,
std::string* error_msg) {
DictionaryValue request_dict;
request_dict.SetString("command", "GetIndicesFromTab");
request_dict.SetInteger("tab_handle", tab_handle);
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, request_dict, &reply_dict, error_msg))
return false;
if (!reply_dict.GetInteger("windex", browser_index))
return false;
if (!reply_dict.GetInteger("tab_index", tab_index))
return false;
return true;
}
bool SendNavigateToURLJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
const GURL& url,
int navigation_count,
AutomationMsg_NavigationResponseValues* nav_response,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "NavigateToURL");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetString("url", url.possibly_invalid_spec());
dict.SetInteger("navigation_count", navigation_count);
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg))
return false;
int response = 0;
if (!reply_dict.GetInteger("result", &response))
return false;
*nav_response = static_cast<AutomationMsg_NavigationResponseValues>(response);
return true;
}
bool SendExecuteJavascriptJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
const std::string& frame_xpath,
const std::string& javascript,
Value** result,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "ExecuteJavascript");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetString("frame_xpath", frame_xpath);
dict.SetString("javascript", javascript);
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg))
return false;
std::string json;
if (!reply_dict.GetString("result", &json)) {
LOG(ERROR) << "Executed javascript but received no 'result'";
return false;
}
// Wrap |json| in an array before deserializing because valid JSON has an
// array or an object as the root.
json.insert(0, "[");
json.append("]");
JSONStringValueSerializer deserializer(json);
Value* value = deserializer.Deserialize(NULL, NULL);
if (!value || !value->IsType(Value::TYPE_LIST)) {
LOG(ERROR) << "Unable to deserialize returned JSON";
return false;
}
scoped_ptr<ListValue> list(static_cast<ListValue*>(value));
return list->Remove(0, result);
}
bool SendGoForwardJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "GoForward");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendGoBackJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "GoBack");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendReloadJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "Reload");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendCaptureEntirePageJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
const FilePath& path,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "CaptureEntirePage");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetString("path", path.value());
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendGetTabURLJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
std::string* url,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "GetTabURL");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg))
return false;
return reply_dict.GetString("url", url);
}
bool SendGetTabTitleJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
std::string* tab_title,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "GetTabTitle");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg))
return false;
return reply_dict.GetString("title", tab_title);
}
bool SendGetCookiesJSONRequest(
AutomationMessageSender* sender,
const std::string& url,
ListValue** cookies,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "GetCookies");
dict.SetString("url", url);
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg))
return false;
Value* cookies_unscoped_value;
if (!reply_dict.Remove("cookies", &cookies_unscoped_value))
return false;
scoped_ptr<Value> cookies_value(cookies_unscoped_value);
if (!cookies_value->IsType(Value::TYPE_LIST))
return false;
*cookies = static_cast<ListValue*>(cookies_value.release());
return true;
}
bool SendGetCookiesJSONRequestDeprecated(
AutomationMessageSender* sender,
int browser_index,
const std::string& url,
std::string* cookies) {
DictionaryValue dict;
dict.SetString("command", "GetCookies");
dict.SetInteger("windex", browser_index);
dict.SetString("url", url);
DictionaryValue reply_dict;
std::string error_msg;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg))
return false;
return reply_dict.GetString("cookies", cookies);
}
bool SendDeleteCookieJSONRequest(
AutomationMessageSender* sender,
const std::string& url,
const std::string& cookie_name,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "DeleteCookie");
dict.SetString("url", url);
dict.SetString("name", cookie_name);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendDeleteCookieJSONRequestDeprecated(
AutomationMessageSender* sender,
int browser_index,
const std::string& url,
const std::string& cookie_name) {
DictionaryValue dict;
dict.SetString("command", "DeleteCookie");
dict.SetInteger("windex", browser_index);
dict.SetString("url", url);
dict.SetString("name", cookie_name);
DictionaryValue reply_dict;
std::string error_msg;
return SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg);
}
bool SendSetCookieJSONRequest(
AutomationMessageSender* sender,
const std::string& url,
DictionaryValue* cookie_dict,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "SetCookie");
dict.SetString("url", url);
dict.Set("cookie", cookie_dict->DeepCopy());
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendSetCookieJSONRequestDeprecated(
AutomationMessageSender* sender,
int browser_index,
const std::string& url,
const std::string& cookie) {
DictionaryValue dict;
dict.SetString("command", "SetCookie");
dict.SetInteger("windex", browser_index);
dict.SetString("url", url);
dict.SetString("cookie", cookie);
DictionaryValue reply_dict;
std::string error_msg;
return SendAutomationJSONRequest(sender, dict, &reply_dict, &error_msg);
}
bool SendGetTabIdsJSONRequest(
AutomationMessageSender* sender,
std::vector<int>* tab_ids,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "GetTabIds");
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg))
return false;
ListValue* id_list;
if (!reply_dict.GetList("ids", &id_list)) {
LOG(ERROR) << "Returned 'ids' key is missing or invalid";
return false;
}
std::vector<int> temp_ids;
for (size_t i = 0; i < id_list->GetSize(); ++i) {
int id;
if (!id_list->GetInteger(i, &id)) {
LOG(ERROR) << "Returned 'ids' key contains non-integer values";
return false;
}
temp_ids.push_back(id);
}
*tab_ids = temp_ids;
return true;
}
bool SendIsTabIdValidJSONRequest(
AutomationMessageSender* sender,
int tab_id,
bool* is_valid,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "IsTabIdValid");
dict.SetInteger("id", tab_id);
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg))
return false;
return reply_dict.GetBoolean("is_valid", is_valid);
}
bool SendCloseTabJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "CloseTab");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendMouseMoveJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
int x,
int y,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "WebkitMouseMove");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetInteger("x", x);
dict.SetInteger("y", y);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendMouseClickJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
automation::MouseButton button,
int x,
int y,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "WebkitMouseClick");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetInteger("button", button);
dict.SetInteger("x", x);
dict.SetInteger("y", y);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendMouseDragJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
int start_x,
int start_y,
int end_x,
int end_y,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "WebkitMouseDrag");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetInteger("start_x", start_x);
dict.SetInteger("start_y", start_y);
dict.SetInteger("end_x", end_x);
dict.SetInteger("end_y", end_y);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendMouseButtonDownJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
int x,
int y,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "WebkitMouseButtonDown");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetInteger("x", x);
dict.SetInteger("y", y);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendMouseButtonUpJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
int x,
int y,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "WebkitMouseButtonUp");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetInteger("x", x);
dict.SetInteger("y", y);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendMouseDoubleClickJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
int x,
int y,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "WebkitMouseDoubleClick");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetInteger("x", x);
dict.SetInteger("y", y);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendWebKeyEventJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
const WebKeyEvent& key_event,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "SendWebkitKeyEvent");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetInteger("type", key_event.type);
dict.SetInteger("nativeKeyCode", key_event.key_code);
dict.SetInteger("windowsKeyCode", key_event.key_code);
dict.SetString("unmodifiedText", key_event.unmodified_text);
dict.SetString("text", key_event.modified_text);
dict.SetInteger("modifiers", key_event.modifiers);
dict.SetBoolean("isSystemKey", false);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendNativeKeyEventJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
ui::KeyboardCode key_code,
int modifiers,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "SendOSLevelKeyEventToTab");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetInteger("keyCode", key_code);
dict.SetInteger("modifiers", modifiers);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendDragAndDropFilePathsJSONRequest(
AutomationMessageSender* sender,
int browser_index,
int tab_index,
int x,
int y,
const std::vector<FilePath::StringType>& paths,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "DragAndDropFilePaths");
dict.SetInteger("windex", browser_index);
dict.SetInteger("tab_index", tab_index);
dict.SetInteger("x", x);
dict.SetInteger("y", y);
ListValue* list_value = new ListValue();
for (size_t path_index = 0; path_index < paths.size(); ++path_index) {
list_value->Append(Value::CreateStringValue(paths[path_index]));
}
dict.Set("paths", list_value);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendGetAppModalDialogMessageJSONRequest(
AutomationMessageSender* sender,
std::string* message,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "GetAppModalDialogMessage");
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg))
return false;
return reply_dict.GetString("message", message);
}
bool SendAcceptOrDismissAppModalDialogJSONRequest(
AutomationMessageSender* sender,
bool accept,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "AcceptOrDismissAppModalDialog");
dict.SetBoolean("accept", accept);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendAcceptPromptAppModalDialogJSONRequest(
AutomationMessageSender* sender,
const std::string& prompt_text,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "AcceptOrDismissAppModalDialog");
dict.SetBoolean("accept", true);
dict.SetString("prompt_text", prompt_text);
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendWaitForAllTabsToStopLoadingJSONRequest(
AutomationMessageSender* sender,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "WaitForAllTabsToStopLoading");
DictionaryValue reply_dict;
return SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg);
}
bool SendGetChromeDriverAutomationVersion(
AutomationMessageSender* sender,
int* version,
std::string* error_msg) {
DictionaryValue dict;
dict.SetString("command", "GetChromeDriverAutomationVersion");
DictionaryValue reply_dict;
if (!SendAutomationJSONRequest(sender, dict, &reply_dict, error_msg))
return false;
return reply_dict.GetInteger("version", version);
}