diff --git a/Libraries/LibWebView/Application.cpp b/Libraries/LibWebView/Application.cpp index 5a3d70271d..9a4aff389e 100644 --- a/Libraries/LibWebView/Application.cpp +++ b/Libraries/LibWebView/Application.cpp @@ -504,14 +504,15 @@ void Application::open_url_in_new_window(URL::URL const& url) dbgln("open_url_in_new_window() is unsupported on this platform (url: {})", url); } -static ErrorOr> create_web_content_client(Optional view) +ErrorOr> Application::create_web_content_client(Optional view, u64 initial_page_id) { auto request_server_handle = TRY(connect_new_request_server_client()); auto image_decoder_handle = TRY(connect_new_image_decoder_client()); - NonnullRefPtr client = view.has_value() - ? TRY(WebView::launch_web_content_process(*view)) - : TRY(WebView::launch_spare_web_content_process()); + auto client = TRY(WebView::launch_web_content_process(initial_page_id)); + client->async_initialize(initial_page_id); + if (view.has_value()) + client->assign_view({}, *view); client->async_connect_to_request_server(move(request_server_handle)); client->async_connect_to_image_decoder(move(image_decoder_handle)); @@ -520,6 +521,12 @@ static ErrorOr> create_web_content_client(Option return client; } +u64 Application::allocate_page_id() +{ + VERIFY(m_next_page_id < Web::Compositor::page_presenting_context_id_tag); + return m_next_page_id++; +} + static bool can_send_compositor_process_ipc(RefPtr const& compositor_client) { if (!compositor_client) @@ -652,7 +659,7 @@ ErrorOr> Application::launch_web_content_process } launch_spare_web_content_process(); - return create_web_content_client(view); + return create_web_content_client(view, allocate_page_id()); } void Application::launch_spare_web_content_process() @@ -676,7 +683,7 @@ void Application::launch_spare_web_content_process() Core::deferred_invoke([this]() { m_has_queued_task_to_launch_spare_web_content_process = false; - auto web_content_client = create_web_content_client({}); + auto web_content_client = create_web_content_client({}, allocate_page_id()); if (web_content_client.is_error()) { dbgln("Unable to create spare web content client: {}", web_content_client.error()); return; diff --git a/Libraries/LibWebView/Application.h b/Libraries/LibWebView/Application.h index 5bd14342f3..c0feef865b 100644 --- a/Libraries/LibWebView/Application.h +++ b/Libraries/LibWebView/Application.h @@ -92,6 +92,7 @@ public: #endif ErrorOr> launch_web_content_process(ViewImplementation&); + u64 allocate_page_id(); ErrorOr connect_web_content_to_compositor(WebContentClient&); void register_compositor_context(WebContentClient&, Web::Compositor::CompositorContextId, Optional page_id, Web::Compositor::PagePresentationRegistration); ErrorOr try_register_compositor_context(WebContentClient&, Web::Compositor::CompositorContextId, Optional page_id, Web::Compositor::PagePresentationRegistration); @@ -231,6 +232,7 @@ protected: Main::Arguments& arguments() { return m_arguments; } private: + ErrorOr> create_web_content_client(Optional, u64 initial_page_id); ErrorOr launch_services(); void launch_spare_web_content_process(); ErrorOr launch_compositor_process(); @@ -327,6 +329,7 @@ private: RefPtr m_spare_web_content_process; bool m_has_queued_task_to_launch_spare_web_content_process { false }; + u64 m_next_page_id { 1 }; RefPtr m_database; RefPtr m_history_database; diff --git a/Libraries/LibWebView/HelperProcess.cpp b/Libraries/LibWebView/HelperProcess.cpp index 92922bc2b9..a06c18ee34 100644 --- a/Libraries/LibWebView/HelperProcess.cpp +++ b/Libraries/LibWebView/HelperProcess.cpp @@ -82,8 +82,7 @@ static ErrorOr> launch_server_process( VERIFY_NOT_REACHED(); } -template -static ErrorOr> launch_web_content_process_impl(ClientArguments&&... client_arguments) +ErrorOr> launch_web_content_process(u64 initial_page_id) { auto const& browser_options = WebView::Application::browser_options(); auto const& web_content_options = WebView::Application::web_content_options(); @@ -142,17 +141,7 @@ static ErrorOr> launch_web_content_proc arguments.append("--mach-server-name"sv); arguments.append(server.value()); } - return launch_server_process("WebContent"sv, move(arguments), forward(client_arguments)...); -} - -ErrorOr> launch_web_content_process(WebView::ViewImplementation& view) -{ - return launch_web_content_process_impl(view); -} - -ErrorOr> launch_spare_web_content_process() -{ - return launch_web_content_process_impl(); + return launch_server_process("WebContent"sv, move(arguments), initial_page_id); } ErrorOr> launch_image_decoder_process() diff --git a/Libraries/LibWebView/HelperProcess.h b/Libraries/LibWebView/HelperProcess.h index 2ef4971a76..301fb7b00e 100644 --- a/Libraries/LibWebView/HelperProcess.h +++ b/Libraries/LibWebView/HelperProcess.h @@ -13,15 +13,12 @@ #include #include #include -#include #include #include namespace WebView { -WEBVIEW_API ErrorOr> launch_web_content_process(WebView::ViewImplementation&); - -WEBVIEW_API ErrorOr> launch_spare_web_content_process(); +WEBVIEW_API ErrorOr> launch_web_content_process(u64 initial_page_id); WEBVIEW_API ErrorOr> launch_image_decoder_process(); WEBVIEW_API ErrorOr> launch_compositor_process(); diff --git a/Libraries/LibWebView/WebContentClient.cpp b/Libraries/LibWebView/WebContentClient.cpp index 3825744714..84692ac5db 100644 --- a/Libraries/LibWebView/WebContentClient.cpp +++ b/Libraries/LibWebView/WebContentClient.cpp @@ -46,16 +46,11 @@ static Optional history_title(Utf16String const& title, URL::URL const& return title_utf8; } -WebContentClient::WebContentClient(NonnullOwnPtr transport, ViewImplementation& view) - : IPC::ConnectionToServer(*this, move(transport)) -{ - s_clients.set(this); - m_views.set(0, view); -} - -WebContentClient::WebContentClient(NonnullOwnPtr transport) +WebContentClient::WebContentClient(NonnullOwnPtr transport, u64 initial_page_id) : IPC::ConnectionToServer(*this, move(transport)) + , m_initial_page_id(initial_page_id) { + VERIFY(m_initial_page_id > 0); s_clients.set(this); } @@ -143,7 +138,8 @@ void WebContentClient::remember_compositor_context(Web::Compositor::CompositorCo void WebContentClient::assign_view(Badge, ViewImplementation& view) { VERIFY(m_views.is_empty()); - m_views.set(0, view); + view.m_client_state.page_index = m_initial_page_id; + m_views.set(m_initial_page_id, view); } void WebContentClient::set_compositor_connection_id(Badge, i32 compositor_connection_id) @@ -157,6 +153,7 @@ void WebContentClient::register_view(u64 page_id, ViewImplementation& view) if (m_detached_page_close_timer) m_detached_page_close_timer->stop(); Application::process_manager().cancel_forced_exit(pid()); + view.m_client_state.page_index = page_id; m_views.set(page_id, view); m_history_recorded_urls_for_current_load.remove(page_id); } @@ -405,7 +402,7 @@ void WebContentClient::did_start_loading(u64 page_id, URL::URL url, bool is_redi void WebContentClient::did_finish_loading(u64 page_id, URL::URL url) { if (url.scheme() == "about"sv && url.paths().size() == 1) { - if (auto web_ui = WebUI::create(*this, url.paths().first()); web_ui.is_error()) + if (auto web_ui = WebUI::create(*this, page_id, url.paths().first()); web_ui.is_error()) warnln("Could not create WebUI for {}: {}", url, web_ui.error()); else m_web_ui = web_ui.release_value(); @@ -1016,14 +1013,16 @@ void WebContentClient::did_post_broadcast_channel_message(u64, Web::HTML::Broadc WorkerProcessManager::the().broadcast_channel_message_from_web_content(message); } -Messages::WebContentClient::DidRequestNewWebViewResponse WebContentClient::did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab activate_tab, Web::HTML::WebViewHints hints, Optional page_index) +Messages::WebContentClient::DidRequestNewWebViewResponse WebContentClient::did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab activate_tab, Web::HTML::WebViewHints hints) { + auto new_page_id = Application::the().allocate_page_id(); + String handle; if (auto view = view_for_page_id(page_id); view.has_value()) { if (view->on_new_web_view) - return view->on_new_web_view(activate_tab, hints, page_index); + handle = view->on_new_web_view(activate_tab, hints, new_page_id); } - return String {}; + return { new_page_id, move(handle) }; } void WebContentClient::did_request_activate_tab(u64 page_id) diff --git a/Libraries/LibWebView/WebContentClient.h b/Libraries/LibWebView/WebContentClient.h index b89855b5c2..4370291b3e 100644 --- a/Libraries/LibWebView/WebContentClient.h +++ b/Libraries/LibWebView/WebContentClient.h @@ -54,8 +54,7 @@ public: static size_t client_count() { return s_clients.size(); } static Optional client_for_compositor_context_id(Web::Compositor::CompositorContextId); - explicit WebContentClient(NonnullOwnPtr); - WebContentClient(NonnullOwnPtr, ViewImplementation&); + WebContentClient(NonnullOwnPtr, u64 initial_page_id); ~WebContentClient(); void assign_view(Badge, ViewImplementation&); @@ -161,7 +160,7 @@ private: virtual Messages::WebContentClient::DidRequestStorageKeysResponse did_request_storage_keys(Web::StorageAPI::StorageEndpointType storage_endpoint, String storage_key) override; virtual void did_clear_storage(Web::StorageAPI::StorageEndpointType storage_endpoint, String storage_key) override; virtual void did_post_broadcast_channel_message(u64 page_id, Web::HTML::BroadcastChannelMessage message) override; - virtual Messages::WebContentClient::DidRequestNewWebViewResponse did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab, Web::HTML::WebViewHints, Optional page_index) override; + virtual Messages::WebContentClient::DidRequestNewWebViewResponse did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab, Web::HTML::WebViewHints) override; virtual void did_request_activate_tab(u64 page_id) override; virtual void did_close_browsing_context(u64 page_id) override; virtual void did_change_needs_beforeunload_check(u64 page_id, bool needs_beforeunload_check) override; @@ -211,6 +210,7 @@ private: HashMap m_page_ids_for_compositor_context_ids; HashMap m_history_recorded_urls_for_current_load; Optional m_compositor_connection_id; + u64 m_initial_page_id { 0 }; ProcessHandle m_process_handle; RefPtr m_detached_page_close_timer; diff --git a/Libraries/LibWebView/WebUI.cpp b/Libraries/LibWebView/WebUI.cpp index 98e4fe6eb4..19c7e44c45 100644 --- a/Libraries/LibWebView/WebUI.cpp +++ b/Libraries/LibWebView/WebUI.cpp @@ -16,29 +16,31 @@ namespace WebView { template -static ErrorOr> create_web_ui(WebContentClient& client, String host) +static ErrorOr> create_web_ui(WebContentClient& client, u64 page_id, String host) { + VERIFY(page_id > 0); + auto paired = TRY(IPC::Transport::create_paired()); auto handle = move(paired.remote_handle); auto web_ui = WebUIType::create(client, move(paired.local), move(host)); - client.async_connect_to_web_ui(0, move(handle)); + client.async_connect_to_web_ui(page_id, move(handle)); return web_ui; } -ErrorOr> WebUI::create(WebContentClient& client, String host) +ErrorOr> WebUI::create(WebContentClient& client, u64 page_id, String host) { RefPtr web_ui; if (host == "bookmarks"sv) - web_ui = TRY(create_web_ui(client, move(host))); + web_ui = TRY(create_web_ui(client, page_id, move(host))); else if (host == "processes"sv) - web_ui = TRY(create_web_ui(client, move(host))); + web_ui = TRY(create_web_ui(client, page_id, move(host))); else if (host == "settings"sv) - web_ui = TRY(create_web_ui(client, move(host))); + web_ui = TRY(create_web_ui(client, page_id, move(host))); else if (host == "version"sv) - web_ui = TRY(create_web_ui(client, move(host))); + web_ui = TRY(create_web_ui(client, page_id, move(host))); if (web_ui) web_ui->register_interfaces(); diff --git a/Libraries/LibWebView/WebUI.h b/Libraries/LibWebView/WebUI.h index 556178ef11..ce56f1497a 100644 --- a/Libraries/LibWebView/WebUI.h +++ b/Libraries/LibWebView/WebUI.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -24,7 +25,7 @@ class WEBVIEW_API WebUI : public IPC::ConnectionToServer , public WebUIClientEndpoint { public: - static ErrorOr> create(WebContentClient&, String host); + static ErrorOr> create(WebContentClient&, u64 page_id, String host); virtual ~WebUI(); String const& host() const { return m_host; } diff --git a/Services/WebContent/ConnectionFromClient.cpp b/Services/WebContent/ConnectionFromClient.cpp index a9db927aec..eac86b11ae 100644 --- a/Services/WebContent/ConnectionFromClient.cpp +++ b/Services/WebContent/ConnectionFromClient.cpp @@ -112,6 +112,11 @@ Messages::WebContentServer::InitTransportResponse ConnectionFromClient::init_tra VERIFY_NOT_REACHED(); } +void ConnectionFromClient::initialize(u64 initial_page_id) +{ + m_page_host->initialize(initial_page_id); +} + Optional ConnectionFromClient::page(u64 index, SourceLocation location) { if (auto page = m_page_host->page(index); page.has_value()) diff --git a/Services/WebContent/ConnectionFromClient.h b/Services/WebContent/ConnectionFromClient.h index 54f85e8393..b4694c8cce 100644 --- a/Services/WebContent/ConnectionFromClient.h +++ b/Services/WebContent/ConnectionFromClient.h @@ -66,6 +66,7 @@ private: Optional page(u64 index, SourceLocation = SourceLocation::current()) const; virtual Messages::WebContentServer::InitTransportResponse init_transport(int peer_pid) override; + virtual void initialize(u64 initial_page_id) override; virtual void close_server() override; virtual Messages::WebContentServer::GetWindowHandleResponse get_window_handle(u64 page_id) override; virtual void set_window_handle(u64 page_id, String handle) override; diff --git a/Services/WebContent/PageClient.cpp b/Services/WebContent/PageClient.cpp index 52ef9b3468..b6db20a14a 100644 --- a/Services/WebContent/PageClient.cpp +++ b/Services/WebContent/PageClient.cpp @@ -702,22 +702,18 @@ void PageClient::page_did_update_resource_count(i32 count_waiting) PageClient::NewWebViewResult PageClient::page_did_request_new_web_view(Web::HTML::ActivateTab activate_tab, Web::HTML::WebViewHints hints, Web::HTML::TokenizedFeature::NoOpener no_opener) { - auto& new_client = m_owner.create_page(); - - Optional page_id; if (no_opener == Web::HTML::TokenizedFeature::NoOpener::Yes) { // FIXME: Create an abstraction to let this WebContent process know about a new process we create? // FIXME: For now, just create a new page in the same process anyway } - page_id = new_client.m_id; - - auto response = client().send_sync_but_allow_failure(m_id, activate_tab, hints, page_id); + auto response = client().send_sync_but_allow_failure(m_id, activate_tab, hints); if (!response) { dbgln("WebContent client disconnected during DidRequestNewWebView. Exiting peacefully."); exit(0); } + auto& new_client = m_owner.create_page(response->new_page_id()); return { &new_client.page(), response->take_handle() }; } diff --git a/Services/WebContent/PageHost.cpp b/Services/WebContent/PageHost.cpp index 0df535944f..34abe982b0 100644 --- a/Services/WebContent/PageHost.cpp +++ b/Services/WebContent/PageHost.cpp @@ -20,25 +20,31 @@ namespace WebContent { PageHost::PageHost(ConnectionFromClient& client) : m_client(client) { - auto& first_page = create_page(); +} + +void PageHost::initialize(u64 initial_page_id) +{ + VERIFY(m_pages.is_empty()); + auto& first_page = create_page(initial_page_id); Web::HTML::TraversableNavigable::create_a_fresh_top_level_traversable(first_page.page(), URL::about_blank()); } -PageClient& PageHost::create_page() +PageClient& PageHost::create_page(u64 page_id) { - m_pages.set(m_next_id, PageClient::create(Web::Bindings::main_thread_vm(), *this, m_next_id)); - ++m_next_id; - return *m_pages.get(m_next_id - 1).value(); + VERIFY(page_id > 0); + VERIFY(!m_pages.contains(page_id)); + m_pages.set(page_id, PageClient::create(Web::Bindings::main_thread_vm(), *this, page_id)); + return *m_pages.get(page_id).value(); } -void PageHost::remove_page(Badge, u64 index) +void PageHost::remove_page(Badge, u64 page_id) { - m_pages.remove(index); + m_pages.remove(page_id); } -Optional PageHost::page(u64 index) +Optional PageHost::page(u64 page_id) { - return m_pages.get(index).map([](auto& value) -> PageClient& { + return m_pages.get(page_id).map([](auto& value) -> PageClient& { return *value; }); } diff --git a/Services/WebContent/PageHost.h b/Services/WebContent/PageHost.h index 78f1702582..16fd2a6c5b 100644 --- a/Services/WebContent/PageHost.h +++ b/Services/WebContent/PageHost.h @@ -35,9 +35,10 @@ public: static NonnullOwnPtr create(ConnectionFromClient& client) { return adopt_own(*new PageHost(client)); } virtual ~PageHost(); - Optional page(u64 index); - PageClient& create_page(); - void remove_page(Badge, u64 index); + void initialize(u64 initial_page_id); + Optional page(u64 page_id); + PageClient& create_page(u64 page_id); + void remove_page(Badge, u64 page_id); ConnectionFromClient& client() const { return m_client; } void ensure_compositor_host(); @@ -51,7 +52,6 @@ private: ConnectionFromClient& m_client; OwnPtr m_compositor_host; HashMap> m_pages; - u64 m_next_id { 0 }; }; } diff --git a/Services/WebContent/WebContentClient.ipc b/Services/WebContent/WebContentClient.ipc index 26b0ee8311..69debe1ff0 100644 --- a/Services/WebContent/WebContentClient.ipc +++ b/Services/WebContent/WebContentClient.ipc @@ -107,7 +107,7 @@ endpoint WebContentClient did_post_broadcast_channel_message(u64 page_id, Web::HTML::BroadcastChannelMessage message) =| did_update_resource_count(u64 page_id, i32 count_waiting) =| - did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab activate_tab, Web::HTML::WebViewHints hints, Optional page_index) => (String handle) + did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab activate_tab, Web::HTML::WebViewHints hints) => (u64 new_page_id, String handle) did_request_activate_tab(u64 page_id) =| did_close_browsing_context(u64 page_id) =| did_change_needs_beforeunload_check(u64 page_id, bool needs_beforeunload_check) =| diff --git a/Services/WebContent/WebContentServer.ipc b/Services/WebContent/WebContentServer.ipc index 0cb7c69a3f..d4d1a60191 100644 --- a/Services/WebContent/WebContentServer.ipc +++ b/Services/WebContent/WebContentServer.ipc @@ -26,6 +26,7 @@ endpoint WebContentServer { init_transport(int peer_pid) => (int peer_pid) + initialize(u64 initial_page_id) =| close_server() =| get_window_handle(u64 page_id) => (String handle) diff --git a/Tests/LibWeb/test-web/TestWebView.cpp b/Tests/LibWeb/test-web/TestWebView.cpp index 24b12bc50a..6f4fbe209e 100644 --- a/Tests/LibWeb/test-web/TestWebView.cpp +++ b/Tests/LibWeb/test-web/TestWebView.cpp @@ -41,7 +41,7 @@ NonnullRefPtr>> TestWebView::take_screen VERIFY(!m_pending_screenshot); m_pending_screenshot = Core::Promise>::construct(); - client().async_take_document_screenshot(0); + client().async_take_document_screenshot(page_id()); return *m_pending_screenshot; }