summaryrefslogtreecommitdiff
path: root/Userland/Services/WebDriver/Client.h
blob: 8367c98f5ea3cc2c664eff350238af05083f52c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
 * Copyright (c) 2022, Florent Castelli <florent.castelli@gmail.com>
 * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
 * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/NonnullOwnPtrVector.h>
#include <LibCore/Object.h>
#include <LibCore/Stream.h>
#include <LibHTTP/Forward.h>
#include <LibHTTP/HttpRequest.h>
#include <WebDriver/Session.h>
#include <WebDriver/WebDriverError.h>

namespace WebDriver {

class Client final : public Core::Object {
    C_OBJECT(Client);

public:
    void start();
    void close_session(unsigned session_id);

private:
    Client(NonnullOwnPtr<Core::Stream::BufferedTCPSocket>, Core::Object* parent);

    ErrorOr<JsonValue> read_body_as_json(HTTP::HttpRequest const&);
    ErrorOr<bool> handle_request(HTTP::HttpRequest const&, JsonValue const& body);
    ErrorOr<void> send_response(StringView content, HTTP::HttpRequest const&);
    ErrorOr<void> send_error_response(WebDriverError const& error, HTTP::HttpRequest const&);
    void die();
    void log_response(unsigned code, HTTP::HttpRequest const&);

    using RouteHandler = ErrorOr<JsonValue, WebDriverError> (Client::*)(Vector<StringView> const&, JsonValue const&);
    struct Route {
        HTTP::HttpRequest::Method method;
        Vector<String> path;
        RouteHandler handler;
    };

    struct RoutingResult {
        RouteHandler handler;
        Vector<StringView> parameters;
    };

    ErrorOr<RoutingResult, WebDriverError> match_route(HTTP::HttpRequest::Method method, String const& resource);
    ErrorOr<JsonValue, WebDriverError> handle_new_session(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_delete_session(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_status(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_timeouts(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_set_timeouts(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_navigate_to(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_current_url(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_back(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_forward(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_refresh(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_title(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_window_handle(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_close_window(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_window_handles(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_window_rect(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_set_window_rect(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_maximize_window(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_minimize_window(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_find_element(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_find_elements(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_find_element_from_element(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_find_elements_from_element(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_is_element_selected(Vector<StringView> const& parameters, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_element_attribute(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_element_property(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_element_css_value(Vector<StringView> const&, JsonValue const& payload);
    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_get_element_rect(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_is_element_enabled(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_get_source(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);
    ErrorOr<JsonValue, WebDriverError> handle_delete_cookie(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_delete_all_cookies(Vector<StringView> const&, JsonValue const& payload);
    ErrorOr<JsonValue, WebDriverError> handle_take_screenshot(Vector<StringView> const&, JsonValue const& payload);

    ErrorOr<Session*, WebDriverError> find_session_with_id(StringView session_id);
    JsonValue make_json_value(JsonValue const&);

    template<typename T>
    static ErrorOr<T, WebDriverError> unwrap_result(ErrorOr<T, Variant<WebDriverError, Error>> result)
    {
        if (result.is_error()) {
            Variant<WebDriverError, Error> error = result.release_error();
            if (error.has<WebDriverError>())
                return error.get<WebDriverError>();
            return WebDriverError::from_code(ErrorCode::UnsupportedOperation, error.get<Error>().string_literal());
        }

        return result.release_value();
    }
    static ErrorOr<void, WebDriverError> unwrap_result(ErrorOr<void, Variant<WebDriverError, Error>> result)
    {
        if (result.is_error()) {
            Variant<WebDriverError, Error> error = result.release_error();
            if (error.has<WebDriverError>())
                return error.get<WebDriverError>();
            return WebDriverError::from_code(ErrorCode::UnsupportedOperation, error.get<Error>().string_literal());
        }
        return {};
    }

    NonnullOwnPtr<Core::Stream::BufferedTCPSocket> m_socket;
    static Vector<Route> s_routes;
    String m_prefix = "/";

    static NonnullOwnPtrVector<Session> s_sessions;
    static Atomic<unsigned> s_next_session_id;
};

}