소스 검색

WebDriver: Implement `POST /session/{session id}/execute/async` endpoint

Linus Groh 2 년 전
부모
커밋
629fbc2cfc
4개의 변경된 파일53개의 추가작업 그리고 0개의 파일을 삭제
  1. 11 0
      Userland/Services/WebDriver/Client.cpp
  2. 1 0
      Userland/Services/WebDriver/Client.h
  3. 40 0
      Userland/Services/WebDriver/Session.cpp
  4. 1 0
      Userland/Services/WebDriver/Session.h

+ 11 - 0
Userland/Services/WebDriver/Client.cpp

@@ -50,6 +50,7 @@ Vector<Client::Route> Client::s_routes = {
     { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "element", ":element_id", "text" }, &Client::handle_get_element_text },
     { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "element", ":element_id", "name" }, &Client::handle_get_element_tag_name },
     { HTTP::HttpRequest::Method::POST, { "session", ":session_id", "execute", "sync" }, &Client::handle_execute_script },
+    { HTTP::HttpRequest::Method::POST, { "session", ":session_id", "execute", "async" }, &Client::handle_execute_async_script },
     { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "cookie" }, &Client::handle_get_all_cookies },
     { HTTP::HttpRequest::Method::GET, { "session", ":session_id", "cookie", ":name" }, &Client::handle_get_named_cookie },
     { HTTP::HttpRequest::Method::POST, { "session", ":session_id", "cookie" }, &Client::handle_add_cookie },
@@ -696,6 +697,16 @@ ErrorOr<JsonValue, WebDriverError> Client::handle_execute_script(Vector<StringVi
     return make_json_value(result);
 }
 
+// 13.2.2 Execute Async Script, https://w3c.github.io/webdriver/#dfn-execute-async-script
+// POST /session/{session id}/execute/async
+ErrorOr<JsonValue, WebDriverError> Client::handle_execute_async_script(Vector<StringView> const& parameters, JsonValue const& payload)
+{
+    dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/execute/async");
+    auto* session = TRY(find_session_with_id(parameters[0]));
+    auto result = TRY(session->execute_async_script(payload));
+    return make_json_value(result);
+}
+
 // 14.1 Get All Cookies, https://w3c.github.io/webdriver/#dfn-get-all-cookies
 // GET /session/{session id}/cookie
 ErrorOr<JsonValue, WebDriverError> Client::handle_get_all_cookies(Vector<StringView> const& parameters, JsonValue const&)

+ 1 - 0
Userland/Services/WebDriver/Client.h

@@ -75,6 +75,7 @@ private:
     ErrorOr<JsonValue, WebDriverError> handle_get_element_text(Vector<StringView> const&, JsonValue const& payload);
     ErrorOr<JsonValue, WebDriverError> handle_get_element_tag_name(Vector<StringView> const&, JsonValue const& payload);
     ErrorOr<JsonValue, WebDriverError> handle_execute_script(Vector<StringView> const&, JsonValue const& payload);
+    ErrorOr<JsonValue, WebDriverError> handle_execute_async_script(Vector<StringView> const&, JsonValue const& payload);
     ErrorOr<JsonValue, WebDriverError> handle_get_all_cookies(Vector<StringView> const&, JsonValue const& payload);
     ErrorOr<JsonValue, WebDriverError> handle_get_named_cookie(Vector<StringView> const&, JsonValue const& payload);
     ErrorOr<JsonValue, WebDriverError> handle_add_cookie(Vector<StringView> const&, JsonValue const& payload);

+ 40 - 0
Userland/Services/WebDriver/Session.cpp

@@ -973,6 +973,46 @@ ErrorOr<JsonValue, WebDriverError> Session::execute_script(JsonValue const& payl
     }
 }
 
+// 13.2.2 Execute Async Script, https://w3c.github.io/webdriver/#dfn-execute-async-script
+ErrorOr<JsonValue, WebDriverError> Session::execute_async_script(JsonValue const& parameters)
+{
+    // 1. Let body and arguments by the result of trying to extract the script arguments from a request with argument parameters.
+    auto [body, arguments] = TRY(extract_the_script_arguments_from_a_request(parameters));
+
+    // 2. If the current browsing context is no longer open, return error with error code no such window.
+    TRY(check_for_open_top_level_browsing_context_or_return_error());
+
+    // FIXME: 3. Handle any user prompts, and return its value if it is an error.
+
+    // 4., 5.1-5.11.
+    Vector<String> json_arguments;
+    arguments.for_each([&](JsonValue const& json_value) {
+        // NOTE: serialized() instead of to_string() ensures proper quoting.
+        json_arguments.append(json_value.serialized<StringBuilder>());
+    });
+
+    dbgln("Executing async script with 'args': [{}] / 'body':\n{}", String::join(", "sv, json_arguments), body);
+    auto execute_script_response = m_browser_connection->execute_script(body, json_arguments, m_timeouts_configuration.script_timeout, true);
+    dbgln("Executing async script returned: {}", execute_script_response.json_result());
+
+    // NOTE: This is assumed to be a valid JSON value.
+    auto result = MUST(JsonValue::from_string(execute_script_response.json_result()));
+
+    switch (execute_script_response.result_type()) {
+    // 6. If promise is still pending and the session script timeout is reached, return error with error code script timeout.
+    case Web::WebDriver::ExecuteScriptResultType::Timeout:
+        return WebDriverError::from_code(ErrorCode::ScriptTimeoutError, "Script timed out");
+    // 7. Upon fulfillment of promise with value v, let result be a JSON clone of v, and return success with data result.
+    case Web::WebDriver::ExecuteScriptResultType::PromiseResolved:
+        return result;
+    // 8. Upon rejection of promise with reason r, let result be a JSON clone of r, and return error with error code javascript error and data result.
+    case Web::WebDriver::ExecuteScriptResultType::PromiseRejected:
+        return WebDriverError::from_code(ErrorCode::JavascriptError, "Script returned an error", move(result));
+    default:
+        VERIFY_NOT_REACHED();
+    }
+}
+
 // https://w3c.github.io/webdriver/#dfn-serialized-cookie
 static JsonObject serialize_cookie(Web::Cookie::Cookie const& cookie)
 {

+ 1 - 0
Userland/Services/WebDriver/Session.h

@@ -64,6 +64,7 @@ public:
     ErrorOr<JsonValue, WebDriverError> get_element_text(JsonValue const& payload, StringView element_id);
     ErrorOr<JsonValue, WebDriverError> get_element_tag_name(JsonValue const& payload, StringView element_id);
     ErrorOr<JsonValue, WebDriverError> execute_script(JsonValue const& payload);
+    ErrorOr<JsonValue, WebDriverError> execute_async_script(JsonValue const& payload);
     ErrorOr<JsonValue, WebDriverError> get_all_cookies();
     ErrorOr<JsonValue, WebDriverError> get_named_cookie(String const& name);
     ErrorOr<JsonValue, WebDriverError> add_cookie(JsonValue const& payload);