Serenity Operating System
at master 189 lines 5.3 kB view raw
1/* 2 * Copyright (c) 2023, Linus Groh <linusg@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Error.h> 8#include <AK/String.h> 9#include <LibWebView/ViewImplementation.h> 10 11namespace WebView { 12 13WebContentClient& ViewImplementation::client() 14{ 15 VERIFY(m_client_state.client); 16 return *m_client_state.client; 17} 18 19WebContentClient const& ViewImplementation::client() const 20{ 21 VERIFY(m_client_state.client); 22 return *m_client_state.client; 23} 24 25void ViewImplementation::load(AK::URL const& url) 26{ 27 m_url = url; 28 client().async_load_url(url); 29} 30 31void ViewImplementation::load_html(StringView html, AK::URL const& url) 32{ 33 m_url = url; 34 client().async_load_html(html, url); 35} 36 37void ViewImplementation::load_empty_document() 38{ 39 load_html(""sv, {}); 40} 41 42void ViewImplementation::zoom_in() 43{ 44 if (m_zoom_level >= ZOOM_MAX_LEVEL) 45 return; 46 m_zoom_level += ZOOM_STEP; 47 update_zoom(); 48} 49 50void ViewImplementation::zoom_out() 51{ 52 if (m_zoom_level <= ZOOM_MIN_LEVEL) 53 return; 54 m_zoom_level -= ZOOM_STEP; 55 update_zoom(); 56} 57 58void ViewImplementation::reset_zoom() 59{ 60 m_zoom_level = 1.0f; 61 update_zoom(); 62} 63 64void ViewImplementation::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme) 65{ 66 client().async_set_preferred_color_scheme(color_scheme); 67} 68 69DeprecatedString ViewImplementation::selected_text() 70{ 71 return client().get_selected_text(); 72} 73 74void ViewImplementation::select_all() 75{ 76 client().async_select_all(); 77} 78 79void ViewImplementation::get_source() 80{ 81 client().async_get_source(); 82} 83 84void ViewImplementation::inspect_dom_tree() 85{ 86 client().async_inspect_dom_tree(); 87} 88 89void ViewImplementation::inspect_accessibility_tree() 90{ 91 client().async_inspect_accessibility_tree(); 92} 93 94ErrorOr<ViewImplementation::DOMNodeProperties> ViewImplementation::inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement> pseudo_element) 95{ 96 auto response = client().inspect_dom_node(node_id, pseudo_element); 97 if (!response.has_style()) 98 return Error::from_string_view("Inspected node returned no style"sv); 99 return DOMNodeProperties { 100 .computed_style_json = TRY(String::from_deprecated_string(response.take_computed_style())), 101 .resolved_style_json = TRY(String::from_deprecated_string(response.take_resolved_style())), 102 .custom_properties_json = TRY(String::from_deprecated_string(response.take_custom_properties())), 103 .node_box_sizing_json = TRY(String::from_deprecated_string(response.take_node_box_sizing())), 104 }; 105} 106 107void ViewImplementation::clear_inspected_dom_node() 108{ 109 client().inspect_dom_node(0, {}); 110} 111 112i32 ViewImplementation::get_hovered_node_id() 113{ 114 return client().get_hovered_node_id(); 115} 116 117void ViewImplementation::debug_request(DeprecatedString const& request, DeprecatedString const& argument) 118{ 119 client().async_debug_request(request, argument); 120} 121 122void ViewImplementation::run_javascript(StringView js_source) 123{ 124 client().async_run_javascript(js_source); 125} 126 127#if !defined(AK_OS_SERENITY) 128 129ErrorOr<NonnullRefPtr<WebView::WebContentClient>> ViewImplementation::launch_web_content_process(ReadonlySpan<String> candidate_web_content_paths, StringView webdriver_content_ipc_path) 130{ 131 int socket_fds[2] {}; 132 TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, socket_fds)); 133 134 int ui_fd = socket_fds[0]; 135 int wc_fd = socket_fds[1]; 136 137 int fd_passing_socket_fds[2] {}; 138 TRY(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, fd_passing_socket_fds)); 139 140 int ui_fd_passing_fd = fd_passing_socket_fds[0]; 141 int wc_fd_passing_fd = fd_passing_socket_fds[1]; 142 143 if (auto child_pid = TRY(Core::System::fork()); child_pid == 0) { 144 TRY(Core::System::close(ui_fd_passing_fd)); 145 TRY(Core::System::close(ui_fd)); 146 147 auto takeover_string = TRY(String::formatted("WebContent:{}", wc_fd)); 148 TRY(Core::System::setenv("SOCKET_TAKEOVER"sv, takeover_string, true)); 149 150 auto webcontent_fd_passing_socket_string = TRY(String::number(wc_fd_passing_fd)); 151 152 Vector<StringView> arguments { 153 "WebContent"sv, 154 "--webcontent-fd-passing-socket"sv, 155 webcontent_fd_passing_socket_string 156 }; 157 158 if (!webdriver_content_ipc_path.is_empty()) { 159 TRY(arguments.try_append("--webdriver-content-path"sv)); 160 TRY(arguments.try_append(webdriver_content_ipc_path)); 161 } 162 163 ErrorOr<void> result; 164 for (auto const& path : candidate_web_content_paths) { 165 result = Core::System::exec(path, arguments, Core::System::SearchInPath::Yes); 166 if (!result.is_error()) 167 break; 168 } 169 170 if (result.is_error()) 171 warnln("Could not launch any of {}: {}", candidate_web_content_paths, result.error()); 172 VERIFY_NOT_REACHED(); 173 } 174 175 TRY(Core::System::close(wc_fd_passing_fd)); 176 TRY(Core::System::close(wc_fd)); 177 178 auto socket = TRY(Core::LocalSocket::adopt_fd(ui_fd)); 179 TRY(socket->set_blocking(true)); 180 181 auto new_client = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) WebView::WebContentClient(move(socket), *this))); 182 new_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(ui_fd_passing_fd))); 183 184 return new_client; 185} 186 187#endif 188 189}