blob: b34860de3109ce7ad346197de83dad0e87666620 [file] [log] [blame]
// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/webdriver/web_driver_module.h"
#include <memory>
#include <string>
#include <vector>
#include "base/base64.h"
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "cobalt/webdriver/dispatcher.h"
#include "cobalt/webdriver/protocol/capabilities.h"
#include "cobalt/webdriver/protocol/window_id.h"
#include "cobalt/webdriver/screencast/screencast_module.h"
#include "cobalt/webdriver/screenshot.h"
#include "cobalt/webdriver/server.h"
#include "cobalt/webdriver/session_driver.h"
#include "cobalt/webdriver/util/command_result.h"
#include "cobalt/webdriver/util/dispatch_command_factory.h"
#include "cobalt/webdriver/window_driver.h"
namespace cobalt {
namespace webdriver {
namespace {
// Only one session is supported. This is the session ID for that session.
const char kWebDriverSessionId[] = "session-0";
// Variable names for variable path components.
const char kSessionIdVariable[] = ":sessionId";
const char kWindowHandleVariable[] = ":windowHandle";
const char kElementId[] = ":id";
const char kOtherElementId[] = ":other";
const char kAttributeName[] = ":name";
const char kCssPropertyName[] = ":propertyName";
const char kCookieName[] = ":name";
// Error messages related to session creation.
const char kMaxSessionsCreatedMessage[] =
"Maximum number of sessions have been created.";
const char kUnsupportedCapabilities[] =
"An unsupported capability was requested.";
const char kUnknownSessionCreationError[] =
"An unknown error occurred trying to create a new session.";
// Looks up the SessionDriver instance that is mapped to the
// the sessionId variable in the path.
SessionDriver* LookUpSessionDriverOrReturnInvalidResponse(
const base::Callback<SessionDriver*(const protocol::SessionId&)>&
get_session_cb,
const WebDriverDispatcher::PathVariableMap* path_variables,
WebDriverDispatcher::CommandResultHandler* result_handler) {
DCHECK(path_variables);
protocol::SessionId session_id(
path_variables->GetVariable(kSessionIdVariable));
SessionDriver* session_driver = get_session_cb.Run(session_id);
// If there is no session with this ID, then return an error.
if (!session_driver) {
result_handler->SendInvalidRequestResponse(
WebDriverDispatcher::CommandResultHandler::kInvalidPathVariable,
session_id.id());
}
return session_driver;
}
// There are no path variables to look up in this case. Ignore the path
// variables and return the session's current window.
WindowDriver* LookUpCurrentWindowDriver(
SessionDriver* session_driver,
const WebDriverDispatcher::PathVariableMap* path_variables,
WebDriverDispatcher::CommandResultHandler* result_handler) {
DCHECK(session_driver);
// If the current window has been closed, an error should be returned, but
// we don't support closing windows on Cobalt.
return session_driver->GetCurrentWindow();
}
// There are no path variables to look up in this case. This function simply
// returns the same SessionDriver that was passed in.
SessionDriver* LookUpSessionDriver(
SessionDriver* session_driver,
const WebDriverDispatcher::PathVariableMap* path_variables,
WebDriverDispatcher::CommandResultHandler* result_handler) {
DCHECK(session_driver);
return session_driver;
}
// Looks up the WindowDriver instance that is mapped to the
// the sessionId variable in the path.
WindowDriver* LookUpWindowDriverOrReturnInvalidResponse(
SessionDriver* session_driver,
const WebDriverDispatcher::PathVariableMap* path_variables,
WebDriverDispatcher::CommandResultHandler* result_handler) {
DCHECK(path_variables);
DCHECK(session_driver);
protocol::WindowId window_id(
path_variables->GetVariable(kWindowHandleVariable));
WindowDriver* window_driver =
session_driver->GetWindow(protocol::WindowId(window_id));
if (!window_driver) {
result_handler->SendInvalidRequestResponse(
WebDriverDispatcher::CommandResultHandler::kInvalidPathVariable,
window_id.id());
}
return window_driver;
}
// Looks up the ElementDriver instance that is mapped to the
// the sessionId variable in the path.
ElementDriver* LookUpElementDriverOrReturnInvalidResponse(
const char* path_variable, SessionDriver* session_driver,
const WebDriverDispatcher::PathVariableMap* path_variables,
WebDriverDispatcher::CommandResultHandler* result_handler) {
DCHECK(path_variables);
DCHECK(session_driver);
ElementDriver* element_driver = NULL;
WindowDriver* window_driver =
LookUpCurrentWindowDriver(session_driver, path_variables, result_handler);
if (window_driver) {
protocol::ElementId element_id(path_variables->GetVariable(path_variable));
element_driver =
window_driver->GetElementDriver(protocol::ElementId(element_id));
if (!element_driver) {
result_handler->SendInvalidRequestResponse(
WebDriverDispatcher::CommandResultHandler::kInvalidPathVariable,
element_id.id());
}
}
return element_driver;
}
} // namespace
WebDriverModule::WebDriverModule(
int server_port, const std::string& listen_ip,
const CreateSessionDriverCB& create_session_driver_cb,
const GetScreenshotFunction& get_screenshot_function,
const SetProxyFunction& set_proxy_function,
const base::Closure& shutdown_cb)
: listen_ip_(listen_ip),
webdriver_thread_("WebDriverThread"),
create_session_driver_cb_(create_session_driver_cb),
get_screenshot_function_(get_screenshot_function),
set_proxy_function_(set_proxy_function),
shutdown_cb_(shutdown_cb),
webdriver_dispatcher_(new WebDriverDispatcher()) {
get_session_driver_ =
base::Bind(&WebDriverModule::GetSessionDriver, base::Unretained(this));
typedef util::DispatchCommandFactory<SessionDriver> SessionCommandFactory;
typedef util::DispatchCommandFactory<WindowDriver> WindowCommandFactory;
typedef util::DispatchCommandFactory<ElementDriver> ElementCommandFactory;
scoped_refptr<SessionCommandFactory> session_command_factory(
new SessionCommandFactory(
base::Bind(&LookUpSessionDriverOrReturnInvalidResponse,
get_session_driver_),
base::Bind(&LookUpSessionDriver)));
scoped_refptr<WindowCommandFactory> current_window_command_factory(
new WindowCommandFactory(
base::Bind(&LookUpSessionDriverOrReturnInvalidResponse,
get_session_driver_),
base::Bind(&LookUpCurrentWindowDriver)));
scoped_refptr<WindowCommandFactory> window_command_factory(
new WindowCommandFactory(
base::Bind(&LookUpSessionDriverOrReturnInvalidResponse,
get_session_driver_),
base::Bind(&LookUpWindowDriverOrReturnInvalidResponse)));
scoped_refptr<ElementCommandFactory> element_command_factory(
new ElementCommandFactory(
base::Bind(&LookUpSessionDriverOrReturnInvalidResponse,
get_session_driver_),
base::Bind(&LookUpElementDriverOrReturnInvalidResponse, kElementId)));
// Server commands.
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet, "/status",
base::Bind(&WebDriverModule::GetServerStatus, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost, "/session",
base::Bind(&WebDriverModule::CreateSession, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet, "/sessions",
base::Bind(&WebDriverModule::GetActiveSessions, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet, "/shutdown",
base::Bind(&WebDriverModule::Shutdown, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kDelete,
base::StringPrintf("/session/%s", kSessionIdVariable),
base::Bind(&WebDriverModule::DeleteSession, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/screenshot", kSessionIdVariable),
base::Bind(&WebDriverModule::RequestScreenshot, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/startscreencast", kSessionIdVariable),
base::Bind(&WebDriverModule::StartScreencast, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/stopscreencast", kSessionIdVariable),
base::Bind(&WebDriverModule::StopScreencast, base::Unretained(this)));
// Session commands.
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s", kSessionIdVariable),
session_command_factory->GetCommandHandler(
base::Bind(&SessionDriver::GetCapabilities)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/window_handle", kSessionIdVariable),
session_command_factory->GetCommandHandler(
base::Bind(&SessionDriver::GetCurrentWindowHandle)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/window_handles", kSessionIdVariable),
session_command_factory->GetCommandHandler(
base::Bind(&SessionDriver::GetWindowHandles)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/alert_text", kSessionIdVariable),
session_command_factory->GetCommandHandler(
base::Bind(&SessionDriver::GetAlertText)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/window", kSessionIdVariable),
session_command_factory->GetCommandHandler(
base::Bind(&SessionDriver::SwitchToWindow)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/log/types", kSessionIdVariable),
session_command_factory->GetCommandHandler(
base::Bind(&SessionDriver::GetLogTypes)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/log", kSessionIdVariable),
session_command_factory->GetCommandHandler(
base::Bind(&SessionDriver::GetLog)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/url", kSessionIdVariable),
session_command_factory->GetCommandHandler(
base::Bind(&SessionDriver::Navigate)));
// Specified window commands.
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/window/%s/size", kSessionIdVariable,
kWindowHandleVariable),
window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::GetWindowSize)));
// Current window commands.
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/url", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::GetCurrentUrl)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/source", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::GetSource)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/title", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::GetTitle)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/execute", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::Execute)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/execute_async", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::ExecuteAsync)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/element", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::FindElement)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/elements", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::FindElements)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/keys", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::SendKeys)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/element/active", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::GetActiveElement)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/frame", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::SwitchFrame)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/cookie", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::GetAllCookies)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/cookie/%s", kSessionIdVariable,
kCookieName),
base::Bind(&WebDriverModule::GetCookieByName, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/cookie", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::AddCookie)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/moveto", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::MouseMoveTo)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/buttondown", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::MouseButtonDown)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/buttonup", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::MouseButtonUp)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/click", kSessionIdVariable),
current_window_command_factory->GetCommandHandler(
base::Bind(&WindowDriver::SendClick)));
// Element commands.
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/name", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::GetTagName)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/text", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::GetText)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/displayed", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::IsDisplayed)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/rect", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::GetRect)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/location", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::GetLocation)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/size", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::GetSize)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/element/%s/value", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::SendKeys)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/element/%s/element", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::FindElement)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/element/%s/elements", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::FindElements)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/element/%s/click", kSessionIdVariable,
kElementId),
element_command_factory->GetCommandHandler(
base::Bind(&ElementDriver::SendClick)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/equals/%s", kSessionIdVariable,
kElementId, kOtherElementId),
base::Bind(&WebDriverModule::ElementEquals, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/attribute/%s",
kSessionIdVariable, kElementId, kAttributeName),
base::Bind(&WebDriverModule::GetAttribute, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/css/%s", kSessionIdVariable,
kElementId, kCssPropertyName),
base::Bind(&WebDriverModule::GetCssProperty, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kGet,
base::StringPrintf("/session/%s/element/%s/screenshot",
kSessionIdVariable, kElementId),
base::Bind(&WebDriverModule::RequestElementScreenshot,
base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/timeouts", kSessionIdVariable),
base::Bind(&WebDriverModule::IgnoreCommand, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/timeouts/async_script",
kSessionIdVariable),
base::Bind(&WebDriverModule::IgnoreCommand, base::Unretained(this)));
webdriver_dispatcher_->RegisterCommand(
WebDriverServer::kPost,
base::StringPrintf("/session/%s/timeouts/implicit_wait",
kSessionIdVariable),
base::Bind(&WebDriverModule::IgnoreCommand, base::Unretained(this)));
// The WebDriver API implementation will be called on the HTTP server thread.
DETACH_FROM_THREAD(thread_checker_);
// Start the thread and create the HTTP server on that thread.
webdriver_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
webdriver_thread_.message_loop()->task_runner()->PostTask(
FROM_HERE, base::Bind(&WebDriverModule::StartServer,
base::Unretained(this), server_port, listen_ip));
} // NOLINT(readability/fn_size)
WebDriverModule::~WebDriverModule() {
webdriver_thread_.message_loop()->task_runner()->PostBlockingTask(
FROM_HERE, base::Bind(&WebDriverModule::StopServerAndSession,
base::Unretained(this)));
webdriver_thread_.Stop();
} // NOLINT(readability/fn_size)
void WebDriverModule::OnWindowRecreated() {
if (base::MessageLoop::current() != webdriver_thread_.message_loop()) {
webdriver_thread_.message_loop()->task_runner()->PostTask(
FROM_HERE, base::Bind(&WebDriverModule::OnWindowRecreated,
base::Unretained(this)));
return;
}
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (session_) {
session_->RefreshWindowDriver();
}
}
void WebDriverModule::StartServer(int server_port,
const std::string& listen_ip) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Create a new WebDriverServer and pass in the Dispatcher.
webdriver_server_.reset(new WebDriverServer(
server_port, listen_ip,
base::Bind(&WebDriverDispatcher::HandleWebDriverServerRequest,
base::Unretained(webdriver_dispatcher_.get())),
"Cobalt.Server.WebDriver"));
}
void WebDriverModule::StopServerAndSession() {
webdriver_server_.reset();
session_.reset();
}
SessionDriver* WebDriverModule::GetSessionDriver(
const protocol::SessionId& session_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
SessionDriver* session_driver = NULL;
if (session_ && (session_->session_id() == session_id)) {
return session_.get();
}
return NULL;
}
// https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#status
void WebDriverModule::GetServerStatus(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
result_handler->SendResult(base::nullopt, protocol::Response::kSuccess,
protocol::ServerStatus::ToValue(status_));
}
// https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessions
void WebDriverModule::GetActiveSessions(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
std::vector<protocol::SessionId> sessions;
if (session_) {
sessions.push_back(session_->session_id());
}
result_handler->SendResult(base::nullopt, protocol::Response::kSuccess,
util::internal::ToValue(sessions));
}
// https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#get-sessionsessionid
void WebDriverModule::CreateSession(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::Optional<protocol::RequestedCapabilities> requested_capabilities =
protocol::RequestedCapabilities::FromValue(parameters);
if (!requested_capabilities) {
result_handler->SendInvalidRequestResponse(
WebDriverDispatcher::CommandResultHandler::kInvalidParameters, "");
return;
}
util::CommandResult<protocol::Capabilities> command_result =
CreateSessionInternal(requested_capabilities.value());
base::Optional<protocol::SessionId> session_id;
if (command_result.is_success()) {
session_id = session_->session_id();
}
util::internal::ReturnResponse(session_id, command_result,
result_handler.get());
}
// https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#delete-sessionsessionid
void WebDriverModule::DeleteSession(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (session_) {
// Extract the sessionId variable from the path
std::string session_id_variable =
path_variables->GetVariable(kSessionIdVariable);
if (session_id_variable == session_->session_id().id()) {
// If the sessionID matches, the delete the session.
session_.reset();
}
}
// If the session doesn't exist, then this is a no-op.
result_handler->SendResult(base::nullopt, protocol::Response::kSuccess,
std::unique_ptr<base::Value>());
}
void WebDriverModule::StartScreencast(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
SessionDriver* session_driver = LookUpSessionDriverOrReturnInvalidResponse(
base::Bind(&WebDriverModule::GetSessionDriver, base::Unretained(this)),
path_variables, result_handler.get());
if (session_driver) {
typedef util::CommandResult<std::string> CommandResult;
int port = 3003;
screencast_driver_module_.reset(new screencast::ScreencastModule(
port, listen_ip_, get_screenshot_function_));
CommandResult result =
util::CommandResult<std::string>(std::to_string(port));
util::internal::ReturnResponse(session_driver->session_id(), result,
result_handler.get());
}
}
void WebDriverModule::StopScreencast(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
SessionDriver* session_driver = LookUpSessionDriverOrReturnInvalidResponse(
base::Bind(&WebDriverModule::GetSessionDriver, base::Unretained(this)),
path_variables, result_handler.get());
if (session_driver) {
typedef util::CommandResult<std::string> CommandResult;
screencast_driver_module_.reset();
CommandResult result = util::CommandResult<std::string>("Server stopped");
util::internal::ReturnResponse(session_driver->session_id(), result,
result_handler.get());
}
}
// https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessionsessionidscreenshot
void WebDriverModule::RequestScreenshot(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
TRACE_EVENT0("cobalt::WebDriver", "WebDriverModule::RequestScreenshot()");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
SessionDriver* session_driver = LookUpSessionDriverOrReturnInvalidResponse(
base::Bind(&WebDriverModule::GetSessionDriver, base::Unretained(this)),
path_variables, result_handler.get());
if (session_driver) {
typedef util::CommandResult<std::string> CommandResult;
CommandResult result =
Screenshot::RequestScreenshot(get_screenshot_function_,
/*clip_rect=*/base::nullopt);
util::internal::ReturnResponse(session_driver->session_id(), result,
result_handler.get());
}
}
void WebDriverModule::Shutdown(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// It's expected that the application will terminate, so it's okay to
// leave the request hanging.
shutdown_cb_.Run();
}
void WebDriverModule::ElementEquals(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
SessionDriver* session_driver = LookUpSessionDriverOrReturnInvalidResponse(
base::Bind(&WebDriverModule::GetSessionDriver, base::Unretained(this)),
path_variables, result_handler.get());
if (!session_driver) {
return;
}
ElementDriver* element_driver = LookUpElementDriverOrReturnInvalidResponse(
kElementId, session_driver, path_variables, result_handler.get());
if (!element_driver) {
return;
}
ElementDriver* other_element = LookUpElementDriverOrReturnInvalidResponse(
kOtherElementId, session_driver, path_variables, result_handler.get());
if (!other_element) {
return;
}
typedef util::CommandResult<bool> CommandResult;
CommandResult result = element_driver->Equals(other_element);
util::internal::ReturnResponse(session_driver->session_id(), result,
result_handler.get());
}
void WebDriverModule::GetAttribute(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
SessionDriver* session_driver = LookUpSessionDriverOrReturnInvalidResponse(
base::Bind(&WebDriverModule::GetSessionDriver, base::Unretained(this)),
path_variables, result_handler.get());
if (session_driver) {
ElementDriver* element_driver = LookUpElementDriverOrReturnInvalidResponse(
kElementId, session_driver, path_variables, result_handler.get());
if (element_driver) {
std::string attribute_name = path_variables->GetVariable(kAttributeName);
typedef util::CommandResult<base::Optional<std::string> > CommandResult;
CommandResult result =
element_driver->GetAttribute(std::move(attribute_name));
util::internal::ReturnResponse(session_driver->session_id(), result,
result_handler.get());
}
}
}
void WebDriverModule::GetCssProperty(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
SessionDriver* session_driver = LookUpSessionDriverOrReturnInvalidResponse(
base::Bind(&WebDriverModule::GetSessionDriver, base::Unretained(this)),
path_variables, result_handler.get());
if (session_driver) {
ElementDriver* element_driver = LookUpElementDriverOrReturnInvalidResponse(
kElementId, session_driver, path_variables, result_handler.get());
if (element_driver) {
std::string property_name = path_variables->GetVariable(kCssPropertyName);
typedef util::CommandResult<std::string> CommandResult;
CommandResult result =
element_driver->GetCssProperty(std::move(property_name));
util::internal::ReturnResponse(session_driver->session_id(), result,
result_handler.get());
}
}
}
void WebDriverModule::RequestElementScreenshot(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
SessionDriver* session_driver = LookUpSessionDriverOrReturnInvalidResponse(
base::Bind(&WebDriverModule::GetSessionDriver, base::Unretained(this)),
path_variables, result_handler.get());
if (session_driver) {
ElementDriver* element_driver = LookUpElementDriverOrReturnInvalidResponse(
kElementId, session_driver, path_variables, result_handler.get());
if (element_driver) {
typedef util::CommandResult<std::string> CommandResult;
CommandResult result =
element_driver->RequestScreenshot(get_screenshot_function_);
util::internal::ReturnResponse(session_driver->session_id(), result,
result_handler.get());
}
}
}
void WebDriverModule::GetCookieByName(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
SessionDriver* session_driver = LookUpSessionDriverOrReturnInvalidResponse(
base::Bind(&WebDriverModule::GetSessionDriver, base::Unretained(this)),
path_variables, result_handler.get());
if (session_driver) {
WindowDriver* window_driver = session_driver->GetCurrentWindow();
DCHECK(window_driver);
if (window_driver) {
std::string cookie_name = path_variables->GetVariable(kCookieName);
typedef util::CommandResult<std::vector<protocol::Cookie> > CommandResult;
CommandResult result = window_driver->GetCookie(std::string(cookie_name));
util::internal::ReturnResponse(session_driver->session_id(), result,
result_handler.get());
}
}
}
void WebDriverModule::IgnoreCommand(
const base::Value* parameters,
const WebDriverDispatcher::PathVariableMap* path_variables,
std::unique_ptr<WebDriverDispatcher::CommandResultHandler> result_handler) {
// TODO: Hook up and implement timeouts.
return result_handler->SendResult(protocol::SessionId(kWebDriverSessionId),
protocol::Response::kSuccess,
std::make_unique<base::Value>());
}
util::CommandResult<protocol::Capabilities>
WebDriverModule::CreateSessionInternal(
const protocol::RequestedCapabilities& requested_capabilities) {
typedef util::CommandResult<protocol::Capabilities> CommandResult;
if (session_) {
// A session has already been created. We can only create one.
return CommandResult(protocol::Response::kSessionNotCreatedException,
kMaxSessionsCreatedMessage);
}
// We will only ever create sessions with one set of capabilities. So ignore
// the desired capabilities (for now).
if (requested_capabilities.required() &&
!requested_capabilities.required()->AreCapabilitiesSupported()) {
return CommandResult(protocol::Response::kSessionNotCreatedException,
kUnsupportedCapabilities);
}
session_ =
create_session_driver_cb_.Run(protocol::SessionId(kWebDriverSessionId));
if (!session_) {
// Some failure to create the new session.
return CommandResult(protocol::Response::kUnknownError,
kUnknownSessionCreationError);
}
// If proxy settings were requested when the session was created, set them
// now.
base::Optional<protocol::Proxy> proxy_settings =
requested_capabilities.desired().proxy();
if (!proxy_settings && requested_capabilities.required()) {
proxy_settings = requested_capabilities.required()->proxy();
}
if (proxy_settings) {
set_proxy_function_.Run(proxy_settings->rules());
}
return session_->GetCapabilities();
}
} // namespace webdriver
} // namespace cobalt