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

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

Issue 23526047: Delete old chromedriver code, and remove mongoose webserver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 3 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
« no previous file with comments | « chrome/test/webdriver/webdriver_session.h ('k') | chrome/test/webdriver/webdriver_session_manager.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/test/webdriver/webdriver_session.cc
diff --git a/chrome/test/webdriver/webdriver_session.cc b/chrome/test/webdriver/webdriver_session.cc
deleted file mode 100644
index d60c77a09972065e28a99eadc531fe2908b64af4..0000000000000000000000000000000000000000
--- a/chrome/test/webdriver/webdriver_session.cc
+++ /dev/null
@@ -1,1947 +0,0 @@
-// 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/webdriver/webdriver_session.h"
-
-#include <sstream>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/process/process.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "base/values.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/test/automation/automation_json_requests.h"
-#include "chrome/test/automation/value_conversion_util.h"
-#include "chrome/test/webdriver/webdriver_capabilities_parser.h"
-#include "chrome/test/webdriver/webdriver_error.h"
-#include "chrome/test/webdriver/webdriver_key_converter.h"
-#include "chrome/test/webdriver/webdriver_logging.h"
-#include "chrome/test/webdriver/webdriver_session_manager.h"
-#include "chrome/test/webdriver/webdriver_util.h"
-#include "third_party/webdriver/atoms.h"
-
-using automation::kLeftButton;
-using automation::kMouseDown;
-using automation::kMouseMove;
-using automation::kMouseUp;
-using automation::kNoButton;
-
-namespace webdriver {
-
-namespace {
-// This is the minimum version of chrome that supports the new mouse API.
-const int kNewMouseAPIMinVersion = 1002;
-}
-
-FrameId::FrameId() {}
-
-FrameId::FrameId(const WebViewId& view_id, const FramePath& frame_path)
- : view_id(view_id),
- frame_path(frame_path) {
-}
-
-Session::Session()
- : session_log_(new InMemoryLog()),
- logger_(kAllLogLevel),
- id_(GenerateRandomID()),
- current_target_(FrameId(WebViewId(), FramePath())),
- thread_(id_.c_str()),
- async_script_timeout_(0),
- implicit_wait_(0),
- has_alert_prompt_text_(false),
- sticky_modifiers_(0),
- build_no_(0) {
- SessionManager::GetInstance()->Add(this);
- logger_.AddHandler(session_log_.get());
- if (FileLog::Get())
- logger_.AddHandler(FileLog::Get());
-}
-
-Session::~Session() {
- SessionManager::GetInstance()->Remove(id_);
-}
-
-Error* Session::Init(const base::DictionaryValue* capabilities_dict) {
- if (!thread_.Start()) {
- delete this;
- return new Error(kUnknownError, "Cannot start session thread");
- }
- if (!temp_dir_.CreateUniqueTempDir()) {
- delete this;
- return new Error(
- kUnknownError, "Unable to create temp directory for unpacking");
- }
- logger_.Log(kFineLogLevel,
- "Initializing session with capabilities " +
- JsonStringifyForDisplay(capabilities_dict));
- CapabilitiesParser parser(
- capabilities_dict, temp_dir_.path(), logger_, &capabilities_);
- Error* error = parser.Parse();
- if (error) {
- delete this;
- return error;
- }
- logger_.set_min_log_level(capabilities_.log_levels[LogType::kDriver]);
-
- Automation::BrowserOptions browser_options;
- browser_options.command = capabilities_.command;
- browser_options.channel_id = capabilities_.channel;
- browser_options.detach_process = capabilities_.detach;
- browser_options.user_data_dir = capabilities_.profile;
- browser_options.exclude_switches = capabilities_.exclude_switches;
- if (!capabilities_.no_website_testing_defaults) {
- browser_options.ignore_certificate_errors = true;
- }
- RunSessionTask(base::Bind(
- &Session::InitOnSessionThread,
- base::Unretained(this),
- browser_options,
- &build_no_,
- &error));
- if (!error)
- error = PostBrowserStartInit();
-
- if (error)
- Terminate();
- return error;
-}
-
-Error* Session::BeforeExecuteCommand() {
- Error* error = AfterExecuteCommand();
- if (!error) {
- scoped_ptr<Error> switch_error(SwitchToTopFrameIfCurrentFrameInvalid());
- if (switch_error.get()) {
- std::string text;
- scoped_ptr<Error> alert_error(GetAlertMessage(&text));
- if (alert_error.get()) {
- // Only return a frame checking error if a modal dialog is not present.
- // TODO(kkania): This is ugly. Fix.
- return switch_error.release();
- }
- }
- }
- return error;
-}
-
-Error* Session::AfterExecuteCommand() {
- Error* error = NULL;
- if (!capabilities_.load_async) {
- error = WaitForAllViewsToStopLoading();
- }
- return error;
-}
-
-void Session::Terminate() {
- RunSessionTask(base::Bind(
- &Session::TerminateOnSessionThread,
- base::Unretained(this)));
- delete this;
-}
-
-Error* Session::ExecuteScript(const FrameId& frame_id,
- const std::string& script,
- const base::ListValue* const args,
- base::Value** value) {
- std::string args_as_json;
- base::JSONWriter::Write(static_cast<const base::Value* const>(args),
- &args_as_json);
-
- // Every injected script is fed through the executeScript atom. This atom
- // will catch any errors that are thrown and convert them to the
- // appropriate JSON structure.
- std::string jscript = base::StringPrintf(
- "window.domAutomationController.send((%s).apply(null,"
- "[function(){%s\n},%s,true]));",
- atoms::asString(atoms::EXECUTE_SCRIPT).c_str(), script.c_str(),
- args_as_json.c_str());
-
- return ExecuteScriptAndParseValue(frame_id, jscript, value);
-}
-
-Error* Session::ExecuteScript(const std::string& script,
- const base::ListValue* const args,
- base::Value** value) {
- 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 base::ListValue* args,
- const ValueParser* parser) {
- scoped_ptr<const base::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());
- base::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<base::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 base::ListValue* const args,
- base::Value** value) {
- std::string args_as_json;
- base::JSONWriter::Write(static_cast<const base::Value* const>(args),
- &args_as_json);
-
- int timeout_ms = async_script_timeout();
-
- // Every injected script is fed through the executeScript atom. This atom
- // will catch any errors that are thrown and convert them to the
- // appropriate JSON structure.
- std::string jscript = base::StringPrintf(
- "(%s).apply(null, [function(){%s},%s,%d,%s,true]);",
- atoms::asString(atoms::EXECUTE_ASYNC_SCRIPT).c_str(),
- script.c_str(),
- args_as_json.c_str(),
- timeout_ms,
- "function(result) {window.domAutomationController.send(result);}");
-
- return ExecuteScriptAndParseValue(frame_id, jscript, value);
-}
-
-Error* Session::SendKeys(const ElementId& element, const string16& keys) {
- bool is_displayed = false;
- Error* error = IsElementDisplayed(
- current_target_, element, true /* ignore_opacity */, &is_displayed);
- if (error)
- return error;
- if (!is_displayed)
- return new Error(kElementNotVisible);
-
- bool is_enabled = false;
- error = IsElementEnabled(current_target_, element, &is_enabled);
- if (error)
- return error;
- if (!is_enabled)
- return new Error(kInvalidElementState);
-
- // 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,
- // because this may cause us to lose the current cursor position in the
- // element.
- // Secondly, we focus the target element.
- // Thirdly, if the target element is newly focused and is a text input, we
- // set the cursor position at the end.
- // Fourthly, we check if the new active element is the target element. If not,
- // we throw an error.
- // Additional notes:
- // - |document.activeElement| is the currently focused element, or body if
- // no element is focused
- // - Even if |document.hasFocus()| returns true and the active element is
- // the body, sometimes we still need to focus the body element for send
- // keys to work. Not sure why
- // - You cannot focus a descendant of a content editable node
- // - V8 throws a TypeError when calling setSelectionRange for a non-text
- // input, which still have setSelectionRange defined.
- // TODO(jleyba): Update this to use the correct atom.
- const char* kFocusScript =
- "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) {"
- " try {"
- " elem.setSelectionRange(elem.value.length, elem.value.length);"
- " } catch (error) {"
- " if (!(error instanceof TypeError)) {"
- " throw error;"
- " }"
- " }"
- " }"
- " 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;
-
- RunSessionTask(base::Bind(
- &Session::SendKeysOnSessionThread,
- base::Unretained(this),
- keys,
- true /* release_modifiers */,
- &error));
- return error;
-}
-
-Error* Session::SendKeys(const string16& keys) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Session::SendKeysOnSessionThread,
- base::Unretained(this),
- keys,
- false /* release_modifiers */,
- &error));
- return error;
-}
-
-Error* Session::DragAndDropFilePaths(
- const Point& location,
- const std::vector<base::FilePath::StringType>& paths) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::DragAndDropFilePaths,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- location,
- paths,
- &error));
- return error;
-}
-
-Error* Session::NavigateToURL(const std::string& url) {
- if (!current_target_.view_id.IsTab()) {
- return new Error(kUnknownError,
- "The current target does not support navigation");
- }
- Error* error = NULL;
- if (capabilities_.load_async) {
- RunSessionTask(base::Bind(
- &Automation::NavigateToURLAsync,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- url,
- &error));
- } else {
- RunSessionTask(base::Bind(
- &Automation::NavigateToURL,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- url,
- &error));
- }
- return error;
-}
-
-Error* Session::GoForward() {
- if (!current_target_.view_id.IsTab()) {
- return new Error(kUnknownError,
- "The current target does not support navigation");
- }
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::GoForward,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- &error));
- return error;
-}
-
-Error* Session::GoBack() {
- if (!current_target_.view_id.IsTab()) {
- return new Error(kUnknownError,
- "The current target does not support navigation");
- }
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::GoBack,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- &error));
- return error;
-}
-
-Error* Session::Reload() {
- if (!current_target_.view_id.IsTab()) {
- return new Error(kUnknownError,
- "The current target does not support navigation");
- }
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::Reload,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- &error));
- return error;
-}
-
-Error* Session::GetURL(std::string* url) {
- return ExecuteScriptAndParse(current_target_,
- "function() { return document.URL }",
- "getUrl",
- new base::ListValue(),
- CreateDirectValueParser(url));
-}
-
-Error* Session::GetTitle(std::string* tab_title) {
- const char* kGetTitleScript =
- "function() {"
- " if (document.title)"
- " return document.title;"
- " else"
- " return document.URL;"
- "}";
- return ExecuteScriptAndParse(FrameId(current_target_.view_id, FramePath()),
- kGetTitleScript,
- "getTitle",
- new base::ListValue(),
- CreateDirectValueParser(tab_title));
-}
-
-Error* Session::MouseMoveAndClick(const Point& location,
- automation::MouseButton button) {
- Error* error = NULL;
- if (build_no_ >= kNewMouseAPIMinVersion) {
- std::vector<WebMouseEvent> events;
- events.push_back(CreateWebMouseEvent(kMouseMove, kNoButton, location, 0));
- events.push_back(CreateWebMouseEvent(kMouseDown, button, location, 1));
- events.push_back(CreateWebMouseEvent(kMouseUp, button, location, 1));
- error = ProcessWebMouseEvents(events);
- } else {
- RunSessionTask(base::Bind(
- &Automation::MouseClickDeprecated,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- location,
- button,
- &error));
- }
- if (!error)
- mouse_position_ = location;
- return error;
-}
-
-Error* Session::MouseMove(const Point& location) {
- Error* error = NULL;
- if (build_no_ >= kNewMouseAPIMinVersion) {
- std::vector<WebMouseEvent> events;
- events.push_back(CreateWebMouseEvent(kMouseMove, kNoButton, location, 0));
- error = ProcessWebMouseEvents(events);
- } else {
- RunSessionTask(base::Bind(
- &Automation::MouseMoveDeprecated,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- location,
- &error));
- }
- if (!error)
- mouse_position_ = location;
- return error;
-}
-
-Error* Session::MouseDrag(const Point& start,
- const Point& end) {
- Error* error = NULL;
- if (build_no_ >= kNewMouseAPIMinVersion) {
- std::vector<WebMouseEvent> events;
- events.push_back(CreateWebMouseEvent(kMouseMove, kNoButton, start, 0));
- events.push_back(CreateWebMouseEvent(kMouseDown, kLeftButton, start, 1));
- events.push_back(CreateWebMouseEvent(kMouseMove, kLeftButton, end, 0));
- events.push_back(CreateWebMouseEvent(kMouseUp, kLeftButton, end, 1));
- error = ProcessWebMouseEvents(events);
- } else {
- RunSessionTask(base::Bind(
- &Automation::MouseDragDeprecated,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- start,
- end,
- &error));
- }
- if (!error)
- mouse_position_ = end;
- return error;
-}
-
-Error* Session::MouseClick(automation::MouseButton button) {
- if (build_no_ >= kNewMouseAPIMinVersion) {
- std::vector<WebMouseEvent> events;
- events.push_back(CreateWebMouseEvent(
- kMouseDown, button, mouse_position_, 1));
- events.push_back(CreateWebMouseEvent(
- kMouseUp, button, mouse_position_, 1));
- return ProcessWebMouseEvents(events);
- } else {
- return MouseMoveAndClick(mouse_position_, button);
- }
-}
-
-Error* Session::MouseButtonDown() {
- Error* error = NULL;
- if (build_no_ >= kNewMouseAPIMinVersion) {
- std::vector<WebMouseEvent> events;
- events.push_back(CreateWebMouseEvent(
- kMouseDown, kLeftButton, mouse_position_, 1));
- error = ProcessWebMouseEvents(events);
- } else {
- RunSessionTask(base::Bind(
- &Automation::MouseButtonDownDeprecated,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- mouse_position_,
- &error));
- }
- return error;
-}
-
-Error* Session::MouseButtonUp() {
- Error* error = NULL;
- if (build_no_ >= kNewMouseAPIMinVersion) {
- std::vector<WebMouseEvent> events;
- events.push_back(CreateWebMouseEvent(
- kMouseUp, kLeftButton, mouse_position_, 1));
- error = ProcessWebMouseEvents(events);
- } else {
- RunSessionTask(base::Bind(
- &Automation::MouseButtonUpDeprecated,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- mouse_position_,
- &error));
- }
- return error;
-}
-
-Error* Session::MouseDoubleClick() {
- Error* error = NULL;
- if (build_no_ >= kNewMouseAPIMinVersion) {
- std::vector<WebMouseEvent> events;
- events.push_back(CreateWebMouseEvent(
- kMouseDown, kLeftButton, mouse_position_, 1));
- events.push_back(CreateWebMouseEvent(
- kMouseUp, kLeftButton, mouse_position_, 1));
- events.push_back(CreateWebMouseEvent(
- kMouseDown, kLeftButton, mouse_position_, 2));
- events.push_back(CreateWebMouseEvent(
- kMouseUp, kLeftButton, mouse_position_, 2));
- error = ProcessWebMouseEvents(events);
- } else {
- RunSessionTask(base::Bind(
- &Automation::MouseDoubleClickDeprecated,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- mouse_position_,
- &error));
- }
- return error;
-}
-
-Error* Session::GetCookies(const std::string& url,
- scoped_ptr<base::ListValue>* cookies) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::GetCookies,
- base::Unretained(automation_.get()),
- url,
- cookies,
- &error));
- return error;
-}
-
-Error* Session::DeleteCookie(const std::string& url,
- const std::string& cookie_name) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::DeleteCookie,
- base::Unretained(automation_.get()),
- url,
- cookie_name,
- &error));
- return error;
-}
-
-// Note that when this is called from CookieCommand::ExecutePost then
-// |cookie_dict| is destroyed as soon as the caller finishes. Therefore
-// it is essential that RunSessionTask executes synchronously.
-Error* Session::SetCookie(const std::string& url,
- base::DictionaryValue* cookie_dict) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::SetCookie,
- base::Unretained(automation_.get()),
- url,
- cookie_dict,
- &error));
- return error;
-}
-
-Error* Session::GetViews(std::vector<WebViewInfo>* views) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::GetViews,
- base::Unretained(automation_.get()),
- views,
- &error));
- return error;
-}
-
-Error* Session::SwitchToView(const std::string& id_or_name) {
- Error* error = NULL;
- bool does_exist = false;
-
- WebViewId new_view;
- StringToWebViewId(id_or_name, &new_view);
- if (new_view.IsValid()) {
- RunSessionTask(base::Bind(
- &Automation::DoesViewExist,
- base::Unretained(automation_.get()),
- new_view,
- &does_exist,
- &error));
- if (error)
- return error;
- }
-
- if (!does_exist) {
- // See if any of the tab window names match |name|.
- std::vector<WebViewInfo> views;
- Error* error = GetViews(&views);
- if (error)
- return error;
- for (size_t i = 0; i < views.size(); ++i) {
- if (!views[i].view_id.IsTab())
- continue;
- std::string window_name;
- Error* error = ExecuteScriptAndParse(
- FrameId(views[i].view_id, FramePath()),
- "function() { return window.name; }",
- "getWindowName",
- new base::ListValue(),
- CreateDirectValueParser(&window_name));
- if (error)
- return error;
- if (id_or_name == window_name) {
- new_view = views[i].view_id;
- does_exist = true;
- break;
- }
- }
- }
-
- if (!does_exist)
- return new Error(kNoSuchWindow);
- frame_elements_.clear();
- current_target_ = FrameId(new_view, FramePath());
- return NULL;
-}
-
-Error* Session::SwitchToFrameWithNameOrId(const std::string& name_or_id) {
- std::string script =
- "function(arg) {"
- " var xpath = '(/html/body//iframe|/html/frameset/frame)';"
- " var sub = function(s) { return s.replace(/\\$/g, arg); };"
- " xpath += sub('[@name=\"$\" or @id=\"$\"]');"
- " return document.evaluate(xpath, document, null, "
- " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
- "}";
- return SwitchToFrameWithJavaScriptLocatedFrame(
- script, CreateListValueFrom(name_or_id));
-}
-
-Error* Session::SwitchToFrameWithIndex(int index) {
- // We cannot simply index into window.frames because we need to know the
- // tagName of the frameElement. If child frame N is from another domain, then
- // the following will run afoul of the same origin policy:
- // window.frames[N].frameElement;
- // Instead of indexing window.frames, we use an XPath expression to 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 =
- "function(index) {"
- " var xpathIndex = '[' + (index + 1) + ']';"
- " var xpath = '(/html/body//iframe|/html/frameset/frame)' + "
- " xpathIndex;"
- " return document.evaluate(xpath, document, null, "
- " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
- "}";
- return SwitchToFrameWithJavaScriptLocatedFrame(
- script, CreateListValueFrom(index));
-}
-
-Error* Session::SwitchToFrameWithElement(const ElementId& element) {
- // TODO(jleyba): Extract this, and the other frame switch methods to an atom.
- std::string script =
- "function(elem) {"
- " if (elem.nodeType != 1 || !/^i?frame$/i.test(elem.tagName)) {"
- " console.error('Element is not a frame');"
- " return null;"
- " }"
- " for (var i = 0; i < window.frames.length; i++) {"
- " if (elem.contentWindow == window.frames[i]) {"
- " return elem;"
- " }"
- " }"
- " console.info('Frame is not connected to this DOM tree');"
- " return null;"
- "}";
- return SwitchToFrameWithJavaScriptLocatedFrame(
- script, CreateListValueFrom(element));
-}
-
-void Session::SwitchToTopFrame() {
- frame_elements_.clear();
- current_target_.frame_path = FramePath();
-}
-
-Error* Session::SwitchToTopFrameIfCurrentFrameInvalid() {
- std::vector<std::string> components;
- current_target_.frame_path.GetComponents(&components);
- if (frame_elements_.size() != components.size()) {
- return new Error(kUnknownError,
- "Frame element vector out of sync with frame path");
- }
- FramePath frame_path;
- // Start from the root path and check that each frame element that makes
- // up the current frame target is valid by executing an empty script.
- // This code should not execute script in any frame before making sure the
- // 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_.view_id, frame_path);
- 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()) {
- return error.release();
- }
- frame_path = frame_path.Append(components[i]);
- }
- return NULL;
-}
-
-Error* Session::CloseWindow() {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::CloseView,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- &error));
-
- if (!error) {
- std::vector<WebViewInfo> views;
- scoped_ptr<Error> error(GetViews(&views));
- if (error.get() || views.empty()) {
- // The automation connection will soon be closed, if not already,
- // because we supposedly just closed the last window. Terminate the
- // session.
- // TODO(kkania): This will cause us problems if GetWindowIds fails for a
- // reason other than the channel is disconnected. Look into having
- // |GetWindowIds| tell us if it just closed the last window.
- Terminate();
- }
- }
- return error;
-}
-
-Error* Session::GetWindowBounds(const WebViewId& window, Rect* bounds) {
- const char* kGetWindowBoundsScript =
- "function() {"
- " return {"
- " 'left': window.screenX,"
- " 'top': window.screenY,"
- " 'width': window.outerWidth,"
- " 'height': window.outerHeight"
- " }"
- "}";
- return ExecuteScriptAndParse(
- FrameId(window, FramePath()),
- kGetWindowBoundsScript,
- "getWindowBoundsScript",
- new base::ListValue(),
- CreateDirectValueParser(bounds));
-}
-
-Error* Session::SetWindowBounds(
- const WebViewId& window,
- const Rect& bounds) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::SetViewBounds,
- base::Unretained(automation_.get()),
- window,
- bounds,
- &error));
- return error;
-}
-
-Error* Session::MaximizeWindow(const WebViewId& window) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::MaximizeView,
- base::Unretained(automation_.get()),
- window,
- &error));
- return error;
-}
-
-Error* Session::GetAlertMessage(std::string* text) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::GetAppModalDialogMessage,
- base::Unretained(automation_.get()),
- text,
- &error));
- return error;
-}
-
-Error* Session::SetAlertPromptText(const std::string& alert_prompt_text) {
- std::string message_text;
- // Only set the alert prompt text if an alert is actually active.
- Error* error = GetAlertMessage(&message_text);
- if (!error) {
- has_alert_prompt_text_ = true;
- alert_prompt_text_ = alert_prompt_text;
- }
- return error;
-}
-
-Error* Session::AcceptOrDismissAlert(bool accept) {
- Error* error = NULL;
- if (accept && has_alert_prompt_text_) {
- RunSessionTask(base::Bind(
- &Automation::AcceptPromptAppModalDialog,
- base::Unretained(automation_.get()),
- alert_prompt_text_,
- &error));
- } else {
- RunSessionTask(base::Bind(
- &Automation::AcceptOrDismissAppModalDialog,
- base::Unretained(automation_.get()),
- accept,
- &error));
- }
- has_alert_prompt_text_ = false;
- return error;
-}
-
-std::string Session::GetBrowserVersion() {
- std::string version;
- RunSessionTask(base::Bind(
- &Automation::GetBrowserVersion,
- base::Unretained(automation_.get()),
- &version));
- return version;
-}
-
-Error* Session::CompareBrowserVersion(int client_build_no,
- int client_patch_no,
- bool* is_newer_or_equal) {
- std::string version = GetBrowserVersion();
- std::vector<std::string> split_version;
- base::SplitString(version, '.', &split_version);
- if (split_version.size() != 4) {
- return new Error(
- kUnknownError, "Browser version has unrecognized format: " + version);
- }
- int build_no, patch_no;
- if (!base::StringToInt(split_version[2], &build_no) ||
- !base::StringToInt(split_version[3], &patch_no)) {
- return new Error(
- kUnknownError, "Browser version has unrecognized format: " + version);
- }
- if (build_no < client_build_no)
- *is_newer_or_equal = false;
- else if (build_no > client_build_no)
- *is_newer_or_equal = true;
- else
- *is_newer_or_equal = patch_no >= client_patch_no;
- return NULL;
-}
-
-Error* Session::FindElement(const FrameId& frame_id,
- const ElementId& root_element,
- const std::string& locator,
- const std::string& query,
- ElementId* element) {
- std::vector<ElementId> elements;
- Error* error = FindElementsHelper(
- frame_id, root_element, locator, query, true, &elements);
- if (!error)
- *element = elements[0];
- return error;
-}
-
-Error* Session::FindElements(const FrameId& frame_id,
- const ElementId& root_element,
- const std::string& locator,
- const std::string& query,
- std::vector<ElementId>* elements) {
- return FindElementsHelper(
- frame_id, root_element, locator, query, false, elements);
-}
-
-Error* Session::GetElementLocationInView(
- const ElementId& element,
- Point* location) {
- Size size;
- Error* error = GetElementSize(current_target_, element, &size);
- if (error)
- return error;
- return GetElementRegionInView(
- element, Rect(Point(0, 0), size),
- false /* center */, false /* verify_clickable_at_middle */, location);
-}
-
-Error* Session::GetElementRegionInView(
- const ElementId& element,
- const Rect& region,
- bool center,
- bool verify_clickable_at_middle,
- Point* location) {
- CHECK(element.is_valid());
-
- Point region_offset = region.origin();
- Size region_size = region.size();
- Error* error = GetElementRegionInViewHelper(
- current_target_, element, region, center, verify_clickable_at_middle,
- &region_offset);
- if (error)
- return error;
-
- for (FramePath frame_path = current_target_.frame_path;
- frame_path.IsSubframe();
- frame_path = frame_path.Parent()) {
- // Find the frame element for the current frame path.
- FrameId frame_id(current_target_.view_id, frame_path.Parent());
- ElementId frame_element;
- error = FindElement(frame_id,
- ElementId(std::string()),
- LocatorType::kXpath,
- frame_path.BaseName().value(),
- &frame_element);
- if (error) {
- std::string context = base::StringPrintf(
- "Could not find frame element (%s) in frame (%s)",
- frame_path.BaseName().value().c_str(),
- frame_path.Parent().value().c_str());
- error->AddDetails(context);
- return error;
- }
- // Modify |region_offset| by the frame's border.
- int border_left, border_top;
- error = GetElementBorder(
- frame_id, frame_element, &border_left, &border_top);
- if (error)
- return error;
- region_offset.Offset(border_left, border_top);
-
- error = GetElementRegionInViewHelper(
- frame_id, frame_element, Rect(region_offset, region_size),
- center, verify_clickable_at_middle, &region_offset);
- if (error)
- return error;
- }
- *location = region_offset;
- return NULL;
-}
-
-Error* Session::GetElementSize(const FrameId& frame_id,
- const ElementId& element,
- Size* size) {
- return ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::GET_SIZE),
- "getSize",
- CreateListValueFrom(element),
- CreateDirectValueParser(size));
-}
-
-Error* Session::GetElementFirstClientRect(const FrameId& frame_id,
- const ElementId& element,
- Rect* rect) {
- return ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::GET_FIRST_CLIENT_RECT),
- "getFirstClientRect",
- CreateListValueFrom(element),
- CreateDirectValueParser(rect));
-}
-
-Error* Session::GetElementEffectiveStyle(
- const FrameId& frame_id,
- const ElementId& element,
- const std::string& prop,
- std::string* value) {
- return ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::GET_EFFECTIVE_STYLE),
- "getEffectiveStyle",
- CreateListValueFrom(element, prop),
- CreateDirectValueParser(value));
-}
-
-Error* Session::GetElementBorder(const FrameId& frame_id,
- const ElementId& element,
- int* border_left,
- int* border_top) {
- std::string border_left_str, border_top_str;
- Error* error = GetElementEffectiveStyle(
- frame_id, element, "border-left-width", &border_left_str);
- if (error)
- return error;
- error = GetElementEffectiveStyle(
- frame_id, element, "border-top-width", &border_top_str);
- if (error)
- return error;
-
- base::StringToInt(border_left_str, border_left);
- base::StringToInt(border_top_str, border_top);
- return NULL;
-}
-
-Error* Session::IsElementDisplayed(const FrameId& frame_id,
- const ElementId& element,
- bool ignore_opacity,
- bool* is_displayed) {
- return ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::IS_DISPLAYED),
- "isDisplayed",
- CreateListValueFrom(element, ignore_opacity),
- CreateDirectValueParser(is_displayed));
-}
-
-Error* Session::IsElementEnabled(const FrameId& frame_id,
- const ElementId& element,
- bool* is_enabled) {
- return ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::IS_ENABLED),
- "isEnabled",
- CreateListValueFrom(element),
- CreateDirectValueParser(is_enabled));
-}
-
-Error* Session::IsOptionElementSelected(const FrameId& frame_id,
- const ElementId& element,
- bool* is_selected) {
- return ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::IS_SELECTED),
- "isSelected",
- CreateListValueFrom(element),
- CreateDirectValueParser(is_selected));
-}
-
-Error* Session::SetOptionElementSelected(const FrameId& frame_id,
- const ElementId& element,
- bool selected) {
- // This wrapper ensures the script is started successfully and
- // allows for an alert to happen when the option selection occurs.
- // See selenium bug 2671.
- const char kSetSelectedWrapper[] =
- "var args = [].slice.apply(arguments);"
- "args[args.length - 1]();"
- "return (%s).apply(null, args.slice(0, args.length - 1));";
- base::Value* value = NULL;
- Error* error = ExecuteAsyncScript(
- frame_id,
- base::StringPrintf(kSetSelectedWrapper,
- atoms::asString(atoms::CLICK).c_str()),
- CreateListValueFrom(element, selected),
- &value);
- scoped_ptr<base::Value> scoped_value(value);
- return error;
-}
-
-Error* Session::ToggleOptionElement(const FrameId& frame_id,
- const ElementId& element) {
- bool is_selected;
- Error* error = IsOptionElementSelected(frame_id, element, &is_selected);
- if (error)
- return error;
-
- return SetOptionElementSelected(frame_id, element, !is_selected);
-}
-
-Error* Session::GetElementTagName(const FrameId& frame_id,
- const ElementId& element,
- std::string* tag_name) {
- return ExecuteScriptAndParse(
- frame_id,
- "function(elem) { return elem.tagName.toLowerCase() }",
- "getElementTagName",
- CreateListValueFrom(element),
- CreateDirectValueParser(tag_name));
-}
-
-Error* Session::GetClickableLocation(const ElementId& element,
- Point* location) {
- bool is_displayed = false;
- Error* error = IsElementDisplayed(
- current_target_, element, true /* ignore_opacity */, &is_displayed);
- if (error)
- return error;
- if (!is_displayed)
- return new Error(kElementNotVisible, "Element must be displayed to click");
-
- // We try 3 methods to determine clickable location. This mostly follows
- // what FirefoxDriver does. Try the first client rect, then the bounding
- // client rect, and lastly the size of the element (via closure).
- // SVG is one case that doesn't have a first client rect.
- Rect rect;
- scoped_ptr<Error> ignore_error(
- GetElementFirstClientRect(current_target_, element, &rect));
- if (ignore_error.get()) {
- Rect client_rect;
- ignore_error.reset(ExecuteScriptAndParse(
- current_target_,
- "function(elem) { return elem.getBoundingClientRect() }",
- "getBoundingClientRect",
- CreateListValueFrom(element),
- CreateDirectValueParser(&client_rect)));
- rect = Rect(0, 0, client_rect.width(), client_rect.height());
- }
- if (ignore_error.get()) {
- Size size;
- ignore_error.reset(GetElementSize(current_target_, element, &size));
- rect = Rect(0, 0, size.width(), size.height());
- }
- if (ignore_error.get()) {
- return new Error(kUnknownError,
- "Unable to determine clickable location of element");
- }
-
- error = GetElementRegionInView(
- element, rect, true /* center */, true /* verify_clickable_at_middle */,
- location);
- if (error)
- return error;
- location->Offset(rect.width() / 2, rect.height() / 2);
- return NULL;
-}
-
-Error* Session::GetAttribute(const ElementId& element,
- const std::string& key,
- base::Value** value) {
- return ExecuteScriptAndParse(
- current_target_,
- atoms::asString(atoms::GET_ATTRIBUTE),
- "getAttribute",
- CreateListValueFrom(element, key),
- CreateDirectValueParser(value));
-}
-
-Error* Session::WaitForAllViewsToStopLoading() {
- if (!automation_.get())
- return NULL;
-
- logger_.Log(kFinerLogLevel, "Waiting for all views to stop loading...");
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::WaitForAllViewsToStopLoading,
- base::Unretained(automation_.get()),
- &error));
- logger_.Log(kFinerLogLevel, "Done waiting for all views to stop loading");
- return error;
-}
-
-Error* Session::InstallExtension(
- const base::FilePath& path, std::string* extension_id) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::InstallExtension,
- base::Unretained(automation_.get()),
- path,
- extension_id,
- &error));
- return error;
-}
-
-Error* Session::GetExtensionsInfo(base::ListValue* extensions_list) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::GetExtensionsInfo,
- base::Unretained(automation_.get()),
- extensions_list,
- &error));
- return error;
-}
-
-Error* Session::IsPageActionVisible(
- const WebViewId& tab_id,
- const std::string& extension_id,
- bool* is_visible) {
- if (!tab_id.IsTab()) {
- return new Error(
- kUnknownError,
- "The current target does not support page actions. Switch to a tab.");
- }
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::IsPageActionVisible,
- base::Unretained(automation_.get()),
- tab_id,
- extension_id,
- is_visible,
- &error));
- return error;
-}
-
-Error* Session::SetExtensionState(
- const std::string& extension_id, bool enable) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::SetExtensionState,
- base::Unretained(automation_.get()),
- extension_id,
- enable,
- &error));
- return error;
-}
-
-Error* Session::ClickExtensionButton(
- const std::string& extension_id, bool browser_action) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::ClickExtensionButton,
- base::Unretained(automation_.get()),
- extension_id,
- browser_action,
- &error));
- return error;
-}
-
-Error* Session::UninstallExtension(const std::string& extension_id) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::UninstallExtension,
- base::Unretained(automation_.get()),
- extension_id,
- &error));
- return error;
-}
-
-Error* Session::SetPreference(
- const std::string& pref,
- bool is_user_pref,
- base::Value* value) {
- Error* error = NULL;
- if (is_user_pref) {
- RunSessionTask(base::Bind(
- &Automation::SetPreference,
- base::Unretained(automation_.get()),
- pref,
- value,
- &error));
- if (error)
- error->AddDetails("Failed to set user pref '" + pref + "'");
- } else {
- RunSessionTask(base::Bind(
- &Automation::SetLocalStatePreference,
- base::Unretained(automation_.get()),
- pref,
- value,
- &error));
- if (error)
- error->AddDetails("Failed to set local state pref '" + pref + "'");
- }
- return error;
-}
-
-base::ListValue* Session::GetLog() const {
- return session_log_->entries_list()->DeepCopy();
-}
-
-Error* Session::GetBrowserConnectionState(bool* online) {
- return ExecuteScriptAndParse(
- current_target_,
- atoms::asString(atoms::IS_ONLINE),
- "isOnline",
- new base::ListValue(),
- CreateDirectValueParser(online));
-}
-
-Error* Session::GetAppCacheStatus(int* status) {
- return ExecuteScriptAndParse(
- current_target_,
- atoms::asString(atoms::GET_APPCACHE_STATUS),
- "getAppcacheStatus",
- new base::ListValue(),
- CreateDirectValueParser(status));
-}
-
-Error* Session::GetStorageSize(StorageType type, int* size) {
- std::string js = atoms::asString(
- type == kLocalStorageType ? atoms::GET_LOCAL_STORAGE_SIZE
- : atoms::GET_SESSION_STORAGE_SIZE);
- return ExecuteScriptAndParse(
- current_target_,
- js,
- "getStorageSize",
- new base::ListValue(),
- CreateDirectValueParser(size));
-}
-
-Error* Session::SetStorageItem(StorageType type,
- const std::string& key,
- const std::string& value) {
- std::string js = atoms::asString(
- type == kLocalStorageType ? atoms::SET_LOCAL_STORAGE_ITEM
- : atoms::SET_SESSION_STORAGE_ITEM);
- return ExecuteScriptAndParse(
- current_target_,
- js,
- "setStorageItem",
- CreateListValueFrom(key, value),
- CreateDirectValueParser(kSkipParsing));
-}
-
-Error* Session::ClearStorage(StorageType type) {
- std::string js = atoms::asString(
- type == kLocalStorageType ? atoms::CLEAR_LOCAL_STORAGE
- : atoms::CLEAR_SESSION_STORAGE);
- return ExecuteScriptAndParse(
- current_target_,
- js,
- "clearStorage",
- new base::ListValue(),
- CreateDirectValueParser(kSkipParsing));
-}
-
-Error* Session::GetStorageKeys(StorageType type, base::ListValue** keys) {
- std::string js = atoms::asString(
- type == kLocalStorageType ? atoms::GET_LOCAL_STORAGE_KEYS
- : atoms::GET_SESSION_STORAGE_KEYS);
- return ExecuteScriptAndParse(
- current_target_,
- js,
- "getStorageKeys",
- new base::ListValue(),
- CreateDirectValueParser(keys));
-}
-
-Error* Session::GetStorageItem(StorageType type,
- const std::string& key,
- std::string* value) {
- std::string js = atoms::asString(
- type == kLocalStorageType ? atoms::GET_LOCAL_STORAGE_ITEM
- : atoms::GET_SESSION_STORAGE_ITEM);
- return ExecuteScriptAndParse(
- current_target_,
- js,
- "getStorageItem",
- CreateListValueFrom(key),
- CreateDirectValueParser(value));
-}
-
-Error* Session::RemoveStorageItem(StorageType type,
- const std::string& key,
- std::string* value) {
- std::string js = atoms::asString(
- type == kLocalStorageType ? atoms::REMOVE_LOCAL_STORAGE_ITEM
- : atoms::REMOVE_SESSION_STORAGE_ITEM);
- return ExecuteScriptAndParse(
- current_target_,
- js,
- "removeStorageItem",
- CreateListValueFrom(key),
- CreateDirectValueParser(value));
-}
-
-Error* Session::GetGeolocation(
- scoped_ptr<base::DictionaryValue>* geolocation) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::GetGeolocation,
- base::Unretained(automation_.get()),
- geolocation,
- &error));
- return error;
-}
-
-Error* Session::OverrideGeolocation(const base::DictionaryValue* geolocation) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::OverrideGeolocation,
- base::Unretained(automation_.get()),
- geolocation,
- &error));
- return error;
-}
-
-const std::string& Session::id() const {
- return id_;
-}
-
-const FrameId& Session::current_target() const {
- return current_target_;
-}
-
-void Session::set_async_script_timeout(int timeout_ms) {
- async_script_timeout_ = timeout_ms;
-}
-
-int Session::async_script_timeout() const {
- return async_script_timeout_;
-}
-
-void Session::set_implicit_wait(int timeout_ms) {
- implicit_wait_ = timeout_ms;
-}
-
-int Session::implicit_wait() const {
- return implicit_wait_;
-}
-
-const Point& Session::get_mouse_position() const {
- return mouse_position_;
-}
-
-const Logger& Session::logger() const {
- return logger_;
-}
-
-const base::FilePath& Session::temp_dir() const {
- return temp_dir_.path();
-}
-
-const Capabilities& Session::capabilities() const {
- return capabilities_;
-}
-
-void Session::RunSessionTask(const base::Closure& task) {
- base::WaitableEvent done_event(false, false);
- thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
- &Session::RunClosureOnSessionThread,
- base::Unretained(this),
- task,
- &done_event));
- // See SetCookie for why it is essential that we wait here.
- done_event.Wait();
-}
-
-void Session::RunClosureOnSessionThread(const base::Closure& task,
- base::WaitableEvent* done_event) {
- task.Run();
- done_event->Signal();
-}
-
-void Session::InitOnSessionThread(const Automation::BrowserOptions& options,
- int* build_no,
- Error** error) {
- automation_.reset(new Automation(logger_));
- automation_->Init(options, build_no, error);
- if (*error)
- return;
-
- std::vector<WebViewInfo> views;
- automation_->GetViews(&views, error);
- if (*error)
- return;
- if (views.empty()) {
- *error = new Error(kUnknownError, "No view ids after initialization");
- return;
- }
- current_target_ = FrameId(views[0].view_id, FramePath());
-}
-
-void Session::TerminateOnSessionThread() {
- if (automation_.get())
- automation_->Terminate();
- automation_.reset();
-}
-
-Error* Session::ExecuteScriptAndParseValue(const FrameId& frame_id,
- const std::string& script,
- base::Value** script_result) {
- std::string response_json;
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::ExecuteScript,
- base::Unretained(automation_.get()),
- frame_id.view_id,
- frame_id.frame_path,
- script,
- &response_json,
- &error));
- if (error)
- return error;
-
- scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
- response_json, base::JSON_ALLOW_TRAILING_COMMAS, NULL, NULL));
- if (!value.get())
- return new Error(kUnknownError, "Failed to parse script result");
- if (value->GetType() != base::Value::TYPE_DICTIONARY)
- return new Error(kUnknownError, "Execute script returned non-dict: " +
- JsonStringify(value.get()));
- base::DictionaryValue* result_dict =
- static_cast<base::DictionaryValue*>(value.get());
-
- int status;
- if (!result_dict->GetInteger("status", &status))
- return new Error(kUnknownError, "Execute script did not return status: " +
- JsonStringify(result_dict));
- ErrorCode code = static_cast<ErrorCode>(status);
- if (code != kSuccess) {
- base::DictionaryValue* error_dict;
- std::string error_msg;
- if (result_dict->GetDictionary("value", &error_dict))
- error_dict->GetString("message", &error_msg);
- if (error_msg.empty())
- error_msg = "Script failed with error code: " + base::IntToString(code);
- return new Error(code, error_msg);
- }
-
- base::Value* tmp;
- if (result_dict->Get("value", &tmp)) {
- *script_result= tmp->DeepCopy();
- } else {
- // "value" was not defined in the returned dictionary; set to null.
- *script_result= base::Value::CreateNullValue();
- }
- return NULL;
-}
-
-void Session::SendKeysOnSessionThread(const string16& keys,
- bool release_modifiers, Error** error) {
- std::vector<WebKeyEvent> key_events;
- std::string error_msg;
- if (!ConvertKeysToWebKeyEvents(keys, logger_, release_modifiers,
- &sticky_modifiers_, &key_events, &error_msg)) {
- *error = new Error(kUnknownError, error_msg);
- return;
- }
- for (size_t i = 0; i < key_events.size(); ++i) {
- automation_->SendWebKeyEvent(
- current_target_.view_id,
- key_events[i], error);
- if (*error) {
- std::string details = base::StringPrintf(
- "Failed to send key event. Event details:\n"
- "Type: %d, KeyCode: %d, UnmodifiedText: %s, ModifiedText: %s, "
- "Modifiers: %d",
- key_events[i].type,
- key_events[i].key_code,
- key_events[i].unmodified_text.c_str(),
- key_events[i].modified_text.c_str(),
- key_events[i].modifiers);
- (*error)->AddDetails(details);
- return;
- }
- }
-}
-
-Error* Session::ProcessWebMouseEvents(
- const std::vector<WebMouseEvent>& events) {
- for (size_t i = 0; i < events.size(); ++i) {
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::SendWebMouseEvent,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- events[i],
- &error));
- if (error)
- return error;
- mouse_position_ = Point(events[i].x, events[i].y);
- }
- return NULL;
-}
-
-WebMouseEvent Session::CreateWebMouseEvent(
- automation::MouseEventType type,
- automation::MouseButton button,
- const Point& point,
- int click_count) {
- return WebMouseEvent(type, button, point.rounded_x(), point.rounded_y(),
- click_count, sticky_modifiers_);
-}
-
-Error* Session::SwitchToFrameWithJavaScriptLocatedFrame(
- const std::string& script, base::ListValue* args) {
- class SwitchFrameValueParser : public ValueParser {
- public:
- SwitchFrameValueParser(
- bool* found_frame, ElementId* frame)
- : found_frame_(found_frame), frame_(frame) { }
-
- virtual ~SwitchFrameValueParser() { }
-
- virtual bool Parse(base::Value* value) const OVERRIDE {
- if (value->IsType(base::Value::TYPE_NULL)) {
- *found_frame_ = false;
- return true;
- }
- ElementId id(value);
- if (!id.is_valid()) {
- return false;
- }
- *frame_ = id;
- *found_frame_ = true;
- return true;
- }
-
- private:
- bool* found_frame_;
- ElementId* frame_;
- };
-
- bool found_frame;
- ElementId new_frame_element;
- Error* error = ExecuteScriptAndParse(
- current_target_, script, "switchFrame", args,
- new SwitchFrameValueParser(&found_frame, &new_frame_element));
- if (error)
- return error;
-
- if (!found_frame)
- return new Error(kNoSuchFrame);
-
- std::string frame_id = GenerateRandomID();
- error = ExecuteScriptAndParse(
- current_target_,
- "function(elem, id) { elem.setAttribute('wd_frame_id_', id); }",
- "setFrameId",
- CreateListValueFrom(new_frame_element, frame_id),
- CreateDirectValueParser(kSkipParsing));
- if (error)
- return error;
-
- frame_elements_.push_back(new_frame_element);
- current_target_.frame_path = current_target_.frame_path.Append(
- base::StringPrintf("//*[@wd_frame_id_ = '%s']", frame_id.c_str()));
- return NULL;
-}
-
-Error* Session::FindElementsHelper(const FrameId& frame_id,
- const ElementId& root_element,
- const std::string& locator,
- const std::string& query,
- bool find_one,
- std::vector<ElementId>* elements) {
- CHECK(root_element.is_valid());
- base::Time start_time = base::Time::Now();
- while (true) {
- std::vector<ElementId> temp_elements;
- Error* error = ExecuteFindElementScriptAndParse(
- frame_id, root_element, locator, query, find_one, &temp_elements);
- if (error)
- return error;
-
- if (temp_elements.size() > 0u) {
- elements->swap(temp_elements);
- break;
- }
-
- if ((base::Time::Now() - start_time).InMilliseconds() > implicit_wait_) {
- if (find_one)
- return new Error(kNoSuchElement);
- break;
- }
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
- }
- return NULL;
-}
-
-Error* Session::ExecuteFindElementScriptAndParse(
- const FrameId& frame_id,
- const ElementId& root_element,
- const std::string& locator,
- const std::string& query,
- bool find_one,
- std::vector<ElementId>* elements) {
- CHECK(root_element.is_valid());
-
- class FindElementsParser : public ValueParser {
- public:
- explicit FindElementsParser(std::vector<ElementId>* elements)
- : elements_(elements) { }
-
- virtual ~FindElementsParser() { }
-
- virtual bool Parse(base::Value* value) const OVERRIDE {
- if (!value->IsType(base::Value::TYPE_LIST))
- return false;
- base::ListValue* list = static_cast<base::ListValue*>(value);
- for (size_t i = 0; i < list->GetSize(); ++i) {
- ElementId element;
- base::Value* element_value = NULL;
- if (!list->Get(i, &element_value))
- return false;
- if (!SetFromValue(element_value, &element))
- return false;
- elements_->push_back(element);
- }
- return true;
- }
- private:
- std::vector<ElementId>* elements_;
- };
-
- class FindElementParser : public ValueParser {
- public:
- explicit FindElementParser(std::vector<ElementId>* elements)
- : elements_(elements) { }
-
- virtual ~FindElementParser() { }
-
- virtual bool Parse(base::Value* value) const OVERRIDE {
- if (value->IsType(base::Value::TYPE_NULL))
- return true;
- ElementId element;
- bool set = SetFromValue(value, &element);
- if (set)
- elements_->push_back(element);
- return set;
- }
- private:
- std::vector<ElementId>* elements_;
- };
-
- base::DictionaryValue locator_dict;
- locator_dict.SetString(locator, query);
- std::vector<ElementId> temp_elements;
- Error* error = NULL;
- if (find_one) {
- error = ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::FIND_ELEMENT),
- "findElement",
- CreateListValueFrom(&locator_dict, root_element),
- new FindElementParser(&temp_elements));
- } else {
- error = ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::FIND_ELEMENTS),
- "findElements",
- CreateListValueFrom(&locator_dict, root_element),
- new FindElementsParser(&temp_elements));
- }
- if (!error)
- elements->swap(temp_elements);
- return error;
-}
-
-Error* Session::VerifyElementIsClickable(
- const FrameId& frame_id,
- const ElementId& element,
- const Point& location) {
- class IsElementClickableParser : public ValueParser {
- public:
- IsElementClickableParser(bool* clickable, std::string* message)
- : clickable_(clickable), message_(message) { }
-
- virtual ~IsElementClickableParser() { }
-
- virtual bool Parse(base::Value* value) const OVERRIDE {
- if (!value->IsType(base::Value::TYPE_DICTIONARY))
- return false;
- base::DictionaryValue* dict = static_cast<base::DictionaryValue*>(value);
- dict->GetString("message", message_);
- return dict->GetBoolean("clickable", clickable_);
- }
-
- private:
- bool* clickable_;
- std::string* message_;
- };
-
- bool clickable;
- std::string message;
- Error* error = ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::IS_ELEMENT_CLICKABLE),
- "isElementClickable",
- CreateListValueFrom(element, location),
- new IsElementClickableParser(&clickable, &message));
- if (error)
- return error;
-
- if (!clickable) {
- if (message.empty())
- message = "element is not clickable";
- return new Error(kUnknownError, message);
- }
- if (message.length()) {
- logger_.Log(kWarningLogLevel, message);
- }
- return NULL;
-}
-
-Error* Session::GetElementRegionInViewHelper(
- const FrameId& frame_id,
- const ElementId& element,
- const Rect& region,
- bool center,
- bool verify_clickable_at_middle,
- Point* location) {
- Point temp_location;
- Error* error = ExecuteScriptAndParse(
- frame_id,
- atoms::asString(atoms::GET_LOCATION_IN_VIEW),
- "getLocationInView",
- CreateListValueFrom(element, center, region),
- CreateDirectValueParser(&temp_location));
-
- if (verify_clickable_at_middle) {
- Point middle_point = temp_location;
- middle_point.Offset(region.width() / 2, region.height() / 2);
- error = VerifyElementIsClickable(frame_id, element, middle_point);
- if (error)
- return error;
- }
- *location = temp_location;
- return NULL;
-}
-
-Error* Session::GetScreenShot(std::string* png) {
- if (!current_target_.view_id.IsTab()) {
- return new Error(kUnknownError,
- "The current target does not support screenshot");
- }
- Error* error = NULL;
- base::ScopedTempDir screenshots_dir;
- if (!screenshots_dir.CreateUniqueTempDir()) {
- return new Error(kUnknownError,
- "Could not create temp directory for screenshot");
- }
-
- base::FilePath path = screenshots_dir.path().AppendASCII("screen");
- RunSessionTask(base::Bind(
- &Automation::CaptureEntirePageAsPNG,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- path,
- &error));
- if (error)
- return error;
- if (!base::ReadFileToString(path, png))
- return new Error(kUnknownError, "Could not read screenshot file");
- return NULL;
-}
-
-#if !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
-Error* Session::HeapProfilerDump(const std::string& reason) {
- // TODO(dmikurube): Support browser processes.
- Error* error = NULL;
- RunSessionTask(base::Bind(
- &Automation::HeapProfilerDump,
- base::Unretained(automation_.get()),
- current_target_.view_id,
- reason,
- &error));
- return error;
-}
-#endif // !defined(NO_TCMALLOC) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
-
-Error* Session::PostBrowserStartInit() {
- Error* error = NULL;
- if (!capabilities_.no_website_testing_defaults)
- error = InitForWebsiteTesting();
- if (!error)
- error = SetPrefs();
- if (error)
- return error;
-
- // Install extensions.
- for (size_t i = 0; i < capabilities_.extensions.size(); ++i) {
- std::string extension_id;
- error = InstallExtension(capabilities_.extensions[i], &extension_id);
- if (error)
- return error;
- }
- return NULL;
-}
-
-Error* Session::InitForWebsiteTesting() {
- bool has_prefs_api = false;
- // Don't set these prefs for Chrome 14 and below.
- // TODO(kkania): Remove this when Chrome 14 is unsupported.
- Error* error = CompareBrowserVersion(874, 0, &has_prefs_api);
- if (error || !has_prefs_api)
- return error;
-
- // Disable checking for SSL certificate revocation.
- error = SetPreference(
- "ssl.rev_checking.enabled",
- false /* is_user_pref */,
- new base::FundamentalValue(false));
- if (error)
- return error;
-
- // Allow content by default.
- // Media-stream cannot be enabled by default; we must specify
- // particular host patterns and devices.
- base::DictionaryValue* devices = new base::DictionaryValue();
- devices->SetString("audio", "Default");
- devices->SetString("video", "Default");
- base::DictionaryValue* content_settings = new base::DictionaryValue();
- content_settings->Set("media-stream", devices);
- base::DictionaryValue* pattern_pairs = new base::DictionaryValue();
- pattern_pairs->Set("https://*,*", content_settings);
- error = SetPreference(
- "profile.content_settings.pattern_pairs",
- true /* is_user_pref */,
- pattern_pairs);
- if (error)
- return error;
- const int kAllowContent = 1;
- base::DictionaryValue* default_content_settings = new base::DictionaryValue();
- default_content_settings->SetInteger("geolocation", kAllowContent);
- default_content_settings->SetInteger("mouselock", kAllowContent);
- default_content_settings->SetInteger("notifications", kAllowContent);
- default_content_settings->SetInteger("popups", kAllowContent);
- return SetPreference(
- "profile.default_content_settings",
- true /* is_user_pref */,
- default_content_settings);
-}
-
-Error* Session::SetPrefs() {
- for (base::DictionaryValue::Iterator iter(*capabilities_.prefs);
- !iter.IsAtEnd(); iter.Advance()) {
- Error* error = SetPreference(iter.key(), true /* is_user_pref */,
- iter.value().DeepCopy());
- if (error)
- return error;
- }
- for (base::DictionaryValue::Iterator iter(*capabilities_.local_state);
- !iter.IsAtEnd(); iter.Advance()) {
- Error* error = SetPreference(iter.key(), false /* is_user_pref */,
- iter.value().DeepCopy());
- if (error)
- return error;
- }
- return NULL;
-}
-
-} // namespace webdriver
« no previous file with comments | « chrome/test/webdriver/webdriver_session.h ('k') | chrome/test/webdriver/webdriver_session_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698