Ver código fonte

WebContent+WebDriver: Fully implement closing a session

There were a couple steps missing to close the remote end. Further, we
were not removing the session from the list of active sessions.
Timothy Flynn 2 anos atrás
pai
commit
cc78a74c51

+ 1 - 0
Userland/Services/WebContent/WebDriverClient.ipc

@@ -1,6 +1,7 @@
 #include <LibWeb/WebDriver/Response.h>
 
 endpoint WebDriverClient {
+    close_session() => ()
     set_is_webdriver_active(bool active) =|
     navigate_to(JsonValue payload) => (Web::WebDriver::Response response)
     get_current_url() => (Web::WebDriver::Response response)

+ 10 - 0
Userland/Services/WebContent/WebDriverConnection.cpp

@@ -50,6 +50,16 @@ WebDriverConnection::WebDriverConnection(NonnullOwnPtr<Core::Stream::LocalSocket
 {
 }
 
+// https://w3c.github.io/webdriver/#dfn-close-the-session
+void WebDriverConnection::close_session()
+{
+    // 1. Set the webdriver-active flag to false.
+    set_is_webdriver_active(false);
+
+    // 2. An endpoint node must close any top-level browsing contexts associated with the session, without prompting to unload.
+    m_page_host.page().top_level_browsing_context().close();
+}
+
 void WebDriverConnection::set_is_webdriver_active(bool is_webdriver_active)
 {
     m_page_host.set_is_webdriver_active(is_webdriver_active);

+ 2 - 0
Userland/Services/WebContent/WebDriverConnection.h

@@ -28,6 +28,8 @@ private:
     WebDriverConnection(NonnullOwnPtr<Core::Stream::LocalSocket> socket, PageHost& page_host);
 
     virtual void die() override { }
+
+    virtual void close_session() override;
     virtual void set_is_webdriver_active(bool) override;
     virtual Messages::WebDriverClient::NavigateToResponse navigate_to(JsonValue const& payload) override;
     virtual Messages::WebDriverClient::GetCurrentUrlResponse get_current_url() override;

+ 17 - 5
Userland/Services/WebDriver/Client.cpp

@@ -331,6 +331,21 @@ ErrorOr<Session*, Web::WebDriver::Error> Client::find_session_with_id(StringView
     return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
 }
 
+ErrorOr<NonnullOwnPtr<Session>, Web::WebDriver::Error> Client::take_session_with_id(StringView session_id)
+{
+    auto session_id_or_error = session_id.to_uint<>();
+    if (!session_id_or_error.has_value())
+        return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
+
+    for (size_t i = 0; i < Client::s_sessions.size(); ++i) {
+        if (Client::s_sessions[i].session_id() == session_id_or_error.value()) {
+            return Client::s_sessions.take(i);
+        }
+    }
+
+    return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidSessionId, "Invalid session id");
+}
+
 void Client::close_session(unsigned session_id)
 {
     bool found = Client::s_sessions.remove_first_matching([&](auto const& it) {
@@ -426,11 +441,8 @@ Web::WebDriver::Response Client::handle_delete_session(Vector<StringView> const&
     dbgln_if(WEBDRIVER_DEBUG, "Handling DELETE /session/<session_id>");
 
     // 1. If the current session is an active session, try to close the session.
-    auto* session = TRY(find_session_with_id(parameters[0]));
-
-    auto stop_result = session->stop();
-    if (stop_result.is_error())
-        return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::UnsupportedOperation, stop_result.error().string_literal());
+    auto session = TRY(take_session_with_id(parameters[0]));
+    TRY(session->stop());
 
     // 2. Return success with data null.
     return make_json_value(JsonValue());

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

@@ -91,6 +91,7 @@ private:
     Web::WebDriver::Response handle_take_element_screenshot(Vector<StringView> const&, JsonValue const& payload);
 
     ErrorOr<Session*, Web::WebDriver::Error> find_session_with_id(StringView session_id);
+    ErrorOr<NonnullOwnPtr<Session>, Web::WebDriver::Error> take_session_with_id(StringView session_id);
     JsonValue make_json_value(JsonValue const&);
 
     template<typename T>

+ 15 - 2
Userland/Services/WebDriver/Session.cpp

@@ -136,10 +136,23 @@ ErrorOr<void> Session::start()
     return {};
 }
 
-ErrorOr<void> Session::stop()
+// https://w3c.github.io/webdriver/#dfn-close-the-session
+Web::WebDriver::Response Session::stop()
 {
+    // 1. Perform the following substeps based on the remote end’s type:
+    // NOTE: We perform the "Remote end is an endpoint node" steps in the WebContent process.
+    m_web_content_connection->close_session();
+    m_web_content_connection = nullptr;
+
+    // 2. Remove the current session from active sessions.
+    // NOTE: Handled by WebDriver::Client.
+
+    // 3. Perform any implementation-specific cleanup steps.
     m_browser_connection->async_quit();
-    return {};
+    m_started = false;
+
+    // 4. If an error has occurred in any of the steps above, return the error, otherwise return success with data null.
+    return JsonValue {};
 }
 
 // 9.1 Get Timeouts, https://w3c.github.io/webdriver/#dfn-get-timeouts

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

@@ -48,7 +48,7 @@ public:
     }
 
     ErrorOr<void> start();
-    ErrorOr<void> stop();
+    Web::WebDriver::Response stop();
     JsonObject get_timeouts();
     Web::WebDriver::Response set_timeouts(JsonValue const& payload);
     Web::WebDriver::Response back();