| 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,
|
| - ®ion_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, ®ion_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
|
|
|