/src/serenity/Userland/Libraries/LibWeb/Page/Page.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2020-2023, Andreas Kling <kling@serenityos.org> |
3 | | * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org> |
4 | | * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> |
5 | | * Copyright (c) 2023, Shannon Booth <shannon@serenityos.org> |
6 | | * |
7 | | * SPDX-License-Identifier: BSD-2-Clause |
8 | | */ |
9 | | |
10 | | #pragma once |
11 | | |
12 | | #include <AK/Noncopyable.h> |
13 | | #include <AK/OwnPtr.h> |
14 | | #include <AK/RefPtr.h> |
15 | | #include <AK/WeakPtr.h> |
16 | | #include <AK/Weakable.h> |
17 | | #include <LibGfx/Forward.h> |
18 | | #include <LibGfx/Palette.h> |
19 | | #include <LibGfx/Point.h> |
20 | | #include <LibGfx/Rect.h> |
21 | | #include <LibGfx/Size.h> |
22 | | #include <LibGfx/StandardCursor.h> |
23 | | #include <LibIPC/Forward.h> |
24 | | #include <LibJS/Heap/Handle.h> |
25 | | #include <LibJS/Heap/Heap.h> |
26 | | #include <LibURL/URL.h> |
27 | | #include <LibWeb/CSS/PreferredColorScheme.h> |
28 | | #include <LibWeb/CSS/PreferredContrast.h> |
29 | | #include <LibWeb/CSS/PreferredMotion.h> |
30 | | #include <LibWeb/CSS/Selector.h> |
31 | | #include <LibWeb/CSS/StyleSheetIdentifier.h> |
32 | | #include <LibWeb/Cookie/Cookie.h> |
33 | | #include <LibWeb/Forward.h> |
34 | | #include <LibWeb/HTML/ActivateTab.h> |
35 | | #include <LibWeb/HTML/AudioPlayState.h> |
36 | | #include <LibWeb/HTML/ColorPickerUpdateState.h> |
37 | | #include <LibWeb/HTML/FileFilter.h> |
38 | | #include <LibWeb/HTML/SelectItem.h> |
39 | | #include <LibWeb/HTML/TokenizedFeatures.h> |
40 | | #include <LibWeb/HTML/WebViewHints.h> |
41 | | #include <LibWeb/Loader/FileRequest.h> |
42 | | #include <LibWeb/Page/EventResult.h> |
43 | | #include <LibWeb/Page/InputEvent.h> |
44 | | #include <LibWeb/PixelUnits.h> |
45 | | #include <LibWeb/UIEvents/KeyCode.h> |
46 | | |
47 | | #ifdef HAS_ACCELERATED_GRAPHICS |
48 | | # include <LibAccelGfx/Context.h> |
49 | | #endif |
50 | | |
51 | | namespace Web { |
52 | | |
53 | | class PageClient; |
54 | | |
55 | | class Page final : public JS::Cell { |
56 | | JS_CELL(Page, JS::Cell); |
57 | | JS_DECLARE_ALLOCATOR(Page); |
58 | | |
59 | | public: |
60 | | static JS::NonnullGCPtr<Page> create(JS::VM&, JS::NonnullGCPtr<PageClient>); |
61 | | |
62 | | ~Page(); |
63 | | |
64 | 0 | PageClient& client() { return m_client; } |
65 | 0 | PageClient const& client() const { return m_client; } |
66 | | |
67 | | void set_top_level_traversable(JS::NonnullGCPtr<HTML::TraversableNavigable>); |
68 | | |
69 | | // FIXME: This is a hack. |
70 | | bool top_level_traversable_is_initialized() const; |
71 | | |
72 | | HTML::BrowsingContext& top_level_browsing_context(); |
73 | | HTML::BrowsingContext const& top_level_browsing_context() const; |
74 | | |
75 | | JS::NonnullGCPtr<HTML::TraversableNavigable> top_level_traversable() const; |
76 | | |
77 | | HTML::Navigable& focused_navigable(); |
78 | 0 | HTML::Navigable const& focused_navigable() const { return const_cast<Page*>(this)->focused_navigable(); } |
79 | | |
80 | | void set_focused_navigable(Badge<EventHandler>, HTML::Navigable&); |
81 | | |
82 | | void load(URL::URL const&); |
83 | | |
84 | | void load_html(StringView); |
85 | | |
86 | | void reload(); |
87 | | |
88 | | void traverse_the_history_by_delta(int delta); |
89 | | |
90 | | CSSPixelPoint device_to_css_point(DevicePixelPoint) const; |
91 | | DevicePixelPoint css_to_device_point(CSSPixelPoint) const; |
92 | | DevicePixelRect css_to_device_rect(CSSPixelRect) const; |
93 | | CSSPixelRect device_to_css_rect(DevicePixelRect) const; |
94 | | CSSPixelSize device_to_css_size(DevicePixelSize) const; |
95 | | DevicePixelRect enclosing_device_rect(CSSPixelRect) const; |
96 | | DevicePixelRect rounded_device_rect(CSSPixelRect) const; |
97 | | |
98 | | EventResult handle_mouseup(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers); |
99 | | EventResult handle_mousedown(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers); |
100 | | EventResult handle_mousemove(DevicePixelPoint, DevicePixelPoint screen_position, unsigned buttons, unsigned modifiers); |
101 | | EventResult handle_mousewheel(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, DevicePixels wheel_delta_x, DevicePixels wheel_delta_y); |
102 | | EventResult handle_doubleclick(DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers); |
103 | | |
104 | | EventResult handle_drag_and_drop_event(DragEvent::Type, DevicePixelPoint, DevicePixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, Vector<HTML::SelectedFile> files); |
105 | | |
106 | | EventResult handle_keydown(UIEvents::KeyCode, unsigned modifiers, u32 code_point); |
107 | | EventResult handle_keyup(UIEvents::KeyCode, unsigned modifiers, u32 code_point); |
108 | | |
109 | | Gfx::Palette palette() const; |
110 | | CSSPixelRect web_exposed_screen_area() const; |
111 | | CSS::PreferredColorScheme preferred_color_scheme() const; |
112 | | CSS::PreferredContrast preferred_contrast() const; |
113 | | CSS::PreferredMotion preferred_motion() const; |
114 | | |
115 | 0 | bool is_same_origin_policy_enabled() const { return m_same_origin_policy_enabled; } |
116 | 0 | void set_same_origin_policy_enabled(bool b) { m_same_origin_policy_enabled = b; } |
117 | | |
118 | 0 | bool is_scripting_enabled() const { return m_is_scripting_enabled; } |
119 | 0 | void set_is_scripting_enabled(bool b) { m_is_scripting_enabled = b; } |
120 | | |
121 | 0 | bool should_block_pop_ups() const { return m_should_block_pop_ups; } |
122 | 0 | void set_should_block_pop_ups(bool b) { m_should_block_pop_ups = b; } |
123 | | |
124 | 0 | bool is_webdriver_active() const { return m_is_webdriver_active; } |
125 | 0 | void set_is_webdriver_active(bool b) { m_is_webdriver_active = b; } |
126 | | |
127 | 0 | DevicePixelPoint window_position() const { return m_window_position; } |
128 | 0 | void set_window_position(DevicePixelPoint position) { m_window_position = position; } |
129 | | |
130 | 0 | DevicePixelSize window_size() const { return m_window_size; } |
131 | 0 | void set_window_size(DevicePixelSize size) { m_window_size = size; } |
132 | | |
133 | | void did_request_alert(String const& message); |
134 | | void alert_closed(); |
135 | | |
136 | | bool did_request_confirm(String const& message); |
137 | | void confirm_closed(bool accepted); |
138 | | |
139 | | Optional<String> did_request_prompt(String const& message, String const& default_); |
140 | | void prompt_closed(Optional<String> response); |
141 | | |
142 | | enum class PendingDialog { |
143 | | None, |
144 | | Alert, |
145 | | Confirm, |
146 | | Prompt, |
147 | | }; |
148 | 0 | bool has_pending_dialog() const { return m_pending_dialog != PendingDialog::None; } |
149 | 0 | PendingDialog pending_dialog() const { return m_pending_dialog; } |
150 | 0 | Optional<String> const& pending_dialog_text() const { return m_pending_dialog_text; } |
151 | | void dismiss_dialog(JS::GCPtr<JS::HeapFunction<void()>> on_dialog_closed = nullptr); |
152 | | void accept_dialog(JS::GCPtr<JS::HeapFunction<void()>> on_dialog_closed = nullptr); |
153 | | |
154 | | void did_request_color_picker(WeakPtr<HTML::HTMLInputElement> target, Color current_color); |
155 | | void color_picker_update(Optional<Color> picked_color, HTML::ColorPickerUpdateState state); |
156 | | |
157 | | void did_request_file_picker(WeakPtr<HTML::HTMLInputElement> target, HTML::FileFilter accepted_file_types, HTML::AllowMultipleFiles); |
158 | | void file_picker_closed(Span<HTML::SelectedFile> selected_files); |
159 | | |
160 | | void did_request_select_dropdown(WeakPtr<HTML::HTMLSelectElement> target, Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items); |
161 | | void select_dropdown_closed(Optional<u32> const& selected_item_id); |
162 | | |
163 | | enum class PendingNonBlockingDialog { |
164 | | None, |
165 | | ColorPicker, |
166 | | FilePicker, |
167 | | Select, |
168 | | }; |
169 | | |
170 | | void register_media_element(Badge<HTML::HTMLMediaElement>, int media_id); |
171 | | void unregister_media_element(Badge<HTML::HTMLMediaElement>, int media_id); |
172 | | |
173 | | struct MediaContextMenu { |
174 | | URL::URL media_url; |
175 | | bool is_video { false }; |
176 | | bool is_playing { false }; |
177 | | bool is_muted { false }; |
178 | | bool has_user_agent_controls { false }; |
179 | | bool is_looping { false }; |
180 | | }; |
181 | | void did_request_media_context_menu(i32 media_id, CSSPixelPoint, ByteString const& target, unsigned modifiers, MediaContextMenu); |
182 | | WebIDL::ExceptionOr<void> toggle_media_play_state(); |
183 | | void toggle_media_mute_state(); |
184 | | WebIDL::ExceptionOr<void> toggle_media_loop_state(); |
185 | | WebIDL::ExceptionOr<void> toggle_media_controls_state(); |
186 | | |
187 | 0 | HTML::MuteState page_mute_state() const { return m_mute_state; } |
188 | | void toggle_page_mute_state(); |
189 | | |
190 | 0 | Optional<String> const& user_style() const { return m_user_style_sheet_source; } |
191 | | void set_user_style(String source); |
192 | | |
193 | 0 | bool pdf_viewer_supported() const { return m_pdf_viewer_supported; } |
194 | | |
195 | | void clear_selection(); |
196 | | |
197 | | enum class WrapAround { |
198 | | Yes, |
199 | | No, |
200 | | }; |
201 | | struct FindInPageQuery { |
202 | | String string {}; |
203 | | CaseSensitivity case_sensitivity { CaseSensitivity::CaseInsensitive }; |
204 | | WrapAround wrap_around { WrapAround::Yes }; |
205 | | }; |
206 | | struct FindInPageResult { |
207 | | size_t current_match_index { 0 }; |
208 | | Optional<size_t> total_match_count {}; |
209 | | }; |
210 | | FindInPageResult find_in_page(FindInPageQuery const&); |
211 | | FindInPageResult find_in_page_next_match(); |
212 | | FindInPageResult find_in_page_previous_match(); |
213 | 0 | Optional<FindInPageQuery> last_find_in_page_query() const { return m_last_find_in_page_query; } |
214 | | |
215 | | private: |
216 | | explicit Page(JS::NonnullGCPtr<PageClient>); |
217 | | virtual void visit_edges(Visitor&) override; |
218 | | |
219 | | JS::GCPtr<HTML::HTMLMediaElement> media_context_menu_element(); |
220 | | |
221 | | Vector<JS::Handle<DOM::Document>> documents_in_active_window() const; |
222 | | |
223 | | enum class SearchDirection { |
224 | | Forward, |
225 | | Backward, |
226 | | }; |
227 | | FindInPageResult perform_find_in_page_query(FindInPageQuery const&, Optional<SearchDirection> = {}); |
228 | | void update_find_in_page_selection(Vector<JS::Handle<DOM::Range>> matches); |
229 | | |
230 | | void on_pending_dialog_closed(); |
231 | | |
232 | | JS::NonnullGCPtr<PageClient> m_client; |
233 | | |
234 | | WeakPtr<HTML::Navigable> m_focused_navigable; |
235 | | |
236 | | JS::GCPtr<HTML::TraversableNavigable> m_top_level_traversable; |
237 | | |
238 | | // FIXME: Enable this by default once CORS preflight checks are supported. |
239 | | bool m_same_origin_policy_enabled { false }; |
240 | | |
241 | | bool m_is_scripting_enabled { true }; |
242 | | |
243 | | bool m_should_block_pop_ups { true }; |
244 | | |
245 | | // https://w3c.github.io/webdriver/#dfn-webdriver-active-flag |
246 | | // The webdriver-active flag is set to true when the user agent is under remote control. It is initially false. |
247 | | bool m_is_webdriver_active { false }; |
248 | | |
249 | | DevicePixelPoint m_window_position {}; |
250 | | DevicePixelSize m_window_size {}; |
251 | | |
252 | | PendingDialog m_pending_dialog { PendingDialog::None }; |
253 | | Optional<String> m_pending_dialog_text; |
254 | | Optional<Empty> m_pending_alert_response; |
255 | | Optional<bool> m_pending_confirm_response; |
256 | | Optional<Optional<String>> m_pending_prompt_response; |
257 | | JS::GCPtr<JS::HeapFunction<void()>> m_on_pending_dialog_closed; |
258 | | |
259 | | PendingNonBlockingDialog m_pending_non_blocking_dialog { PendingNonBlockingDialog::None }; |
260 | | WeakPtr<HTML::HTMLElement> m_pending_non_blocking_dialog_target; |
261 | | |
262 | | Vector<int> m_media_elements; |
263 | | Optional<int> m_media_context_menu_element_id; |
264 | | |
265 | | Web::HTML::MuteState m_mute_state { Web::HTML::MuteState::Unmuted }; |
266 | | |
267 | | Optional<String> m_user_style_sheet_source; |
268 | | |
269 | | // https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewer-supported |
270 | | // Each user agent has a PDF viewer supported boolean, whose value is implementation-defined (and might vary according to user preferences). |
271 | | // Spec Note: This value also impacts the navigation processing model. |
272 | | // FIXME: Actually support pdf viewing |
273 | | bool m_pdf_viewer_supported { false }; |
274 | | size_t m_find_in_page_match_index { 0 }; |
275 | | Optional<FindInPageQuery> m_last_find_in_page_query; |
276 | | URL::URL m_last_find_in_page_url; |
277 | | }; |
278 | | |
279 | | struct PaintOptions { |
280 | | enum class PaintOverlay { |
281 | | No, |
282 | | Yes, |
283 | | }; |
284 | | |
285 | | PaintOverlay paint_overlay { PaintOverlay::Yes }; |
286 | | bool should_show_line_box_borders { false }; |
287 | | bool has_focus { false }; |
288 | | |
289 | | #ifdef HAS_ACCELERATED_GRAPHICS |
290 | | AccelGfx::Context* accelerated_graphics_context { nullptr }; |
291 | | #endif |
292 | | }; |
293 | | |
294 | | enum class DisplayListPlayerType { |
295 | | CPU, |
296 | | CPUWithExperimentalTransformSupport, |
297 | | GPU, |
298 | | }; |
299 | | |
300 | | class PageClient : public JS::Cell { |
301 | | JS_CELL(PageClient, JS::Cell); |
302 | | |
303 | | public: |
304 | | virtual Page& page() = 0; |
305 | | virtual Page const& page() const = 0; |
306 | | virtual bool is_connection_open() const = 0; |
307 | | virtual Gfx::Palette palette() const = 0; |
308 | | virtual DevicePixelRect screen_rect() const = 0; |
309 | | virtual double device_pixels_per_css_pixel() const = 0; |
310 | | virtual CSS::PreferredColorScheme preferred_color_scheme() const = 0; |
311 | | virtual CSS::PreferredContrast preferred_contrast() const = 0; |
312 | | virtual CSS::PreferredMotion preferred_motion() const = 0; |
313 | | virtual void paint_next_frame() = 0; |
314 | | virtual void paint(DevicePixelRect const&, Gfx::Bitmap&, PaintOptions = {}) = 0; |
315 | 0 | virtual void page_did_change_title(ByteString const&) { } |
316 | 0 | virtual void page_did_change_url(URL::URL const&) { } |
317 | 0 | virtual void page_did_request_navigate_back() { } |
318 | 0 | virtual void page_did_request_navigate_forward() { } |
319 | 0 | virtual void page_did_request_refresh() { } |
320 | 0 | virtual Gfx::IntSize page_did_request_resize_window(Gfx::IntSize) { return {}; } |
321 | 0 | virtual Gfx::IntPoint page_did_request_reposition_window(Gfx::IntPoint) { return {}; } |
322 | 0 | virtual void page_did_request_restore_window() { } |
323 | 0 | virtual Gfx::IntRect page_did_request_maximize_window() { return {}; } |
324 | 0 | virtual Gfx::IntRect page_did_request_minimize_window() { return {}; } |
325 | 0 | virtual Gfx::IntRect page_did_request_fullscreen_window() { return {}; } |
326 | 0 | virtual void page_did_start_loading(URL::URL const&, bool is_redirect) { (void)is_redirect; } |
327 | 0 | virtual void page_did_create_new_document(Web::DOM::Document&) { } |
328 | 0 | virtual void page_did_change_active_document_in_top_level_browsing_context(Web::DOM::Document&) { } |
329 | 0 | virtual void page_did_finish_loading(URL::URL const&) { } |
330 | 0 | virtual void page_did_request_cursor_change(Gfx::StandardCursor) { } |
331 | 0 | virtual void page_did_request_context_menu(CSSPixelPoint) { } |
332 | 0 | virtual void page_did_request_link_context_menu(CSSPixelPoint, URL::URL const&, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers) { } |
333 | 0 | virtual void page_did_request_image_context_menu(CSSPixelPoint, URL::URL const&, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers, Gfx::Bitmap const*) { } |
334 | 0 | virtual void page_did_request_media_context_menu(CSSPixelPoint, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers, Page::MediaContextMenu) { } |
335 | 0 | virtual void page_did_click_link(URL::URL const&, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers) { } |
336 | 0 | virtual void page_did_middle_click_link(URL::URL const&, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers) { } |
337 | 0 | virtual void page_did_request_tooltip_override(CSSPixelPoint, ByteString const&) { } |
338 | 0 | virtual void page_did_stop_tooltip_override() { } |
339 | 0 | virtual void page_did_enter_tooltip_area(ByteString const&) { } |
340 | 0 | virtual void page_did_leave_tooltip_area() { } |
341 | 0 | virtual void page_did_hover_link(URL::URL const&) { } |
342 | 0 | virtual void page_did_unhover_link() { } |
343 | 0 | virtual void page_did_change_favicon(Gfx::Bitmap const&) { } |
344 | 0 | virtual void page_did_layout() { } |
345 | 0 | virtual void page_did_request_alert(String const&) { } |
346 | 0 | virtual void page_did_request_confirm(String const&) { } |
347 | 0 | virtual void page_did_request_prompt(String const&, String const&) { } |
348 | 0 | virtual void page_did_request_set_prompt_text(String const&) { } |
349 | 0 | virtual void page_did_request_accept_dialog() { } |
350 | 0 | virtual void page_did_request_dismiss_dialog() { } |
351 | 0 | virtual Vector<Web::Cookie::Cookie> page_did_request_all_cookies(URL::URL const&) { return {}; } |
352 | 0 | virtual Optional<Web::Cookie::Cookie> page_did_request_named_cookie(URL::URL const&, String const&) { return {}; } |
353 | 0 | virtual String page_did_request_cookie(URL::URL const&, Cookie::Source) { return {}; } |
354 | 0 | virtual void page_did_set_cookie(URL::URL const&, Cookie::ParsedCookie const&, Cookie::Source) { } |
355 | 0 | virtual void page_did_update_cookie(Web::Cookie::Cookie) { } |
356 | 0 | virtual void page_did_update_resource_count(i32) { } |
357 | | struct NewWebViewResult { |
358 | | JS::GCPtr<Page> page; |
359 | | String window_handle; |
360 | | }; |
361 | 0 | virtual NewWebViewResult page_did_request_new_web_view(HTML::ActivateTab, HTML::WebViewHints, HTML::TokenizedFeature::NoOpener) { return {}; } |
362 | 0 | virtual void page_did_request_activate_tab() { } |
363 | 0 | virtual void page_did_close_top_level_traversable() { } |
364 | 0 | virtual void page_did_update_navigation_buttons_state([[maybe_unused]] bool back_enabled, [[maybe_unused]] bool forward_enabled) { } |
365 | | |
366 | | virtual void request_file(FileRequest) = 0; |
367 | | |
368 | | // https://html.spec.whatwg.org/multipage/input.html#show-the-picker,-if-applicable |
369 | 0 | virtual void page_did_request_color_picker([[maybe_unused]] Color current_color) { } |
370 | 0 | virtual void page_did_request_file_picker([[maybe_unused]] HTML::FileFilter accepted_file_types, Web::HTML::AllowMultipleFiles) { } |
371 | 0 | virtual void page_did_request_select_dropdown([[maybe_unused]] Web::CSSPixelPoint content_position, [[maybe_unused]] Web::CSSPixels minimum_width, [[maybe_unused]] Vector<Web::HTML::SelectItem> items) { } |
372 | | |
373 | 0 | virtual void page_did_finish_text_test([[maybe_unused]] String const& text) { } |
374 | | |
375 | 0 | virtual void page_did_change_theme_color(Gfx::Color) { } |
376 | | |
377 | 0 | virtual void page_did_insert_clipboard_entry([[maybe_unused]] String data, [[maybe_unused]] String presentation_style, [[maybe_unused]] String mime_type) { } |
378 | | |
379 | 0 | virtual void page_did_change_audio_play_state(HTML::AudioPlayState) { } |
380 | | |
381 | 0 | virtual IPC::File request_worker_agent() { return IPC::File {}; } |
382 | | |
383 | 0 | virtual void inspector_did_load() { } |
384 | 0 | virtual void inspector_did_select_dom_node([[maybe_unused]] i32 node_id, [[maybe_unused]] Optional<CSS::Selector::PseudoElement::Type> const& pseudo_element) { } |
385 | 0 | virtual void inspector_did_set_dom_node_text([[maybe_unused]] i32 node_id, [[maybe_unused]] String const& text) { } |
386 | 0 | virtual void inspector_did_set_dom_node_tag([[maybe_unused]] i32 node_id, [[maybe_unused]] String const& tag) { } |
387 | 0 | virtual void inspector_did_add_dom_node_attributes([[maybe_unused]] i32 node_id, [[maybe_unused]] JS::NonnullGCPtr<DOM::NamedNodeMap> attributes) { } |
388 | 0 | virtual void inspector_did_replace_dom_node_attribute([[maybe_unused]] i32 node_id, [[maybe_unused]] size_t attribute_index, [[maybe_unused]] JS::NonnullGCPtr<DOM::NamedNodeMap> replacement_attributes) { } |
389 | 0 | virtual void inspector_did_request_dom_tree_context_menu([[maybe_unused]] i32 node_id, [[maybe_unused]] CSSPixelPoint position, [[maybe_unused]] String const& type, [[maybe_unused]] Optional<String> const& tag, [[maybe_unused]] Optional<size_t> const& attribute_index) { } |
390 | 0 | virtual void inspector_did_request_style_sheet_source([[maybe_unused]] CSS::StyleSheetIdentifier const& identifier) { } |
391 | 0 | virtual void inspector_did_execute_console_script([[maybe_unused]] String const& script) { } |
392 | 0 | virtual void inspector_did_export_inspector_html([[maybe_unused]] String const& html) { } |
393 | | |
394 | | virtual void schedule_repaint() = 0; |
395 | | virtual bool is_ready_to_paint() const = 0; |
396 | | |
397 | | virtual DisplayListPlayerType display_list_player_type() const = 0; |
398 | | |
399 | | protected: |
400 | | virtual ~PageClient() = default; |
401 | | }; |
402 | | |
403 | | } |
404 | | |
405 | | namespace IPC { |
406 | | |
407 | | template<> |
408 | | ErrorOr<void> encode(Encoder&, Web::Page::MediaContextMenu const&); |
409 | | |
410 | | template<> |
411 | | ErrorOr<Web::Page::MediaContextMenu> decode(Decoder&); |
412 | | |
413 | | } |