Client.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. /*
  2. * Copyright (c) 2022, Florent Castelli <florent.castelli@gmail.com>
  3. * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
  4. * Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
  5. * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
  6. * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
  7. *
  8. * SPDX-License-Identifier: BSD-2-Clause
  9. */
  10. #include <AK/Debug.h>
  11. #include <AK/JsonObject.h>
  12. #include <AK/JsonValue.h>
  13. #include <LibWeb/WebDriver/Capabilities.h>
  14. #include <LibWeb/WebDriver/TimeoutsConfiguration.h>
  15. #include <WebDriver/Client.h>
  16. namespace WebDriver {
  17. Atomic<unsigned> Client::s_next_session_id;
  18. NonnullOwnPtrVector<Session> Client::s_sessions;
  19. ErrorOr<NonnullRefPtr<Client>> Client::try_create(NonnullOwnPtr<Core::Stream::BufferedTCPSocket> socket, Core::Object* parent)
  20. {
  21. TRY(socket->set_blocking(true));
  22. return adopt_nonnull_ref_or_enomem(new (nothrow) Client(move(socket), parent));
  23. }
  24. Client::Client(NonnullOwnPtr<Core::Stream::BufferedTCPSocket> socket, Core::Object* parent)
  25. : Web::WebDriver::Client(move(socket), parent)
  26. {
  27. }
  28. Client::~Client() = default;
  29. ErrorOr<Session*, Web::WebDriver::Error> Client::find_session_with_id(StringView session_id)
  30. {
  31. auto session_id_or_error = session_id.to_uint<>();
  32. if (!session_id_or_error.has_value())
  33. return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
  34. for (auto& session : Client::s_sessions) {
  35. if (session.session_id() == session_id_or_error.value())
  36. return &session;
  37. }
  38. return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
  39. }
  40. ErrorOr<NonnullOwnPtr<Session>, Web::WebDriver::Error> Client::take_session_with_id(StringView session_id)
  41. {
  42. auto session_id_or_error = session_id.to_uint<>();
  43. if (!session_id_or_error.has_value())
  44. return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
  45. for (size_t i = 0; i < Client::s_sessions.size(); ++i) {
  46. if (Client::s_sessions[i].session_id() == session_id_or_error.value()) {
  47. return Client::s_sessions.take(i);
  48. }
  49. }
  50. return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
  51. }
  52. void Client::close_session(unsigned session_id)
  53. {
  54. bool found = Client::s_sessions.remove_first_matching([&](auto const& it) {
  55. return it->session_id() == session_id;
  56. });
  57. if (found)
  58. dbgln_if(WEBDRIVER_DEBUG, "Shut down session {}", session_id);
  59. else
  60. dbgln_if(WEBDRIVER_DEBUG, "Unable to shut down session {}: Not found", session_id);
  61. }
  62. // Step 12 of https://w3c.github.io/webdriver/#dfn-new-sessions
  63. static void initialize_session_from_capabilities(WebContentConnection& web_content_connection, JsonObject& capabilities)
  64. {
  65. // 1. Let strategy be the result of getting property "pageLoadStrategy" from capabilities.
  66. auto const* strategy = capabilities.get_ptr("pageLoadStrategy"sv);
  67. // 2. If strategy is a string, set the current session’s page loading strategy to strategy. Otherwise, set the page loading strategy to normal and set a property of capabilities with name "pageLoadStrategy" and value "normal".
  68. if (strategy && strategy->is_string())
  69. web_content_connection.async_set_page_load_strategy(Web::WebDriver::page_load_strategy_from_string(strategy->as_string()));
  70. else
  71. capabilities.set("pageLoadStrategy"sv, "normal"sv);
  72. // 3. Let strictFileInteractability be the result of getting property "strictFileInteractability" from capabilities.
  73. auto const* strict_file_interactiblity = capabilities.get_ptr("strictFileInteractability"sv);
  74. // 4. If strictFileInteractability is a boolean, set the current session’s strict file interactability to strictFileInteractability. Otherwise set the current session’s strict file interactability to false.
  75. if (strict_file_interactiblity && strict_file_interactiblity->is_bool())
  76. web_content_connection.async_set_strict_file_interactability(strict_file_interactiblity->as_bool());
  77. else
  78. capabilities.set("strictFileInteractability"sv, false);
  79. // FIXME: 5. Let proxy be the result of getting property "proxy" from capabilities and run the substeps of the first matching statement:
  80. // FIXME: proxy is a proxy configuration object
  81. // FIXME: Take implementation-defined steps to set the user agent proxy using the extracted proxy configuration. If the defined proxy cannot be configured return error with error code session not created.
  82. // FIXME: Otherwise
  83. // FIXME: Set a property of capabilities with name "proxy" and a value that is a new JSON Object.
  84. // 6. If capabilities has a property with the key "timeouts":
  85. if (auto const* timeouts = capabilities.get_ptr("timeouts"sv); timeouts && timeouts->is_object()) {
  86. // a. Let timeouts be the result of trying to JSON deserialize as a timeouts configuration the value of the "timeouts" property.
  87. // NOTE: This happens on the remote end.
  88. // b. Make the session timeouts the new timeouts.
  89. MUST(web_content_connection.set_timeouts(*timeouts));
  90. } else {
  91. // 7. Set a property on capabilities with name "timeouts" and value that of the JSON deserialization of the session timeouts.
  92. capabilities.set("timeouts"sv, Web::WebDriver::timeouts_object({}));
  93. }
  94. // 8. Apply changes to the user agent for any implementation-defined capabilities selected during the capabilities processing step.
  95. auto const* behavior = capabilities.get_ptr("unhandledPromptBehavior"sv);
  96. if (behavior && behavior->is_string())
  97. web_content_connection.async_set_unhandled_prompt_behavior(Web::WebDriver::unhandled_prompt_behavior_from_string(behavior->as_string()));
  98. else
  99. capabilities.set("unhandledPromptBehavior"sv, "dismiss and notify"sv);
  100. }
  101. // 8.1 New Session, https://w3c.github.io/webdriver/#dfn-new-sessions
  102. // POST /session
  103. Web::WebDriver::Response Client::new_session(Web::WebDriver::Parameters, JsonValue payload)
  104. {
  105. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session");
  106. // FIXME: 1. If the maximum active sessions is equal to the length of the list of active sessions,
  107. // return error with error code session not created.
  108. // FIXME: 2. If the remote end is an intermediary node, take implementation-defined steps that either
  109. // result in returning an error with error code session not created, or in returning a
  110. // success with data that is isomorphic to that returned by remote ends according to the
  111. // rest of this algorithm. If an error is not returned, the intermediary node must retain a
  112. // reference to the session created on the upstream node as the associated session such
  113. // that commands may be forwarded to this associated session on subsequent commands.
  114. // FIXME: 3. If the maximum active sessions is equal to the length of the list of active sessions,
  115. // return error with error code session not created.
  116. // 4. Let capabilities be the result of trying to process capabilities with parameters as an argument.
  117. auto capabilities = TRY(Web::WebDriver::process_capabilities(payload));
  118. // 5. If capabilities’s is null, return error with error code session not created.
  119. if (capabilities.is_null())
  120. return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::SessionNotCreated, "Could not match capabilities"sv);
  121. // 6. Let session id be the result of generating a UUID.
  122. // FIXME: Actually create a UUID.
  123. auto session_id = Client::s_next_session_id++;
  124. // 7. Let session be a new session with the session ID of session id.
  125. NonnullOwnPtr<Session> session = make<Session>(session_id, *this);
  126. auto start_result = session->start();
  127. if (start_result.is_error()) {
  128. return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::SessionNotCreated, String::formatted("Failed to start session: {}", start_result.error().string_literal()));
  129. }
  130. auto& web_content_connection = session->web_content_connection();
  131. // FIXME: 8. Set the current session to session.
  132. // FIXME: 9. Run any WebDriver new session algorithm defined in external specifications,
  133. // with arguments session and capabilities.
  134. // 10. Append session to active sessions.
  135. Client::s_sessions.append(move(session));
  136. // NOTE: We do step 12 before 11 because step 12 mutates the capabilities we set in step 11.
  137. // 12. Initialize the following from capabilities:
  138. initialize_session_from_capabilities(web_content_connection, capabilities.as_object());
  139. // 11. Let body be a JSON Object initialized with:
  140. JsonObject body;
  141. // "sessionId"
  142. // session id
  143. body.set("sessionId", String::number(session_id));
  144. // "capabilities"
  145. // capabilities
  146. body.set("capabilities", move(capabilities));
  147. // 13. Set the webdriver-active flag to true.
  148. web_content_connection.async_set_is_webdriver_active(true);
  149. // FIXME: 14. Set the current top-level browsing context for session with the top-level browsing context
  150. // of the UA’s current browsing context.
  151. // FIXME: 15. Set the request queue to a new queue.
  152. // 16. Return success with data body.
  153. return JsonValue { move(body) };
  154. }
  155. // 8.2 Delete Session, https://w3c.github.io/webdriver/#dfn-delete-session
  156. // DELETE /session/{session id}
  157. Web::WebDriver::Response Client::delete_session(Web::WebDriver::Parameters parameters, JsonValue)
  158. {
  159. dbgln_if(WEBDRIVER_DEBUG, "Handling DELETE /session/<session_id>");
  160. // 1. If the current session is an active session, try to close the session.
  161. auto session = TRY(take_session_with_id(parameters[0]));
  162. TRY(session->stop());
  163. // 2. Return success with data null.
  164. return JsonValue {};
  165. }
  166. // 8.3 Status, https://w3c.github.io/webdriver/#dfn-status
  167. // GET /status
  168. Web::WebDriver::Response Client::get_status(Web::WebDriver::Parameters, JsonValue)
  169. {
  170. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /status");
  171. // 1. Let body be a new JSON Object with the following properties:
  172. // "ready"
  173. // The remote end’s readiness state.
  174. // "message"
  175. // An implementation-defined string explaining the remote end’s readiness state.
  176. // FIXME: Report if we are somehow not ready.
  177. JsonObject body;
  178. body.set("ready", true);
  179. body.set("message", "Ready to start some sessions!");
  180. // 2. Return success with data body.
  181. return JsonValue { body };
  182. }
  183. // 9.1 Get Timeouts, https://w3c.github.io/webdriver/#dfn-get-timeouts
  184. // GET /session/{session id}/timeouts
  185. Web::WebDriver::Response Client::get_timeouts(Web::WebDriver::Parameters parameters, JsonValue)
  186. {
  187. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session id>/timeouts");
  188. auto* session = TRY(find_session_with_id(parameters[0]));
  189. return session->web_content_connection().get_timeouts();
  190. }
  191. // 9.2 Set Timeouts, https://w3c.github.io/webdriver/#dfn-set-timeouts
  192. // POST /session/{session id}/timeouts
  193. Web::WebDriver::Response Client::set_timeouts(Web::WebDriver::Parameters parameters, JsonValue payload)
  194. {
  195. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session id>/timeouts");
  196. auto* session = TRY(find_session_with_id(parameters[0]));
  197. return session->web_content_connection().set_timeouts(payload);
  198. }
  199. // 10.1 Navigate To, https://w3c.github.io/webdriver/#dfn-navigate-to
  200. // POST /session/{session id}/url
  201. Web::WebDriver::Response Client::navigate_to(Web::WebDriver::Parameters parameters, JsonValue payload)
  202. {
  203. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/url");
  204. auto* session = TRY(find_session_with_id(parameters[0]));
  205. return session->web_content_connection().navigate_to(payload);
  206. }
  207. // 10.2 Get Current URL, https://w3c.github.io/webdriver/#dfn-get-current-url
  208. // GET /session/{session id}/url
  209. Web::WebDriver::Response Client::get_current_url(Web::WebDriver::Parameters parameters, JsonValue)
  210. {
  211. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/url");
  212. auto* session = TRY(find_session_with_id(parameters[0]));
  213. return session->web_content_connection().get_current_url();
  214. }
  215. // 10.3 Back, https://w3c.github.io/webdriver/#dfn-back
  216. // POST /session/{session id}/back
  217. Web::WebDriver::Response Client::back(Web::WebDriver::Parameters parameters, JsonValue)
  218. {
  219. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/back");
  220. auto* session = TRY(find_session_with_id(parameters[0]));
  221. return session->web_content_connection().back();
  222. }
  223. // 10.4 Forward, https://w3c.github.io/webdriver/#dfn-forward
  224. // POST /session/{session id}/forward
  225. Web::WebDriver::Response Client::forward(Web::WebDriver::Parameters parameters, JsonValue)
  226. {
  227. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/forward");
  228. auto* session = TRY(find_session_with_id(parameters[0]));
  229. return session->web_content_connection().forward();
  230. }
  231. // 10.5 Refresh, https://w3c.github.io/webdriver/#dfn-refresh
  232. // POST /session/{session id}/refresh
  233. Web::WebDriver::Response Client::refresh(Web::WebDriver::Parameters parameters, JsonValue)
  234. {
  235. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/refresh");
  236. auto* session = TRY(find_session_with_id(parameters[0]));
  237. return session->web_content_connection().refresh();
  238. }
  239. // 10.6 Get Title, https://w3c.github.io/webdriver/#dfn-get-title
  240. // GET /session/{session id}/title
  241. Web::WebDriver::Response Client::get_title(Web::WebDriver::Parameters parameters, JsonValue)
  242. {
  243. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/title");
  244. auto* session = TRY(find_session_with_id(parameters[0]));
  245. return session->web_content_connection().get_title();
  246. }
  247. // 11.1 Get Window Handle, https://w3c.github.io/webdriver/#get-window-handle
  248. // GET /session/{session id}/window
  249. Web::WebDriver::Response Client::get_window_handle(Web::WebDriver::Parameters parameters, JsonValue)
  250. {
  251. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/window");
  252. auto* session = TRY(find_session_with_id(parameters[0]));
  253. return session->web_content_connection().get_window_handle();
  254. }
  255. // 11.2 Close Window, https://w3c.github.io/webdriver/#dfn-close-window
  256. // DELETE /session/{session id}/window
  257. Web::WebDriver::Response Client::close_window(Web::WebDriver::Parameters parameters, JsonValue)
  258. {
  259. dbgln_if(WEBDRIVER_DEBUG, "Handling DELETE /session/<session_id>/window");
  260. auto* session = TRY(find_session_with_id(parameters[0]));
  261. auto open_windows = TRY(session->web_content_connection().close_window());
  262. if (open_windows.is_array() && open_windows.as_array().is_empty())
  263. TRY(session->stop());
  264. return open_windows;
  265. }
  266. // 11.4 Get Window Handles, https://w3c.github.io/webdriver/#dfn-get-window-handles
  267. // GET /session/{session id}/window/handles
  268. Web::WebDriver::Response Client::get_window_handles(Web::WebDriver::Parameters parameters, JsonValue)
  269. {
  270. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/window/handles");
  271. auto* session = TRY(find_session_with_id(parameters[0]));
  272. return session->web_content_connection().get_window_handles();
  273. }
  274. // 11.8.1 Get Window Rect, https://w3c.github.io/webdriver/#dfn-get-window-rect
  275. // GET /session/{session id}/window/rect
  276. Web::WebDriver::Response Client::get_window_rect(Web::WebDriver::Parameters parameters, JsonValue)
  277. {
  278. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/window/rect");
  279. auto* session = TRY(find_session_with_id(parameters[0]));
  280. return session->web_content_connection().get_window_rect();
  281. }
  282. // 11.8.2 Set Window Rect, https://w3c.github.io/webdriver/#dfn-set-window-rect
  283. // POST /session/{session id}/window/rect
  284. Web::WebDriver::Response Client::set_window_rect(Web::WebDriver::Parameters parameters, JsonValue payload)
  285. {
  286. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/rect");
  287. auto* session = TRY(find_session_with_id(parameters[0]));
  288. return session->web_content_connection().set_window_rect(payload);
  289. }
  290. // 11.8.3 Maximize Window, https://w3c.github.io/webdriver/#dfn-maximize-window
  291. // POST /session/{session id}/window/maximize
  292. Web::WebDriver::Response Client::maximize_window(Web::WebDriver::Parameters parameters, JsonValue)
  293. {
  294. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/maximize");
  295. auto* session = TRY(find_session_with_id(parameters[0]));
  296. return session->web_content_connection().maximize_window();
  297. }
  298. // 11.8.4 Minimize Window, https://w3c.github.io/webdriver/#minimize-window
  299. // POST /session/{session id}/window/minimize
  300. Web::WebDriver::Response Client::minimize_window(Web::WebDriver::Parameters parameters, JsonValue)
  301. {
  302. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/minimize");
  303. auto* session = TRY(find_session_with_id(parameters[0]));
  304. return session->web_content_connection().minimize_window();
  305. }
  306. // 11.8.5 Fullscreen Window, https://w3c.github.io/webdriver/#dfn-fullscreen-window
  307. // POST /session/{session id}/window/fullscreen
  308. Web::WebDriver::Response Client::fullscreen_window(Web::WebDriver::Parameters parameters, JsonValue)
  309. {
  310. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/fullscreen");
  311. auto* session = TRY(find_session_with_id(parameters[0]));
  312. return session->web_content_connection().fullscreen_window();
  313. }
  314. // 12.3.2 Find Element, https://w3c.github.io/webdriver/#dfn-find-element
  315. // POST /session/{session id}/element
  316. Web::WebDriver::Response Client::find_element(Web::WebDriver::Parameters parameters, JsonValue payload)
  317. {
  318. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/element");
  319. auto* session = TRY(find_session_with_id(parameters[0]));
  320. return session->web_content_connection().find_element(payload);
  321. }
  322. // 12.3.3 Find Elements, https://w3c.github.io/webdriver/#dfn-find-elements
  323. // POST /session/{session id}/elements
  324. Web::WebDriver::Response Client::find_elements(Web::WebDriver::Parameters parameters, JsonValue payload)
  325. {
  326. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/elements");
  327. auto* session = TRY(find_session_with_id(parameters[0]));
  328. return session->web_content_connection().find_elements(payload);
  329. }
  330. // 12.3.4 Find Element From Element, https://w3c.github.io/webdriver/#dfn-find-element-from-element
  331. // POST /session/{session id}/element/{element id}/element
  332. Web::WebDriver::Response Client::find_element_from_element(Web::WebDriver::Parameters parameters, JsonValue payload)
  333. {
  334. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/element/<element_id>/element");
  335. auto* session = TRY(find_session_with_id(parameters[0]));
  336. return session->web_content_connection().find_element_from_element(payload, parameters[1]);
  337. }
  338. // 12.3.5 Find Elements From Element, https://w3c.github.io/webdriver/#dfn-find-elements-from-element
  339. // POST /session/{session id}/element/{element id}/elements
  340. Web::WebDriver::Response Client::find_elements_from_element(Web::WebDriver::Parameters parameters, JsonValue payload)
  341. {
  342. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/element/<element_id>/elements");
  343. auto* session = TRY(find_session_with_id(parameters[0]));
  344. return session->web_content_connection().find_elements_from_element(payload, parameters[1]);
  345. }
  346. // 12.3.6 Find Element From Shadow Root, https://w3c.github.io/webdriver/#find-element-from-shadow-root
  347. // POST /session/{session id}/shadow/{shadow id}/element
  348. Web::WebDriver::Response Client::find_element_from_shadow_root(Web::WebDriver::Parameters parameters, JsonValue payload)
  349. {
  350. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/shadow/<shadow_id>/element");
  351. auto* session = TRY(find_session_with_id(parameters[0]));
  352. return session->web_content_connection().find_element_from_shadow_root(payload, parameters[1]);
  353. }
  354. // 12.3.7 Find Elements From Shadow Root, https://w3c.github.io/webdriver/#find-elements-from-shadow-root
  355. // POST /session/{session id}/shadow/{shadow id}/elements
  356. Web::WebDriver::Response Client::find_elements_from_shadow_root(Web::WebDriver::Parameters parameters, JsonValue payload)
  357. {
  358. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/shadow/<shadow_id>/elements");
  359. auto* session = TRY(find_session_with_id(parameters[0]));
  360. return session->web_content_connection().find_elements_from_shadow_root(payload, parameters[1]);
  361. }
  362. // 12.3.8 Get Active Element, https://w3c.github.io/webdriver/#get-active-element
  363. // GET /session/{session id}/element/active
  364. Web::WebDriver::Response Client::get_active_element(Web::WebDriver::Parameters parameters, JsonValue)
  365. {
  366. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/active");
  367. auto* session = TRY(find_session_with_id(parameters[0]));
  368. return session->web_content_connection().get_active_element();
  369. }
  370. // 12.3.9 Get Element Shadow Root, https://w3c.github.io/webdriver/#get-element-shadow-root
  371. // GET /session/{session id}/element/{element id}/shadow
  372. Web::WebDriver::Response Client::get_element_shadow_root(Web::WebDriver::Parameters parameters, JsonValue)
  373. {
  374. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/shadow");
  375. auto* session = TRY(find_session_with_id(parameters[0]));
  376. return session->web_content_connection().get_element_shadow_root(parameters[1]);
  377. }
  378. // 12.4.1 Is Element Selected, https://w3c.github.io/webdriver/#dfn-is-element-selected
  379. // GET /session/{session id}/element/{element id}/selected
  380. Web::WebDriver::Response Client::is_element_selected(Web::WebDriver::Parameters parameters, JsonValue)
  381. {
  382. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/selected");
  383. auto* session = TRY(find_session_with_id(parameters[0]));
  384. return session->web_content_connection().is_element_selected(parameters[1]);
  385. }
  386. // 12.4.2 Get Element Attribute, https://w3c.github.io/webdriver/#dfn-get-element-attribute
  387. // GET /session/{session id}/element/{element id}/attribute/{name}
  388. Web::WebDriver::Response Client::get_element_attribute(Web::WebDriver::Parameters parameters, JsonValue)
  389. {
  390. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/attribute/<name>");
  391. auto* session = TRY(find_session_with_id(parameters[0]));
  392. return session->web_content_connection().get_element_attribute(parameters[1], parameters[2]);
  393. }
  394. // 12.4.3 Get Element Property, https://w3c.github.io/webdriver/#dfn-get-element-property
  395. // GET /session/{session id}/element/{element id}/property/{name}
  396. Web::WebDriver::Response Client::get_element_property(Web::WebDriver::Parameters parameters, JsonValue)
  397. {
  398. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/property/<name>");
  399. auto* session = TRY(find_session_with_id(parameters[0]));
  400. return session->web_content_connection().get_element_property(parameters[1], parameters[2]);
  401. }
  402. // 12.4.4 Get Element CSS Value, https://w3c.github.io/webdriver/#dfn-get-element-css-value
  403. // GET /session/{session id}/element/{element id}/css/{property name}
  404. Web::WebDriver::Response Client::get_element_css_value(Web::WebDriver::Parameters parameters, JsonValue)
  405. {
  406. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/css/<property_name>");
  407. auto* session = TRY(find_session_with_id(parameters[0]));
  408. return session->web_content_connection().get_element_css_value(parameters[1], parameters[2]);
  409. }
  410. // 12.4.5 Get Element Text, https://w3c.github.io/webdriver/#dfn-get-element-text
  411. // GET /session/{session id}/element/{element id}/text
  412. Web::WebDriver::Response Client::get_element_text(Web::WebDriver::Parameters parameters, JsonValue)
  413. {
  414. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/text");
  415. auto* session = TRY(find_session_with_id(parameters[0]));
  416. return session->web_content_connection().get_element_text(parameters[1]);
  417. }
  418. // 12.4.6 Get Element Tag Name, https://w3c.github.io/webdriver/#dfn-get-element-tag-name
  419. // GET /session/{session id}/element/{element id}/name
  420. Web::WebDriver::Response Client::get_element_tag_name(Web::WebDriver::Parameters parameters, JsonValue)
  421. {
  422. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/name");
  423. auto* session = TRY(find_session_with_id(parameters[0]));
  424. return session->web_content_connection().get_element_tag_name(parameters[1]);
  425. }
  426. // 12.4.7 Get Element Rect, https://w3c.github.io/webdriver/#dfn-get-element-rect
  427. // GET /session/{session id}/element/{element id}/rect
  428. Web::WebDriver::Response Client::get_element_rect(Web::WebDriver::Parameters parameters, JsonValue)
  429. {
  430. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/rect");
  431. auto* session = TRY(find_session_with_id(parameters[0]));
  432. return session->web_content_connection().get_element_rect(parameters[1]);
  433. }
  434. // 12.4.8 Is Element Enabled, https://w3c.github.io/webdriver/#dfn-is-element-enabled
  435. // GET /session/{session id}/element/{element id}/enabled
  436. Web::WebDriver::Response Client::is_element_enabled(Web::WebDriver::Parameters parameters, JsonValue)
  437. {
  438. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/enabled");
  439. auto* session = TRY(find_session_with_id(parameters[0]));
  440. return session->web_content_connection().is_element_enabled(parameters[1]);
  441. }
  442. // 13.1 Get Page Source, https://w3c.github.io/webdriver/#dfn-get-page-source
  443. // GET /session/{session id}/source
  444. Web::WebDriver::Response Client::get_source(Web::WebDriver::Parameters parameters, JsonValue)
  445. {
  446. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/source");
  447. auto* session = TRY(find_session_with_id(parameters[0]));
  448. return session->web_content_connection().get_source();
  449. }
  450. // 13.2.1 Execute Script, https://w3c.github.io/webdriver/#dfn-execute-script
  451. // POST /session/{session id}/execute/sync
  452. Web::WebDriver::Response Client::execute_script(Web::WebDriver::Parameters parameters, JsonValue payload)
  453. {
  454. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/execute/sync");
  455. auto* session = TRY(find_session_with_id(parameters[0]));
  456. return session->web_content_connection().execute_script(payload);
  457. }
  458. // 13.2.2 Execute Async Script, https://w3c.github.io/webdriver/#dfn-execute-async-script
  459. // POST /session/{session id}/execute/async
  460. Web::WebDriver::Response Client::execute_async_script(Web::WebDriver::Parameters parameters, JsonValue payload)
  461. {
  462. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/execute/async");
  463. auto* session = TRY(find_session_with_id(parameters[0]));
  464. return session->web_content_connection().execute_async_script(payload);
  465. }
  466. // 14.1 Get All Cookies, https://w3c.github.io/webdriver/#dfn-get-all-cookies
  467. // GET /session/{session id}/cookie
  468. Web::WebDriver::Response Client::get_all_cookies(Web::WebDriver::Parameters parameters, JsonValue)
  469. {
  470. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/cookie");
  471. auto* session = TRY(find_session_with_id(parameters[0]));
  472. return session->web_content_connection().get_all_cookies();
  473. }
  474. // 14.2 Get Named Cookie, https://w3c.github.io/webdriver/#dfn-get-named-cookie
  475. // GET /session/{session id}/cookie/{name}
  476. Web::WebDriver::Response Client::get_named_cookie(Web::WebDriver::Parameters parameters, JsonValue)
  477. {
  478. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/cookie/<name>");
  479. auto* session = TRY(find_session_with_id(parameters[0]));
  480. return session->web_content_connection().get_named_cookie(parameters[1]);
  481. }
  482. // 14.3 Add Cookie, https://w3c.github.io/webdriver/#dfn-adding-a-cookie
  483. // POST /session/{session id}/cookie
  484. Web::WebDriver::Response Client::add_cookie(Web::WebDriver::Parameters parameters, JsonValue payload)
  485. {
  486. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/cookie");
  487. auto* session = TRY(find_session_with_id(parameters[0]));
  488. return session->web_content_connection().add_cookie(payload);
  489. }
  490. // 14.4 Delete Cookie, https://w3c.github.io/webdriver/#dfn-delete-cookie
  491. // DELETE /session/{session id}/cookie/{name}
  492. Web::WebDriver::Response Client::delete_cookie(Web::WebDriver::Parameters parameters, JsonValue)
  493. {
  494. dbgln_if(WEBDRIVER_DEBUG, "Handling DELETE /session/<session_id>/cookie/<name>");
  495. auto* session = TRY(find_session_with_id(parameters[0]));
  496. return session->web_content_connection().delete_cookie(parameters[1]);
  497. }
  498. // 14.5 Delete All Cookies, https://w3c.github.io/webdriver/#dfn-delete-all-cookies
  499. // DELETE /session/{session id}/cookie
  500. Web::WebDriver::Response Client::delete_all_cookies(Web::WebDriver::Parameters parameters, JsonValue)
  501. {
  502. dbgln_if(WEBDRIVER_DEBUG, "Handling DELETE /session/<session_id>/cookie");
  503. auto* session = TRY(find_session_with_id(parameters[0]));
  504. return session->web_content_connection().delete_all_cookies();
  505. }
  506. // 16.1 Dismiss Alert, https://w3c.github.io/webdriver/#dismiss-alert
  507. // POST /session/{session id}/alert/dismiss
  508. Web::WebDriver::Response Client::dismiss_alert(Web::WebDriver::Parameters parameters, JsonValue)
  509. {
  510. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/alert/dismiss");
  511. auto* session = TRY(find_session_with_id(parameters[0]));
  512. return session->web_content_connection().dismiss_alert();
  513. }
  514. // 16.2 Accept Alert, https://w3c.github.io/webdriver/#accept-alert
  515. // POST /session/{session id}/alert/accept
  516. Web::WebDriver::Response Client::accept_alert(Web::WebDriver::Parameters parameters, JsonValue)
  517. {
  518. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/alert/accept");
  519. auto* session = TRY(find_session_with_id(parameters[0]));
  520. return session->web_content_connection().accept_alert();
  521. }
  522. // 16.3 Get Alert Text, https://w3c.github.io/webdriver/#get-alert-text
  523. // GET /session/{session id}/alert/text
  524. Web::WebDriver::Response Client::get_alert_text(Web::WebDriver::Parameters parameters, JsonValue)
  525. {
  526. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/alert/text");
  527. auto* session = TRY(find_session_with_id(parameters[0]));
  528. return session->web_content_connection().get_alert_text();
  529. }
  530. // 16.4 Send Alert Text, https://w3c.github.io/webdriver/#send-alert-text
  531. // POST /session/{session id}/alert/text
  532. Web::WebDriver::Response Client::send_alert_text(Web::WebDriver::Parameters parameters, JsonValue payload)
  533. {
  534. dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/alert/text");
  535. auto* session = TRY(find_session_with_id(parameters[0]));
  536. return session->web_content_connection().send_alert_text(payload);
  537. }
  538. // 17.1 Take Screenshot, https://w3c.github.io/webdriver/#take-screenshot
  539. // GET /session/{session id}/screenshot
  540. Web::WebDriver::Response Client::take_screenshot(Web::WebDriver::Parameters parameters, JsonValue)
  541. {
  542. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/screenshot");
  543. auto* session = TRY(find_session_with_id(parameters[0]));
  544. return session->web_content_connection().take_screenshot();
  545. }
  546. // 17.2 Take Element Screenshot, https://w3c.github.io/webdriver/#dfn-take-element-screenshot
  547. // GET /session/{session id}/element/{element id}/screenshot
  548. Web::WebDriver::Response Client::take_element_screenshot(Web::WebDriver::Parameters parameters, JsonValue)
  549. {
  550. dbgln_if(WEBDRIVER_DEBUG, "Handling GET /session/<session_id>/element/<element_id>/screenshot");
  551. auto* session = TRY(find_session_with_id(parameters[0]));
  552. return session->web_content_connection().take_element_screenshot(parameters[1]);
  553. }
  554. }