Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5433)

Unified Diff: chrome/test/webdriver/session.cc

Issue 7522024: Refactor chromedriver's script execution to reduce amount of custom Value parsing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/test/webdriver/session.cc
diff --git a/chrome/test/webdriver/session.cc b/chrome/test/webdriver/session.cc
index 7249bfa54a25aa8d8619f4e791835ec02e76fe83..14f06ede7b7790ff7f141bc47606221a1f67f916 100644
--- a/chrome/test/webdriver/session.cc
+++ b/chrome/test/webdriver/session.cc
@@ -32,14 +32,12 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/automation/automation_json_requests.h"
-#include "chrome/test/webdriver/webdriver_error.h"
+#include "chrome/test/automation/value_conversion_util.h"
#include "chrome/test/webdriver/session_manager.h"
-#include "chrome/test/webdriver/utility_functions.h"
+#include "chrome/test/webdriver/webdriver_error.h"
#include "chrome/test/webdriver/webdriver_key_converter.h"
+#include "chrome/test/webdriver/webdriver_util.h"
#include "third_party/webdriver/atoms.h"
-#include "ui/gfx/point.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size.h"
namespace webdriver {
@@ -115,7 +113,7 @@ Error* Session::ExecuteScript(const FrameId& frame_id,
"[function(){%s\n},%s,true]));",
atoms::EXECUTE_SCRIPT, script.c_str(), args_as_json.c_str());
- return ExecuteScriptAndParseResponse(frame_id, jscript, value);
+ return ExecuteScriptAndParseValue(frame_id, jscript, value);
}
Error* Session::ExecuteScript(const std::string& script,
@@ -124,6 +122,32 @@ Error* Session::ExecuteScript(const std::string& script,
return ExecuteScript(current_target_, script, args, value);
}
+Error* Session::ExecuteScriptAndParse(const FrameId& frame_id,
+ const std::string& anonymous_func_script,
+ const std::string& script_name,
+ const ListValue* args,
+ const ValueParser* parser) {
+ scoped_ptr<const ListValue> scoped_args(args);
+ scoped_ptr<const ValueParser> scoped_parser(parser);
+ std::string called_script = base::StringPrintf(
+ "return (%s).apply(null, arguments);", anonymous_func_script.c_str());
+ Value* unscoped_value = NULL;
+ Error* error = ExecuteScript(frame_id, called_script, args, &unscoped_value);
+ if (error) {
+ error->AddDetails(script_name + " execution failed");
+ return error;
+ }
+
+ scoped_ptr<Value> value(unscoped_value);
+ std::string error_msg;
+ if (!parser->Parse(value.get())) {
+ error_msg = base::StringPrintf("%s returned invalid value: %s",
+ script_name.c_str(), JsonStringify(value.get()).c_str());
+ return new Error(kUnknownError, error_msg);
+ }
+ return NULL;
+}
+
Error* Session::ExecuteAsyncScript(const FrameId& frame_id,
const std::string& script,
const ListValue* const args,
@@ -146,7 +170,7 @@ Error* Session::ExecuteAsyncScript(const FrameId& frame_id,
timeout_ms,
"function(result) {window.domAutomationController.send(result);}");
- return ExecuteScriptAndParseResponse(frame_id, jscript, value);
+ return ExecuteScriptAndParseValue(frame_id, jscript, value);
}
Error* Session::SendKeys(const WebElementId& element, const string16& keys) {
@@ -165,8 +189,6 @@ Error* Session::SendKeys(const WebElementId& element, const string16& keys) {
if (!is_enabled)
return new Error(kInvalidElementState);
- ListValue args;
- args.Append(element.ToValue());
// Focus the target element in order to send keys to it.
// First, the currently active element is blurred, if it is different from
// the target element. We do not want to blur an element unnecessarily,
@@ -186,24 +208,27 @@ Error* Session::SendKeys(const WebElementId& element, const string16& keys) {
// - You cannot focus a descendant of a content editable node
// TODO(jleyba): Update this to use the correct atom.
const char* kFocusScript =
- "var elem = arguments[0];"
- "var doc = elem.ownerDocument || elem;"
- "var prevActiveElem = doc.activeElement;"
- "if (elem != prevActiveElem && prevActiveElem)"
- " prevActiveElem.blur();"
- "elem.focus();"
- "if (elem != prevActiveElem && elem.value && elem.value.length &&"
- " elem.setSelectionRange) {"
- " elem.setSelectionRange(elem.value.length, elem.value.length);"
- "}"
- "if (elem != doc.activeElement)"
- " throw new Error('Failed to send keys because cannot focus element.');";
- Value* unscoped_result = NULL;
- error = ExecuteScript(kFocusScript, &args, &unscoped_result);
+ "function(elem) {"
+ " var doc = elem.ownerDocument || elem;"
+ " var prevActiveElem = doc.activeElement;"
+ " if (elem != prevActiveElem && prevActiveElem)"
+ " prevActiveElem.blur();"
+ " elem.focus();"
+ " if (elem != prevActiveElem && elem.value && elem.value.length &&"
+ " elem.setSelectionRange) {"
+ " elem.setSelectionRange(elem.value.length, elem.value.length);"
+ " }"
+ " if (elem != doc.activeElement)"
+ " throw new Error('Failed to send keys because cannot focus element');"
+ "}";
+ error = ExecuteScriptAndParse(current_target_,
+ kFocusScript,
+ "focusElement",
+ CreateListValueFrom(element),
+ CreateDirectValueParser(kSkipParsing));
if (error)
return error;
- error = NULL;
RunSessionTask(NewRunnableMethod(
this,
&Session::SendKeysOnSessionThread,
@@ -213,7 +238,7 @@ Error* Session::SendKeys(const WebElementId& element, const string16& keys) {
}
Error* Session::DragAndDropFilePaths(
- const gfx::Point& location,
+ const Point& location,
const std::vector<FilePath::StringType>& paths) {
Error* error = NULL;
RunSessionTask(NewRunnableMethod(
@@ -268,44 +293,29 @@ Error* Session::Reload() {
}
Error* Session::GetURL(std::string* url) {
- ListValue no_args;
- Value* unscoped_value = NULL;
- Error* error = ExecuteScript(current_target_,
- "return document.URL;",
- &no_args,
- &unscoped_value);
- scoped_ptr<Value> value(unscoped_value);
- if (error)
- return error;
- if (!value->GetAsString(url))
- return new Error(kUnknownError, "GetURL Script returned non-string: " +
- JsonStringify(value.get()));
- return NULL;
+ return ExecuteScriptAndParse(current_target_,
+ "function() { return document.URL }",
+ "getUrl",
+ new ListValue(),
+ CreateDirectValueParser(url));
}
Error* Session::GetTitle(std::string* tab_title) {
- std::string script =
- "if (document.title)"
- " return document.title;"
- "else"
- " return document.URL;";
-
- ListValue no_args;
- Value* unscoped_value = NULL;
- Error* error = ExecuteScript(current_target_,
- script,
- &no_args,
- &unscoped_value);
- scoped_ptr<Value> value(unscoped_value);
- if (error)
- return error;
- if (!value->GetAsString(tab_title))
- return new Error(kUnknownError, "GetTitle script returned non-string: " +
- JsonStringify(value.get()));
- return NULL;
-}
-
-Error* Session::MouseMoveAndClick(const gfx::Point& location,
+ const char* kGetTitleScript =
+ "function() {"
+ " if (document.title)"
+ " return document.title;"
+ " else"
+ " return document.URL;"
+ "}";
+ return ExecuteScriptAndParse(current_target_,
+ kGetTitleScript,
+ "getTitle",
+ new ListValue(),
+ CreateDirectValueParser(tab_title));
+}
+
+Error* Session::MouseMoveAndClick(const Point& location,
automation::MouseButton button) {
Error* error = NULL;
RunSessionTask(NewRunnableMethod(
@@ -320,7 +330,7 @@ Error* Session::MouseMoveAndClick(const gfx::Point& location,
return error;
}
-Error* Session::MouseMove(const gfx::Point& location) {
+Error* Session::MouseMove(const Point& location) {
Error* error = NULL;
RunSessionTask(NewRunnableMethod(
automation_.get(),
@@ -333,8 +343,8 @@ Error* Session::MouseMove(const gfx::Point& location) {
return error;
}
-Error* Session::MouseDrag(const gfx::Point& start,
- const gfx::Point& end) {
+Error* Session::MouseDrag(const Point& start,
+ const Point& end) {
Error* error = NULL;
RunSessionTask(NewRunnableMethod(
automation_.get(),
@@ -455,18 +465,16 @@ Error* Session::SwitchToWindow(const std::string& name) {
return error;
// See if any of the window names match |name|.
for (size_t i = 0; i < window_ids.size(); ++i) {
- ListValue empty_list;
- Value* unscoped_name_value = NULL;
std::string window_name;
- Error* error = ExecuteScript(FrameId(window_ids[i], FramePath()),
- "return window.name;",
- &empty_list,
- &unscoped_name_value);
+ Error* error = ExecuteScriptAndParse(
+ FrameId(window_ids[i], FramePath()),
+ "function() { return window.name; }",
+ "getWindowName",
+ new ListValue(),
+ CreateDirectValueParser(&window_name));
if (error)
return error;
- scoped_ptr<Value> name_value(unscoped_name_value);
- if (name_value->GetAsString(&window_name) &&
- name == window_name) {
+ if (name == window_name) {
switch_to_id = window_ids[i];
break;
}
@@ -482,21 +490,21 @@ Error* Session::SwitchToWindow(const std::string& name) {
Error* Session::SwitchToFrameWithNameOrId(const std::string& name_or_id) {
std::string script =
- "var arg = arguments[0];"
- "var xpath = '(/html/body//iframe|/html/frameset/frame)';"
- "var sub = function(s) { return s.replace(/\\$/g, arg); };"
- "xpath += sub('[@name=\"$\" or @id=\"$\"]');"
- "var frame = document.evaluate(xpath, document, null, "
- " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
- "if (!frame) { return null; }"
- "xpath = frame.tagName == 'IFRAME' ? '/html/body//iframe'"
- " : '/html/frameset/frame';"
- "frame_xpath = xpath + "
- " sub('[@' + (frame.id == arg ? 'id' : 'name') + '=\"$\"]');"
- "return [frame, frame_xpath];";
- ListValue args;
- args.Append(new StringValue(name_or_id));
- return SwitchToFrameWithJavaScriptLocatedFrame(script, &args);
+ "function(arg) {"
+ " var xpath = '(/html/body//iframe|/html/frameset/frame)';"
+ " var sub = function(s) { return s.replace(/\\$/g, arg); };"
+ " xpath += sub('[@name=\"$\" or @id=\"$\"]');"
+ " var frame = document.evaluate(xpath, document, null, "
+ " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
+ " if (!frame) { return null; }"
+ " xpath = frame.tagName == 'IFRAME' ? '/html/body//iframe'"
+ " : '/html/frameset/frame';"
+ " frame_xpath = xpath + "
+ " sub('[@' + (frame.id == arg ? 'id' : 'name') + '=\"$\"]');"
+ " return [frame, frame_xpath];"
+ "}";
+ return SwitchToFrameWithJavaScriptLocatedFrame(
+ script, CreateListValueFrom(name_or_id));
}
Error* Session::SwitchToFrameWithIndex(int index) {
@@ -508,43 +516,39 @@ Error* Session::SwitchToFrameWithIndex(int index) {
// into the list of all IFRAME and FRAME elements on the page - if we find
// something, then that XPath expression can be used as the new frame's XPath.
std::string script =
- "var index = '[' + (arguments[0] + 1) + ']';"
- "var xpath = '(/html/body//iframe|/html/frameset/frame)' + "
- " index;"
- "console.info('searching for frame by xpath: ' + xpath);"
- "var frame = document.evaluate(xpath, document, null, "
- "XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
- "console.info(frame == null ? 'found nothing' : frame);"
- "if (!frame) { return null; }"
- "frame_xpath = ((frame.tagName == 'IFRAME' ? "
- " '(/html/body//iframe)' : '/html/frameset/frame') + index);"
- "return [frame, frame_xpath];";
- ListValue args;
- args.Append(Value::CreateIntegerValue(index));
- return SwitchToFrameWithJavaScriptLocatedFrame(script, &args);
+ "function(index) {"
+ " var xpathIndex = '[' + (index + 1) + ']';"
+ " var xpath = '(/html/body//iframe|/html/frameset/frame)' + "
+ " xpathIndex;"
+ " var frame = document.evaluate(xpath, document, null, "
+ " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
+ " if (!frame) { return null; }"
+ " frame_xpath = ((frame.tagName == 'IFRAME' ? "
+ " '(/html/body//iframe)' : '/html/frameset/frame') + xpathIndex);"
+ " return [frame, frame_xpath];"
+ "}";
+ return SwitchToFrameWithJavaScriptLocatedFrame(
+ script, CreateListValueFrom(index));
}
Error* Session::SwitchToFrameWithElement(const WebElementId& element) {
// TODO(jleyba): Extract this, and the other frame switch methods to an atom.
std::string script =
- "var element = arguments[0];"
- "console.info('Attempting to switch to ' + element);"
- "if (element.nodeType != 1 || !/^i?frame$/i.test(element.tagName)) {"
- " console.info('Element is not a frame: ' + element + "
- "' {nodeType:' + element.nodeType + ',tagName:' + element.tagName + '}');"
- " return null;"
- "}"
- "for (var i = 0; i < window.frames.length; i++) {"
- " if (element.contentWindow == window.frames[i]) {"
- " return [element, '(//iframe|//frame)[' + (i + 1) + ']'];"
+ "function(elem) {"
+ " if (elem.nodeType != 1 || !/^i?frame$/i.test(elem.tagName)) {"
+ " console.error('Element is not a frame');"
+ " return null;"
" }"
- "}"
- "console.info('Frame is not connected to this DOM tree');"
- "return null;";
-
- ListValue args;
- args.Append(element.ToValue());
- return SwitchToFrameWithJavaScriptLocatedFrame(script, &args);
+ " for (var i = 0; i < window.frames.length; i++) {"
+ " if (elem.contentWindow == window.frames[i]) {"
+ " return [elem, '(//iframe|//frame)[' + (i + 1) + ']'];"
+ " }"
+ " }"
+ " console.info('Frame is not connected to this DOM tree');"
+ " return null;"
+ "}";
+ return SwitchToFrameWithJavaScriptLocatedFrame(
+ script, CreateListValueFrom(element));
}
void Session::SwitchToTopFrame() {
@@ -566,13 +570,12 @@ Error* Session::SwitchToTopFrameIfCurrentFrameInvalid() {
// frame element is valid, otherwise the automation hangs until a timeout.
for (size_t i = 0; i < frame_elements_.size(); ++i) {
FrameId frame_id(current_target_.window_id, frame_path);
- ListValue args;
- args.Append(frame_elements_[i].ToValue());
- Value* unscoped_value = NULL;
- scoped_ptr<Error> error(ExecuteScript(
- frame_id, "", &args, &unscoped_value));
-
- scoped_ptr<Value> value(unscoped_value);
+ scoped_ptr<Error> error(ExecuteScriptAndParse(
+ frame_id,
+ "function(){ }",
+ "emptyScript",
+ CreateListValueFrom(frame_elements_[i]),
+ CreateDirectValueParser(kSkipParsing)));
if (error.get() && error->code() == kStaleElementReference) {
SwitchToTopFrame();
} else if (error.get()) {
@@ -705,25 +708,24 @@ Error* Session::FindElements(const FrameId& frame_id,
Error* Session::GetElementLocationInView(
const WebElementId& element,
- gfx::Point* location) {
- gfx::Size size;
+ Point* location) {
+ Size size;
Error* error = GetElementSize(current_target_, element, &size);
if (error)
return error;
return GetElementRegionInView(
- element, gfx::Rect(gfx::Point(0, 0), size),
- false /* center */, location);
+ element, Rect(Point(0, 0), size), false /* center */, location);
}
Error* Session::GetElementRegionInView(
const WebElementId& element,
- const gfx::Rect& region,
+ const Rect& region,
bool center,
- gfx::Point* location) {
+ Point* location) {
CHECK(element.is_valid());
- gfx::Point region_offset = region.origin();
- gfx::Size region_size = region.size();
+ Point region_offset = region.origin();
+ Size region_size = region.size();
Error* error = GetElementRegionInViewHelper(
current_target_, element, region, center, &region_offset);
if (error)
@@ -755,7 +757,7 @@ Error* Session::GetElementRegionInView(
region_offset.Offset(border_left, border_top);
error = GetElementRegionInViewHelper(
- frame_id, frame_element, gfx::Rect(region_offset, region_size),
+ frame_id, frame_element, Rect(region_offset, region_size),
center, &region_offset);
if (error)
return error;
@@ -766,66 +768,22 @@ Error* Session::GetElementRegionInView(
Error* Session::GetElementSize(const FrameId& frame_id,
const WebElementId& element,
- gfx::Size* size) {
- std::string script = base::StringPrintf(
- "return (%s).apply(null, arguments);", atoms::GET_SIZE);
- ListValue args;
- args.Append(element.ToValue());
-
- Value* unscoped_result = NULL;
- Error* error = ExecuteScript(frame_id, script, &args, &unscoped_result);
- scoped_ptr<Value> result(unscoped_result);
- if (error)
- return error;
- if (!result->IsType(Value::TYPE_DICTIONARY)) {
- return new Error(kUnknownError, "GetSize atom returned non-dict type: " +
- JsonStringify(result.get()));
- }
- DictionaryValue* dict = static_cast<DictionaryValue*>(result.get());
- int width, height;
- if (!dict->GetInteger("width", &width) ||
- !dict->GetInteger("height", &height)) {
- return new Error(kUnknownError, "GetSize atom returned invalid dict: " +
- JsonStringify(dict));
- }
- *size = gfx::Size(width, height);
- return NULL;
+ Size* size) {
+ return ExecuteScriptAndParse(frame_id,
+ atoms::GET_SIZE,
+ "getSize",
+ CreateListValueFrom(element),
+ CreateDirectValueParser(size));
}
Error* Session::GetElementFirstClientRect(const FrameId& frame_id,
const WebElementId& element,
- gfx::Rect* rect) {
- std::string script = base::StringPrintf(
- "return (%s).apply(null, arguments);", atoms::GET_FIRST_CLIENT_RECT);
- ListValue args;
- args.Append(element.ToValue());
-
- Value* unscoped_result = NULL;
- Error* error = ExecuteScript(frame_id, script, &args, &unscoped_result);
- scoped_ptr<Value> result(unscoped_result);
- if (error)
- return error;
- if (!result->IsType(Value::TYPE_DICTIONARY)) {
- return new Error(
- kUnknownError,
- "GetFirstClientRect atom returned non-dict type: " +
- JsonStringify(result.get()));
- }
- DictionaryValue* dict = static_cast<DictionaryValue*>(result.get());
- // TODO(kkania): Convert the atom to return integers.
- double left, top, width, height;
- if (!dict->GetDouble("left", &left) ||
- !dict->GetDouble("top", &top) ||
- !dict->GetDouble("width", &width) ||
- !dict->GetDouble("height", &height)) {
- return new Error(
- kUnknownError,
- "GetFirstClientRect atom returned invalid dict: " +
- JsonStringify(dict));
- }
- *rect = gfx::Rect(static_cast<int>(left), static_cast<int>(top),
- static_cast<int>(width), static_cast<int>(height));
- return NULL;
+ Rect* rect) {
+ return ExecuteScriptAndParse(frame_id,
+ atoms::GET_FIRST_CLIENT_RECT,
+ "getFirstClientRect",
+ CreateListValueFrom(element),
+ CreateDirectValueParser(rect));
}
Error* Session::GetElementEffectiveStyle(
@@ -833,28 +791,11 @@ Error* Session::GetElementEffectiveStyle(
const WebElementId& element,
const std::string& prop,
std::string* value) {
- std::string script = base::StringPrintf(
- "return (%s).apply(null, arguments);", atoms::GET_EFFECTIVE_STYLE);
- ListValue args;
- args.Append(element.ToValue());
- args.Append(Value::CreateStringValue(prop));
- Value* unscoped_result = NULL;
- Error* error = ExecuteScript(
- frame_id, script, &args, &unscoped_result);
- scoped_ptr<Value> result(unscoped_result);
- if (error) {
- error->AddDetails(base::StringPrintf(
- "GetEffectiveStyle atom failed for property (%s)", prop.c_str()));
- return error;
- }
-
- if (!result->GetAsString(value)) {
- std::string context = base::StringPrintf(
- "GetEffectiveStyle atom returned non-string for property (%s): %s",
- prop.c_str(), JsonStringify(result.get()).c_str());
- return new Error(kUnknownError, context);
- }
- return NULL;
+ return ExecuteScriptAndParse(frame_id,
+ atoms::GET_EFFECTIVE_STYLE,
+ "getEffectiveStyle",
+ CreateListValueFrom(element, prop),
+ CreateDirectValueParser(value));
}
Error* Session::GetElementBorder(const FrameId& frame_id,
@@ -880,78 +821,45 @@ Error* Session::IsElementDisplayed(const FrameId& frame_id,
const WebElementId& element,
bool ignore_opacity,
bool* is_displayed) {
- std::string script = base::StringPrintf(
- "return (%s).apply(null, arguments);", atoms::IS_DISPLAYED);
- ListValue args;
- args.Append(element.ToValue());
- args.Append(Value::CreateBooleanValue(ignore_opacity));
-
- Value* unscoped_result = NULL;
- Error* error = ExecuteScript(frame_id, script, &args, &unscoped_result);
- scoped_ptr<Value> result(unscoped_result);
- if (error)
- return error;
- if (!result->GetAsBoolean(is_displayed))
- return new Error(kUnknownError, "IsDisplayed atom returned non-boolean: " +
- JsonStringify(result.get()));
- return NULL;
+ return ExecuteScriptAndParse(frame_id,
+ atoms::IS_DISPLAYED,
+ "isDisplayed",
+ CreateListValueFrom(element, ignore_opacity),
+ CreateDirectValueParser(is_displayed));
}
Error* Session::IsElementEnabled(const FrameId& frame_id,
const WebElementId& element,
bool* is_enabled) {
- std::string script = base::StringPrintf(
- "return (%s).apply(null, arguments);", atoms::IS_ENABLED);
- ListValue args;
- args.Append(element.ToValue());
-
- Value* unscoped_result = NULL;
- Error* error = ExecuteScript(frame_id, script, &args, &unscoped_result);
- scoped_ptr<Value> result(unscoped_result);
- if (error)
- return error;
- if (!result->GetAsBoolean(is_enabled))
- return new Error(kUnknownError, "IsEnabled atom returned non-boolean: " +
- JsonStringify(result.get()));
- return NULL;
+ return ExecuteScriptAndParse(frame_id,
+ atoms::IS_ENABLED,
+ "isEnabled",
+ CreateListValueFrom(element),
+ CreateDirectValueParser(is_enabled));
}
Error* Session::SelectOptionElement(const FrameId& frame_id,
const WebElementId& element) {
- ListValue args;
- args.Append(element.ToValue());
- args.Append(Value::CreateBooleanValue(true));
-
- std::string script = base::StringPrintf(
- "return (%s).apply(null, arguments);", atoms::SET_SELECTED);
-
- Value* unscoped_result = NULL;
- Error* error = ExecuteScript(frame_id, script, &args, &unscoped_result);
- scoped_ptr<Value> result(unscoped_result);
- return error;
+ return ExecuteScriptAndParse(frame_id,
+ atoms::SET_SELECTED,
+ "setSelected",
+ CreateListValueFrom(element, true),
+ CreateDirectValueParser(kSkipParsing));
}
Error* Session::GetElementTagName(const FrameId& frame_id,
const WebElementId& element,
std::string* tag_name) {
- ListValue args;
- args.Append(element.ToValue());
-
- std::string script = "return arguments[0].tagName.toLocaleLowerCase();";
-
- Value* unscoped_result = NULL;
- Error* error = ExecuteScript(frame_id, script, &args, &unscoped_result);
- scoped_ptr<Value> result(unscoped_result);
- if (error)
- return error;
- if (!result->GetAsString(tag_name))
- return new Error(kUnknownError, "TagName script returned non-string: " +
- JsonStringify(result.get()));
- return NULL;
+ return ExecuteScriptAndParse(
+ frame_id,
+ "function(elem) { return elem.tagName.toLowerCase() }",
+ "getElementTagName",
+ CreateListValueFrom(element),
+ CreateDirectValueParser(tag_name));
}
Error* Session::GetClickableLocation(const WebElementId& element,
- gfx::Point* location) {
+ Point* location) {
bool is_displayed = false;
Error* error = IsElementDisplayed(
current_target_, element, true /* ignore_opacity */, &is_displayed);
@@ -960,12 +868,13 @@ Error* Session::GetClickableLocation(const WebElementId& element,
if (!is_displayed)
return new Error(kElementNotVisible, "Element must be displayed to click");
- gfx::Rect rect;
+ Rect rect;
error = GetElementFirstClientRect(current_target_, element, &rect);
if (error)
return error;
- error = GetElementRegionInView(element, rect, true /* center */, location);
+ error = GetElementRegionInView(
+ element, rect, true /* center */, location);
if (error)
return error;
location->Offset(rect.width() / 2, rect.height() / 2);
@@ -973,20 +882,13 @@ Error* Session::GetClickableLocation(const WebElementId& element,
}
Error* Session::GetAttribute(const WebElementId& element,
- const std::string& key, Value** value) {
- std::string script = base::StringPrintf(
- "return (%s).apply(null, arguments);", atoms::GET_ATTRIBUTE);
-
- ListValue args;
- args.Append(element.ToValue());
- args.Append(Value::CreateStringValue(key));
-
- Error* error = ExecuteScript(script, &args, value);
- if (error) {
- return error;
- }
-
- return NULL;
+ const std::string& key,
+ Value** value) {
+ return ExecuteScriptAndParse(current_target_,
+ atoms::GET_ATTRIBUTE,
+ "getAttribute",
+ CreateListValueFrom(element, key),
+ CreateDirectValueParser(value));
}
Error* Session::WaitForAllTabsToStopLoading() {
@@ -1040,7 +942,7 @@ bool Session::use_native_events() const {
return use_native_events_;
}
-const gfx::Point& Session::get_mouse_position() const {
+const Point& Session::get_mouse_position() const {
return mouse_position_;
}
@@ -1093,9 +995,9 @@ void Session::TerminateOnSessionThread() {
automation_.reset();
}
-Error* Session::ExecuteScriptAndParseResponse(const FrameId& frame_id,
- const std::string& script,
- Value** script_result) {
+Error* Session::ExecuteScriptAndParseValue(const FrameId& frame_id,
+ const std::string& script,
+ Value** script_result) {
std::string response_json;
Error* error = NULL;
RunSessionTask(NewRunnableMethod(
@@ -1184,31 +1086,43 @@ void Session::SendKeysOnSessionThread(const string16& keys, Error** error) {
Error* Session::SwitchToFrameWithJavaScriptLocatedFrame(
const std::string& script, ListValue* args) {
- Value* unscoped_result = NULL;
- Error* error = ExecuteScript(script, args, &unscoped_result);
- scoped_ptr<Value> result(unscoped_result);
+ class SwitchFrameValueParser : public ValueParser {
+ public:
+ SwitchFrameValueParser(
+ bool* found_frame, WebElementId* frame, std::string* xpath)
+ : found_frame_(found_frame), frame_(frame), xpath_(xpath) { }
+
+ virtual ~SwitchFrameValueParser() { }
+
+ virtual bool Parse(base::Value* value) const OVERRIDE {
+ if (value->IsType(Value::TYPE_NULL)) {
+ *found_frame_ = false;
+ return true;
+ }
+ ListValue* list;
+ if (!value->GetAsList(&list))
+ return false;
+ *found_frame_ = true;
+ return SetFromListValue(list, frame_, xpath_);
+ }
+
+ private:
+ bool* found_frame_;
+ WebElementId* frame_;
+ std::string* xpath_;
+ };
+
+ bool found_frame;
+ WebElementId new_frame_element;
+ std::string xpath;
+ Error* error = ExecuteScriptAndParse(
+ current_target_, script, "switchFrame", args,
+ new SwitchFrameValueParser(&found_frame, &new_frame_element, &xpath));
if (error)
return error;
- ListValue* frame_and_xpath_list;
- if (!result->GetAsList(&frame_and_xpath_list))
+ if (!found_frame)
return new Error(kNoSuchFrame);
- DictionaryValue* element_dict;
- std::string xpath;
- if (!frame_and_xpath_list->GetDictionary(0, &element_dict) ||
- !frame_and_xpath_list->GetString(1, &xpath)) {
- return new Error(
- kUnknownError,
- "Frame finding script did not return correct type: " +
- JsonStringify(frame_and_xpath_list));
- }
- WebElementId new_frame_element(element_dict);
- if (!new_frame_element.is_valid()) {
- return new Error(
- kUnknownError,
- "Frame finding script did not return a frame element: " +
- JsonStringify(element_dict));
- }
frame_elements_.push_back(new_frame_element);
current_target_.frame_path = current_target_.frame_path.Append(xpath);
@@ -1277,38 +1191,27 @@ Error* Session::FindElementsHelper(const FrameId& frame_id,
// Parse the results.
const std::string kInvalidElementDictionaryMessage =
- "Find element script returned invalid element dictionary: " +
+ "findElement script returned invalid element dictionary: " +
JsonStringify(value.get());
- if (value->IsType(Value::TYPE_LIST)) {
- ListValue* element_list = static_cast<ListValue*>(value.get());
+ if (find_one) {
+ WebElementId element;
+ if (!SetFromValue(value.get(), &element))
+ return new Error(kUnknownError, kInvalidElementDictionaryMessage);
+ elements->push_back(element);
+ } else {
+ ListValue* element_list;
+ if (!value->GetAsList(&element_list)) {
+ return new Error(
+ kUnknownError,
+ "findElements script returned unsupported type: " +
+ JsonStringify(value.get()));
+ }
for (size_t i = 0; i < element_list->GetSize(); ++i) {
- DictionaryValue* element_dict = NULL;
- if (!element_list->GetDictionary(i, &element_dict)) {
- return new Error(
- kUnknownError,
- "Find element script returned non-dictionary: " +
- JsonStringify(element_list));
- }
-
- WebElementId element(element_dict);
- if (!element.is_valid()) {
+ WebElementId element;
+ if (!SetFromValue(value.get(), &element))
return new Error(kUnknownError, kInvalidElementDictionaryMessage);
- }
elements->push_back(element);
}
- } else if (value->IsType(Value::TYPE_DICTIONARY)) {
- DictionaryValue* element_dict =
- static_cast<DictionaryValue*>(value.get());
- WebElementId element(element_dict);
- if (!element.is_valid()) {
- return new Error(kUnknownError, kInvalidElementDictionaryMessage);
- }
- elements->push_back(element);
- } else {
- return new Error(
- kUnknownError,
- "Find element script returned unsupported type: " +
- JsonStringify(value.get()));
}
return NULL;
}
@@ -1316,43 +1219,14 @@ Error* Session::FindElementsHelper(const FrameId& frame_id,
Error* Session::GetElementRegionInViewHelper(
const FrameId& frame_id,
const WebElementId& element,
- const gfx::Rect& region,
+ const Rect& region,
bool center,
- gfx::Point* location) {
- std::string jscript = base::StringPrintf(
- "return (%s).apply(null, arguments);", atoms::GET_LOCATION_IN_VIEW);
- ListValue jscript_args;
- jscript_args.Append(element.ToValue());
- jscript_args.Append(Value::CreateBooleanValue(center));
- DictionaryValue* elem_offset_dict = new DictionaryValue();
- elem_offset_dict->SetInteger("left", region.x());
- elem_offset_dict->SetInteger("top", region.y());
- elem_offset_dict->SetInteger("width", region.width());
- elem_offset_dict->SetInteger("height", region.height());
- jscript_args.Append(elem_offset_dict);
- Value* unscoped_value = NULL;
- Error* error = ExecuteScript(frame_id, jscript, &jscript_args,
- &unscoped_value);
- scoped_ptr<Value> value(unscoped_value);
- if (error)
- return error;
- if (!value->IsType(Value::TYPE_DICTIONARY)) {
- return new Error(
- kUnknownError,
- "Location atom returned non-dictionary type: " +
- JsonStringify(value.get()));
- }
- DictionaryValue* loc_dict = static_cast<DictionaryValue*>(value.get());
- int x = 0, y = 0;
- if (!loc_dict->GetInteger("x", &x) ||
- !loc_dict->GetInteger("y", &y)) {
- return new Error(
- kUnknownError,
- "Location atom returned bad coordinate dictionary: " +
- JsonStringify(loc_dict));
- }
- *location = gfx::Point(x, y);
- return NULL;
+ Point* location) {
+ return ExecuteScriptAndParse(frame_id,
+ atoms::GET_LOCATION_IN_VIEW,
+ "getLocationInView",
+ CreateListValueFrom(element, center, region),
+ CreateDirectValueParser(location));
}
Error* Session::GetScreenShot(std::string* png) {

Powered by Google App Engine
This is Rietveld 408576698