Client.cpp 34 KB

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