| // 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 |