/src/serenity/Userland/Libraries/LibWeb/Loader/ResourceLoader.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org> |
3 | | * Copyright (c) 2022, Dex♪ <dexes.ttp@gmail.com> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #pragma once |
9 | | |
10 | | #include <AK/ByteString.h> |
11 | | #include <AK/Function.h> |
12 | | #include <AK/HashMap.h> |
13 | | #include <LibCore/EventReceiver.h> |
14 | | #include <LibCore/Proxy.h> |
15 | | #include <LibJS/SafeFunction.h> |
16 | | #include <LibProtocol/Request.h> |
17 | | #include <LibURL/URL.h> |
18 | | #include <LibWeb/Loader/Resource.h> |
19 | | #include <LibWeb/Loader/UserAgent.h> |
20 | | #include <LibWeb/Page/Page.h> |
21 | | |
22 | | namespace Web { |
23 | | |
24 | | namespace WebSockets { |
25 | | class WebSocketClientSocket; |
26 | | } |
27 | | |
28 | | class ResourceLoaderConnectorRequest : public RefCounted<ResourceLoaderConnectorRequest> { |
29 | | public: |
30 | | virtual ~ResourceLoaderConnectorRequest(); |
31 | | |
32 | | struct CertificateAndKey { |
33 | | ByteString certificate; |
34 | | ByteString key; |
35 | | }; |
36 | | |
37 | | // Configure the request such that the entirety of the response data is buffered. The callback receives that data and |
38 | | // the response headers all at once. Using this method is mutually exclusive with `set_unbuffered_data_received_callback`. |
39 | | virtual void set_buffered_request_finished_callback(Protocol::Request::BufferedRequestFinished) = 0; |
40 | | |
41 | | // Configure the request such that the response data is provided unbuffered as it is received. Using this method is |
42 | | // mutually exclusive with `set_buffered_request_finished_callback`. |
43 | | virtual void set_unbuffered_request_callbacks(Protocol::Request::HeadersReceived, Protocol::Request::DataReceived, Protocol::Request::RequestFinished) = 0; |
44 | | |
45 | | virtual bool stop() = 0; |
46 | | |
47 | | Function<void(Optional<u64> total_size, u64 downloaded_size)> on_progress; |
48 | | Function<CertificateAndKey()> on_certificate_requested; |
49 | | |
50 | | protected: |
51 | | explicit ResourceLoaderConnectorRequest(); |
52 | | }; |
53 | | |
54 | | class ResourceLoaderConnector : public RefCounted<ResourceLoaderConnector> { |
55 | | public: |
56 | | virtual ~ResourceLoaderConnector(); |
57 | | |
58 | | virtual void prefetch_dns(URL::URL const&) = 0; |
59 | | virtual void preconnect(URL::URL const&) = 0; |
60 | | |
61 | | virtual RefPtr<ResourceLoaderConnectorRequest> start_request(ByteString const& method, URL::URL const&, HTTP::HeaderMap const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {}) = 0; |
62 | | virtual RefPtr<Web::WebSockets::WebSocketClientSocket> websocket_connect(const URL::URL&, ByteString const& origin, Vector<ByteString> const& protocols) = 0; |
63 | | |
64 | | protected: |
65 | | explicit ResourceLoaderConnector(); |
66 | | }; |
67 | | |
68 | | class ResourceLoader : public Core::EventReceiver { |
69 | | C_OBJECT_ABSTRACT(ResourceLoader) |
70 | | public: |
71 | | static void initialize(RefPtr<ResourceLoaderConnector>); |
72 | | static ResourceLoader& the(); |
73 | | |
74 | | RefPtr<Resource> load_resource(Resource::Type, LoadRequest&); |
75 | | |
76 | | using SuccessCallback = JS::SafeFunction<void(ReadonlyBytes, HTTP::HeaderMap const& response_headers, Optional<u32> status_code)>; |
77 | | using ErrorCallback = JS::SafeFunction<void(ByteString const&, Optional<u32> status_code, ReadonlyBytes payload, HTTP::HeaderMap const& response_headers)>; |
78 | | using TimeoutCallback = JS::SafeFunction<void()>; |
79 | | |
80 | | void load(LoadRequest&, SuccessCallback success_callback, ErrorCallback error_callback = nullptr, Optional<u32> timeout = {}, TimeoutCallback timeout_callback = nullptr); |
81 | | |
82 | | using OnHeadersReceived = JS::SafeFunction<void(HTTP::HeaderMap const& response_headers, Optional<u32> status_code)>; |
83 | | using OnDataReceived = JS::SafeFunction<void(ReadonlyBytes data)>; |
84 | | using OnComplete = JS::SafeFunction<void(bool success, Optional<StringView> error_message)>; |
85 | | |
86 | | void load_unbuffered(LoadRequest&, OnHeadersReceived, OnDataReceived, OnComplete); |
87 | | |
88 | 0 | ResourceLoaderConnector& connector() { return *m_connector; } |
89 | | |
90 | | void prefetch_dns(URL::URL const&); |
91 | | void preconnect(URL::URL const&); |
92 | | |
93 | | Function<void()> on_load_counter_change; |
94 | | |
95 | 0 | int pending_loads() const { return m_pending_loads; } |
96 | | |
97 | 0 | String const& user_agent() const { return m_user_agent; } |
98 | 0 | void set_user_agent(String user_agent) { m_user_agent = move(user_agent); } |
99 | | |
100 | 0 | String const& platform() const { return m_platform; } |
101 | 0 | void set_platform(String platform) { m_platform = move(platform); } |
102 | | |
103 | 0 | Vector<String> preferred_languages() const { return m_preferred_languages; } |
104 | | void set_preferred_languages(Vector<String> preferred_languages) |
105 | 0 | { |
106 | 0 | // Default to "en" if no preferred languages are specified. |
107 | 0 | if (preferred_languages.is_empty() || (preferred_languages.size() == 1 && preferred_languages[0].is_empty())) { |
108 | 0 | m_preferred_languages = { "en"_string }; |
109 | 0 | } else { |
110 | 0 | m_preferred_languages = move(preferred_languages); |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | 0 | NavigatorCompatibilityMode navigator_compatibility_mode() { return m_navigator_compatibility_mode; } |
115 | 0 | void set_navigator_compatibility_mode(NavigatorCompatibilityMode mode) { m_navigator_compatibility_mode = mode; } |
116 | | |
117 | 0 | bool enable_do_not_track() const { return m_enable_do_not_track; } |
118 | 0 | void set_enable_do_not_track(bool enable) { m_enable_do_not_track = enable; } |
119 | | |
120 | | void clear_cache(); |
121 | | void evict_from_cache(LoadRequest const&); |
122 | | |
123 | | private: |
124 | | ResourceLoader(NonnullRefPtr<ResourceLoaderConnector>); |
125 | | static ErrorOr<NonnullRefPtr<ResourceLoader>> try_create(NonnullRefPtr<ResourceLoaderConnector>); |
126 | | |
127 | | RefPtr<ResourceLoaderConnectorRequest> start_network_request(LoadRequest const&); |
128 | | void handle_network_response_headers(LoadRequest const&, HTTP::HeaderMap const&); |
129 | | void finish_network_request(NonnullRefPtr<ResourceLoaderConnectorRequest> const&); |
130 | | |
131 | | int m_pending_loads { 0 }; |
132 | | |
133 | | HashTable<NonnullRefPtr<ResourceLoaderConnectorRequest>> m_active_requests; |
134 | | NonnullRefPtr<ResourceLoaderConnector> m_connector; |
135 | | String m_user_agent; |
136 | | String m_platform; |
137 | | Vector<String> m_preferred_languages = { "en"_string }; |
138 | | NavigatorCompatibilityMode m_navigator_compatibility_mode; |
139 | | bool m_enable_do_not_track { false }; |
140 | | Optional<JS::GCPtr<Page>> m_page {}; |
141 | | }; |
142 | | |
143 | | } |