Browse Source

Ladybird+WebContent: Update IPC calls to handle multiple traversables

The IPC layer between chromes and LibWeb now understands that multiple
top level traversables can live in each WebContent process.

This largely mechanical change adds a billion page_id/page_index
arguments to make sure that pages that end up opening new WebViews
through mechanisms like window.open() still work properly with those
extra windows.
Andrew Kaster 1 year ago
parent
commit
36cd2fb7c5

+ 19 - 19
Ladybird/AppKit/UI/LadybirdWebViewBridge.cpp

@@ -63,12 +63,12 @@ WebViewBridge::~WebViewBridge() = default;
 void WebViewBridge::set_device_pixel_ratio(float device_pixel_ratio)
 void WebViewBridge::set_device_pixel_ratio(float device_pixel_ratio)
 {
 {
     m_device_pixel_ratio = device_pixel_ratio;
     m_device_pixel_ratio = device_pixel_ratio;
-    client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio * m_zoom_level);
+    client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
 }
 }
 
 
 void WebViewBridge::set_system_visibility_state(bool is_visible)
 void WebViewBridge::set_system_visibility_state(bool is_visible)
 {
 {
-    client().async_set_system_visibility_state(is_visible);
+    client().async_set_system_visibility_state(m_client_state.page_index, is_visible);
 }
 }
 
 
 void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect, ForResize for_resize)
 void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect, ForResize for_resize)
@@ -76,7 +76,7 @@ void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect, ForResize for_
     viewport_rect.set_size(scale_for_device(viewport_rect.size(), m_device_pixel_ratio));
     viewport_rect.set_size(scale_for_device(viewport_rect.size(), m_device_pixel_ratio));
     m_viewport_rect = viewport_rect;
     m_viewport_rect = viewport_rect;
 
 
-    client().async_set_viewport_rect(m_viewport_rect.to_type<Web::DevicePixels>());
+    client().async_set_viewport_rect(m_client_state.page_index, m_viewport_rect.to_type<Web::DevicePixels>());
 
 
     if (for_resize == ForResize::Yes) {
     if (for_resize == ForResize::Yes) {
         handle_resize();
         handle_resize();
@@ -86,48 +86,48 @@ void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect, ForResize for_
 void WebViewBridge::update_palette()
 void WebViewBridge::update_palette()
 {
 {
     auto theme = create_system_palette();
     auto theme = create_system_palette();
-    client().async_update_system_theme(move(theme));
+    client().async_update_system_theme(m_client_state.page_index, move(theme));
 }
 }
 
 
 void WebViewBridge::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme)
 void WebViewBridge::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme)
 {
 {
     m_preferred_color_scheme = color_scheme;
     m_preferred_color_scheme = color_scheme;
-    client().async_set_preferred_color_scheme(color_scheme);
+    client().async_set_preferred_color_scheme(m_client_state.page_index, color_scheme);
 }
 }
 
 
 void WebViewBridge::mouse_down_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
 void WebViewBridge::mouse_down_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
 {
 {
-    client().async_mouse_down(to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), to_underlying(button), to_underlying(button), modifiers);
+    client().async_mouse_down(m_client_state.page_index, to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), to_underlying(button), to_underlying(button), modifiers);
 }
 }
 
 
 void WebViewBridge::mouse_up_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
 void WebViewBridge::mouse_up_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
 {
 {
-    client().async_mouse_up(to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), to_underlying(button), to_underlying(button), modifiers);
+    client().async_mouse_up(m_client_state.page_index, to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), to_underlying(button), to_underlying(button), modifiers);
 }
 }
 
 
 void WebViewBridge::mouse_move_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
 void WebViewBridge::mouse_move_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
 {
 {
-    client().async_mouse_move(to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), 0, to_underlying(button), modifiers);
+    client().async_mouse_move(m_client_state.page_index, to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), 0, to_underlying(button), modifiers);
 }
 }
 
 
 void WebViewBridge::mouse_wheel_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers, int wheel_delta_x, int wheel_delta_y)
 void WebViewBridge::mouse_wheel_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers, int wheel_delta_x, int wheel_delta_y)
 {
 {
-    client().async_mouse_wheel(to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), to_underlying(button), to_underlying(button), modifiers, wheel_delta_x, wheel_delta_y);
+    client().async_mouse_wheel(m_client_state.page_index, to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), to_underlying(button), to_underlying(button), modifiers, wheel_delta_x, wheel_delta_y);
 }
 }
 
 
 void WebViewBridge::mouse_double_click_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
 void WebViewBridge::mouse_double_click_event(Gfx::IntPoint position, Gfx::IntPoint screen_position, GUI::MouseButton button, KeyModifier modifiers)
 {
 {
-    client().async_doubleclick(to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), button, to_underlying(button), modifiers);
+    client().async_doubleclick(m_client_state.page_index, to_content_position(position).to_type<Web::DevicePixels>(), to_content_position(screen_position).to_type<Web::DevicePixels>(), button, to_underlying(button), modifiers);
 }
 }
 
 
 void WebViewBridge::key_down_event(KeyCode key_code, KeyModifier modifiers, u32 code_point)
 void WebViewBridge::key_down_event(KeyCode key_code, KeyModifier modifiers, u32 code_point)
 {
 {
-    client().async_key_down(key_code, modifiers, code_point);
+    client().async_key_down(m_client_state.page_index, key_code, modifiers, code_point);
 }
 }
 
 
 void WebViewBridge::key_up_event(KeyCode key_code, KeyModifier modifiers, u32 code_point)
 void WebViewBridge::key_up_event(KeyCode key_code, KeyModifier modifiers, u32 code_point)
 {
 {
-    client().async_key_up(key_code, modifiers, code_point);
+    client().async_key_up(m_client_state.page_index, key_code, modifiers, code_point);
 }
 }
 
 
 Optional<WebViewBridge::Paintable> WebViewBridge::paintable()
 Optional<WebViewBridge::Paintable> WebViewBridge::paintable()
@@ -150,7 +150,7 @@ Optional<WebViewBridge::Paintable> WebViewBridge::paintable()
 
 
 void WebViewBridge::update_zoom()
 void WebViewBridge::update_zoom()
 {
 {
-    client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio * m_zoom_level);
+    client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
 
 
     if (on_zoom_level_changed)
     if (on_zoom_level_changed)
         on_zoom_level_changed();
         on_zoom_level_changed();
@@ -188,20 +188,20 @@ void WebViewBridge::initialize_client(CreateNewClient)
     };
     };
 
 
     m_client_state.client_handle = MUST(Web::Crypto::generate_random_uuid());
     m_client_state.client_handle = MUST(Web::Crypto::generate_random_uuid());
-    client().async_set_window_handle(m_client_state.client_handle);
+    client().async_set_window_handle(m_client_state.page_index, m_client_state.client_handle);
 
 
-    client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio);
-    client().async_update_system_fonts(Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query(), Gfx::FontDatabase::window_title_font_query());
-    client().async_set_preferred_color_scheme(m_preferred_color_scheme);
+    client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio);
+    client().async_update_system_fonts(m_client_state.page_index, Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query(), Gfx::FontDatabase::window_title_font_query());
+    client().async_set_preferred_color_scheme(m_client_state.page_index, m_preferred_color_scheme);
     update_palette();
     update_palette();
 
 
     if (!m_screen_rects.is_empty()) {
     if (!m_screen_rects.is_empty()) {
         // FIXME: Update the screens again if they ever change.
         // FIXME: Update the screens again if they ever change.
-        client().async_update_screen_rects(m_screen_rects, 0);
+        client().async_update_screen_rects(m_client_state.page_index, m_screen_rects, 0);
     }
     }
 
 
     if (m_webdriver_content_ipc_path.has_value()) {
     if (m_webdriver_content_ipc_path.has_value()) {
-        client().async_connect_to_webdriver(*m_webdriver_content_ipc_path);
+        client().async_connect_to_webdriver(m_client_state.page_index, *m_webdriver_content_ipc_path);
     }
     }
 }
 }
 
 

+ 32 - 26
Ladybird/Qt/WebContentView.cpp

@@ -124,7 +124,11 @@ WebContentView::WebContentView(WebContentOptions const& web_content_options, Str
     };
     };
 }
 }
 
 
-WebContentView::~WebContentView() = default;
+WebContentView::~WebContentView()
+{
+    if (m_client_state.client)
+        m_client_state.client->unregister_view(m_client_state.page_index);
+}
 
 
 unsigned get_button_from_qt_event(QSinglePointEvent const& event)
 unsigned get_button_from_qt_event(QSinglePointEvent const& event)
 {
 {
@@ -326,7 +330,7 @@ void WebContentView::mouseMoveEvent(QMouseEvent* event)
     Gfx::IntPoint screen_position(event->globalPosition().x() * m_device_pixel_ratio, event->globalPosition().y() * m_device_pixel_ratio);
     Gfx::IntPoint screen_position(event->globalPosition().x() * m_device_pixel_ratio, event->globalPosition().y() * m_device_pixel_ratio);
     auto buttons = get_buttons_from_qt_event(*event);
     auto buttons = get_buttons_from_qt_event(*event);
     auto modifiers = get_modifiers_from_qt_mouse_event(*event);
     auto modifiers = get_modifiers_from_qt_mouse_event(*event);
-    client().async_mouse_move(Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint { screen_position }, 0, buttons, modifiers);
+    client().async_mouse_move(m_client_state.page_index, Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint { screen_position }, 0, buttons, modifiers);
 }
 }
 
 
 void WebContentView::mousePressEvent(QMouseEvent* event)
 void WebContentView::mousePressEvent(QMouseEvent* event)
@@ -342,7 +346,7 @@ void WebContentView::mousePressEvent(QMouseEvent* event)
     }
     }
     auto modifiers = get_modifiers_from_qt_mouse_event(*event);
     auto modifiers = get_modifiers_from_qt_mouse_event(*event);
     auto buttons = get_buttons_from_qt_event(*event);
     auto buttons = get_buttons_from_qt_event(*event);
-    client().async_mouse_down(Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint { screen_position }, button, buttons, modifiers);
+    client().async_mouse_down(m_client_state.page_index, Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint { screen_position }, button, buttons, modifiers);
 }
 }
 
 
 void WebContentView::mouseReleaseEvent(QMouseEvent* event)
 void WebContentView::mouseReleaseEvent(QMouseEvent* event)
@@ -367,7 +371,7 @@ void WebContentView::mouseReleaseEvent(QMouseEvent* event)
     }
     }
     auto modifiers = get_modifiers_from_qt_mouse_event(*event);
     auto modifiers = get_modifiers_from_qt_mouse_event(*event);
     auto buttons = get_buttons_from_qt_event(*event);
     auto buttons = get_buttons_from_qt_event(*event);
-    client().async_mouse_up(Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint { screen_position }, button, buttons, modifiers);
+    client().async_mouse_up(m_client_state.page_index, Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint { screen_position }, button, buttons, modifiers);
 }
 }
 
 
 void WebContentView::wheelEvent(QWheelEvent* event)
 void WebContentView::wheelEvent(QWheelEvent* event)
@@ -381,7 +385,7 @@ void WebContentView::wheelEvent(QWheelEvent* event)
 
 
         auto num_pixels = -event->pixelDelta();
         auto num_pixels = -event->pixelDelta();
         if (!num_pixels.isNull()) {
         if (!num_pixels.isNull()) {
-            client().async_mouse_wheel(Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint(screen_position), button, buttons, modifiers, num_pixels.x(), num_pixels.y());
+            client().async_mouse_wheel(m_client_state.page_index, Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint(screen_position), button, buttons, modifiers, num_pixels.x(), num_pixels.y());
         } else {
         } else {
             auto num_degrees = -event->angleDelta();
             auto num_degrees = -event->angleDelta();
             float delta_x = -num_degrees.x() / 120;
             float delta_x = -num_degrees.x() / 120;
@@ -389,7 +393,7 @@ void WebContentView::wheelEvent(QWheelEvent* event)
             auto step_x = delta_x * QApplication::wheelScrollLines() * m_device_pixel_ratio;
             auto step_x = delta_x * QApplication::wheelScrollLines() * m_device_pixel_ratio;
             auto step_y = delta_y * QApplication::wheelScrollLines() * m_device_pixel_ratio;
             auto step_y = delta_y * QApplication::wheelScrollLines() * m_device_pixel_ratio;
             int scroll_step_size = verticalScrollBar()->singleStep();
             int scroll_step_size = verticalScrollBar()->singleStep();
-            client().async_mouse_wheel(Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint(screen_position), button, buttons, modifiers, step_x * scroll_step_size, step_y * scroll_step_size);
+            client().async_mouse_wheel(m_client_state.page_index, Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint(screen_position), button, buttons, modifiers, step_x * scroll_step_size, step_y * scroll_step_size);
         }
         }
         event->accept();
         event->accept();
         return;
         return;
@@ -410,7 +414,7 @@ void WebContentView::mouseDoubleClickEvent(QMouseEvent* event)
     }
     }
     auto modifiers = get_modifiers_from_qt_mouse_event(*event);
     auto modifiers = get_modifiers_from_qt_mouse_event(*event);
     auto buttons = get_buttons_from_qt_event(*event);
     auto buttons = get_buttons_from_qt_event(*event);
-    client().async_doubleclick(Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint { screen_position }, button, buttons, modifiers);
+    client().async_doubleclick(m_client_state.page_index, Web::DevicePixelPoint { to_content_position(position) }, Web::DevicePixelPoint { screen_position }, button, buttons, modifiers);
 }
 }
 
 
 void WebContentView::dragEnterEvent(QDragEnterEvent* event)
 void WebContentView::dragEnterEvent(QDragEnterEvent* event)
@@ -443,7 +447,7 @@ void WebContentView::keyPressEvent(QKeyEvent* event)
 
 
     if (event->key() == Qt::Key_Backtab) {
     if (event->key() == Qt::Key_Backtab) {
         // NOTE: Qt transforms Shift+Tab into a "Backtab", so we undo that transformation here.
         // NOTE: Qt transforms Shift+Tab into a "Backtab", so we undo that transformation here.
-        client().async_key_down(KeyCode::Key_Tab, Mod_Shift, '\t');
+        client().async_key_down(m_client_state.page_index, KeyCode::Key_Tab, Mod_Shift, '\t');
         return;
         return;
     }
     }
 
 
@@ -451,7 +455,7 @@ void WebContentView::keyPressEvent(QKeyEvent* event)
     auto point = text.isEmpty() ? 0u : event->text()[0].unicode();
     auto point = text.isEmpty() ? 0u : event->text()[0].unicode();
     auto keycode = get_keycode_from_qt_keyboard_event(*event);
     auto keycode = get_keycode_from_qt_keyboard_event(*event);
     auto modifiers = get_modifiers_from_qt_keyboard_event(*event);
     auto modifiers = get_modifiers_from_qt_keyboard_event(*event);
-    client().async_key_down(keycode, modifiers, point);
+    client().async_key_down(m_client_state.page_index, keycode, modifiers, point);
 }
 }
 
 
 void WebContentView::keyReleaseEvent(QKeyEvent* event)
 void WebContentView::keyReleaseEvent(QKeyEvent* event)
@@ -460,17 +464,17 @@ void WebContentView::keyReleaseEvent(QKeyEvent* event)
     auto point = text.isEmpty() ? 0u : event->text()[0].unicode();
     auto point = text.isEmpty() ? 0u : event->text()[0].unicode();
     auto keycode = get_keycode_from_qt_keyboard_event(*event);
     auto keycode = get_keycode_from_qt_keyboard_event(*event);
     auto modifiers = get_modifiers_from_qt_keyboard_event(*event);
     auto modifiers = get_modifiers_from_qt_keyboard_event(*event);
-    client().async_key_up(keycode, modifiers, point);
+    client().async_key_up(m_client_state.page_index, keycode, modifiers, point);
 }
 }
 
 
 void WebContentView::focusInEvent(QFocusEvent*)
 void WebContentView::focusInEvent(QFocusEvent*)
 {
 {
-    client().async_set_has_focus(true);
+    client().async_set_has_focus(m_client_state.page_index, true);
 }
 }
 
 
 void WebContentView::focusOutEvent(QFocusEvent*)
 void WebContentView::focusOutEvent(QFocusEvent*)
 {
 {
-    client().async_set_has_focus(false);
+    client().async_set_has_focus(m_client_state.page_index, false);
 }
 }
 
 
 void WebContentView::paintEvent(QPaintEvent*)
 void WebContentView::paintEvent(QPaintEvent*)
@@ -517,23 +521,23 @@ void WebContentView::resizeEvent(QResizeEvent* event)
 void WebContentView::set_viewport_rect(Gfx::IntRect rect)
 void WebContentView::set_viewport_rect(Gfx::IntRect rect)
 {
 {
     m_viewport_rect = rect;
     m_viewport_rect = rect;
-    client().async_set_viewport_rect(rect.to_type<Web::DevicePixels>());
+    client().async_set_viewport_rect(m_client_state.page_index, rect.to_type<Web::DevicePixels>());
 }
 }
 
 
 void WebContentView::set_window_size(Gfx::IntSize size)
 void WebContentView::set_window_size(Gfx::IntSize size)
 {
 {
-    client().async_set_window_size(size.to_type<Web::DevicePixels>());
+    client().async_set_window_size(m_client_state.page_index, size.to_type<Web::DevicePixels>());
 }
 }
 
 
 void WebContentView::set_window_position(Gfx::IntPoint position)
 void WebContentView::set_window_position(Gfx::IntPoint position)
 {
 {
-    client().async_set_window_position(position.to_type<Web::DevicePixels>());
+    client().async_set_window_position(m_client_state.page_index, position.to_type<Web::DevicePixels>());
 }
 }
 
 
 void WebContentView::set_device_pixel_ratio(double device_pixel_ratio)
 void WebContentView::set_device_pixel_ratio(double device_pixel_ratio)
 {
 {
     m_device_pixel_ratio = device_pixel_ratio;
     m_device_pixel_ratio = device_pixel_ratio;
-    client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio * m_zoom_level);
+    client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
     update_viewport_rect();
     update_viewport_rect();
     handle_resize();
     handle_resize();
 }
 }
@@ -549,20 +553,20 @@ void WebContentView::update_viewport_rect()
 
 
 void WebContentView::update_zoom()
 void WebContentView::update_zoom()
 {
 {
-    client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio * m_zoom_level);
+    client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
     update_viewport_rect();
     update_viewport_rect();
 }
 }
 
 
 void WebContentView::showEvent(QShowEvent* event)
 void WebContentView::showEvent(QShowEvent* event)
 {
 {
     QAbstractScrollArea::showEvent(event);
     QAbstractScrollArea::showEvent(event);
-    client().async_set_system_visibility_state(true);
+    client().async_set_system_visibility_state(m_client_state.page_index, true);
 }
 }
 
 
 void WebContentView::hideEvent(QHideEvent* event)
 void WebContentView::hideEvent(QHideEvent* event)
 {
 {
     QAbstractScrollArea::hideEvent(event);
     QAbstractScrollArea::hideEvent(event);
-    client().async_set_system_visibility_state(false);
+    client().async_set_system_visibility_state(m_client_state.page_index, false);
 }
 }
 
 
 static Core::AnonymousBuffer make_system_theme_from_qt_palette(QWidget& widget, WebContentView::PaletteMode mode)
 static Core::AnonymousBuffer make_system_theme_from_qt_palette(QWidget& widget, WebContentView::PaletteMode mode)
@@ -599,7 +603,7 @@ static Core::AnonymousBuffer make_system_theme_from_qt_palette(QWidget& widget,
 
 
 void WebContentView::update_palette(PaletteMode mode)
 void WebContentView::update_palette(PaletteMode mode)
 {
 {
-    client().async_update_system_theme(make_system_theme_from_qt_palette(*this, mode));
+    client().async_update_system_theme(m_client_state.page_index, make_system_theme_from_qt_palette(*this, mode));
 }
 }
 
 
 void WebContentView::initialize_client(WebView::ViewImplementation::CreateNewClient create_new_client)
 void WebContentView::initialize_client(WebView::ViewImplementation::CreateNewClient create_new_client)
@@ -611,6 +615,8 @@ void WebContentView::initialize_client(WebView::ViewImplementation::CreateNewCli
         auto new_client = launch_web_content_process(*this, candidate_web_content_paths, m_web_content_options).release_value_but_fixme_should_propagate_errors();
         auto new_client = launch_web_content_process(*this, candidate_web_content_paths, m_web_content_options).release_value_but_fixme_should_propagate_errors();
 
 
         m_client_state.client = new_client;
         m_client_state.client = new_client;
+    } else {
+        m_client_state.client->register_view(m_client_state.page_index, *this);
     }
     }
 
 
     m_client_state.client->on_web_content_process_crash = [this] {
     m_client_state.client->on_web_content_process_crash = [this] {
@@ -620,11 +626,11 @@ void WebContentView::initialize_client(WebView::ViewImplementation::CreateNewCli
     };
     };
 
 
     m_client_state.client_handle = Web::Crypto::generate_random_uuid().release_value_but_fixme_should_propagate_errors();
     m_client_state.client_handle = Web::Crypto::generate_random_uuid().release_value_but_fixme_should_propagate_errors();
-    client().async_set_window_handle(m_client_state.client_handle);
+    client().async_set_window_handle(m_client_state.page_index, m_client_state.client_handle);
 
 
-    client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio);
+    client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio);
     update_palette();
     update_palette();
-    client().async_update_system_fonts(Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query(), Gfx::FontDatabase::window_title_font_query());
+    client().async_update_system_fonts(m_client_state.page_index, Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query(), Gfx::FontDatabase::window_title_font_query());
 
 
     auto screens = QGuiApplication::screens();
     auto screens = QGuiApplication::screens();
 
 
@@ -640,11 +646,11 @@ void WebContentView::initialize_client(WebView::ViewImplementation::CreateNewCli
         // NOTE: The first item in QGuiApplication::screens is always the primary screen.
         // NOTE: The first item in QGuiApplication::screens is always the primary screen.
         //       This is not specified in the documentation but QGuiApplication::primaryScreen
         //       This is not specified in the documentation but QGuiApplication::primaryScreen
         //       always returns the first item in the list if it isn't empty.
         //       always returns the first item in the list if it isn't empty.
-        client().async_update_screen_rects(screen_rects, 0);
+        client().async_update_screen_rects(m_client_state.page_index, screen_rects, 0);
     }
     }
 
 
     if (!m_webdriver_content_ipc_path.is_empty())
     if (!m_webdriver_content_ipc_path.is_empty())
-        client().async_connect_to_webdriver(m_webdriver_content_ipc_path);
+        client().async_connect_to_webdriver(m_client_state.page_index, m_webdriver_content_ipc_path);
 }
 }
 
 
 void WebContentView::update_cursor(Gfx::StandardCursor cursor)
 void WebContentView::update_cursor(Gfx::StandardCursor cursor)
@@ -749,7 +755,7 @@ bool WebContentView::event(QEvent* event)
 
 
 ErrorOr<String> WebContentView::dump_layout_tree()
 ErrorOr<String> WebContentView::dump_layout_tree()
 {
 {
-    return String::from_byte_string(client().dump_layout_tree());
+    return String::from_byte_string(client().dump_layout_tree(m_client_state.page_index));
 }
 }
 
 
 }
 }

+ 2 - 1
Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp

@@ -890,7 +890,8 @@ void TraversableNavigable::destroy_top_level_traversable()
     // 3. Remove browsingContext.
     // 3. Remove browsingContext.
     browsing_context->remove();
     browsing_context->remove();
 
 
-    // FIXME: 4. Remove traversable from the user interface (e.g., close or hide its tab in a tabbed browser).
+    // 4. Remove traversable from the user interface (e.g., close or hide its tab in a tabbed browser).
+    page().client().page_did_close_top_level_traversable();
 
 
     // 5. Remove traversable from the user agent's top-level traversable set.
     // 5. Remove traversable from the user agent's top-level traversable set.
     user_agent_top_level_traversable_set().remove(this);
     user_agent_top_level_traversable_set().remove(this);

+ 1 - 1
Userland/Libraries/LibWeb/Page/Page.h

@@ -276,7 +276,7 @@ public:
     };
     };
     virtual NewWebViewResult page_did_request_new_web_view(HTML::ActivateTab, HTML::WebViewHints, HTML::TokenizedFeature::NoOpener) { return {}; }
     virtual NewWebViewResult page_did_request_new_web_view(HTML::ActivateTab, HTML::WebViewHints, HTML::TokenizedFeature::NoOpener) { return {}; }
     virtual void page_did_request_activate_tab() { }
     virtual void page_did_request_activate_tab() { }
-    virtual void page_did_close_browsing_context(HTML::BrowsingContext const&) { }
+    virtual void page_did_close_top_level_traversable() { }
 
 
     virtual void request_file(FileRequest) = 0;
     virtual void request_file(FileRequest) = 0;
 
 

+ 31 - 31
Userland/Libraries/LibWebView/OutOfProcessWebView.cpp

@@ -42,9 +42,9 @@ OutOfProcessWebView::OutOfProcessWebView()
         auto file = FileSystemAccessClient::Client::the().request_file_read_only_approved(window(), path);
         auto file = FileSystemAccessClient::Client::the().request_file_read_only_approved(window(), path);
 
 
         if (file.is_error())
         if (file.is_error())
-            client().async_handle_file_return(file.error().code(), {}, request_id);
+            client().async_handle_file_return(m_client_state.page_index, file.error().code(), {}, request_id);
         else
         else
-            client().async_handle_file_return(0, IPC::File(file.value().stream()), request_id);
+            client().async_handle_file_return(m_client_state.page_index, 0, IPC::File(file.value().stream()), request_id);
     };
     };
 
 
     on_scroll_by_delta = [this](auto x_delta, auto y_delta) {
     on_scroll_by_delta = [this](auto x_delta, auto y_delta) {
@@ -95,16 +95,16 @@ void OutOfProcessWebView::initialize_client(WebView::ViewImplementation::CreateN
     };
     };
 
 
     m_client_state.client_handle = Web::Crypto::generate_random_uuid().release_value_but_fixme_should_propagate_errors();
     m_client_state.client_handle = Web::Crypto::generate_random_uuid().release_value_but_fixme_should_propagate_errors();
-    client().async_set_window_handle(m_client_state.client_handle);
+    client().async_set_window_handle(m_client_state.page_index, m_client_state.client_handle);
 
 
-    client().async_update_system_theme(Gfx::current_system_theme_buffer());
-    client().async_update_system_fonts(Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query(), Gfx::FontDatabase::window_title_font_query());
+    client().async_update_system_theme(m_client_state.page_index, Gfx::current_system_theme_buffer());
+    client().async_update_system_fonts(m_client_state.page_index, Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query(), Gfx::FontDatabase::window_title_font_query());
 
 
     Vector<Web::DevicePixelRect> screen_rects;
     Vector<Web::DevicePixelRect> screen_rects;
     for (auto const& screen_rect : GUI::Desktop::the().rects()) {
     for (auto const& screen_rect : GUI::Desktop::the().rects()) {
         screen_rects.append(screen_rect.to_type<Web::DevicePixels>());
         screen_rects.append(screen_rect.to_type<Web::DevicePixels>());
     }
     }
-    client().async_update_screen_rects(screen_rects, GUI::Desktop::the().main_screen_index());
+    client().async_update_screen_rects(m_client_state.page_index, screen_rects, GUI::Desktop::the().main_screen_index());
 }
 }
 
 
 void OutOfProcessWebView::paint_event(GUI::PaintEvent& event)
 void OutOfProcessWebView::paint_event(GUI::PaintEvent& event)
@@ -141,7 +141,7 @@ void OutOfProcessWebView::paint_event(GUI::PaintEvent& event)
 void OutOfProcessWebView::resize_event(GUI::ResizeEvent& event)
 void OutOfProcessWebView::resize_event(GUI::ResizeEvent& event)
 {
 {
     Super::resize_event(event);
     Super::resize_event(event);
-    client().async_set_viewport_rect(Web::DevicePixelRect({ horizontal_scrollbar().value(), vertical_scrollbar().value() }, available_size()));
+    client().async_set_viewport_rect(m_client_state.page_index, Web::DevicePixelRect({ horizontal_scrollbar().value(), vertical_scrollbar().value() }, available_size()));
     handle_resize();
     handle_resize();
 }
 }
 
 
@@ -162,7 +162,7 @@ Gfx::IntPoint OutOfProcessWebView::to_widget_position(Gfx::IntPoint content_posi
 
 
 void OutOfProcessWebView::update_zoom()
 void OutOfProcessWebView::update_zoom()
 {
 {
-    client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio * m_zoom_level);
+    client().async_set_device_pixels_per_css_pixel(m_client_state.page_index, m_device_pixel_ratio * m_zoom_level);
     // FIXME: Refactor this into separate update_viewport_rect() + request_repaint() like in Ladybird
     // FIXME: Refactor this into separate update_viewport_rect() + request_repaint() like in Ladybird
     handle_resize();
     handle_resize();
 }
 }
@@ -213,7 +213,7 @@ void OutOfProcessWebView::doubleclick_event(GUI::MouseEvent& event)
 void OutOfProcessWebView::theme_change_event(GUI::ThemeChangeEvent& event)
 void OutOfProcessWebView::theme_change_event(GUI::ThemeChangeEvent& event)
 {
 {
     Super::theme_change_event(event);
     Super::theme_change_event(event);
-    client().async_update_system_theme(Gfx::current_system_theme_buffer());
+    client().async_update_system_theme(m_client_state.page_index, Gfx::current_system_theme_buffer());
 }
 }
 
 
 void OutOfProcessWebView::screen_rects_change_event(GUI::ScreenRectsChangeEvent& event)
 void OutOfProcessWebView::screen_rects_change_event(GUI::ScreenRectsChangeEvent& event)
@@ -222,77 +222,77 @@ void OutOfProcessWebView::screen_rects_change_event(GUI::ScreenRectsChangeEvent&
     for (auto const& screen_rect : event.rects()) {
     for (auto const& screen_rect : event.rects()) {
         screen_rects.append(screen_rect.to_type<Web::DevicePixels>());
         screen_rects.append(screen_rect.to_type<Web::DevicePixels>());
     }
     }
-    client().async_update_screen_rects(screen_rects, event.main_screen_index());
+    client().async_update_screen_rects(m_client_state.page_index, screen_rects, event.main_screen_index());
 }
 }
 
 
 void OutOfProcessWebView::did_scroll()
 void OutOfProcessWebView::did_scroll()
 {
 {
-    client().async_set_viewport_rect(visible_content_rect().to_type<Web::DevicePixels>());
+    client().async_set_viewport_rect(m_client_state.page_index, visible_content_rect().to_type<Web::DevicePixels>());
 }
 }
 
 
 ByteString OutOfProcessWebView::dump_layout_tree()
 ByteString OutOfProcessWebView::dump_layout_tree()
 {
 {
-    return client().dump_layout_tree();
+    return client().dump_layout_tree(m_client_state.page_index);
 }
 }
 
 
 OrderedHashMap<String, String> OutOfProcessWebView::get_local_storage_entries()
 OrderedHashMap<String, String> OutOfProcessWebView::get_local_storage_entries()
 {
 {
-    return client().get_local_storage_entries();
+    return client().get_local_storage_entries(m_client_state.page_index);
 }
 }
 
 
 OrderedHashMap<String, String> OutOfProcessWebView::get_session_storage_entries()
 OrderedHashMap<String, String> OutOfProcessWebView::get_session_storage_entries()
 {
 {
-    return client().get_session_storage_entries();
+    return client().get_session_storage_entries(m_client_state.page_index);
 }
 }
 
 
 void OutOfProcessWebView::set_content_filters(Vector<String> filters)
 void OutOfProcessWebView::set_content_filters(Vector<String> filters)
 {
 {
-    client().async_set_content_filters(move(filters));
+    client().async_set_content_filters(m_client_state.page_index, move(filters));
 }
 }
 
 
 void OutOfProcessWebView::set_autoplay_allowed_on_all_websites()
 void OutOfProcessWebView::set_autoplay_allowed_on_all_websites()
 {
 {
-    client().async_set_autoplay_allowed_on_all_websites();
+    client().async_set_autoplay_allowed_on_all_websites(m_client_state.page_index);
 }
 }
 
 
 void OutOfProcessWebView::set_autoplay_allowlist(Vector<String> allowlist)
 void OutOfProcessWebView::set_autoplay_allowlist(Vector<String> allowlist)
 {
 {
-    client().async_set_autoplay_allowlist(move(allowlist));
+    client().async_set_autoplay_allowlist(m_client_state.page_index, move(allowlist));
 }
 }
 
 
 void OutOfProcessWebView::set_proxy_mappings(Vector<ByteString> proxies, HashMap<ByteString, size_t> mappings)
 void OutOfProcessWebView::set_proxy_mappings(Vector<ByteString> proxies, HashMap<ByteString, size_t> mappings)
 {
 {
-    client().async_set_proxy_mappings(move(proxies), move(mappings));
+    client().async_set_proxy_mappings(m_client_state.page_index, move(proxies), move(mappings));
 }
 }
 
 
 void OutOfProcessWebView::connect_to_webdriver(ByteString const& webdriver_ipc_path)
 void OutOfProcessWebView::connect_to_webdriver(ByteString const& webdriver_ipc_path)
 {
 {
-    client().async_connect_to_webdriver(webdriver_ipc_path);
+    client().async_connect_to_webdriver(m_client_state.page_index, webdriver_ipc_path);
 }
 }
 
 
 void OutOfProcessWebView::set_window_position(Gfx::IntPoint position)
 void OutOfProcessWebView::set_window_position(Gfx::IntPoint position)
 {
 {
-    client().async_set_window_position(position.to_type<Web::DevicePixels>());
+    client().async_set_window_position(m_client_state.page_index, position.to_type<Web::DevicePixels>());
 }
 }
 
 
 void OutOfProcessWebView::set_window_size(Gfx::IntSize size)
 void OutOfProcessWebView::set_window_size(Gfx::IntSize size)
 {
 {
-    client().async_set_window_size(size.to_type<Web::DevicePixels>());
+    client().async_set_window_size(m_client_state.page_index, size.to_type<Web::DevicePixels>());
 }
 }
 
 
 void OutOfProcessWebView::focusin_event(GUI::FocusEvent&)
 void OutOfProcessWebView::focusin_event(GUI::FocusEvent&)
 {
 {
-    client().async_set_has_focus(true);
+    client().async_set_has_focus(m_client_state.page_index, true);
 }
 }
 
 
 void OutOfProcessWebView::focusout_event(GUI::FocusEvent&)
 void OutOfProcessWebView::focusout_event(GUI::FocusEvent&)
 {
 {
-    client().async_set_has_focus(false);
+    client().async_set_has_focus(m_client_state.page_index, false);
 }
 }
 
 
 void OutOfProcessWebView::set_system_visibility_state(bool visible)
 void OutOfProcessWebView::set_system_visibility_state(bool visible)
 {
 {
-    client().async_set_system_visibility_state(visible);
+    client().async_set_system_visibility_state(m_client_state.page_index, visible);
 }
 }
 
 
 void OutOfProcessWebView::show_event(GUI::ShowEvent&)
 void OutOfProcessWebView::show_event(GUI::ShowEvent&)
@@ -328,10 +328,10 @@ void OutOfProcessWebView::process_next_input_event()
         [this](GUI::KeyEvent const& event) {
         [this](GUI::KeyEvent const& event) {
             switch (event.type()) {
             switch (event.type()) {
             case GUI::Event::Type::KeyDown:
             case GUI::Event::Type::KeyDown:
-                client().async_key_down(event.key(), event.modifiers(), event.code_point());
+                client().async_key_down(m_client_state.page_index, event.key(), event.modifiers(), event.code_point());
                 break;
                 break;
             case GUI::Event::Type::KeyUp:
             case GUI::Event::Type::KeyUp:
-                client().async_key_up(event.key(), event.modifiers(), event.code_point());
+                client().async_key_up(m_client_state.page_index, event.key(), event.modifiers(), event.code_point());
                 break;
                 break;
             default:
             default:
                 dbgln("Unrecognized key event type in OOPWV input event queue: {}", event.type());
                 dbgln("Unrecognized key event type in OOPWV input event queue: {}", event.type());
@@ -343,22 +343,22 @@ void OutOfProcessWebView::process_next_input_event()
             auto screen_position = (event.position() + (window()->position() + relative_position())).to_type<Web::DevicePixels>();
             auto screen_position = (event.position() + (window()->position() + relative_position())).to_type<Web::DevicePixels>();
             switch (event.type()) {
             switch (event.type()) {
             case GUI::Event::Type::MouseDown:
             case GUI::Event::Type::MouseDown:
-                client().async_mouse_down(position, screen_position, event.button(), event.buttons(), event.modifiers());
+                client().async_mouse_down(m_client_state.page_index, position, screen_position, event.button(), event.buttons(), event.modifiers());
                 break;
                 break;
             case GUI::Event::Type::MouseUp:
             case GUI::Event::Type::MouseUp:
-                client().async_mouse_up(position, screen_position, event.button(), event.buttons(), event.modifiers());
+                client().async_mouse_up(m_client_state.page_index, position, screen_position, event.button(), event.buttons(), event.modifiers());
                 break;
                 break;
             case GUI::Event::Type::MouseMove:
             case GUI::Event::Type::MouseMove:
-                client().async_mouse_move(position, screen_position, event.button(), event.buttons(), event.modifiers());
+                client().async_mouse_move(m_client_state.page_index, position, screen_position, event.button(), event.buttons(), event.modifiers());
                 break;
                 break;
             case GUI::Event::Type::MouseWheel: {
             case GUI::Event::Type::MouseWheel: {
                 // FIXME: This wheel delta step size multiplier is used to remain the old scroll behaviour, in future use system step size.
                 // FIXME: This wheel delta step size multiplier is used to remain the old scroll behaviour, in future use system step size.
                 constexpr int scroll_step_size = 24;
                 constexpr int scroll_step_size = 24;
-                client().async_mouse_wheel(position, screen_position, event.button(), event.buttons(), event.modifiers(), event.wheel_delta_x() * scroll_step_size, event.wheel_delta_y() * scroll_step_size);
+                client().async_mouse_wheel(m_client_state.page_index, position, screen_position, event.button(), event.buttons(), event.modifiers(), event.wheel_delta_x() * scroll_step_size, event.wheel_delta_y() * scroll_step_size);
                 break;
                 break;
             }
             }
             case GUI::Event::Type::MouseDoubleClick:
             case GUI::Event::Type::MouseDoubleClick:
-                client().async_doubleclick(position, screen_position, event.button(), event.buttons(), event.modifiers());
+                client().async_doubleclick(m_client_state.page_index, position, screen_position, event.button(), event.buttons(), event.modifiers());
                 break;
                 break;
             default:
             default:
                 dbgln("Unrecognized mouse event type in OOPWV input event queue: {}", event.type());
                 dbgln("Unrecognized mouse event type in OOPWV input event queue: {}", event.type());

+ 54 - 42
Userland/Libraries/LibWebView/ViewImplementation.cpp

@@ -30,12 +30,18 @@ ViewImplementation::ViewImplementation()
         auto file = Core::File::open(path, Core::File::OpenMode::Read);
         auto file = Core::File::open(path, Core::File::OpenMode::Read);
 
 
         if (file.is_error())
         if (file.is_error())
-            client().async_handle_file_return(file.error().code(), {}, request_id);
+            client().async_handle_file_return(page_id(), file.error().code(), {}, request_id);
         else
         else
-            client().async_handle_file_return(0, IPC::File(*file.value()), request_id);
+            client().async_handle_file_return(page_id(), 0, IPC::File(*file.value()), request_id);
     };
     };
 }
 }
 
 
+ViewImplementation::~ViewImplementation()
+{
+    if (m_client_state.client)
+        m_client_state.client->unregister_view(m_client_state.page_index);
+}
+
 WebContentClient& ViewImplementation::client()
 WebContentClient& ViewImplementation::client()
 {
 {
     VERIFY(m_client_state.client);
     VERIFY(m_client_state.client);
@@ -48,6 +54,12 @@ WebContentClient const& ViewImplementation::client() const
     return *m_client_state.client;
     return *m_client_state.client;
 }
 }
 
 
+u64 ViewImplementation::page_id() const
+{
+    VERIFY(m_client_state.client);
+    return m_client_state.page_index;
+}
+
 void ViewImplementation::server_did_paint(Badge<WebContentClient>, i32 bitmap_id, Gfx::IntSize size)
 void ViewImplementation::server_did_paint(Badge<WebContentClient>, i32 bitmap_id, Gfx::IntSize size)
 {
 {
     if (m_client_state.back_bitmap.id == bitmap_id) {
     if (m_client_state.back_bitmap.id == bitmap_id) {
@@ -59,18 +71,18 @@ void ViewImplementation::server_did_paint(Badge<WebContentClient>, i32 bitmap_id
             on_ready_to_paint();
             on_ready_to_paint();
     }
     }
 
 
-    client().async_ready_to_paint();
+    client().async_ready_to_paint(page_id());
 }
 }
 
 
 void ViewImplementation::load(AK::URL const& url)
 void ViewImplementation::load(AK::URL const& url)
 {
 {
     m_url = url;
     m_url = url;
-    client().async_load_url(url);
+    client().async_load_url(page_id(), url);
 }
 }
 
 
 void ViewImplementation::load_html(StringView html)
 void ViewImplementation::load_html(StringView html)
 {
 {
-    client().async_load_html(html);
+    client().async_load_html(page_id(), html);
 }
 }
 
 
 void ViewImplementation::load_empty_document()
 void ViewImplementation::load_empty_document()
@@ -102,12 +114,12 @@ void ViewImplementation::reset_zoom()
 
 
 void ViewImplementation::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme)
 void ViewImplementation::set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme)
 {
 {
-    client().async_set_preferred_color_scheme(color_scheme);
+    client().async_set_preferred_color_scheme(page_id(), color_scheme);
 }
 }
 
 
 ByteString ViewImplementation::selected_text()
 ByteString ViewImplementation::selected_text()
 {
 {
-    return client().get_selected_text();
+    return client().get_selected_text(page_id());
 }
 }
 
 
 Optional<String> ViewImplementation::selected_text_with_whitespace_collapsed()
 Optional<String> ViewImplementation::selected_text_with_whitespace_collapsed()
@@ -120,27 +132,27 @@ Optional<String> ViewImplementation::selected_text_with_whitespace_collapsed()
 
 
 void ViewImplementation::select_all()
 void ViewImplementation::select_all()
 {
 {
-    client().async_select_all();
+    client().async_select_all(page_id());
 }
 }
 
 
 void ViewImplementation::get_source()
 void ViewImplementation::get_source()
 {
 {
-    client().async_get_source();
+    client().async_get_source(page_id());
 }
 }
 
 
 void ViewImplementation::inspect_dom_tree()
 void ViewImplementation::inspect_dom_tree()
 {
 {
-    client().async_inspect_dom_tree();
+    client().async_inspect_dom_tree(page_id());
 }
 }
 
 
 void ViewImplementation::inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element)
 void ViewImplementation::inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element)
 {
 {
-    client().async_inspect_dom_node(node_id, move(pseudo_element));
+    client().async_inspect_dom_node(page_id(), node_id, move(pseudo_element));
 }
 }
 
 
 void ViewImplementation::inspect_accessibility_tree()
 void ViewImplementation::inspect_accessibility_tree()
 {
 {
-    client().async_inspect_accessibility_tree();
+    client().async_inspect_accessibility_tree(page_id());
 }
 }
 
 
 void ViewImplementation::clear_inspected_dom_node()
 void ViewImplementation::clear_inspected_dom_node()
@@ -150,117 +162,117 @@ void ViewImplementation::clear_inspected_dom_node()
 
 
 void ViewImplementation::get_hovered_node_id()
 void ViewImplementation::get_hovered_node_id()
 {
 {
-    client().async_get_hovered_node_id();
+    client().async_get_hovered_node_id(page_id());
 }
 }
 
 
 void ViewImplementation::set_dom_node_text(i32 node_id, String text)
 void ViewImplementation::set_dom_node_text(i32 node_id, String text)
 {
 {
-    client().async_set_dom_node_text(node_id, move(text));
+    client().async_set_dom_node_text(page_id(), node_id, move(text));
 }
 }
 
 
 void ViewImplementation::set_dom_node_tag(i32 node_id, String name)
 void ViewImplementation::set_dom_node_tag(i32 node_id, String name)
 {
 {
-    client().async_set_dom_node_tag(node_id, move(name));
+    client().async_set_dom_node_tag(page_id(), node_id, move(name));
 }
 }
 
 
 void ViewImplementation::add_dom_node_attributes(i32 node_id, Vector<Attribute> attributes)
 void ViewImplementation::add_dom_node_attributes(i32 node_id, Vector<Attribute> attributes)
 {
 {
-    client().async_add_dom_node_attributes(node_id, move(attributes));
+    client().async_add_dom_node_attributes(page_id(), node_id, move(attributes));
 }
 }
 
 
 void ViewImplementation::replace_dom_node_attribute(i32 node_id, String name, Vector<Attribute> replacement_attributes)
 void ViewImplementation::replace_dom_node_attribute(i32 node_id, String name, Vector<Attribute> replacement_attributes)
 {
 {
-    client().async_replace_dom_node_attribute(node_id, move(name), move(replacement_attributes));
+    client().async_replace_dom_node_attribute(page_id(), node_id, move(name), move(replacement_attributes));
 }
 }
 
 
 void ViewImplementation::create_child_element(i32 node_id)
 void ViewImplementation::create_child_element(i32 node_id)
 {
 {
-    client().async_create_child_element(node_id);
+    client().async_create_child_element(page_id(), node_id);
 }
 }
 
 
 void ViewImplementation::create_child_text_node(i32 node_id)
 void ViewImplementation::create_child_text_node(i32 node_id)
 {
 {
-    client().async_create_child_text_node(node_id);
+    client().async_create_child_text_node(page_id(), node_id);
 }
 }
 
 
 void ViewImplementation::clone_dom_node(i32 node_id)
 void ViewImplementation::clone_dom_node(i32 node_id)
 {
 {
-    client().async_clone_dom_node(node_id);
+    client().async_clone_dom_node(page_id(), node_id);
 }
 }
 
 
 void ViewImplementation::remove_dom_node(i32 node_id)
 void ViewImplementation::remove_dom_node(i32 node_id)
 {
 {
-    client().async_remove_dom_node(node_id);
+    client().async_remove_dom_node(page_id(), node_id);
 }
 }
 
 
 void ViewImplementation::get_dom_node_html(i32 node_id)
 void ViewImplementation::get_dom_node_html(i32 node_id)
 {
 {
-    client().async_get_dom_node_html(node_id);
+    client().async_get_dom_node_html(page_id(), node_id);
 }
 }
 
 
 void ViewImplementation::debug_request(ByteString const& request, ByteString const& argument)
 void ViewImplementation::debug_request(ByteString const& request, ByteString const& argument)
 {
 {
-    client().async_debug_request(request, argument);
+    client().async_debug_request(page_id(), request, argument);
 }
 }
 
 
 void ViewImplementation::run_javascript(StringView js_source)
 void ViewImplementation::run_javascript(StringView js_source)
 {
 {
-    client().async_run_javascript(js_source);
+    client().async_run_javascript(page_id(), js_source);
 }
 }
 
 
 void ViewImplementation::js_console_input(ByteString const& js_source)
 void ViewImplementation::js_console_input(ByteString const& js_source)
 {
 {
-    client().async_js_console_input(js_source);
+    client().async_js_console_input(page_id(), js_source);
 }
 }
 
 
 void ViewImplementation::js_console_request_messages(i32 start_index)
 void ViewImplementation::js_console_request_messages(i32 start_index)
 {
 {
-    client().async_js_console_request_messages(start_index);
+    client().async_js_console_request_messages(page_id(), start_index);
 }
 }
 
 
 void ViewImplementation::alert_closed()
 void ViewImplementation::alert_closed()
 {
 {
-    client().async_alert_closed();
+    client().async_alert_closed(page_id());
 }
 }
 
 
 void ViewImplementation::confirm_closed(bool accepted)
 void ViewImplementation::confirm_closed(bool accepted)
 {
 {
-    client().async_confirm_closed(accepted);
+    client().async_confirm_closed(page_id(), accepted);
 }
 }
 
 
 void ViewImplementation::prompt_closed(Optional<String> response)
 void ViewImplementation::prompt_closed(Optional<String> response)
 {
 {
-    client().async_prompt_closed(move(response));
+    client().async_prompt_closed(page_id(), move(response));
 }
 }
 
 
 void ViewImplementation::color_picker_update(Optional<Color> picked_color, Web::HTML::ColorPickerUpdateState state)
 void ViewImplementation::color_picker_update(Optional<Color> picked_color, Web::HTML::ColorPickerUpdateState state)
 {
 {
-    client().async_color_picker_update(picked_color, state);
+    client().async_color_picker_update(page_id(), picked_color, state);
 }
 }
 
 
 void ViewImplementation::select_dropdown_closed(Optional<String> value)
 void ViewImplementation::select_dropdown_closed(Optional<String> value)
 {
 {
-    client().async_select_dropdown_closed(value);
+    client().async_select_dropdown_closed(page_id(), value);
 }
 }
 
 
 void ViewImplementation::toggle_media_play_state()
 void ViewImplementation::toggle_media_play_state()
 {
 {
-    client().async_toggle_media_play_state();
+    client().async_toggle_media_play_state(page_id());
 }
 }
 
 
 void ViewImplementation::toggle_media_mute_state()
 void ViewImplementation::toggle_media_mute_state()
 {
 {
-    client().async_toggle_media_mute_state();
+    client().async_toggle_media_mute_state(page_id());
 }
 }
 
 
 void ViewImplementation::toggle_media_loop_state()
 void ViewImplementation::toggle_media_loop_state()
 {
 {
-    client().async_toggle_media_loop_state();
+    client().async_toggle_media_loop_state(page_id());
 }
 }
 
 
 void ViewImplementation::toggle_media_controls_state()
 void ViewImplementation::toggle_media_controls_state()
 {
 {
-    client().async_toggle_media_controls_state();
+    client().async_toggle_media_controls_state(page_id());
 }
 }
 
 
 void ViewImplementation::handle_resize()
 void ViewImplementation::handle_resize()
@@ -315,9 +327,9 @@ void ViewImplementation::resize_backing_stores_if_needed(WindowResizeInProgress
     auto& back_bitmap = m_client_state.back_bitmap;
     auto& back_bitmap = m_client_state.back_bitmap;
 
 
     if (front_bitmap.id != old_front_bitmap_id || back_bitmap.id != old_back_bitmap_id) {
     if (front_bitmap.id != old_front_bitmap_id || back_bitmap.id != old_back_bitmap_id) {
-        client().async_add_backing_store(front_bitmap.id, front_bitmap.bitmap->to_shareable_bitmap(), back_bitmap.id,
+        client().async_add_backing_store(page_id(), front_bitmap.id, front_bitmap.bitmap->to_shareable_bitmap(), back_bitmap.id,
             back_bitmap.bitmap->to_shareable_bitmap());
             back_bitmap.bitmap->to_shareable_bitmap());
-        client().async_set_viewport_rect(viewport_rect);
+        client().async_set_viewport_rect(page_id(), viewport_rect);
     }
     }
 }
 }
 
 
@@ -397,7 +409,7 @@ NonnullRefPtr<Core::Promise<LexicalPath>> ViewImplementation::take_screenshot(Sc
 
 
     case ScreenshotType::Full:
     case ScreenshotType::Full:
         m_pending_screenshot = promise;
         m_pending_screenshot = promise;
-        client().async_take_document_screenshot();
+        client().async_take_document_screenshot(page_id());
         break;
         break;
     }
     }
 
 
@@ -416,7 +428,7 @@ NonnullRefPtr<Core::Promise<LexicalPath>> ViewImplementation::take_dom_node_scre
     }
     }
 
 
     m_pending_screenshot = promise;
     m_pending_screenshot = promise;
-    client().async_take_dom_node_screenshot(node_id);
+    client().async_take_dom_node_screenshot(page_id(), node_id);
 
 
     return promise;
     return promise;
 }
 }
@@ -435,7 +447,7 @@ void ViewImplementation::did_receive_screenshot(Badge<WebContentClient>, Gfx::Sh
 
 
 ErrorOr<LexicalPath> ViewImplementation::dump_gc_graph()
 ErrorOr<LexicalPath> ViewImplementation::dump_gc_graph()
 {
 {
-    auto gc_graph_json = client().dump_gc_graph();
+    auto gc_graph_json = client().dump_gc_graph(page_id());
 
 
     LexicalPath path { Core::StandardPaths::tempfile_directory() };
     LexicalPath path { Core::StandardPaths::tempfile_directory() };
     path = path.append(TRY(Core::DateTime::now().to_string("gc-graph-%Y-%m-%d-%H-%M-%S.json"sv)));
     path = path.append(TRY(Core::DateTime::now().to_string("gc-graph-%Y-%m-%d-%H-%M-%S.json"sv)));
@@ -448,7 +460,7 @@ ErrorOr<LexicalPath> ViewImplementation::dump_gc_graph()
 
 
 void ViewImplementation::set_user_style_sheet(String source)
 void ViewImplementation::set_user_style_sheet(String source)
 {
 {
-    client().async_set_user_style(move(source));
+    client().async_set_user_style(page_id(), move(source));
 }
 }
 
 
 void ViewImplementation::use_native_user_style_sheet()
 void ViewImplementation::use_native_user_style_sheet()
@@ -459,7 +471,7 @@ void ViewImplementation::use_native_user_style_sheet()
 
 
 void ViewImplementation::enable_inspector_prototype()
 void ViewImplementation::enable_inspector_prototype()
 {
 {
-    client().async_enable_inspector_prototype();
+    client().async_enable_inspector_prototype(page_id());
 }
 }
 
 
 }
 }

+ 2 - 1
Userland/Libraries/LibWebView/ViewImplementation.h

@@ -25,7 +25,7 @@ namespace WebView {
 
 
 class ViewImplementation {
 class ViewImplementation {
 public:
 public:
-    virtual ~ViewImplementation() { }
+    virtual ~ViewImplementation();
 
 
     struct DOMNodeProperties {
     struct DOMNodeProperties {
         String computed_style_json;
         String computed_style_json;
@@ -192,6 +192,7 @@ protected:
 
 
     WebContentClient& client();
     WebContentClient& client();
     WebContentClient const& client() const;
     WebContentClient const& client() const;
+    u64 page_id() const;
     virtual void update_zoom() = 0;
     virtual void update_zoom() = 0;
 
 
     enum class WindowResizeInProgress {
     enum class WindowResizeInProgress {

+ 700 - 209
Userland/Libraries/LibWebView/WebContentClient.cpp

@@ -13,8 +13,8 @@ namespace WebView {
 
 
 WebContentClient::WebContentClient(NonnullOwnPtr<Core::LocalSocket> socket, ViewImplementation& view)
 WebContentClient::WebContentClient(NonnullOwnPtr<Core::LocalSocket> socket, ViewImplementation& view)
     : IPC::ConnectionToServer<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(socket))
     : IPC::ConnectionToServer<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(socket))
-    , m_view(view)
 {
 {
+    m_views.set(0, &view);
 }
 }
 
 
 void WebContentClient::die()
 void WebContentClient::die()
@@ -23,173 +23,356 @@ void WebContentClient::die()
     on_web_content_process_crash();
     on_web_content_process_crash();
 }
 }
 
 
-void WebContentClient::did_paint(Gfx::IntRect const& rect, i32 bitmap_id)
+void WebContentClient::register_view(u64 page_id, ViewImplementation& view)
 {
 {
-    m_view.server_did_paint({}, bitmap_id, rect.size());
+    VERIFY(page_id > 0);
+    m_views.set(page_id, &view);
 }
 }
 
 
-void WebContentClient::did_start_loading(AK::URL const& url, bool is_redirect)
+void WebContentClient::unregister_view(u64 page_id)
 {
 {
-    m_view.set_url({}, url);
+    m_views.remove(page_id);
+}
 
 
-    if (m_view.on_load_start)
-        m_view.on_load_start(url, is_redirect);
+void WebContentClient::did_paint(u64 page_id, Gfx::IntRect const& rect, i32 bitmap_id)
+{
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received paint for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    view.server_did_paint({}, bitmap_id, rect.size());
 }
 }
 
 
-void WebContentClient::did_finish_loading(AK::URL const& url)
+void WebContentClient::did_start_loading(u64 page_id, AK::URL const& url, bool is_redirect)
 {
 {
-    m_view.set_url({}, url);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received start loading for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
 
 
-    if (m_view.on_load_finish)
-        m_view.on_load_finish(url);
+    view.set_url({}, url);
+
+    if (view.on_load_start)
+        view.on_load_start(url, is_redirect);
 }
 }
 
 
-void WebContentClient::did_finish_text_test()
+void WebContentClient::did_finish_loading(u64 page_id, AK::URL const& url)
 {
 {
-    if (m_view.on_text_test_finish)
-        m_view.on_text_test_finish();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received finish loading for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    view.set_url({}, url);
+
+    if (view.on_load_finish)
+        view.on_load_finish(url);
 }
 }
 
 
-void WebContentClient::did_request_navigate_back()
+void WebContentClient::did_finish_text_test(u64 page_id)
 {
 {
-    if (m_view.on_navigate_back)
-        m_view.on_navigate_back();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received finish text test for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_text_test_finish)
+        view.on_text_test_finish();
+}
+
+void WebContentClient::did_request_navigate_back(u64 page_id)
+{
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received navigate back for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_navigate_back)
+        view.on_navigate_back();
 }
 }
 
 
-void WebContentClient::did_request_navigate_forward()
+void WebContentClient::did_request_navigate_forward(u64 page_id)
 {
 {
-    if (m_view.on_navigate_forward)
-        m_view.on_navigate_forward();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received navigate forward for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_navigate_forward)
+        view.on_navigate_forward();
 }
 }
 
 
-void WebContentClient::did_request_refresh()
+void WebContentClient::did_request_refresh(u64 page_id)
 {
 {
-    if (m_view.on_refresh)
-        m_view.on_refresh();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received refresh for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_refresh)
+        view.on_refresh();
 }
 }
 
 
-void WebContentClient::did_request_cursor_change(i32 cursor_type)
+void WebContentClient::did_request_cursor_change(u64 page_id, i32 cursor_type)
 {
 {
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received cursor change for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
     if (cursor_type < 0 || cursor_type >= (i32)Gfx::StandardCursor::__Count) {
     if (cursor_type < 0 || cursor_type >= (i32)Gfx::StandardCursor::__Count) {
         dbgln("DidRequestCursorChange: Bad cursor type");
         dbgln("DidRequestCursorChange: Bad cursor type");
         return;
         return;
     }
     }
 
 
-    if (m_view.on_cursor_change)
-        m_view.on_cursor_change(static_cast<Gfx::StandardCursor>(cursor_type));
+    if (view.on_cursor_change)
+        view.on_cursor_change(static_cast<Gfx::StandardCursor>(cursor_type));
 }
 }
 
 
-void WebContentClient::did_layout(Gfx::IntSize content_size)
+void WebContentClient::did_layout(u64 page_id, Gfx::IntSize content_size)
 {
 {
     dbgln_if(SPAM_DEBUG, "handle: WebContentClient::DidLayout! content_size={}", content_size);
     dbgln_if(SPAM_DEBUG, "handle: WebContentClient::DidLayout! content_size={}", content_size);
-    if (m_view.on_did_layout)
-        m_view.on_did_layout(content_size);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received layout for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_did_layout)
+        view.on_did_layout(content_size);
 }
 }
 
 
-void WebContentClient::did_change_title(ByteString const& title)
+void WebContentClient::did_change_title(u64 page_id, ByteString const& title)
 {
 {
     dbgln_if(SPAM_DEBUG, "handle: WebContentClient::DidChangeTitle! title={}", title);
     dbgln_if(SPAM_DEBUG, "handle: WebContentClient::DidChangeTitle! title={}", title);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received title change for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
 
 
-    if (!m_view.on_title_change)
+    if (!view.on_title_change)
         return;
         return;
 
 
     if (title.is_empty())
     if (title.is_empty())
-        m_view.on_title_change(m_view.url().to_byte_string());
+        view.on_title_change(view.url().to_byte_string());
     else
     else
-        m_view.on_title_change(title);
+        view.on_title_change(title);
 }
 }
 
 
-void WebContentClient::did_request_scroll(i32 x_delta, i32 y_delta)
+void WebContentClient::did_request_scroll(u64 page_id, i32 x_delta, i32 y_delta)
 {
 {
-    if (m_view.on_scroll_by_delta)
-        m_view.on_scroll_by_delta(x_delta, y_delta);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received scroll request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_scroll_by_delta)
+        view.on_scroll_by_delta(x_delta, y_delta);
 }
 }
 
 
-void WebContentClient::did_request_scroll_to(Gfx::IntPoint scroll_position)
+void WebContentClient::did_request_scroll_to(u64 page_id, Gfx::IntPoint scroll_position)
 {
 {
-    if (m_view.on_scroll_to_point)
-        m_view.on_scroll_to_point(scroll_position);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received scroll request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_scroll_to_point)
+        view.on_scroll_to_point(scroll_position);
 }
 }
 
 
-void WebContentClient::did_enter_tooltip_area(Gfx::IntPoint content_position, ByteString const& title)
+void WebContentClient::did_enter_tooltip_area(u64 page_id, Gfx::IntPoint content_position, ByteString const& title)
 {
 {
-    if (m_view.on_enter_tooltip_area)
-        m_view.on_enter_tooltip_area(m_view.to_widget_position(content_position), title);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received tooltip enter for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_enter_tooltip_area)
+        view.on_enter_tooltip_area(view.to_widget_position(content_position), title);
 }
 }
 
 
-void WebContentClient::did_leave_tooltip_area()
+void WebContentClient::did_leave_tooltip_area(u64 page_id)
 {
 {
-    if (m_view.on_leave_tooltip_area)
-        m_view.on_leave_tooltip_area();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received tooltip leave for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_leave_tooltip_area)
+        view.on_leave_tooltip_area();
 }
 }
 
 
-void WebContentClient::did_hover_link(AK::URL const& url)
+void WebContentClient::did_hover_link(u64 page_id, AK::URL const& url)
 {
 {
     dbgln_if(SPAM_DEBUG, "handle: WebContentClient::DidHoverLink! url={}", url);
     dbgln_if(SPAM_DEBUG, "handle: WebContentClient::DidHoverLink! url={}", url);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received hover link for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
 
 
-    if (m_view.on_link_hover)
-        m_view.on_link_hover(url);
+    if (view.on_link_hover)
+        view.on_link_hover(url);
 }
 }
 
 
-void WebContentClient::did_unhover_link()
+void WebContentClient::did_unhover_link(u64 page_id)
 {
 {
     dbgln_if(SPAM_DEBUG, "handle: WebContentClient::DidUnhoverLink!");
     dbgln_if(SPAM_DEBUG, "handle: WebContentClient::DidUnhoverLink!");
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received unhover link for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
 
 
-    if (m_view.on_link_unhover)
-        m_view.on_link_unhover();
+    if (view.on_link_unhover)
+        view.on_link_unhover();
 }
 }
 
 
-void WebContentClient::did_click_link(AK::URL const& url, ByteString const& target, unsigned modifiers)
+void WebContentClient::did_click_link(u64 page_id, AK::URL const& url, ByteString const& target, unsigned modifiers)
 {
 {
-    if (m_view.on_link_click)
-        m_view.on_link_click(url, target, modifiers);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received click link for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_link_click)
+        view.on_link_click(url, target, modifiers);
 }
 }
 
 
-void WebContentClient::did_middle_click_link(AK::URL const& url, ByteString const& target, unsigned modifiers)
+void WebContentClient::did_middle_click_link(u64 page_id, AK::URL const& url, ByteString const& target, unsigned modifiers)
 {
 {
-    if (m_view.on_link_middle_click)
-        m_view.on_link_middle_click(url, target, modifiers);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received middle click link for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_link_middle_click)
+        view.on_link_middle_click(url, target, modifiers);
 }
 }
 
 
-void WebContentClient::did_request_context_menu(Gfx::IntPoint content_position)
+void WebContentClient::did_request_context_menu(u64 page_id, Gfx::IntPoint content_position)
 {
 {
-    if (m_view.on_context_menu_request)
-        m_view.on_context_menu_request(m_view.to_widget_position(content_position));
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received context menu request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_context_menu_request)
+        view.on_context_menu_request(view.to_widget_position(content_position));
 }
 }
 
 
-void WebContentClient::did_request_link_context_menu(Gfx::IntPoint content_position, AK::URL const& url, ByteString const&, unsigned)
+void WebContentClient::did_request_link_context_menu(u64 page_id, Gfx::IntPoint content_position, AK::URL const& url, ByteString const&, unsigned)
 {
 {
-    if (m_view.on_link_context_menu_request)
-        m_view.on_link_context_menu_request(url, m_view.to_widget_position(content_position));
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received link context menu request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_link_context_menu_request)
+        view.on_link_context_menu_request(url, view.to_widget_position(content_position));
 }
 }
 
 
-void WebContentClient::did_request_image_context_menu(Gfx::IntPoint content_position, AK::URL const& url, ByteString const&, unsigned, Gfx::ShareableBitmap const& bitmap)
+void WebContentClient::did_request_image_context_menu(u64 page_id, Gfx::IntPoint content_position, AK::URL const& url, ByteString const&, unsigned, Gfx::ShareableBitmap const& bitmap)
 {
 {
-    if (m_view.on_image_context_menu_request)
-        m_view.on_image_context_menu_request(url, m_view.to_widget_position(content_position), bitmap);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received image context menu request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_image_context_menu_request)
+        view.on_image_context_menu_request(url, view.to_widget_position(content_position), bitmap);
 }
 }
 
 
-void WebContentClient::did_request_media_context_menu(Gfx::IntPoint content_position, ByteString const&, unsigned, Web::Page::MediaContextMenu const& menu)
+void WebContentClient::did_request_media_context_menu(u64 page_id, Gfx::IntPoint content_position, ByteString const&, unsigned, Web::Page::MediaContextMenu const& menu)
 {
 {
-    if (m_view.on_media_context_menu_request)
-        m_view.on_media_context_menu_request(m_view.to_widget_position(content_position), menu);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received media context menu request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_media_context_menu_request)
+        view.on_media_context_menu_request(view.to_widget_position(content_position), menu);
 }
 }
 
 
-void WebContentClient::did_get_source(AK::URL const& url, ByteString const& source)
+void WebContentClient::did_get_source(u64 page_id, AK::URL const& url, ByteString const& source)
 {
 {
-    if (m_view.on_received_source)
-        m_view.on_received_source(url, source);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received get source for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_received_source)
+        view.on_received_source(url, source);
 }
 }
 
 
-void WebContentClient::did_inspect_dom_tree(ByteString const& dom_tree)
+void WebContentClient::did_inspect_dom_tree(u64 page_id, ByteString const& dom_tree)
 {
 {
-    if (m_view.on_received_dom_tree)
-        m_view.on_received_dom_tree(dom_tree);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received Inspect DOM tree for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_received_dom_tree)
+        view.on_received_dom_tree(dom_tree);
 }
 }
 
 
-void WebContentClient::did_inspect_dom_node(bool has_style, ByteString const& computed_style, ByteString const& resolved_style, ByteString const& custom_properties, ByteString const& node_box_sizing, ByteString const& aria_properties_state)
+void WebContentClient::did_inspect_dom_node(u64 page_id, bool has_style, ByteString const& computed_style, ByteString const& resolved_style, ByteString const& custom_properties, ByteString const& node_box_sizing, ByteString const& aria_properties_state)
 {
 {
-    if (!m_view.on_received_dom_node_properties)
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received Inspect DOM node for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (!view.on_received_dom_node_properties)
         return;
         return;
 
 
     Optional<ViewImplementation::DOMNodeProperties> properties;
     Optional<ViewImplementation::DOMNodeProperties> properties;
@@ -204,284 +387,592 @@ void WebContentClient::did_inspect_dom_node(bool has_style, ByteString const& co
         };
         };
     }
     }
 
 
-    m_view.on_received_dom_node_properties(move(properties));
+    view.on_received_dom_node_properties(move(properties));
 }
 }
 
 
-void WebContentClient::did_inspect_accessibility_tree(ByteString const& accessibility_tree)
+void WebContentClient::did_inspect_accessibility_tree(u64 page_id, ByteString const& accessibility_tree)
 {
 {
-    if (m_view.on_received_accessibility_tree)
-        m_view.on_received_accessibility_tree(accessibility_tree);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received Inspect Accessibility tree for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_received_accessibility_tree)
+        view.on_received_accessibility_tree(accessibility_tree);
 }
 }
 
 
-void WebContentClient::did_get_hovered_node_id(i32 node_id)
+void WebContentClient::did_get_hovered_node_id(u64 page_id, i32 node_id)
 {
 {
-    if (m_view.on_received_hovered_node_id)
-        m_view.on_received_hovered_node_id(node_id);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received get hovered node ID for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_received_hovered_node_id)
+        view.on_received_hovered_node_id(node_id);
 }
 }
 
 
-void WebContentClient::did_finish_editing_dom_node(Optional<i32> const& node_id)
+void WebContentClient::did_finish_editing_dom_node(u64 page_id, Optional<i32> const& node_id)
 {
 {
-    if (m_view.on_finshed_editing_dom_node)
-        m_view.on_finshed_editing_dom_node(node_id);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received finish editing DOM node for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_finshed_editing_dom_node)
+        view.on_finshed_editing_dom_node(node_id);
 }
 }
 
 
-void WebContentClient::did_get_dom_node_html(String const& html)
+void WebContentClient::did_get_dom_node_html(u64 page_id, String const& html)
 {
 {
-    if (m_view.on_received_dom_node_html)
-        m_view.on_received_dom_node_html(html);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received get DOM node HTML for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_received_dom_node_html)
+        view.on_received_dom_node_html(html);
 }
 }
 
 
-void WebContentClient::did_take_screenshot(Gfx::ShareableBitmap const& screenshot)
+void WebContentClient::did_take_screenshot(u64 page_id, Gfx::ShareableBitmap const& screenshot)
 {
 {
-    m_view.did_receive_screenshot({}, screenshot);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received take screenshot for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    view.did_receive_screenshot({}, screenshot);
 }
 }
 
 
-void WebContentClient::did_output_js_console_message(i32 message_index)
+void WebContentClient::did_output_js_console_message(u64 page_id, i32 message_index)
 {
 {
-    if (m_view.on_received_console_message)
-        m_view.on_received_console_message(message_index);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received output JS console message for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_received_console_message)
+        view.on_received_console_message(message_index);
 }
 }
 
 
-void WebContentClient::did_get_js_console_messages(i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages)
+void WebContentClient::did_get_js_console_messages(u64 page_id, i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages)
 {
 {
-    if (m_view.on_received_console_messages)
-        m_view.on_received_console_messages(start_index, message_types, messages);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received get JS console messages for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_received_console_messages)
+        view.on_received_console_messages(start_index, message_types, messages);
 }
 }
 
 
-void WebContentClient::did_request_alert(String const& message)
+void WebContentClient::did_request_alert(u64 page_id, String const& message)
 {
 {
-    if (m_view.on_request_alert)
-        m_view.on_request_alert(message);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received alert request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_alert)
+        view.on_request_alert(message);
 }
 }
 
 
-void WebContentClient::did_request_confirm(String const& message)
+void WebContentClient::did_request_confirm(u64 page_id, String const& message)
 {
 {
-    if (m_view.on_request_confirm)
-        m_view.on_request_confirm(message);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received confirm request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_confirm)
+        view.on_request_confirm(message);
 }
 }
 
 
-void WebContentClient::did_request_prompt(String const& message, String const& default_)
+void WebContentClient::did_request_prompt(u64 page_id, String const& message, String const& default_)
 {
 {
-    if (m_view.on_request_prompt)
-        m_view.on_request_prompt(message, default_);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received prompt request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_prompt)
+        view.on_request_prompt(message, default_);
 }
 }
 
 
-void WebContentClient::did_request_set_prompt_text(String const& message)
+void WebContentClient::did_request_set_prompt_text(u64 page_id, String const& message)
 {
 {
-    if (m_view.on_request_set_prompt_text)
-        m_view.on_request_set_prompt_text(message);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received set prompt text request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_set_prompt_text)
+        view.on_request_set_prompt_text(message);
 }
 }
 
 
-void WebContentClient::did_request_accept_dialog()
+void WebContentClient::did_request_accept_dialog(u64 page_id)
 {
 {
-    if (m_view.on_request_accept_dialog)
-        m_view.on_request_accept_dialog();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received accept dialog request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_accept_dialog)
+        view.on_request_accept_dialog();
 }
 }
 
 
-void WebContentClient::did_request_dismiss_dialog()
+void WebContentClient::did_request_dismiss_dialog(u64 page_id)
 {
 {
-    if (m_view.on_request_dismiss_dialog)
-        m_view.on_request_dismiss_dialog();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received dismiss dialog request for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_dismiss_dialog)
+        view.on_request_dismiss_dialog();
 }
 }
 
 
-void WebContentClient::did_change_favicon(Gfx::ShareableBitmap const& favicon)
+void WebContentClient::did_change_favicon(u64 page_id, Gfx::ShareableBitmap const& favicon)
 {
 {
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received change favicon for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
     if (!favicon.is_valid()) {
     if (!favicon.is_valid()) {
         dbgln("DidChangeFavicon: Received invalid favicon");
         dbgln("DidChangeFavicon: Received invalid favicon");
         return;
         return;
     }
     }
 
 
-    if (m_view.on_favicon_change)
-        m_view.on_favicon_change(*favicon.bitmap());
+    if (view.on_favicon_change)
+        view.on_favicon_change(*favicon.bitmap());
 }
 }
 
 
-Messages::WebContentClient::DidRequestAllCookiesResponse WebContentClient::did_request_all_cookies(AK::URL const& url)
+Messages::WebContentClient::DidRequestAllCookiesResponse WebContentClient::did_request_all_cookies(u64 page_id, AK::URL const& url)
 {
 {
-    if (m_view.on_get_all_cookies)
-        return m_view.on_get_all_cookies(url);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request all cookies for unknown page ID {}", page_id);
+        return Vector<Web::Cookie::Cookie> {};
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_get_all_cookies)
+        return view.on_get_all_cookies(url);
     return Vector<Web::Cookie::Cookie> {};
     return Vector<Web::Cookie::Cookie> {};
 }
 }
 
 
-Messages::WebContentClient::DidRequestNamedCookieResponse WebContentClient::did_request_named_cookie(AK::URL const& url, String const& name)
+Messages::WebContentClient::DidRequestNamedCookieResponse WebContentClient::did_request_named_cookie(u64 page_id, AK::URL const& url, String const& name)
 {
 {
-    if (m_view.on_get_named_cookie)
-        return m_view.on_get_named_cookie(url, name);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request named cookie for unknown page ID {}", page_id);
+        return OptionalNone {};
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_get_named_cookie)
+        return view.on_get_named_cookie(url, name);
     return OptionalNone {};
     return OptionalNone {};
 }
 }
 
 
-Messages::WebContentClient::DidRequestCookieResponse WebContentClient::did_request_cookie(AK::URL const& url, Web::Cookie::Source source)
+Messages::WebContentClient::DidRequestCookieResponse WebContentClient::did_request_cookie(u64 page_id, AK::URL const& url, Web::Cookie::Source source)
 {
 {
-    if (m_view.on_get_cookie)
-        return m_view.on_get_cookie(url, source);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request cookie for unknown page ID {}", page_id);
+        return String {};
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_get_cookie)
+        return view.on_get_cookie(url, source);
     return String {};
     return String {};
 }
 }
 
 
-void WebContentClient::did_set_cookie(AK::URL const& url, Web::Cookie::ParsedCookie const& cookie, Web::Cookie::Source source)
+void WebContentClient::did_set_cookie(u64 page_id, AK::URL const& url, Web::Cookie::ParsedCookie const& cookie, Web::Cookie::Source source)
 {
 {
-    if (m_view.on_set_cookie)
-        m_view.on_set_cookie(url, cookie, source);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received set cookie for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_set_cookie)
+        view.on_set_cookie(url, cookie, source);
 }
 }
 
 
-void WebContentClient::did_update_cookie(Web::Cookie::Cookie const& cookie)
+void WebContentClient::did_update_cookie(u64 page_id, Web::Cookie::Cookie const& cookie)
 {
 {
-    if (m_view.on_update_cookie)
-        m_view.on_update_cookie(cookie);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received update cookie for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_update_cookie)
+        view.on_update_cookie(cookie);
 }
 }
 
 
-Messages::WebContentClient::DidRequestNewWebViewResponse WebContentClient::did_request_new_web_view(Web::HTML::ActivateTab const& activate_tab, Web::HTML::WebViewHints const& hints, Optional<u64> const& page_index)
+Messages::WebContentClient::DidRequestNewWebViewResponse WebContentClient::did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab const& activate_tab, Web::HTML::WebViewHints const& hints, Optional<u64> const& page_index)
 {
 {
-    if (m_view.on_new_web_view)
-        return m_view.on_new_web_view(activate_tab, hints, page_index);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request new web view for unknown page ID {}", page_id);
+        return String {};
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_new_web_view)
+        return view.on_new_web_view(activate_tab, hints, page_index);
     return String {};
     return String {};
 }
 }
 
 
-void WebContentClient::did_request_activate_tab()
+void WebContentClient::did_request_activate_tab(u64 page_id)
 {
 {
-    if (m_view.on_activate_tab)
-        m_view.on_activate_tab();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request activate tab for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_activate_tab)
+        view.on_activate_tab();
 }
 }
 
 
-void WebContentClient::did_close_browsing_context()
+void WebContentClient::did_close_browsing_context(u64 page_id)
 {
 {
-    if (m_view.on_close)
-        m_view.on_close();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received close browsing context for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_close)
+        view.on_close();
 }
 }
 
 
-void WebContentClient::did_update_resource_count(i32 count_waiting)
+void WebContentClient::did_update_resource_count(u64 page_id, i32 count_waiting)
 {
 {
-    if (m_view.on_resource_status_change)
-        m_view.on_resource_status_change(count_waiting);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received update resource count for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_resource_status_change)
+        view.on_resource_status_change(count_waiting);
 }
 }
 
 
-void WebContentClient::did_request_restore_window()
+void WebContentClient::did_request_restore_window(u64 page_id)
 {
 {
-    if (m_view.on_restore_window)
-        m_view.on_restore_window();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request restore window for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_restore_window)
+        view.on_restore_window();
 }
 }
 
 
-Messages::WebContentClient::DidRequestRepositionWindowResponse WebContentClient::did_request_reposition_window(Gfx::IntPoint position)
+Messages::WebContentClient::DidRequestRepositionWindowResponse WebContentClient::did_request_reposition_window(u64 page_id, Gfx::IntPoint position)
 {
 {
-    if (m_view.on_reposition_window)
-        return m_view.on_reposition_window(position);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request reposition window for unknown page ID {}", page_id);
+        return Gfx::IntPoint {};
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_reposition_window)
+        return view.on_reposition_window(position);
     return Gfx::IntPoint {};
     return Gfx::IntPoint {};
 }
 }
 
 
-Messages::WebContentClient::DidRequestResizeWindowResponse WebContentClient::did_request_resize_window(Gfx::IntSize size)
+Messages::WebContentClient::DidRequestResizeWindowResponse WebContentClient::did_request_resize_window(u64 page_id, Gfx::IntSize size)
 {
 {
-    if (m_view.on_resize_window)
-        return m_view.on_resize_window(size);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request resize window for unknown page ID {}", page_id);
+        return Gfx::IntSize {};
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_resize_window)
+        return view.on_resize_window(size);
     return Gfx::IntSize {};
     return Gfx::IntSize {};
 }
 }
 
 
-Messages::WebContentClient::DidRequestMaximizeWindowResponse WebContentClient::did_request_maximize_window()
+Messages::WebContentClient::DidRequestMaximizeWindowResponse WebContentClient::did_request_maximize_window(u64 page_id)
 {
 {
-    if (m_view.on_maximize_window)
-        return m_view.on_maximize_window();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request maximize window for unknown page ID {}", page_id);
+        return Gfx::IntRect {};
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_maximize_window)
+        return view.on_maximize_window();
     return Gfx::IntRect {};
     return Gfx::IntRect {};
 }
 }
 
 
-Messages::WebContentClient::DidRequestMinimizeWindowResponse WebContentClient::did_request_minimize_window()
+Messages::WebContentClient::DidRequestMinimizeWindowResponse WebContentClient::did_request_minimize_window(u64 page_id)
 {
 {
-    if (m_view.on_minimize_window)
-        return m_view.on_minimize_window();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request minimize window for unknown page ID {}", page_id);
+        return Gfx::IntRect {};
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_minimize_window)
+        return view.on_minimize_window();
     return Gfx::IntRect {};
     return Gfx::IntRect {};
 }
 }
 
 
-Messages::WebContentClient::DidRequestFullscreenWindowResponse WebContentClient::did_request_fullscreen_window()
+Messages::WebContentClient::DidRequestFullscreenWindowResponse WebContentClient::did_request_fullscreen_window(u64 page_id)
 {
 {
-    if (m_view.on_fullscreen_window)
-        return m_view.on_fullscreen_window();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request fullscreen window for unknown page ID {}", page_id);
+        return Gfx::IntRect {};
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_fullscreen_window)
+        return view.on_fullscreen_window();
     return Gfx::IntRect {};
     return Gfx::IntRect {};
 }
 }
 
 
-void WebContentClient::did_request_file(ByteString const& path, i32 request_id)
+void WebContentClient::did_request_file(u64 page_id, ByteString const& path, i32 request_id)
 {
 {
-    if (m_view.on_request_file)
-        m_view.on_request_file(path, request_id);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request file for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_file)
+        view.on_request_file(path, request_id);
 }
 }
 
 
-void WebContentClient::did_request_color_picker(Color const& current_color)
+void WebContentClient::did_request_color_picker(u64 page_id, Color const& current_color)
 {
 {
-    if (m_view.on_request_color_picker)
-        m_view.on_request_color_picker(current_color);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request color picker for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_color_picker)
+        view.on_request_color_picker(current_color);
 }
 }
 
 
-void WebContentClient::did_request_select_dropdown(Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> const& items)
+void WebContentClient::did_request_select_dropdown(u64 page_id, Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> const& items)
 {
 {
-    if (m_view.on_request_select_dropdown)
-        m_view.on_request_select_dropdown(content_position, minimum_width, items);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request select dropdown for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_select_dropdown)
+        view.on_request_select_dropdown(content_position, minimum_width, items);
 }
 }
 
 
-void WebContentClient::did_finish_handling_input_event(bool event_was_accepted)
+void WebContentClient::did_finish_handling_input_event(u64 page_id, bool event_was_accepted)
 {
 {
-    if (m_view.on_finish_handling_input_event)
-        m_view.on_finish_handling_input_event(event_was_accepted);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received finish handling input event for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_finish_handling_input_event)
+        view.on_finish_handling_input_event(event_was_accepted);
 }
 }
 
 
-void WebContentClient::did_change_theme_color(Gfx::Color color)
+void WebContentClient::did_change_theme_color(u64 page_id, Gfx::Color color)
 {
 {
-    if (m_view.on_theme_color_change)
-        m_view.on_theme_color_change(color);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received change theme color for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_theme_color_change)
+        view.on_theme_color_change(color);
 }
 }
 
 
-void WebContentClient::did_insert_clipboard_entry(String const& data, String const& presentation_style, String const& mime_type)
+void WebContentClient::did_insert_clipboard_entry(u64 page_id, String const& data, String const& presentation_style, String const& mime_type)
 {
 {
-    if (m_view.on_insert_clipboard_entry)
-        m_view.on_insert_clipboard_entry(data, presentation_style, mime_type);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received insert clipboard entry for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_insert_clipboard_entry)
+        view.on_insert_clipboard_entry(data, presentation_style, mime_type);
 }
 }
 
 
-void WebContentClient::inspector_did_load()
+void WebContentClient::inspector_did_load(u64 page_id)
 {
 {
-    if (m_view.on_inspector_loaded)
-        m_view.on_inspector_loaded();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received inspector loaded for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_inspector_loaded)
+        view.on_inspector_loaded();
 }
 }
 
 
-void WebContentClient::inspector_did_select_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element)
+void WebContentClient::inspector_did_select_dom_node(u64 page_id, i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element)
 {
 {
-    if (m_view.on_inspector_selected_dom_node)
-        m_view.on_inspector_selected_dom_node(node_id, pseudo_element);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received inspector select DOM node for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_inspector_selected_dom_node)
+        view.on_inspector_selected_dom_node(node_id, pseudo_element);
 }
 }
 
 
-void WebContentClient::inspector_did_set_dom_node_text(i32 node_id, String const& text)
+void WebContentClient::inspector_did_set_dom_node_text(u64 page_id, i32 node_id, String const& text)
 {
 {
-    if (m_view.on_inspector_set_dom_node_text)
-        m_view.on_inspector_set_dom_node_text(node_id, text);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received inspector set DOM node text for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_inspector_set_dom_node_text)
+        view.on_inspector_set_dom_node_text(node_id, text);
 }
 }
 
 
-void WebContentClient::inspector_did_set_dom_node_tag(i32 node_id, String const& tag)
+void WebContentClient::inspector_did_set_dom_node_tag(u64 page_id, i32 node_id, String const& tag)
 {
 {
-    if (m_view.on_inspector_set_dom_node_tag)
-        m_view.on_inspector_set_dom_node_tag(node_id, tag);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received inspector set DOM node tag for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_inspector_set_dom_node_tag)
+        view.on_inspector_set_dom_node_tag(node_id, tag);
 }
 }
 
 
-void WebContentClient::inspector_did_add_dom_node_attributes(i32 node_id, Vector<Attribute> const& attributes)
+void WebContentClient::inspector_did_add_dom_node_attributes(u64 page_id, i32 node_id, Vector<Attribute> const& attributes)
 {
 {
-    if (m_view.on_inspector_added_dom_node_attributes)
-        m_view.on_inspector_added_dom_node_attributes(node_id, attributes);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received inspector add DOM node attributes for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_inspector_added_dom_node_attributes)
+        view.on_inspector_added_dom_node_attributes(node_id, attributes);
 }
 }
 
 
-void WebContentClient::inspector_did_replace_dom_node_attribute(i32 node_id, String const& name, Vector<Attribute> const& replacement_attributes)
+void WebContentClient::inspector_did_replace_dom_node_attribute(u64 page_id, i32 node_id, String const& name, Vector<Attribute> const& replacement_attributes)
 {
 {
-    if (m_view.on_inspector_replaced_dom_node_attribute)
-        m_view.on_inspector_replaced_dom_node_attribute(node_id, name, replacement_attributes);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received inspector replace DOM node attribute for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_inspector_replaced_dom_node_attribute)
+        view.on_inspector_replaced_dom_node_attribute(node_id, name, replacement_attributes);
 }
 }
 
 
-void WebContentClient::inspector_did_request_dom_tree_context_menu(i32 node_id, Gfx::IntPoint position, String const& type, Optional<String> const& tag, Optional<Attribute> const& attribute)
+void WebContentClient::inspector_did_request_dom_tree_context_menu(u64 page_id, i32 node_id, Gfx::IntPoint position, String const& type, Optional<String> const& tag, Optional<Attribute> const& attribute)
 {
 {
-    if (m_view.on_inspector_requested_dom_tree_context_menu)
-        m_view.on_inspector_requested_dom_tree_context_menu(node_id, m_view.to_widget_position(position), type, tag, attribute);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received inspector request DOM tree context menu for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_inspector_requested_dom_tree_context_menu)
+        view.on_inspector_requested_dom_tree_context_menu(node_id, view.to_widget_position(position), type, tag, attribute);
 }
 }
 
 
-void WebContentClient::inspector_did_execute_console_script(String const& script)
+void WebContentClient::inspector_did_execute_console_script(u64 page_id, String const& script)
 {
 {
-    if (m_view.on_inspector_executed_console_script)
-        m_view.on_inspector_executed_console_script(script);
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received inspector execute console script for unknown page ID {}", page_id);
+        return;
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_inspector_executed_console_script)
+        view.on_inspector_executed_console_script(script);
 }
 }
 
 
-Messages::WebContentClient::RequestWorkerAgentResponse WebContentClient::request_worker_agent()
+Messages::WebContentClient::RequestWorkerAgentResponse WebContentClient::request_worker_agent(u64 page_id)
 {
 {
-    if (m_view.on_request_worker_agent)
-        return m_view.on_request_worker_agent();
+    auto maybe_view = m_views.get(page_id);
+    if (!maybe_view.has_value()) {
+        dbgln("Received request worker agent for unknown page ID {}", page_id);
+        return WebView::SocketPair { -1, -1 };
+    }
+    auto& view = *maybe_view.value();
+
+    if (view.on_request_worker_agent)
+        return view.on_request_worker_agent();
 
 
     return Messages::WebContentClient::RequestWorkerAgentResponse { WebView::SocketPair { -1, -1 } };
     return Messages::WebContentClient::RequestWorkerAgentResponse { WebView::SocketPair { -1, -1 } };
 }
 }

+ 74 - 70
Userland/Libraries/LibWebView/WebContentClient.h

@@ -26,82 +26,86 @@ class WebContentClient final
 public:
 public:
     WebContentClient(NonnullOwnPtr<Core::LocalSocket>, ViewImplementation&);
     WebContentClient(NonnullOwnPtr<Core::LocalSocket>, ViewImplementation&);
 
 
+    void register_view(u64 page_id, ViewImplementation&);
+    void unregister_view(u64 page_id);
+
     Function<void()> on_web_content_process_crash;
     Function<void()> on_web_content_process_crash;
 
 
 private:
 private:
     virtual void die() override;
     virtual void die() override;
 
 
-    virtual void did_paint(Gfx::IntRect const&, i32) override;
-    virtual void did_finish_loading(AK::URL const&) override;
-    virtual void did_request_navigate_back() override;
-    virtual void did_request_navigate_forward() override;
-    virtual void did_request_refresh() override;
-    virtual void did_request_cursor_change(i32) override;
-    virtual void did_layout(Gfx::IntSize) override;
-    virtual void did_change_title(ByteString const&) override;
-    virtual void did_request_scroll(i32, i32) override;
-    virtual void did_request_scroll_to(Gfx::IntPoint) override;
-    virtual void did_enter_tooltip_area(Gfx::IntPoint, ByteString const&) override;
-    virtual void did_leave_tooltip_area() override;
-    virtual void did_hover_link(AK::URL const&) override;
-    virtual void did_unhover_link() override;
-    virtual void did_click_link(AK::URL const&, ByteString const&, unsigned) override;
-    virtual void did_middle_click_link(AK::URL const&, ByteString const&, unsigned) override;
-    virtual void did_start_loading(AK::URL const&, bool) override;
-    virtual void did_request_context_menu(Gfx::IntPoint) override;
-    virtual void did_request_link_context_menu(Gfx::IntPoint, AK::URL const&, ByteString const&, unsigned) override;
-    virtual void did_request_image_context_menu(Gfx::IntPoint, AK::URL const&, ByteString const&, unsigned, Gfx::ShareableBitmap const&) override;
-    virtual void did_request_media_context_menu(Gfx::IntPoint, ByteString const&, unsigned, Web::Page::MediaContextMenu const&) override;
-    virtual void did_get_source(AK::URL const&, ByteString const&) override;
-    virtual void did_inspect_dom_tree(ByteString const&) override;
-    virtual void did_inspect_dom_node(bool has_style, ByteString const& computed_style, ByteString const& resolved_style, ByteString const& custom_properties, ByteString const& node_box_sizing, ByteString const& aria_properties_state) override;
-    virtual void did_inspect_accessibility_tree(ByteString const&) override;
-    virtual void did_get_hovered_node_id(i32 node_id) override;
-    virtual void did_finish_editing_dom_node(Optional<i32> const& node_id) override;
-    virtual void did_get_dom_node_html(String const& html) override;
-    virtual void did_take_screenshot(Gfx::ShareableBitmap const& screenshot) override;
-    virtual void did_output_js_console_message(i32 message_index) override;
-    virtual void did_get_js_console_messages(i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages) override;
-    virtual void did_change_favicon(Gfx::ShareableBitmap const&) override;
-    virtual void did_request_alert(String const&) override;
-    virtual void did_request_confirm(String const&) override;
-    virtual void did_request_prompt(String const&, String const&) override;
-    virtual void did_request_set_prompt_text(String const& message) override;
-    virtual void did_request_accept_dialog() override;
-    virtual void did_request_dismiss_dialog() override;
-    virtual Messages::WebContentClient::DidRequestAllCookiesResponse did_request_all_cookies(AK::URL const&) override;
-    virtual Messages::WebContentClient::DidRequestNamedCookieResponse did_request_named_cookie(AK::URL const&, String const&) override;
-    virtual Messages::WebContentClient::DidRequestCookieResponse did_request_cookie(AK::URL const&, Web::Cookie::Source) override;
-    virtual void did_set_cookie(AK::URL const&, Web::Cookie::ParsedCookie const&, Web::Cookie::Source) override;
-    virtual void did_update_cookie(Web::Cookie::Cookie const&) override;
-    virtual Messages::WebContentClient::DidRequestNewWebViewResponse did_request_new_web_view(Web::HTML::ActivateTab const&, Web::HTML::WebViewHints const&, Optional<u64> const& page_index) override;
-    virtual void did_request_activate_tab() override;
-    virtual void did_close_browsing_context() override;
-    virtual void did_update_resource_count(i32 count_waiting) override;
-    virtual void did_request_restore_window() override;
-    virtual Messages::WebContentClient::DidRequestRepositionWindowResponse did_request_reposition_window(Gfx::IntPoint) override;
-    virtual Messages::WebContentClient::DidRequestResizeWindowResponse did_request_resize_window(Gfx::IntSize) override;
-    virtual Messages::WebContentClient::DidRequestMaximizeWindowResponse did_request_maximize_window() override;
-    virtual Messages::WebContentClient::DidRequestMinimizeWindowResponse did_request_minimize_window() override;
-    virtual Messages::WebContentClient::DidRequestFullscreenWindowResponse did_request_fullscreen_window() override;
-    virtual void did_request_file(ByteString const& path, i32) override;
-    virtual void did_request_color_picker(Color const& current_color) override;
-    virtual void did_request_select_dropdown(Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> const& items) override;
-    virtual void did_finish_handling_input_event(bool event_was_accepted) override;
-    virtual void did_finish_text_test() override;
-    virtual void did_change_theme_color(Gfx::Color color) override;
-    virtual void did_insert_clipboard_entry(String const& data, String const& presentation_style, String const& mime_type) override;
-    virtual void inspector_did_load() override;
-    virtual void inspector_did_select_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element) override;
-    virtual void inspector_did_set_dom_node_text(i32 node_id, String const& text) override;
-    virtual void inspector_did_set_dom_node_tag(i32 node_id, String const& tag) override;
-    virtual void inspector_did_add_dom_node_attributes(i32 node_id, Vector<Attribute> const& attributes) override;
-    virtual void inspector_did_replace_dom_node_attribute(i32 node_id, String const& name, Vector<Attribute> const& replacement_attributes) override;
-    virtual void inspector_did_request_dom_tree_context_menu(i32 node_id, Gfx::IntPoint position, String const& type, Optional<String> const& tag, Optional<Attribute> const& attribute) override;
-    virtual void inspector_did_execute_console_script(String const& script) override;
-    virtual Messages::WebContentClient::RequestWorkerAgentResponse request_worker_agent() override;
+    virtual void did_paint(u64 page_id, Gfx::IntRect const&, i32) override;
+    virtual void did_finish_loading(u64 page_id, AK::URL const&) override;
+    virtual void did_request_navigate_back(u64 page_id) override;
+    virtual void did_request_navigate_forward(u64 page_id) override;
+    virtual void did_request_refresh(u64 page_id) override;
+    virtual void did_request_cursor_change(u64 page_id, i32) override;
+    virtual void did_layout(u64 page_id, Gfx::IntSize) override;
+    virtual void did_change_title(u64 page_id, ByteString const&) override;
+    virtual void did_request_scroll(u64 page_id, i32, i32) override;
+    virtual void did_request_scroll_to(u64 page_id, Gfx::IntPoint) override;
+    virtual void did_enter_tooltip_area(u64 page_id, Gfx::IntPoint, ByteString const&) override;
+    virtual void did_leave_tooltip_area(u64 page_id) override;
+    virtual void did_hover_link(u64 page_id, AK::URL const&) override;
+    virtual void did_unhover_link(u64 page_id) override;
+    virtual void did_click_link(u64 page_id, AK::URL const&, ByteString const&, unsigned) override;
+    virtual void did_middle_click_link(u64 page_id, AK::URL const&, ByteString const&, unsigned) override;
+    virtual void did_start_loading(u64 page_id, AK::URL const&, bool) override;
+    virtual void did_request_context_menu(u64 page_id, Gfx::IntPoint) override;
+    virtual void did_request_link_context_menu(u64 page_id, Gfx::IntPoint, AK::URL const&, ByteString const&, unsigned) override;
+    virtual void did_request_image_context_menu(u64 page_id, Gfx::IntPoint, AK::URL const&, ByteString const&, unsigned, Gfx::ShareableBitmap const&) override;
+    virtual void did_request_media_context_menu(u64 page_id, Gfx::IntPoint, ByteString const&, unsigned, Web::Page::MediaContextMenu const&) override;
+    virtual void did_get_source(u64 page_id, AK::URL const&, ByteString const&) override;
+    virtual void did_inspect_dom_tree(u64 page_id, ByteString const&) override;
+    virtual void did_inspect_dom_node(u64 page_id, bool has_style, ByteString const& computed_style, ByteString const& resolved_style, ByteString const& custom_properties, ByteString const& node_box_sizing, ByteString const& aria_properties_state) override;
+    virtual void did_inspect_accessibility_tree(u64 page_id, ByteString const&) override;
+    virtual void did_get_hovered_node_id(u64 page_id, i32 node_id) override;
+    virtual void did_finish_editing_dom_node(u64 page_id, Optional<i32> const& node_id) override;
+    virtual void did_get_dom_node_html(u64 page_id, String const& html) override;
+    virtual void did_take_screenshot(u64 page_id, Gfx::ShareableBitmap const& screenshot) override;
+    virtual void did_output_js_console_message(u64 page_id, i32 message_index) override;
+    virtual void did_get_js_console_messages(u64 page_id, i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages) override;
+    virtual void did_change_favicon(u64 page_id, Gfx::ShareableBitmap const&) override;
+    virtual void did_request_alert(u64 page_id, String const&) override;
+    virtual void did_request_confirm(u64 page_id, String const&) override;
+    virtual void did_request_prompt(u64 page_id, String const&, String const&) override;
+    virtual void did_request_set_prompt_text(u64 page_id, String const& message) override;
+    virtual void did_request_accept_dialog(u64 page_id) override;
+    virtual void did_request_dismiss_dialog(u64 page_id) override;
+    virtual Messages::WebContentClient::DidRequestAllCookiesResponse did_request_all_cookies(u64 page_id, AK::URL const&) override;
+    virtual Messages::WebContentClient::DidRequestNamedCookieResponse did_request_named_cookie(u64 page_id, AK::URL const&, String const&) override;
+    virtual Messages::WebContentClient::DidRequestCookieResponse did_request_cookie(u64 page_id, AK::URL const&, Web::Cookie::Source) override;
+    virtual void did_set_cookie(u64 page_id, AK::URL const&, Web::Cookie::ParsedCookie const&, Web::Cookie::Source) override;
+    virtual void did_update_cookie(u64 page_id, Web::Cookie::Cookie const&) override;
+    virtual Messages::WebContentClient::DidRequestNewWebViewResponse did_request_new_web_view(u64 page_id, Web::HTML::ActivateTab const&, Web::HTML::WebViewHints const&, Optional<u64> const& page_index) override;
+    virtual void did_request_activate_tab(u64 page_id) override;
+    virtual void did_close_browsing_context(u64 page_id) override;
+    virtual void did_update_resource_count(u64 page_id, i32 count_waiting) override;
+    virtual void did_request_restore_window(u64 page_id) override;
+    virtual Messages::WebContentClient::DidRequestRepositionWindowResponse did_request_reposition_window(u64 page_id, Gfx::IntPoint) override;
+    virtual Messages::WebContentClient::DidRequestResizeWindowResponse did_request_resize_window(u64 page_id, Gfx::IntSize) override;
+    virtual Messages::WebContentClient::DidRequestMaximizeWindowResponse did_request_maximize_window(u64 page_id) override;
+    virtual Messages::WebContentClient::DidRequestMinimizeWindowResponse did_request_minimize_window(u64 page_id) override;
+    virtual Messages::WebContentClient::DidRequestFullscreenWindowResponse did_request_fullscreen_window(u64 page_id) override;
+    virtual void did_request_file(u64 page_id, ByteString const& path, i32) override;
+    virtual void did_request_color_picker(u64 page_id, Color const& current_color) override;
+    virtual void did_request_select_dropdown(u64 page_id, Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> const& items) override;
+    virtual void did_finish_handling_input_event(u64 page_id, bool event_was_accepted) override;
+    virtual void did_finish_text_test(u64 page_id) override;
+    virtual void did_change_theme_color(u64 page_id, Gfx::Color color) override;
+    virtual void did_insert_clipboard_entry(u64 page_id, String const& data, String const& presentation_style, String const& mime_type) override;
+    virtual void inspector_did_load(u64 page_id) override;
+    virtual void inspector_did_select_dom_node(u64 page_id, i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element) override;
+    virtual void inspector_did_set_dom_node_text(u64 page_id, i32 node_id, String const& text) override;
+    virtual void inspector_did_set_dom_node_tag(u64 page_id, i32 node_id, String const& tag) override;
+    virtual void inspector_did_add_dom_node_attributes(u64 page_id, i32 node_id, Vector<Attribute> const& attributes) override;
+    virtual void inspector_did_replace_dom_node_attribute(u64 page_id, i32 node_id, String const& name, Vector<Attribute> const& replacement_attributes) override;
+    virtual void inspector_did_request_dom_tree_context_menu(u64 page_id, i32 node_id, Gfx::IntPoint position, String const& type, Optional<String> const& tag, Optional<Attribute> const& attribute) override;
+    virtual void inspector_did_execute_console_script(u64 page_id, String const& script) override;
+    virtual Messages::WebContentClient::RequestWorkerAgentResponse request_worker_agent(u64 page_id) override;
 
 
-    ViewImplementation& m_view;
+    // FIXME: Does a HashMap holding references make sense?
+    HashMap<u64, ViewImplementation*> m_views;
 };
 };
 
 
 }
 }

+ 204 - 253
Userland/Services/WebContent/ConnectionFromClient.cpp

@@ -4,7 +4,7 @@
  * Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
  * Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
  * Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
  * Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
  * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
  * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
- * Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
+ * Copyright (c) 2023-2024, Andrew Kaster <akaster@serenityos.org>
  *
  *
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
  */
  */
@@ -15,8 +15,6 @@
 #include <LibGfx/Bitmap.h>
 #include <LibGfx/Bitmap.h>
 #include <LibGfx/Font/FontDatabase.h>
 #include <LibGfx/Font/FontDatabase.h>
 #include <LibGfx/SystemTheme.h>
 #include <LibGfx/SystemTheme.h>
-#include <LibJS/Bytecode/Interpreter.h>
-#include <LibJS/Console.h>
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Runtime/ConsoleObject.h>
 #include <LibJS/Runtime/ConsoleObject.h>
 #include <LibWeb/ARIA/RoleType.h>
 #include <LibWeb/ARIA/RoleType.h>
@@ -30,7 +28,6 @@
 #include <LibWeb/DOM/Text.h>
 #include <LibWeb/DOM/Text.h>
 #include <LibWeb/Dump.h>
 #include <LibWeb/Dump.h>
 #include <LibWeb/HTML/BrowsingContext.h>
 #include <LibWeb/HTML/BrowsingContext.h>
-#include <LibWeb/HTML/Scripting/ClassicScript.h>
 #include <LibWeb/HTML/Storage.h>
 #include <LibWeb/HTML/Storage.h>
 #include <LibWeb/HTML/TraversableNavigable.h>
 #include <LibWeb/HTML/TraversableNavigable.h>
 #include <LibWeb/HTML/Window.h>
 #include <LibWeb/HTML/Window.h>
@@ -49,7 +46,10 @@
 #include <WebContent/PageClient.h>
 #include <WebContent/PageClient.h>
 #include <WebContent/PageHost.h>
 #include <WebContent/PageHost.h>
 #include <WebContent/WebContentClientEndpoint.h>
 #include <WebContent/WebContentClientEndpoint.h>
-#include <pthread.h>
+
+#ifdef AK_OS_SERENITY
+#    include <pthread.h>
+#endif
 
 
 namespace WebContent {
 namespace WebContent {
 
 
@@ -75,43 +75,43 @@ PageClient const& ConnectionFromClient::page(u64 index) const
     return m_page_host->page(index);
     return m_page_host->page(index);
 }
 }
 
 
-Messages::WebContentServer::GetWindowHandleResponse ConnectionFromClient::get_window_handle()
+Messages::WebContentServer::GetWindowHandleResponse ConnectionFromClient::get_window_handle(u64 page_id)
 {
 {
-    return page().page().top_level_browsing_context().window_handle();
+    return page(page_id).page().top_level_browsing_context().window_handle();
 }
 }
 
 
-void ConnectionFromClient::set_window_handle(String const& handle)
+void ConnectionFromClient::set_window_handle(u64 page_id, String const& handle)
 {
 {
-    page().page().top_level_browsing_context().set_window_handle(handle);
+    page(page_id).page().top_level_browsing_context().set_window_handle(handle);
 }
 }
 
 
-void ConnectionFromClient::connect_to_webdriver(ByteString const& webdriver_ipc_path)
+void ConnectionFromClient::connect_to_webdriver(u64 page_id, ByteString const& webdriver_ipc_path)
 {
 {
     // FIXME: Propagate this error back to the browser.
     // FIXME: Propagate this error back to the browser.
-    if (auto result = page().connect_to_webdriver(webdriver_ipc_path); result.is_error())
+    if (auto result = page(page_id).connect_to_webdriver(webdriver_ipc_path); result.is_error())
         dbgln("Unable to connect to the WebDriver process: {}", result.error());
         dbgln("Unable to connect to the WebDriver process: {}", result.error());
 }
 }
 
 
-void ConnectionFromClient::update_system_theme(Core::AnonymousBuffer const& theme_buffer)
+void ConnectionFromClient::update_system_theme(u64 page_id, Core::AnonymousBuffer const& theme_buffer)
 {
 {
     Gfx::set_system_theme(theme_buffer);
     Gfx::set_system_theme(theme_buffer);
     auto impl = Gfx::PaletteImpl::create_with_anonymous_buffer(theme_buffer);
     auto impl = Gfx::PaletteImpl::create_with_anonymous_buffer(theme_buffer);
-    page().set_palette_impl(*impl);
+    page(page_id).set_palette_impl(*impl);
 }
 }
 
 
-void ConnectionFromClient::update_system_fonts(ByteString const& default_font_query, ByteString const& fixed_width_font_query, ByteString const& window_title_font_query)
+void ConnectionFromClient::update_system_fonts(u64, ByteString const& default_font_query, ByteString const& fixed_width_font_query, ByteString const& window_title_font_query)
 {
 {
     Gfx::FontDatabase::set_default_font_query(default_font_query);
     Gfx::FontDatabase::set_default_font_query(default_font_query);
     Gfx::FontDatabase::set_fixed_width_font_query(fixed_width_font_query);
     Gfx::FontDatabase::set_fixed_width_font_query(fixed_width_font_query);
     Gfx::FontDatabase::set_window_title_font_query(window_title_font_query);
     Gfx::FontDatabase::set_window_title_font_query(window_title_font_query);
 }
 }
 
 
-void ConnectionFromClient::update_screen_rects(Vector<Web::DevicePixelRect> const& rects, u32 main_screen)
+void ConnectionFromClient::update_screen_rects(u64 page_id, Vector<Web::DevicePixelRect> const& rects, u32 main_screen)
 {
 {
-    page().set_screen_rects(rects, main_screen);
+    page(page_id).set_screen_rects(rects, main_screen);
 }
 }
 
 
-void ConnectionFromClient::load_url(const URL& url)
+void ConnectionFromClient::load_url(u64 page_id, const URL& url)
 {
 {
     dbgln_if(SPAM_DEBUG, "handle: WebContentServer::LoadURL: url={}", url);
     dbgln_if(SPAM_DEBUG, "handle: WebContentServer::LoadURL: url={}", url);
 
 
@@ -125,32 +125,29 @@ void ConnectionFromClient::load_url(const URL& url)
     pthread_setname_np(pthread_self(), process_name.characters());
     pthread_setname_np(pthread_self(), process_name.characters());
 #endif
 #endif
 
 
-    page().page().load(url);
+    page(page_id).page().load(url);
 }
 }
 
 
-void ConnectionFromClient::load_html(ByteString const& html)
+void ConnectionFromClient::load_html(u64 page_id, ByteString const& html)
 {
 {
     dbgln_if(SPAM_DEBUG, "handle: WebContentServer::LoadHTML: html={}", html);
     dbgln_if(SPAM_DEBUG, "handle: WebContentServer::LoadHTML: html={}", html);
-    page().page().load_html(html);
+    page(page_id).page().load_html(html);
 }
 }
 
 
-void ConnectionFromClient::set_viewport_rect(Web::DevicePixelRect const& rect)
+void ConnectionFromClient::set_viewport_rect(u64 page_id, Web::DevicePixelRect const& rect)
 {
 {
     dbgln_if(SPAM_DEBUG, "handle: WebContentServer::SetViewportRect: rect={}", rect);
     dbgln_if(SPAM_DEBUG, "handle: WebContentServer::SetViewportRect: rect={}", rect);
-    page().set_viewport_rect(rect);
+    page(page_id).set_viewport_rect(rect);
 }
 }
 
 
-void ConnectionFromClient::add_backing_store(i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap)
+void ConnectionFromClient::add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap)
 {
 {
-    m_backing_stores.front_bitmap_id = front_bitmap_id;
-    m_backing_stores.back_bitmap_id = back_bitmap_id;
-    m_backing_stores.front_bitmap = *const_cast<Gfx::ShareableBitmap&>(front_bitmap).bitmap();
-    m_backing_stores.back_bitmap = *const_cast<Gfx::ShareableBitmap&>(back_bitmap).bitmap();
+    page(page_id).add_backing_store(front_bitmap_id, front_bitmap, back_bitmap_id, back_bitmap);
 }
 }
 
 
-void ConnectionFromClient::ready_to_paint()
+void ConnectionFromClient::ready_to_paint(u64 page_id)
 {
 {
-    page().ready_to_paint();
+    page(page_id).ready_to_paint();
 }
 }
 
 
 void ConnectionFromClient::process_next_input_event()
 void ConnectionFromClient::process_next_input_event()
@@ -163,48 +160,37 @@ void ConnectionFromClient::process_next_input_event()
         [&](QueuedMouseEvent const& event) {
         [&](QueuedMouseEvent const& event) {
             switch (event.type) {
             switch (event.type) {
             case QueuedMouseEvent::Type::MouseDown:
             case QueuedMouseEvent::Type::MouseDown:
-                report_finished_handling_input_event(page().page().handle_mousedown(
-                    event.position, event.screen_position,
-                    event.button, event.buttons, event.modifiers));
+                report_finished_handling_input_event(event.page_id, page(event.page_id).page().handle_mousedown(event.position, event.screen_position, event.button, event.buttons, event.modifiers));
                 break;
                 break;
             case QueuedMouseEvent::Type::MouseUp:
             case QueuedMouseEvent::Type::MouseUp:
-                report_finished_handling_input_event(page().page().handle_mouseup(
-                    event.position, event.screen_position,
-                    event.button, event.buttons, event.modifiers));
+                report_finished_handling_input_event(event.page_id, page(event.page_id).page().handle_mouseup(event.position, event.screen_position, event.button, event.buttons, event.modifiers));
                 break;
                 break;
             case QueuedMouseEvent::Type::MouseMove:
             case QueuedMouseEvent::Type::MouseMove:
                 // NOTE: We have to notify the client about coalesced MouseMoves,
                 // NOTE: We have to notify the client about coalesced MouseMoves,
                 //       so we do that by saying none of them were handled by the web page.
                 //       so we do that by saying none of them were handled by the web page.
                 for (size_t i = 0; i < event.coalesced_event_count; ++i) {
                 for (size_t i = 0; i < event.coalesced_event_count; ++i) {
-                    report_finished_handling_input_event(false);
+                    report_finished_handling_input_event(event.page_id, false);
                 }
                 }
-                report_finished_handling_input_event(page().page().handle_mousemove(
-                    event.position, event.screen_position,
-                    event.buttons, event.modifiers));
+                report_finished_handling_input_event(event.page_id, page(event.page_id).page().handle_mousemove(event.position, event.screen_position, event.buttons, event.modifiers));
                 break;
                 break;
             case QueuedMouseEvent::Type::DoubleClick:
             case QueuedMouseEvent::Type::DoubleClick:
-                report_finished_handling_input_event(page().page().handle_doubleclick(
-                    event.position, event.screen_position,
-                    event.button, event.buttons, event.modifiers));
+                report_finished_handling_input_event(event.page_id, page(event.page_id).page().handle_doubleclick(event.position, event.screen_position, event.button, event.buttons, event.modifiers));
                 break;
                 break;
             case QueuedMouseEvent::Type::MouseWheel:
             case QueuedMouseEvent::Type::MouseWheel:
                 for (size_t i = 0; i < event.coalesced_event_count; ++i) {
                 for (size_t i = 0; i < event.coalesced_event_count; ++i) {
-                    report_finished_handling_input_event(false);
+                    report_finished_handling_input_event(event.page_id, false);
                 }
                 }
-                report_finished_handling_input_event(page().page().handle_mousewheel(
-                    event.position, event.screen_position,
-                    event.button, event.buttons, event.modifiers,
-                    event.wheel_delta_x, event.wheel_delta_y));
+                report_finished_handling_input_event(event.page_id, page(event.page_id).page().handle_mousewheel(event.position, event.screen_position, event.button, event.buttons, event.modifiers, event.wheel_delta_x, event.wheel_delta_y));
                 break;
                 break;
             }
             }
         },
         },
         [&](QueuedKeyboardEvent const& event) {
         [&](QueuedKeyboardEvent const& event) {
             switch (event.type) {
             switch (event.type) {
             case QueuedKeyboardEvent::Type::KeyDown:
             case QueuedKeyboardEvent::Type::KeyDown:
-                report_finished_handling_input_event(page().page().handle_keydown((KeyCode)event.key, event.modifiers, event.code_point));
+                report_finished_handling_input_event(event.page_id, page(event.page_id).page().handle_keydown((KeyCode)event.key, event.modifiers, event.code_point));
                 break;
                 break;
             case QueuedKeyboardEvent::Type::KeyUp:
             case QueuedKeyboardEvent::Type::KeyUp:
-                report_finished_handling_input_event(page().page().handle_keyup((KeyCode)event.key, event.modifiers, event.code_point));
+                report_finished_handling_input_event(event.page_id, page(event.page_id).page().handle_keyup((KeyCode)event.key, event.modifiers, event.code_point));
                 break;
                 break;
             }
             }
         });
         });
@@ -213,7 +199,7 @@ void ConnectionFromClient::process_next_input_event()
         m_input_event_queue_timer->start();
         m_input_event_queue_timer->start();
 }
 }
 
 
-void ConnectionFromClient::mouse_down(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
+void ConnectionFromClient::mouse_down(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
 {
 {
     enqueue_input_event(
     enqueue_input_event(
         QueuedMouseEvent {
         QueuedMouseEvent {
@@ -223,10 +209,11 @@ void ConnectionFromClient::mouse_down(Web::DevicePixelPoint position, Web::Devic
             .button = button,
             .button = button,
             .buttons = buttons,
             .buttons = buttons,
             .modifiers = modifiers,
             .modifiers = modifiers,
+            .page_id = page_id,
         });
         });
 }
 }
 
 
-void ConnectionFromClient::mouse_move(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, [[maybe_unused]] u32 button, u32 buttons, u32 modifiers)
+void ConnectionFromClient::mouse_move(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, [[maybe_unused]] u32 button, u32 buttons, u32 modifiers)
 {
 {
     auto event = QueuedMouseEvent {
     auto event = QueuedMouseEvent {
         .type = QueuedMouseEvent::Type::MouseMove,
         .type = QueuedMouseEvent::Type::MouseMove,
@@ -235,12 +222,14 @@ void ConnectionFromClient::mouse_move(Web::DevicePixelPoint position, Web::Devic
         .button = button,
         .button = button,
         .buttons = buttons,
         .buttons = buttons,
         .modifiers = modifiers,
         .modifiers = modifiers,
+        .page_id = page_id,
     };
     };
 
 
     // OPTIMIZATION: Coalesce with previous unprocessed event iff the previous event is also a MouseMove event.
     // OPTIMIZATION: Coalesce with previous unprocessed event iff the previous event is also a MouseMove event.
     if (!m_input_event_queue.is_empty()
     if (!m_input_event_queue.is_empty()
         && m_input_event_queue.tail().has<QueuedMouseEvent>()
         && m_input_event_queue.tail().has<QueuedMouseEvent>()
-        && m_input_event_queue.tail().get<QueuedMouseEvent>().type == QueuedMouseEvent::Type::MouseMove) {
+        && m_input_event_queue.tail().get<QueuedMouseEvent>().type == QueuedMouseEvent::Type::MouseMove
+        && m_input_event_queue.tail().get<QueuedMouseEvent>().page_id == page_id) {
         event.coalesced_event_count = m_input_event_queue.tail().get<QueuedMouseEvent>().coalesced_event_count + 1;
         event.coalesced_event_count = m_input_event_queue.tail().get<QueuedMouseEvent>().coalesced_event_count + 1;
         m_input_event_queue.tail() = event;
         m_input_event_queue.tail() = event;
         return;
         return;
@@ -249,7 +238,7 @@ void ConnectionFromClient::mouse_move(Web::DevicePixelPoint position, Web::Devic
     enqueue_input_event(move(event));
     enqueue_input_event(move(event));
 }
 }
 
 
-void ConnectionFromClient::mouse_up(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
+void ConnectionFromClient::mouse_up(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
 {
 {
     enqueue_input_event(
     enqueue_input_event(
         QueuedMouseEvent {
         QueuedMouseEvent {
@@ -259,10 +248,11 @@ void ConnectionFromClient::mouse_up(Web::DevicePixelPoint position, Web::DeviceP
             .button = button,
             .button = button,
             .buttons = buttons,
             .buttons = buttons,
             .modifiers = modifiers,
             .modifiers = modifiers,
+            .page_id = page_id,
         });
         });
 }
 }
 
 
-void ConnectionFromClient::mouse_wheel(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, Web::DevicePixels wheel_delta_x, Web::DevicePixels wheel_delta_y)
+void ConnectionFromClient::mouse_wheel(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, Web::DevicePixels wheel_delta_x, Web::DevicePixels wheel_delta_y)
 {
 {
     auto event = QueuedMouseEvent {
     auto event = QueuedMouseEvent {
         .type = QueuedMouseEvent::Type::MouseWheel,
         .type = QueuedMouseEvent::Type::MouseWheel,
@@ -273,12 +263,14 @@ void ConnectionFromClient::mouse_wheel(Web::DevicePixelPoint position, Web::Devi
         .modifiers = modifiers,
         .modifiers = modifiers,
         .wheel_delta_x = wheel_delta_x,
         .wheel_delta_x = wheel_delta_x,
         .wheel_delta_y = wheel_delta_y,
         .wheel_delta_y = wheel_delta_y,
+        .page_id = page_id,
     };
     };
 
 
     // OPTIMIZATION: Coalesce with previous unprocessed event if the previous event is also a MouseWheel event.
     // OPTIMIZATION: Coalesce with previous unprocessed event if the previous event is also a MouseWheel event.
     if (!m_input_event_queue.is_empty()
     if (!m_input_event_queue.is_empty()
         && m_input_event_queue.tail().has<QueuedMouseEvent>()
         && m_input_event_queue.tail().has<QueuedMouseEvent>()
-        && m_input_event_queue.tail().get<QueuedMouseEvent>().type == QueuedMouseEvent::Type::MouseWheel) {
+        && m_input_event_queue.tail().get<QueuedMouseEvent>().type == QueuedMouseEvent::Type::MouseWheel
+        && m_input_event_queue.tail().get<QueuedMouseEvent>().page_id == page_id) {
         auto const& last_event = m_input_event_queue.tail().get<QueuedMouseEvent>();
         auto const& last_event = m_input_event_queue.tail().get<QueuedMouseEvent>();
         event.coalesced_event_count = last_event.coalesced_event_count + 1;
         event.coalesced_event_count = last_event.coalesced_event_count + 1;
         event.wheel_delta_x += last_event.wheel_delta_x;
         event.wheel_delta_x += last_event.wheel_delta_x;
@@ -290,7 +282,7 @@ void ConnectionFromClient::mouse_wheel(Web::DevicePixelPoint position, Web::Devi
     enqueue_input_event(move(event));
     enqueue_input_event(move(event));
 }
 }
 
 
-void ConnectionFromClient::doubleclick(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
+void ConnectionFromClient::doubleclick(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers)
 {
 {
     enqueue_input_event(
     enqueue_input_event(
         QueuedMouseEvent {
         QueuedMouseEvent {
@@ -300,10 +292,11 @@ void ConnectionFromClient::doubleclick(Web::DevicePixelPoint position, Web::Devi
             .button = button,
             .button = button,
             .buttons = buttons,
             .buttons = buttons,
             .modifiers = modifiers,
             .modifiers = modifiers,
+            .page_id = page_id,
         });
         });
 }
 }
 
 
-void ConnectionFromClient::key_down(i32 key, u32 modifiers, u32 code_point)
+void ConnectionFromClient::key_down(u64 page_id, i32 key, u32 modifiers, u32 code_point)
 {
 {
     enqueue_input_event(
     enqueue_input_event(
         QueuedKeyboardEvent {
         QueuedKeyboardEvent {
@@ -311,10 +304,11 @@ void ConnectionFromClient::key_down(i32 key, u32 modifiers, u32 code_point)
             .key = key,
             .key = key,
             .modifiers = modifiers,
             .modifiers = modifiers,
             .code_point = code_point,
             .code_point = code_point,
+            .page_id = page_id,
         });
         });
 }
 }
 
 
-void ConnectionFromClient::key_up(i32 key, u32 modifiers, u32 code_point)
+void ConnectionFromClient::key_up(u64 page_id, i32 key, u32 modifiers, u32 code_point)
 {
 {
     enqueue_input_event(
     enqueue_input_event(
         QueuedKeyboardEvent {
         QueuedKeyboardEvent {
@@ -322,6 +316,7 @@ void ConnectionFromClient::key_up(i32 key, u32 modifiers, u32 code_point)
             .key = key,
             .key = key,
             .modifiers = modifiers,
             .modifiers = modifiers,
             .code_point = code_point,
             .code_point = code_point,
+            .page_id = page_id,
         });
         });
 }
 }
 
 
@@ -331,26 +326,26 @@ void ConnectionFromClient::enqueue_input_event(Variant<QueuedMouseEvent, QueuedK
     m_input_event_queue_timer->start();
     m_input_event_queue_timer->start();
 }
 }
 
 
-void ConnectionFromClient::report_finished_handling_input_event(bool event_was_handled)
+void ConnectionFromClient::report_finished_handling_input_event(u64 page_id, bool event_was_handled)
 {
 {
-    async_did_finish_handling_input_event(event_was_handled);
+    async_did_finish_handling_input_event(page_id, event_was_handled);
 }
 }
 
 
-void ConnectionFromClient::debug_request(ByteString const& request, ByteString const& argument)
+void ConnectionFromClient::debug_request(u64 page_id, ByteString const& request, ByteString const& argument)
 {
 {
     if (request == "dump-session-history") {
     if (request == "dump-session-history") {
-        auto const& traversable = page().page().top_level_traversable();
+        auto const& traversable = page(page_id).page().top_level_traversable();
         Web::dump_tree(*traversable);
         Web::dump_tree(*traversable);
     }
     }
 
 
     if (request == "dump-dom-tree") {
     if (request == "dump-dom-tree") {
-        if (auto* doc = page().page().top_level_browsing_context().active_document())
+        if (auto* doc = page(page_id).page().top_level_browsing_context().active_document())
             Web::dump_tree(*doc);
             Web::dump_tree(*doc);
         return;
         return;
     }
     }
 
 
     if (request == "dump-layout-tree") {
     if (request == "dump-layout-tree") {
-        if (auto* doc = page().page().top_level_browsing_context().active_document()) {
+        if (auto* doc = page(page_id).page().top_level_browsing_context().active_document()) {
             if (auto* viewport = doc->layout_node())
             if (auto* viewport = doc->layout_node())
                 Web::dump_tree(*viewport);
                 Web::dump_tree(*viewport);
         }
         }
@@ -358,7 +353,7 @@ void ConnectionFromClient::debug_request(ByteString const& request, ByteString c
     }
     }
 
 
     if (request == "dump-paint-tree") {
     if (request == "dump-paint-tree") {
-        if (auto* doc = page().page().top_level_browsing_context().active_document()) {
+        if (auto* doc = page(page_id).page().top_level_browsing_context().active_document()) {
             if (auto* paintable = doc->paintable())
             if (auto* paintable = doc->paintable())
                 Web::dump_tree(*paintable);
                 Web::dump_tree(*paintable);
         }
         }
@@ -366,7 +361,7 @@ void ConnectionFromClient::debug_request(ByteString const& request, ByteString c
     }
     }
 
 
     if (request == "dump-stacking-context-tree") {
     if (request == "dump-stacking-context-tree") {
-        if (auto* doc = page().page().top_level_browsing_context().active_document()) {
+        if (auto* doc = page(page_id).page().top_level_browsing_context().active_document()) {
             if (auto* viewport = doc->layout_node()) {
             if (auto* viewport = doc->layout_node()) {
                 if (auto* stacking_context = viewport->paintable_box()->stacking_context())
                 if (auto* stacking_context = viewport->paintable_box()->stacking_context())
                     stacking_context->dump();
                     stacking_context->dump();
@@ -376,7 +371,7 @@ void ConnectionFromClient::debug_request(ByteString const& request, ByteString c
     }
     }
 
 
     if (request == "dump-style-sheets") {
     if (request == "dump-style-sheets") {
-        if (auto* doc = page().page().top_level_browsing_context().active_document()) {
+        if (auto* doc = page(page_id).page().top_level_browsing_context().active_document()) {
             for (auto& sheet : doc->style_sheets().sheets()) {
             for (auto& sheet : doc->style_sheets().sheets()) {
                 if (auto result = Web::dump_sheet(sheet); result.is_error())
                 if (auto result = Web::dump_sheet(sheet); result.is_error())
                     dbgln("Failed to dump style sheets: {}", result.error());
                     dbgln("Failed to dump style sheets: {}", result.error());
@@ -386,7 +381,7 @@ void ConnectionFromClient::debug_request(ByteString const& request, ByteString c
     }
     }
 
 
     if (request == "dump-all-resolved-styles") {
     if (request == "dump-all-resolved-styles") {
-        if (auto* doc = page().page().top_level_browsing_context().active_document()) {
+        if (auto* doc = page(page_id).page().top_level_browsing_context().active_document()) {
             Queue<Web::DOM::Node*> elements_to_visit;
             Queue<Web::DOM::Node*> elements_to_visit;
             elements_to_visit.enqueue(doc->document_element());
             elements_to_visit.enqueue(doc->document_element());
             while (!elements_to_visit.is_empty()) {
             while (!elements_to_visit.is_empty()) {
@@ -413,8 +408,8 @@ void ConnectionFromClient::debug_request(ByteString const& request, ByteString c
 
 
     if (request == "set-line-box-borders") {
     if (request == "set-line-box-borders") {
         bool state = argument == "on";
         bool state = argument == "on";
-        page().set_should_show_line_box_borders(state);
-        page().page().top_level_traversable()->set_needs_display(page().page().top_level_traversable()->viewport_rect());
+        page(page_id).set_should_show_line_box_borders(state);
+        page(page_id).page().top_level_traversable()->set_needs_display(page(page_id).page().top_level_traversable()->viewport_rect());
         return;
         return;
     }
     }
 
 
@@ -429,59 +424,59 @@ void ConnectionFromClient::debug_request(ByteString const& request, ByteString c
     }
     }
 
 
     if (request == "same-origin-policy") {
     if (request == "same-origin-policy") {
-        page().page().set_same_origin_policy_enabled(argument == "on");
+        page(page_id).page().set_same_origin_policy_enabled(argument == "on");
         return;
         return;
     }
     }
 
 
     if (request == "scripting") {
     if (request == "scripting") {
-        page().page().set_is_scripting_enabled(argument == "on");
+        page(page_id).page().set_is_scripting_enabled(argument == "on");
         return;
         return;
     }
     }
 
 
     if (request == "block-pop-ups") {
     if (request == "block-pop-ups") {
-        page().page().set_should_block_pop_ups(argument == "on");
+        page(page_id).page().set_should_block_pop_ups(argument == "on");
         return;
         return;
     }
     }
 
 
     if (request == "dump-local-storage") {
     if (request == "dump-local-storage") {
-        if (auto* document = page().page().top_level_browsing_context().active_document())
+        if (auto* document = page(page_id).page().top_level_browsing_context().active_document())
             document->window().local_storage().release_value_but_fixme_should_propagate_errors()->dump();
             document->window().local_storage().release_value_but_fixme_should_propagate_errors()->dump();
         return;
         return;
     }
     }
 
 
     if (request == "load-reference-page") {
     if (request == "load-reference-page") {
-        if (auto* document = page().page().top_level_browsing_context().active_document()) {
+        if (auto* document = page(page_id).page().top_level_browsing_context().active_document()) {
             auto maybe_link = document->query_selector("link[rel=match]"sv);
             auto maybe_link = document->query_selector("link[rel=match]"sv);
             if (maybe_link.is_error() || !maybe_link.value()) {
             if (maybe_link.is_error() || !maybe_link.value()) {
                 // To make sure that we fail the ref-test if the link is missing, load the error page.
                 // To make sure that we fail the ref-test if the link is missing, load the error page.
-                load_html("<h1>Failed to find &lt;link rel=&quot;match&quot; /&gt; in ref test page!</h1> Make sure you added it.");
+                load_html(page_id, "<h1>Failed to find &lt;link rel=&quot;match&quot; /&gt; in ref test page!</h1> Make sure you added it.");
             } else {
             } else {
                 auto link = maybe_link.release_value();
                 auto link = maybe_link.release_value();
                 auto url = document->parse_url(link->get_attribute_value(Web::HTML::AttributeNames::href));
                 auto url = document->parse_url(link->get_attribute_value(Web::HTML::AttributeNames::href));
-                load_url(url);
+                load_url(page_id, url);
             }
             }
         }
         }
         return;
         return;
     }
     }
 }
 }
 
 
-void ConnectionFromClient::get_source()
+void ConnectionFromClient::get_source(u64 page_id)
 {
 {
-    if (auto* doc = page().page().top_level_browsing_context().active_document()) {
-        async_did_get_source(doc->url(), doc->source().to_byte_string());
+    if (auto* doc = page(page_id).page().top_level_browsing_context().active_document()) {
+        async_did_get_source(page_id, doc->url(), doc->source().to_byte_string());
     }
     }
 }
 }
 
 
-void ConnectionFromClient::inspect_dom_tree()
+void ConnectionFromClient::inspect_dom_tree(u64 page_id)
 {
 {
-    if (auto* doc = page().page().top_level_browsing_context().active_document()) {
-        async_did_inspect_dom_tree(doc->dump_dom_tree_as_json().to_byte_string());
+    if (auto* doc = page(page_id).page().top_level_browsing_context().active_document()) {
+        async_did_inspect_dom_tree(page_id, doc->dump_dom_tree_as_json().to_byte_string());
     }
     }
 }
 }
 
 
-void ConnectionFromClient::inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element)
+void ConnectionFromClient::inspect_dom_node(u64 page_id, i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element)
 {
 {
-    auto& top_context = page().page().top_level_browsing_context();
+    auto& top_context = page(page_id).page().top_level_browsing_context();
 
 
     top_context.for_each_in_inclusive_subtree([&](auto& ctx) {
     top_context.for_each_in_inclusive_subtree([&](auto& ctx) {
         if (ctx.active_document() != nullptr) {
         if (ctx.active_document() != nullptr) {
@@ -493,7 +488,7 @@ void ConnectionFromClient::inspect_dom_node(i32 node_id, Optional<Web::CSS::Sele
     Web::DOM::Node* node = Web::DOM::Node::from_unique_id(node_id);
     Web::DOM::Node* node = Web::DOM::Node::from_unique_id(node_id);
     // Note: Nodes without layout (aka non-visible nodes, don't have style computed)
     // Note: Nodes without layout (aka non-visible nodes, don't have style computed)
     if (!node || !node->layout_node()) {
     if (!node || !node->layout_node()) {
-        async_did_inspect_dom_node(false, {}, {}, {}, {}, {});
+        async_did_inspect_dom_node(page_id, false, {}, {}, {}, {}, {});
         return;
         return;
     }
     }
 
 
@@ -502,7 +497,7 @@ void ConnectionFromClient::inspect_dom_node(i32 node_id, Optional<Web::CSS::Sele
     if (node->is_element()) {
     if (node->is_element()) {
         auto& element = verify_cast<Web::DOM::Element>(*node);
         auto& element = verify_cast<Web::DOM::Element>(*node);
         if (!element.computed_css_values()) {
         if (!element.computed_css_values()) {
-            async_did_inspect_dom_node(false, {}, {}, {}, {}, {});
+            async_did_inspect_dom_node(page_id, false, {}, {}, {}, {}, {});
             return;
             return;
         }
         }
 
 
@@ -589,20 +584,20 @@ void ConnectionFromClient::inspect_dom_node(i32 node_id, Optional<Web::CSS::Sele
         if (pseudo_element.has_value()) {
         if (pseudo_element.has_value()) {
             auto pseudo_element_node = element.get_pseudo_element_node(pseudo_element.value());
             auto pseudo_element_node = element.get_pseudo_element_node(pseudo_element.value());
             if (!pseudo_element_node) {
             if (!pseudo_element_node) {
-                async_did_inspect_dom_node(false, {}, {}, {}, {}, {});
+                async_did_inspect_dom_node(page_id, false, {}, {}, {}, {}, {});
                 return;
                 return;
             }
             }
 
 
             // FIXME: Pseudo-elements only exist as Layout::Nodes, which don't have style information
             // FIXME: Pseudo-elements only exist as Layout::Nodes, which don't have style information
             //        in a format we can use. So, we run the StyleComputer again to get the specified
             //        in a format we can use. So, we run the StyleComputer again to get the specified
             //        values, and have to ignore the computed values and custom properties.
             //        values, and have to ignore the computed values and custom properties.
-            auto pseudo_element_style = MUST(page().page().focused_context().active_document()->style_computer().compute_style(element, pseudo_element));
+            auto pseudo_element_style = MUST(page(page_id).page().focused_context().active_document()->style_computer().compute_style(element, pseudo_element));
             ByteString computed_values = serialize_json(pseudo_element_style);
             ByteString computed_values = serialize_json(pseudo_element_style);
             ByteString resolved_values = "{}";
             ByteString resolved_values = "{}";
             ByteString custom_properties_json = serialize_custom_properties_json(element, pseudo_element);
             ByteString custom_properties_json = serialize_custom_properties_json(element, pseudo_element);
             ByteString node_box_sizing_json = serialize_node_box_sizing_json(pseudo_element_node.ptr());
             ByteString node_box_sizing_json = serialize_node_box_sizing_json(pseudo_element_node.ptr());
 
 
-            async_did_inspect_dom_node(true, move(computed_values), move(resolved_values), move(custom_properties_json), move(node_box_sizing_json), {});
+            async_did_inspect_dom_node(page_id, true, move(computed_values), move(resolved_values), move(custom_properties_json), move(node_box_sizing_json), {});
             return;
             return;
         }
         }
 
 
@@ -612,51 +607,51 @@ void ConnectionFromClient::inspect_dom_node(i32 node_id, Optional<Web::CSS::Sele
         ByteString node_box_sizing_json = serialize_node_box_sizing_json(element.layout_node());
         ByteString node_box_sizing_json = serialize_node_box_sizing_json(element.layout_node());
         ByteString aria_properties_state_json = serialize_aria_properties_state_json(element);
         ByteString aria_properties_state_json = serialize_aria_properties_state_json(element);
 
 
-        async_did_inspect_dom_node(true, move(computed_values), move(resolved_values), move(custom_properties_json), move(node_box_sizing_json), move(aria_properties_state_json));
+        async_did_inspect_dom_node(page_id, true, move(computed_values), move(resolved_values), move(custom_properties_json), move(node_box_sizing_json), move(aria_properties_state_json));
         return;
         return;
     }
     }
 
 
-    async_did_inspect_dom_node(false, {}, {}, {}, {}, {});
+    async_did_inspect_dom_node(page_id, false, {}, {}, {}, {}, {});
 }
 }
 
 
-void ConnectionFromClient::inspect_accessibility_tree()
+void ConnectionFromClient::inspect_accessibility_tree(u64 page_id)
 {
 {
-    if (auto* doc = page().page().top_level_browsing_context().active_document()) {
-        async_did_inspect_accessibility_tree(doc->dump_accessibility_tree_as_json().to_byte_string());
+    if (auto* doc = page(page_id).page().top_level_browsing_context().active_document()) {
+        async_did_inspect_accessibility_tree(page_id, doc->dump_accessibility_tree_as_json().to_byte_string());
     }
     }
 }
 }
 
 
-void ConnectionFromClient::get_hovered_node_id()
+void ConnectionFromClient::get_hovered_node_id(u64 page_id)
 {
 {
     i32 node_id = 0;
     i32 node_id = 0;
 
 
-    if (auto* document = page().page().top_level_browsing_context().active_document()) {
+    if (auto* document = page(page_id).page().top_level_browsing_context().active_document()) {
         if (auto* hovered_node = document->hovered_node())
         if (auto* hovered_node = document->hovered_node())
             node_id = hovered_node->unique_id();
             node_id = hovered_node->unique_id();
     }
     }
 
 
-    async_did_get_hovered_node_id(node_id);
+    async_did_get_hovered_node_id(page_id, node_id);
 }
 }
 
 
-void ConnectionFromClient::set_dom_node_text(i32 node_id, String const& text)
+void ConnectionFromClient::set_dom_node_text(u64 page_id, i32 node_id, String const& text)
 {
 {
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node || (!dom_node->is_text() && !dom_node->is_comment())) {
     if (!dom_node || (!dom_node->is_text() && !dom_node->is_comment())) {
-        async_did_finish_editing_dom_node({});
+        async_did_finish_editing_dom_node(page_id, {});
         return;
         return;
     }
     }
 
 
     auto& character_data = static_cast<Web::DOM::CharacterData&>(*dom_node);
     auto& character_data = static_cast<Web::DOM::CharacterData&>(*dom_node);
     character_data.set_data(text);
     character_data.set_data(text);
 
 
-    async_did_finish_editing_dom_node(character_data.unique_id());
+    async_did_finish_editing_dom_node(page_id, character_data.unique_id());
 }
 }
 
 
-void ConnectionFromClient::set_dom_node_tag(i32 node_id, String const& name)
+void ConnectionFromClient::set_dom_node_tag(u64 page_id, i32 node_id, String const& name)
 {
 {
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node || !dom_node->is_element() || !dom_node->parent()) {
     if (!dom_node || !dom_node->is_element() || !dom_node->parent()) {
-        async_did_finish_editing_dom_node({});
+        async_did_finish_editing_dom_node(page_id, {});
         return;
         return;
     }
     }
 
 
@@ -673,14 +668,14 @@ void ConnectionFromClient::set_dom_node_tag(i32 node_id, String const& name)
     }
     }
 
 
     element.parent()->replace_child(*new_element, element).release_value_but_fixme_should_propagate_errors();
     element.parent()->replace_child(*new_element, element).release_value_but_fixme_should_propagate_errors();
-    async_did_finish_editing_dom_node(new_element->unique_id());
+    async_did_finish_editing_dom_node(page_id, new_element->unique_id());
 }
 }
 
 
-void ConnectionFromClient::add_dom_node_attributes(i32 node_id, Vector<WebView::Attribute> const& attributes)
+void ConnectionFromClient::add_dom_node_attributes(u64 page_id, i32 node_id, Vector<WebView::Attribute> const& attributes)
 {
 {
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node || !dom_node->is_element()) {
     if (!dom_node || !dom_node->is_element()) {
-        async_did_finish_editing_dom_node({});
+        async_did_finish_editing_dom_node(page_id, {});
         return;
         return;
     }
     }
 
 
@@ -689,14 +684,14 @@ void ConnectionFromClient::add_dom_node_attributes(i32 node_id, Vector<WebView::
     for (auto const& attribute : attributes)
     for (auto const& attribute : attributes)
         element.set_attribute(attribute.name, attribute.value).release_value_but_fixme_should_propagate_errors();
         element.set_attribute(attribute.name, attribute.value).release_value_but_fixme_should_propagate_errors();
 
 
-    async_did_finish_editing_dom_node(element.unique_id());
+    async_did_finish_editing_dom_node(page_id, element.unique_id());
 }
 }
 
 
-void ConnectionFromClient::replace_dom_node_attribute(i32 node_id, String const& name, Vector<WebView::Attribute> const& replacement_attributes)
+void ConnectionFromClient::replace_dom_node_attribute(u64 page_id, i32 node_id, String const& name, Vector<WebView::Attribute> const& replacement_attributes)
 {
 {
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node || !dom_node->is_element()) {
     if (!dom_node || !dom_node->is_element()) {
-        async_did_finish_editing_dom_node({});
+        async_did_finish_editing_dom_node(page_id, {});
         return;
         return;
     }
     }
 
 
@@ -713,62 +708,62 @@ void ConnectionFromClient::replace_dom_node_attribute(i32 node_id, String const&
     if (should_remove_attribute)
     if (should_remove_attribute)
         element.remove_attribute(name);
         element.remove_attribute(name);
 
 
-    async_did_finish_editing_dom_node(element.unique_id());
+    async_did_finish_editing_dom_node(page_id, element.unique_id());
 }
 }
 
 
-void ConnectionFromClient::create_child_element(i32 node_id)
+void ConnectionFromClient::create_child_element(u64 page_id, i32 node_id)
 {
 {
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node) {
     if (!dom_node) {
-        async_did_finish_editing_dom_node({});
+        async_did_finish_editing_dom_node(page_id, {});
         return;
         return;
     }
     }
 
 
     auto element = Web::DOM::create_element(dom_node->document(), Web::HTML::TagNames::div, Web::Namespace::HTML).release_value_but_fixme_should_propagate_errors();
     auto element = Web::DOM::create_element(dom_node->document(), Web::HTML::TagNames::div, Web::Namespace::HTML).release_value_but_fixme_should_propagate_errors();
     dom_node->append_child(element).release_value_but_fixme_should_propagate_errors();
     dom_node->append_child(element).release_value_but_fixme_should_propagate_errors();
 
 
-    async_did_finish_editing_dom_node(element->unique_id());
+    async_did_finish_editing_dom_node(page_id, element->unique_id());
 }
 }
 
 
-void ConnectionFromClient::create_child_text_node(i32 node_id)
+void ConnectionFromClient::create_child_text_node(u64 page_id, i32 node_id)
 {
 {
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node) {
     if (!dom_node) {
-        async_did_finish_editing_dom_node({});
+        async_did_finish_editing_dom_node(page_id, {});
         return;
         return;
     }
     }
 
 
     auto text_node = dom_node->heap().allocate<Web::DOM::Text>(dom_node->realm(), dom_node->document(), "text"_string);
     auto text_node = dom_node->heap().allocate<Web::DOM::Text>(dom_node->realm(), dom_node->document(), "text"_string);
     dom_node->append_child(text_node).release_value_but_fixme_should_propagate_errors();
     dom_node->append_child(text_node).release_value_but_fixme_should_propagate_errors();
 
 
-    async_did_finish_editing_dom_node(text_node->unique_id());
+    async_did_finish_editing_dom_node(page_id, text_node->unique_id());
 }
 }
 
 
-void ConnectionFromClient::clone_dom_node(i32 node_id)
+void ConnectionFromClient::clone_dom_node(u64 page_id, i32 node_id)
 {
 {
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node || !dom_node->parent_node()) {
     if (!dom_node || !dom_node->parent_node()) {
-        async_did_finish_editing_dom_node({});
+        async_did_finish_editing_dom_node(page_id, {});
         return;
         return;
     }
     }
 
 
     auto dom_node_clone = dom_node->clone_node(nullptr, true);
     auto dom_node_clone = dom_node->clone_node(nullptr, true);
     dom_node->parent_node()->insert_before(dom_node_clone, dom_node->next_sibling());
     dom_node->parent_node()->insert_before(dom_node_clone, dom_node->next_sibling());
 
 
-    async_did_finish_editing_dom_node(dom_node_clone->unique_id());
+    async_did_finish_editing_dom_node(page_id, dom_node_clone->unique_id());
 }
 }
 
 
-void ConnectionFromClient::remove_dom_node(i32 node_id)
+void ConnectionFromClient::remove_dom_node(u64 page_id, i32 node_id)
 {
 {
-    auto* active_document = page().page().top_level_browsing_context().active_document();
+    auto* active_document = page(page_id).page().top_level_browsing_context().active_document();
     if (!active_document) {
     if (!active_document) {
-        async_did_finish_editing_dom_node({});
+        async_did_finish_editing_dom_node(page_id, {});
         return;
         return;
     }
     }
 
 
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node) {
     if (!dom_node) {
-        async_did_finish_editing_dom_node({});
+        async_did_finish_editing_dom_node(page_id, {});
         return;
         return;
     }
     }
 
 
@@ -783,10 +778,10 @@ void ConnectionFromClient::remove_dom_node(i32 node_id)
     //        which really hurts performance.
     //        which really hurts performance.
     active_document->force_layout();
     active_document->force_layout();
 
 
-    async_did_finish_editing_dom_node(previous_dom_node->unique_id());
+    async_did_finish_editing_dom_node(page_id, previous_dom_node->unique_id());
 }
 }
 
 
-void ConnectionFromClient::get_dom_node_html(i32 node_id)
+void ConnectionFromClient::get_dom_node_html(u64 page_id, i32 node_id)
 {
 {
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node)
     if (!dom_node)
@@ -797,120 +792,61 @@ void ConnectionFromClient::get_dom_node_html(i32 node_id)
     container->append_child(dom_node->clone_node(nullptr, true)).release_value_but_fixme_should_propagate_errors();
     container->append_child(dom_node->clone_node(nullptr, true)).release_value_but_fixme_should_propagate_errors();
 
 
     auto html = container->inner_html().release_value_but_fixme_should_propagate_errors();
     auto html = container->inner_html().release_value_but_fixme_should_propagate_errors();
-    async_did_get_dom_node_html(move(html));
-}
-
-void ConnectionFromClient::initialize_js_console(Badge<PageClient>, Web::DOM::Document& document)
-{
-    auto& realm = document.realm();
-    auto console_object = realm.intrinsics().console_object();
-    auto console_client = make<WebContentConsoleClient>(console_object->console(), document.realm(), *this);
-    console_object->console().set_client(*console_client);
-
-    VERIFY(document.browsing_context());
-    if (document.browsing_context()->is_top_level()) {
-        m_top_level_document_console_client = console_client->make_weak_ptr();
-    }
-
-    m_console_clients.set(&document, move(console_client));
+    async_did_get_dom_node_html(page_id, move(html));
 }
 }
 
 
-void ConnectionFromClient::destroy_js_console(Badge<PageClient>, Web::DOM::Document& document)
+void ConnectionFromClient::take_document_screenshot(u64 page_id)
 {
 {
-    m_console_clients.remove(&document);
-}
-
-void ConnectionFromClient::js_console_input(ByteString const& js_source)
-{
-    if (m_top_level_document_console_client)
-        m_top_level_document_console_client->handle_input(js_source);
-}
-
-void ConnectionFromClient::run_javascript(ByteString const& js_source)
-{
-    auto* active_document = page().page().top_level_browsing_context().active_document();
-
-    if (!active_document)
-        return;
-
-    // This is partially based on "execute a javascript: URL request" https://html.spec.whatwg.org/multipage/browsing-the-web.html#javascript-protocol
-
-    // Let settings be browsingContext's active document's relevant settings object.
-    auto& settings = active_document->relevant_settings_object();
-
-    // Let baseURL be settings's API base URL.
-    auto base_url = settings.api_base_url();
-
-    // Let script be the result of creating a classic script given scriptSource, settings, baseURL, and the default classic script fetch options.
-    // FIXME: This doesn't pass in "default classic script fetch options"
-    // FIXME: What should the filename be here?
-    auto script = Web::HTML::ClassicScript::create("(client connection run_javascript)", js_source, settings, move(base_url));
-
-    // Let evaluationStatus be the result of running the classic script script.
-    auto evaluation_status = script->run();
-
-    if (evaluation_status.is_error())
-        dbgln("Exception :(");
-}
-
-void ConnectionFromClient::js_console_request_messages(i32 start_index)
-{
-    if (m_top_level_document_console_client)
-        m_top_level_document_console_client->send_messages(start_index);
-}
-
-void ConnectionFromClient::take_document_screenshot()
-{
-    auto* document = page().page().top_level_browsing_context().active_document();
+    auto* document = page(page_id).page().top_level_browsing_context().active_document();
     if (!document || !document->document_element()) {
     if (!document || !document->document_element()) {
-        async_did_take_screenshot({});
+        async_did_take_screenshot(page_id, {});
         return;
         return;
     }
     }
 
 
-    auto const& content_size = page().content_size();
+    auto const& content_size = page(page_id).content_size();
     Web::DevicePixelRect rect { { 0, 0 }, content_size };
     Web::DevicePixelRect rect { { 0, 0 }, content_size };
 
 
     auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, rect.size().to_type<int>()).release_value_but_fixme_should_propagate_errors();
     auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, rect.size().to_type<int>()).release_value_but_fixme_should_propagate_errors();
-    page().paint(rect, *bitmap);
+    page(page_id).paint(rect, *bitmap);
 
 
-    async_did_take_screenshot(bitmap->to_shareable_bitmap());
+    async_did_take_screenshot(page_id, bitmap->to_shareable_bitmap());
 }
 }
 
 
-void ConnectionFromClient::take_dom_node_screenshot(i32 node_id)
+void ConnectionFromClient::take_dom_node_screenshot(u64 page_id, i32 node_id)
 {
 {
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
     if (!dom_node || !dom_node->paintable_box()) {
     if (!dom_node || !dom_node->paintable_box()) {
-        async_did_take_screenshot({});
+        async_did_take_screenshot(page_id, {});
         return;
         return;
     }
     }
 
 
-    auto rect = page().page().enclosing_device_rect(dom_node->paintable_box()->absolute_border_box_rect());
+    auto rect = page(page_id).page().enclosing_device_rect(dom_node->paintable_box()->absolute_border_box_rect());
 
 
     auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, rect.size().to_type<int>()).release_value_but_fixme_should_propagate_errors();
     auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, rect.size().to_type<int>()).release_value_but_fixme_should_propagate_errors();
-    page().paint(rect, *bitmap, { .paint_overlay = Web::PaintOptions::PaintOverlay::No });
+    page(page_id).paint(rect, *bitmap, { .paint_overlay = Web::PaintOptions::PaintOverlay::No });
 
 
-    async_did_take_screenshot(bitmap->to_shareable_bitmap());
+    async_did_take_screenshot(page_id, bitmap->to_shareable_bitmap());
 }
 }
 
 
-Messages::WebContentServer::DumpGcGraphResponse ConnectionFromClient::dump_gc_graph()
+Messages::WebContentServer::DumpGcGraphResponse ConnectionFromClient::dump_gc_graph(u64)
 {
 {
     auto gc_graph_json = Web::Bindings::main_thread_vm().heap().dump_graph();
     auto gc_graph_json = Web::Bindings::main_thread_vm().heap().dump_graph();
     return MUST(String::from_byte_string(gc_graph_json.to_byte_string()));
     return MUST(String::from_byte_string(gc_graph_json.to_byte_string()));
 }
 }
 
 
-Messages::WebContentServer::GetSelectedTextResponse ConnectionFromClient::get_selected_text()
+Messages::WebContentServer::GetSelectedTextResponse ConnectionFromClient::get_selected_text(u64 page_id)
 {
 {
-    return page().page().focused_context().selected_text().to_byte_string();
+    return page(page_id).page().focused_context().selected_text().to_byte_string();
 }
 }
 
 
-void ConnectionFromClient::select_all()
+void ConnectionFromClient::select_all(u64 page_id)
 {
 {
-    page().page().focused_context().select_all();
+    page(page_id).page().focused_context().select_all();
 }
 }
 
 
-Messages::WebContentServer::DumpLayoutTreeResponse ConnectionFromClient::dump_layout_tree()
+Messages::WebContentServer::DumpLayoutTreeResponse ConnectionFromClient::dump_layout_tree(u64 page_id)
 {
 {
-    auto* document = page().page().top_level_browsing_context().active_document();
+    auto* document = page(page_id).page().top_level_browsing_context().active_document();
     if (!document)
     if (!document)
         return ByteString { "(no DOM tree)" };
         return ByteString { "(no DOM tree)" };
     document->update_layout();
     document->update_layout();
@@ -922,9 +858,9 @@ Messages::WebContentServer::DumpLayoutTreeResponse ConnectionFromClient::dump_la
     return builder.to_byte_string();
     return builder.to_byte_string();
 }
 }
 
 
-Messages::WebContentServer::DumpPaintTreeResponse ConnectionFromClient::dump_paint_tree()
+Messages::WebContentServer::DumpPaintTreeResponse ConnectionFromClient::dump_paint_tree(u64 page_id)
 {
 {
-    auto* document = page().page().top_level_browsing_context().active_document();
+    auto* document = page(page_id).page().top_level_browsing_context().active_document();
     if (!document)
     if (!document)
         return ByteString { "(no DOM tree)" };
         return ByteString { "(no DOM tree)" };
     document->update_layout();
     document->update_layout();
@@ -938,9 +874,9 @@ Messages::WebContentServer::DumpPaintTreeResponse ConnectionFromClient::dump_pai
     return builder.to_byte_string();
     return builder.to_byte_string();
 }
 }
 
 
-Messages::WebContentServer::DumpTextResponse ConnectionFromClient::dump_text()
+Messages::WebContentServer::DumpTextResponse ConnectionFromClient::dump_text(u64 page_id)
 {
 {
-    auto* document = page().page().top_level_browsing_context().active_document();
+    auto* document = page(page_id).page().top_level_browsing_context().active_document();
     if (!document)
     if (!document)
         return ByteString { "(no DOM tree)" };
         return ByteString { "(no DOM tree)" };
     if (!document->body())
     if (!document->body())
@@ -948,24 +884,24 @@ Messages::WebContentServer::DumpTextResponse ConnectionFromClient::dump_text()
     return document->body()->inner_text();
     return document->body()->inner_text();
 }
 }
 
 
-void ConnectionFromClient::set_content_filters(Vector<String> const& filters)
+void ConnectionFromClient::set_content_filters(u64, Vector<String> const& filters)
 {
 {
     Web::ContentFilter::the().set_patterns(filters).release_value_but_fixme_should_propagate_errors();
     Web::ContentFilter::the().set_patterns(filters).release_value_but_fixme_should_propagate_errors();
 }
 }
 
 
-void ConnectionFromClient::set_autoplay_allowed_on_all_websites()
+void ConnectionFromClient::set_autoplay_allowed_on_all_websites(u64)
 {
 {
     auto& autoplay_allowlist = Web::PermissionsPolicy::AutoplayAllowlist::the();
     auto& autoplay_allowlist = Web::PermissionsPolicy::AutoplayAllowlist::the();
     autoplay_allowlist.enable_globally();
     autoplay_allowlist.enable_globally();
 }
 }
 
 
-void ConnectionFromClient::set_autoplay_allowlist(Vector<String> const& allowlist)
+void ConnectionFromClient::set_autoplay_allowlist(u64, Vector<String> const& allowlist)
 {
 {
     auto& autoplay_allowlist = Web::PermissionsPolicy::AutoplayAllowlist::the();
     auto& autoplay_allowlist = Web::PermissionsPolicy::AutoplayAllowlist::the();
     autoplay_allowlist.enable_for_origins(allowlist).release_value_but_fixme_should_propagate_errors();
     autoplay_allowlist.enable_for_origins(allowlist).release_value_but_fixme_should_propagate_errors();
 }
 }
 
 
-void ConnectionFromClient::set_proxy_mappings(Vector<ByteString> const& proxies, HashMap<ByteString, size_t> const& mappings)
+void ConnectionFromClient::set_proxy_mappings(u64, Vector<ByteString> const& proxies, HashMap<ByteString, size_t> const& mappings)
 {
 {
     auto keys = mappings.keys();
     auto keys = mappings.keys();
     quick_sort(keys, [&](auto& a, auto& b) { return a.length() < b.length(); });
     quick_sort(keys, [&](auto& a, auto& b) { return a.length() < b.length(); });
@@ -981,51 +917,51 @@ void ConnectionFromClient::set_proxy_mappings(Vector<ByteString> const& proxies,
     Web::ProxyMappings::the().set_mappings(proxies, move(sorted_mappings));
     Web::ProxyMappings::the().set_mappings(proxies, move(sorted_mappings));
 }
 }
 
 
-void ConnectionFromClient::set_preferred_color_scheme(Web::CSS::PreferredColorScheme const& color_scheme)
+void ConnectionFromClient::set_preferred_color_scheme(u64 page_id, Web::CSS::PreferredColorScheme const& color_scheme)
 {
 {
-    page().set_preferred_color_scheme(color_scheme);
+    page(page_id).set_preferred_color_scheme(color_scheme);
 }
 }
 
 
-void ConnectionFromClient::set_has_focus(bool has_focus)
+void ConnectionFromClient::set_has_focus(u64 page_id, bool has_focus)
 {
 {
-    page().set_has_focus(has_focus);
+    page(page_id).set_has_focus(has_focus);
 }
 }
 
 
-void ConnectionFromClient::set_is_scripting_enabled(bool is_scripting_enabled)
+void ConnectionFromClient::set_is_scripting_enabled(u64 page_id, bool is_scripting_enabled)
 {
 {
-    page().set_is_scripting_enabled(is_scripting_enabled);
+    page(page_id).set_is_scripting_enabled(is_scripting_enabled);
 }
 }
 
 
-void ConnectionFromClient::set_device_pixels_per_css_pixel(float device_pixels_per_css_pixel)
+void ConnectionFromClient::set_device_pixels_per_css_pixel(u64 page_id, float device_pixels_per_css_pixel)
 {
 {
-    page().set_device_pixels_per_css_pixel(device_pixels_per_css_pixel);
+    page(page_id).set_device_pixels_per_css_pixel(device_pixels_per_css_pixel);
 }
 }
 
 
-void ConnectionFromClient::set_window_position(Web::DevicePixelPoint position)
+void ConnectionFromClient::set_window_position(u64 page_id, Web::DevicePixelPoint position)
 {
 {
-    page().set_window_position(position);
+    page(page_id).set_window_position(position);
 }
 }
 
 
-void ConnectionFromClient::set_window_size(Web::DevicePixelSize size)
+void ConnectionFromClient::set_window_size(u64 page_id, Web::DevicePixelSize size)
 {
 {
-    page().set_window_size(size);
+    page(page_id).set_window_size(size);
 }
 }
 
 
-Messages::WebContentServer::GetLocalStorageEntriesResponse ConnectionFromClient::get_local_storage_entries()
+Messages::WebContentServer::GetLocalStorageEntriesResponse ConnectionFromClient::get_local_storage_entries(u64 page_id)
 {
 {
-    auto* document = page().page().top_level_browsing_context().active_document();
+    auto* document = page(page_id).page().top_level_browsing_context().active_document();
     auto local_storage = document->window().local_storage().release_value_but_fixme_should_propagate_errors();
     auto local_storage = document->window().local_storage().release_value_but_fixme_should_propagate_errors();
     return local_storage->map();
     return local_storage->map();
 }
 }
 
 
-Messages::WebContentServer::GetSessionStorageEntriesResponse ConnectionFromClient::get_session_storage_entries()
+Messages::WebContentServer::GetSessionStorageEntriesResponse ConnectionFromClient::get_session_storage_entries(u64 page_id)
 {
 {
-    auto* document = page().page().top_level_browsing_context().active_document();
+    auto* document = page(page_id).page().top_level_browsing_context().active_document();
     auto session_storage = document->window().session_storage().release_value_but_fixme_should_propagate_errors();
     auto session_storage = document->window().session_storage().release_value_but_fixme_should_propagate_errors();
     return session_storage->map();
     return session_storage->map();
 }
 }
 
 
-void ConnectionFromClient::handle_file_return(i32 error, Optional<IPC::File> const& file, i32 request_id)
+void ConnectionFromClient::handle_file_return(u64, i32 error, Optional<IPC::File> const& file, i32 request_id)
 {
 {
     auto file_request = m_requested_files.take(request_id);
     auto file_request = m_requested_files.take(request_id);
 
 
@@ -1035,75 +971,90 @@ void ConnectionFromClient::handle_file_return(i32 error, Optional<IPC::File> con
     file_request.value().on_file_request_finish(error != 0 ? Error::from_errno(error) : ErrorOr<i32> { file->take_fd() });
     file_request.value().on_file_request_finish(error != 0 ? Error::from_errno(error) : ErrorOr<i32> { file->take_fd() });
 }
 }
 
 
-void ConnectionFromClient::request_file(Web::FileRequest file_request)
+void ConnectionFromClient::request_file(u64 page_id, Web::FileRequest file_request)
 {
 {
     i32 const id = last_id++;
     i32 const id = last_id++;
 
 
     auto path = file_request.path();
     auto path = file_request.path();
     m_requested_files.set(id, move(file_request));
     m_requested_files.set(id, move(file_request));
 
 
-    async_did_request_file(path, id);
+    async_did_request_file(page_id, path, id);
 }
 }
 
 
-void ConnectionFromClient::set_system_visibility_state(bool visible)
+void ConnectionFromClient::set_system_visibility_state(u64 page_id, bool visible)
 {
 {
-    page().page().top_level_traversable()->set_system_visibility_state(
+    page(page_id).page().top_level_traversable()->set_system_visibility_state(
         visible
         visible
             ? Web::HTML::VisibilityState::Visible
             ? Web::HTML::VisibilityState::Visible
             : Web::HTML::VisibilityState::Hidden);
             : Web::HTML::VisibilityState::Hidden);
 }
 }
 
 
-void ConnectionFromClient::alert_closed()
+void ConnectionFromClient::js_console_input(u64 page_id, ByteString const& js_source)
+{
+    page(page_id).js_console_input(js_source);
+}
+
+void ConnectionFromClient::run_javascript(u64 page_id, ByteString const& js_source)
+{
+    page(page_id).run_javascript(js_source);
+}
+
+void ConnectionFromClient::js_console_request_messages(u64 page_id, i32 start_index)
+{
+    page(page_id).js_console_request_messages(start_index);
+}
+
+void ConnectionFromClient::alert_closed(u64 page_id)
 {
 {
-    page().page().alert_closed();
+    page(page_id).page().alert_closed();
 }
 }
 
 
-void ConnectionFromClient::confirm_closed(bool accepted)
+void ConnectionFromClient::confirm_closed(u64 page_id, bool accepted)
 {
 {
-    page().page().confirm_closed(accepted);
+    page(page_id).page().confirm_closed(accepted);
 }
 }
 
 
-void ConnectionFromClient::prompt_closed(Optional<String> const& response)
+void ConnectionFromClient::prompt_closed(u64 page_id, Optional<String> const& response)
 {
 {
-    page().page().prompt_closed(response);
+    page(page_id).page().prompt_closed(response);
 }
 }
 
 
-void ConnectionFromClient::color_picker_update(Optional<Color> const& picked_color, Web::HTML::ColorPickerUpdateState const& state)
+void ConnectionFromClient::color_picker_update(u64 page_id, Optional<Color> const& picked_color, Web::HTML::ColorPickerUpdateState const& state)
 {
 {
-    page().page().color_picker_update(picked_color, state);
+    page(page_id).page().color_picker_update(picked_color, state);
 }
 }
 
 
-void ConnectionFromClient::select_dropdown_closed(Optional<String> const& value)
+void ConnectionFromClient::select_dropdown_closed(u64 page_id, Optional<String> const& value)
 {
 {
-    page().page().select_dropdown_closed(value);
+    page(page_id).page().select_dropdown_closed(value);
 }
 }
 
 
-void ConnectionFromClient::toggle_media_play_state()
+void ConnectionFromClient::toggle_media_play_state(u64 page_id)
 {
 {
-    page().page().toggle_media_play_state().release_value_but_fixme_should_propagate_errors();
+    page(page_id).page().toggle_media_play_state().release_value_but_fixme_should_propagate_errors();
 }
 }
 
 
-void ConnectionFromClient::toggle_media_mute_state()
+void ConnectionFromClient::toggle_media_mute_state(u64 page_id)
 {
 {
-    page().page().toggle_media_mute_state();
+    page(page_id).page().toggle_media_mute_state();
 }
 }
 
 
-void ConnectionFromClient::toggle_media_loop_state()
+void ConnectionFromClient::toggle_media_loop_state(u64 page_id)
 {
 {
-    page().page().toggle_media_loop_state().release_value_but_fixme_should_propagate_errors();
+    page(page_id).page().toggle_media_loop_state().release_value_but_fixme_should_propagate_errors();
 }
 }
 
 
-void ConnectionFromClient::toggle_media_controls_state()
+void ConnectionFromClient::toggle_media_controls_state(u64 page_id)
 {
 {
-    page().page().toggle_media_controls_state().release_value_but_fixme_should_propagate_errors();
+    page(page_id).page().toggle_media_controls_state().release_value_but_fixme_should_propagate_errors();
 }
 }
 
 
-void ConnectionFromClient::set_user_style(String const& source)
+void ConnectionFromClient::set_user_style(u64 page_id, String const& source)
 {
 {
-    page().page().set_user_style(source);
+    page(page_id).page().set_user_style(source);
 }
 }
 
 
-void ConnectionFromClient::enable_inspector_prototype()
+void ConnectionFromClient::enable_inspector_prototype(u64)
 {
 {
     Web::HTML::Window::set_inspector_object_exposed(true);
     Web::HTML::Window::set_inspector_object_exposed(true);
 }
 }

+ 88 - 104
Userland/Services/WebContent/ConnectionFromClient.h

@@ -34,122 +34,104 @@ public:
 
 
     virtual void die() override;
     virtual void die() override;
 
 
-    void initialize_js_console(Badge<PageClient>, Web::DOM::Document& document);
-    void destroy_js_console(Badge<PageClient>, Web::DOM::Document& document);
-
-    void request_file(Web::FileRequest);
+    void request_file(u64 page_id, Web::FileRequest);
 
 
     Optional<int> fd() { return socket().fd(); }
     Optional<int> fd() { return socket().fd(); }
 
 
     PageHost& page_host() { return *m_page_host; }
     PageHost& page_host() { return *m_page_host; }
     PageHost const& page_host() const { return *m_page_host; }
     PageHost const& page_host() const { return *m_page_host; }
 
 
-    auto& backing_stores() { return m_backing_stores; }
-
 private:
 private:
     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>);
     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>);
 
 
-    PageClient& page(u64 index = 0);
-    PageClient const& page(u64 index = 0) const;
-
-    virtual Messages::WebContentServer::GetWindowHandleResponse get_window_handle() override;
-    virtual void set_window_handle(String const& handle) override;
-    virtual void connect_to_webdriver(ByteString const& webdriver_ipc_path) override;
-    virtual void update_system_theme(Core::AnonymousBuffer const&) override;
-    virtual void update_system_fonts(ByteString const&, ByteString const&, ByteString const&) override;
-    virtual void update_screen_rects(Vector<Web::DevicePixelRect> const&, u32) override;
-    virtual void load_url(URL const&) override;
-    virtual void load_html(ByteString const&) override;
-    virtual void set_viewport_rect(Web::DevicePixelRect const&) override;
-    virtual void mouse_down(Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32) override;
-    virtual void mouse_move(Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32) override;
-    virtual void mouse_up(Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32) override;
-    virtual void mouse_wheel(Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32, Web::DevicePixels, Web::DevicePixels) override;
-    virtual void doubleclick(Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32) override;
-    virtual void key_down(i32, u32, u32) override;
-    virtual void key_up(i32, u32, u32) override;
-    virtual void add_backing_store(i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) override;
-    virtual void ready_to_paint() override;
-    virtual void debug_request(ByteString const&, ByteString const&) override;
-    virtual void get_source() override;
-    virtual void inspect_dom_tree() override;
-    virtual void inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element) override;
-    virtual void inspect_accessibility_tree() override;
-    virtual void get_hovered_node_id() override;
-
-    virtual void set_dom_node_text(i32 node_id, String const& text) override;
-    virtual void set_dom_node_tag(i32 node_id, String const& name) override;
-    virtual void add_dom_node_attributes(i32 node_id, Vector<WebView::Attribute> const& attributes) override;
-    virtual void replace_dom_node_attribute(i32 node_id, String const& name, Vector<WebView::Attribute> const& replacement_attributes) override;
-    virtual void create_child_element(i32 node_id) override;
-    virtual void create_child_text_node(i32 node_id) override;
-    virtual void clone_dom_node(i32 node_id) override;
-    virtual void remove_dom_node(i32 node_id) override;
-    virtual void get_dom_node_html(i32 node_id) override;
-
-    virtual Messages::WebContentServer::DumpLayoutTreeResponse dump_layout_tree() override;
-    virtual Messages::WebContentServer::DumpPaintTreeResponse dump_paint_tree() override;
-    virtual Messages::WebContentServer::DumpTextResponse dump_text() override;
-    virtual void set_content_filters(Vector<String> const&) override;
-    virtual void set_autoplay_allowed_on_all_websites() override;
-    virtual void set_autoplay_allowlist(Vector<String> const& allowlist) override;
-    virtual void set_proxy_mappings(Vector<ByteString> const&, HashMap<ByteString, size_t> const&) override;
-    virtual void set_preferred_color_scheme(Web::CSS::PreferredColorScheme const&) override;
-    virtual void set_has_focus(bool) override;
-    virtual void set_is_scripting_enabled(bool) override;
-    virtual void set_device_pixels_per_css_pixel(float) override;
-    virtual void set_window_position(Web::DevicePixelPoint) override;
-    virtual void set_window_size(Web::DevicePixelSize) override;
-    virtual void handle_file_return(i32 error, Optional<IPC::File> const& file, i32 request_id) override;
-    virtual void set_system_visibility_state(bool visible) override;
-
-    virtual void js_console_input(ByteString const&) override;
-    virtual void run_javascript(ByteString const&) override;
-    virtual void js_console_request_messages(i32) override;
-
-    virtual void alert_closed() override;
-    virtual void confirm_closed(bool accepted) override;
-    virtual void prompt_closed(Optional<String> const& response) override;
-    virtual void color_picker_update(Optional<Color> const& picked_color, Web::HTML::ColorPickerUpdateState const& state) override;
-    virtual void select_dropdown_closed(Optional<String> const& value) override;
-
-    virtual void toggle_media_play_state() override;
-    virtual void toggle_media_mute_state() override;
-    virtual void toggle_media_loop_state() override;
-    virtual void toggle_media_controls_state() override;
-
-    virtual void set_user_style(String const&) override;
-
-    virtual void enable_inspector_prototype() override;
-
-    virtual void take_document_screenshot() override;
-    virtual void take_dom_node_screenshot(i32 node_id) override;
-
-    virtual Messages::WebContentServer::DumpGcGraphResponse dump_gc_graph() override;
-
-    virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override;
-    virtual Messages::WebContentServer::GetSessionStorageEntriesResponse get_session_storage_entries() override;
-
-    virtual Messages::WebContentServer::GetSelectedTextResponse get_selected_text() override;
-    virtual void select_all() override;
-
-    void report_finished_handling_input_event(bool event_was_handled);
+    PageClient& page(u64 index);
+    PageClient const& page(u64 index) const;
+
+    virtual Messages::WebContentServer::GetWindowHandleResponse get_window_handle(u64 page_id) override;
+    virtual void set_window_handle(u64 page_id, String const& handle) override;
+    virtual void connect_to_webdriver(u64 page_id, ByteString const& webdriver_ipc_path) override;
+    virtual void update_system_theme(u64 page_id, Core::AnonymousBuffer const&) override;
+    virtual void update_system_fonts(u64 page_id, ByteString const&, ByteString const&, ByteString const&) override;
+    virtual void update_screen_rects(u64 page_id, Vector<Web::DevicePixelRect> const&, u32) override;
+    virtual void load_url(u64 page_id, URL const&) override;
+    virtual void load_html(u64 page_id, ByteString const&) override;
+    virtual void set_viewport_rect(u64 page_id, Web::DevicePixelRect const&) override;
+    virtual void mouse_down(u64 page_id, Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32) override;
+    virtual void mouse_move(u64 page_id, Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32) override;
+    virtual void mouse_up(u64 page_id, Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32) override;
+    virtual void mouse_wheel(u64 page_id, Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32, Web::DevicePixels, Web::DevicePixels) override;
+    virtual void doubleclick(u64 page_id, Web::DevicePixelPoint, Web::DevicePixelPoint, u32, u32, u32) override;
+    virtual void key_down(u64 page_id, i32, u32, u32) override;
+    virtual void key_up(u64 page_id, i32, u32, u32) override;
+    virtual void add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap) override;
+    virtual void ready_to_paint(u64 page_id) override;
+    virtual void debug_request(u64 page_id, ByteString const&, ByteString const&) override;
+    virtual void get_source(u64 page_id) override;
+    virtual void inspect_dom_tree(u64 page_id) override;
+    virtual void inspect_dom_node(u64 page_id, i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element) override;
+    virtual void inspect_accessibility_tree(u64 page_id) override;
+    virtual void get_hovered_node_id(u64 page_id) override;
+
+    virtual void set_dom_node_text(u64 page_id, i32 node_id, String const& text) override;
+    virtual void set_dom_node_tag(u64 page_id, i32 node_id, String const& name) override;
+    virtual void add_dom_node_attributes(u64 page_id, i32 node_id, Vector<WebView::Attribute> const& attributes) override;
+    virtual void replace_dom_node_attribute(u64 page_id, i32 node_id, String const& name, Vector<WebView::Attribute> const& replacement_attributes) override;
+    virtual void create_child_element(u64 page_id, i32 node_id) override;
+    virtual void create_child_text_node(u64 page_id, i32 node_id) override;
+    virtual void clone_dom_node(u64 page_id, i32 node_id) override;
+    virtual void remove_dom_node(u64 page_id, i32 node_id) override;
+    virtual void get_dom_node_html(u64 page_id, i32 node_id) override;
+
+    virtual Messages::WebContentServer::DumpLayoutTreeResponse dump_layout_tree(u64 page_id) override;
+    virtual Messages::WebContentServer::DumpPaintTreeResponse dump_paint_tree(u64 page_id) override;
+    virtual Messages::WebContentServer::DumpTextResponse dump_text(u64 page_id) override;
+    virtual void set_content_filters(u64 page_id, Vector<String> const&) override;
+    virtual void set_autoplay_allowed_on_all_websites(u64 page_id) override;
+    virtual void set_autoplay_allowlist(u64 page_id, Vector<String> const& allowlist) override;
+    virtual void set_proxy_mappings(u64 page_id, Vector<ByteString> const&, HashMap<ByteString, size_t> const&) override;
+    virtual void set_preferred_color_scheme(u64 page_id, Web::CSS::PreferredColorScheme const&) override;
+    virtual void set_has_focus(u64 page_id, bool) override;
+    virtual void set_is_scripting_enabled(u64 page_id, bool) override;
+    virtual void set_device_pixels_per_css_pixel(u64 page_id, float) override;
+    virtual void set_window_position(u64 page_id, Web::DevicePixelPoint) override;
+    virtual void set_window_size(u64 page_id, Web::DevicePixelSize) override;
+    virtual void handle_file_return(u64 page_id, i32 error, Optional<IPC::File> const& file, i32 request_id) override;
+    virtual void set_system_visibility_state(u64 page_id, bool visible) override;
+
+    virtual void js_console_input(u64 page_id, ByteString const&) override;
+    virtual void run_javascript(u64 page_id, ByteString const&) override;
+    virtual void js_console_request_messages(u64 page_id, i32) override;
+
+    virtual void alert_closed(u64 page_id) override;
+    virtual void confirm_closed(u64 page_id, bool accepted) override;
+    virtual void prompt_closed(u64 page_id, Optional<String> const& response) override;
+    virtual void color_picker_update(u64 page_id, Optional<Color> const& picked_color, Web::HTML::ColorPickerUpdateState const& state) override;
+    virtual void select_dropdown_closed(u64 page_id, Optional<String> const& value) override;
+
+    virtual void toggle_media_play_state(u64 page_id) override;
+    virtual void toggle_media_mute_state(u64 page_id) override;
+    virtual void toggle_media_loop_state(u64 page_id) override;
+    virtual void toggle_media_controls_state(u64 page_id) override;
+
+    virtual void set_user_style(u64 page_id, String const&) override;
+
+    virtual void enable_inspector_prototype(u64 page_id) override;
+
+    virtual void take_document_screenshot(u64 page_id) override;
+    virtual void take_dom_node_screenshot(u64 page_id, i32 node_id) override;
+
+    virtual Messages::WebContentServer::DumpGcGraphResponse dump_gc_graph(u64 page_id) override;
+
+    virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries(u64 page_id) override;
+    virtual Messages::WebContentServer::GetSessionStorageEntriesResponse get_session_storage_entries(u64 page_id) override;
+
+    virtual Messages::WebContentServer::GetSelectedTextResponse get_selected_text(u64 page_id) override;
+    virtual void select_all(u64 page_id) override;
+
+    void report_finished_handling_input_event(u64 page_id, bool event_was_handled);
 
 
     NonnullOwnPtr<PageHost> m_page_host;
     NonnullOwnPtr<PageHost> m_page_host;
 
 
-    struct BackingStores {
-        i32 front_bitmap_id { -1 };
-        i32 back_bitmap_id { -1 };
-        RefPtr<Gfx::Bitmap> front_bitmap;
-        RefPtr<Gfx::Bitmap> back_bitmap;
-    };
-    BackingStores m_backing_stores;
-
-    HashMap<Web::DOM::Document*, NonnullOwnPtr<WebContentConsoleClient>> m_console_clients;
-    WeakPtr<WebContentConsoleClient> m_top_level_document_console_client;
-
-    JS::Handle<JS::GlobalObject> m_console_global_object;
-
     HashMap<int, Web::FileRequest> m_requested_files {};
     HashMap<int, Web::FileRequest> m_requested_files {};
     int last_id { 0 };
     int last_id { 0 };
 
 
@@ -170,6 +152,7 @@ private:
         Web::DevicePixels wheel_delta_x {};
         Web::DevicePixels wheel_delta_x {};
         Web::DevicePixels wheel_delta_y {};
         Web::DevicePixels wheel_delta_y {};
         size_t coalesced_event_count { 0 };
         size_t coalesced_event_count { 0 };
+        u64 page_id { 0 };
     };
     };
 
 
     struct QueuedKeyboardEvent {
     struct QueuedKeyboardEvent {
@@ -181,6 +164,7 @@ private:
         i32 key {};
         i32 key {};
         u32 modifiers {};
         u32 modifiers {};
         u32 code_point {};
         u32 code_point {};
+        u64 page_id { 0 };
     };
     };
 
 
     void enqueue_input_event(Variant<QueuedMouseEvent, QueuedKeyboardEvent>);
     void enqueue_input_event(Variant<QueuedMouseEvent, QueuedKeyboardEvent>);

+ 153 - 63
Userland/Services/WebContent/PageClient.cpp

@@ -8,12 +8,15 @@
 
 
 #include <LibGfx/ShareableBitmap.h>
 #include <LibGfx/ShareableBitmap.h>
 #include <LibGfx/SystemTheme.h>
 #include <LibGfx/SystemTheme.h>
+#include <LibJS/Console.h>
+#include <LibJS/Runtime/ConsoleObject.h>
 #include <LibWeb/Bindings/MainThreadVM.h>
 #include <LibWeb/Bindings/MainThreadVM.h>
 #include <LibWeb/CSS/SystemColor.h>
 #include <LibWeb/CSS/SystemColor.h>
 #include <LibWeb/Cookie/ParsedCookie.h>
 #include <LibWeb/Cookie/ParsedCookie.h>
 #include <LibWeb/DOM/Attr.h>
 #include <LibWeb/DOM/Attr.h>
 #include <LibWeb/DOM/NamedNodeMap.h>
 #include <LibWeb/DOM/NamedNodeMap.h>
 #include <LibWeb/HTML/BrowsingContext.h>
 #include <LibWeb/HTML/BrowsingContext.h>
+#include <LibWeb/HTML/Scripting/ClassicScript.h>
 #include <LibWeb/HTML/TraversableNavigable.h>
 #include <LibWeb/HTML/TraversableNavigable.h>
 #include <LibWeb/Layout/Viewport.h>
 #include <LibWeb/Layout/Viewport.h>
 #include <LibWeb/Painting/PaintableBox.h>
 #include <LibWeb/Painting/PaintableBox.h>
@@ -54,20 +57,20 @@ PageClient::PageClient(PageHost& owner, u64 id)
     setup_palette();
     setup_palette();
 
 
     m_repaint_timer = Web::Platform::Timer::create_single_shot(0, [this] {
     m_repaint_timer = Web::Platform::Timer::create_single_shot(0, [this] {
-        if (!client().backing_stores().back_bitmap) {
+        if (!m_backing_stores.back_bitmap) {
             return;
             return;
         }
         }
 
 
-        auto& back_bitmap = *client().backing_stores().back_bitmap;
+        auto& back_bitmap = *m_backing_stores.back_bitmap;
         auto viewport_rect = page().css_to_device_rect(page().top_level_traversable()->viewport_rect());
         auto viewport_rect = page().css_to_device_rect(page().top_level_traversable()->viewport_rect());
         paint(viewport_rect, back_bitmap);
         paint(viewport_rect, back_bitmap);
 
 
-        auto& backing_stores = client().backing_stores();
+        auto& backing_stores = m_backing_stores;
         swap(backing_stores.front_bitmap, backing_stores.back_bitmap);
         swap(backing_stores.front_bitmap, backing_stores.back_bitmap);
         swap(backing_stores.front_bitmap_id, backing_stores.back_bitmap_id);
         swap(backing_stores.front_bitmap_id, backing_stores.back_bitmap_id);
 
 
         m_paint_state = PaintState::WaitingForClient;
         m_paint_state = PaintState::WaitingForClient;
-        client().async_did_paint(viewport_rect.to_type<int>(), backing_stores.front_bitmap_id);
+        client().async_did_paint(m_id, viewport_rect.to_type<int>(), backing_stores.front_bitmap_id);
     });
     });
 
 
 #ifdef HAS_ACCELERATED_GRAPHICS
 #ifdef HAS_ACCELERATED_GRAPHICS
@@ -101,6 +104,14 @@ void PageClient::ready_to_paint()
         schedule_repaint();
         schedule_repaint();
 }
 }
 
 
+void PageClient::add_backing_store(i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap)
+{
+    m_backing_stores.front_bitmap_id = front_bitmap_id;
+    m_backing_stores.back_bitmap_id = back_bitmap_id;
+    m_backing_stores.front_bitmap = *const_cast<Gfx::ShareableBitmap&>(front_bitmap).bitmap();
+    m_backing_stores.back_bitmap = *const_cast<Gfx::ShareableBitmap&>(back_bitmap).bitmap();
+}
+
 void PageClient::visit_edges(JS::Cell::Visitor& visitor)
 void PageClient::visit_edges(JS::Cell::Visitor& visitor)
 {
 {
     Base::visit_edges(visitor);
     Base::visit_edges(visitor);
@@ -220,7 +231,7 @@ void PageClient::page_did_invalidate(Web::CSSPixelRect const&)
 
 
 void PageClient::page_did_request_cursor_change(Gfx::StandardCursor cursor)
 void PageClient::page_did_request_cursor_change(Gfx::StandardCursor cursor)
 {
 {
-    client().async_did_request_cursor_change((u32)cursor);
+    client().async_did_request_cursor_change(m_id, (u32)cursor);
 }
 }
 
 
 void PageClient::page_did_layout()
 void PageClient::page_did_layout()
@@ -231,62 +242,62 @@ void PageClient::page_did_layout()
         m_content_size = page().enclosing_device_rect(layout_root->paintable_box()->scrollable_overflow_rect().value()).size();
         m_content_size = page().enclosing_device_rect(layout_root->paintable_box()->scrollable_overflow_rect().value()).size();
     else
     else
         m_content_size = page().enclosing_device_rect(layout_root->paintable_box()->absolute_rect()).size();
         m_content_size = page().enclosing_device_rect(layout_root->paintable_box()->absolute_rect()).size();
-    client().async_did_layout(m_content_size.to_type<int>());
+    client().async_did_layout(m_id, m_content_size.to_type<int>());
 }
 }
 
 
 void PageClient::page_did_change_title(ByteString const& title)
 void PageClient::page_did_change_title(ByteString const& title)
 {
 {
-    client().async_did_change_title(title);
+    client().async_did_change_title(m_id, title);
 }
 }
 
 
 void PageClient::page_did_request_navigate_back()
 void PageClient::page_did_request_navigate_back()
 {
 {
-    client().async_did_request_navigate_back();
+    client().async_did_request_navigate_back(m_id);
 }
 }
 
 
 void PageClient::page_did_request_navigate_forward()
 void PageClient::page_did_request_navigate_forward()
 {
 {
-    client().async_did_request_navigate_forward();
+    client().async_did_request_navigate_forward(m_id);
 }
 }
 
 
 void PageClient::page_did_request_refresh()
 void PageClient::page_did_request_refresh()
 {
 {
-    client().async_did_request_refresh();
+    client().async_did_request_refresh(m_id);
 }
 }
 
 
 Gfx::IntSize PageClient::page_did_request_resize_window(Gfx::IntSize size)
 Gfx::IntSize PageClient::page_did_request_resize_window(Gfx::IntSize size)
 {
 {
-    return client().did_request_resize_window(size);
+    return client().did_request_resize_window(m_id, size);
 }
 }
 
 
 Gfx::IntPoint PageClient::page_did_request_reposition_window(Gfx::IntPoint position)
 Gfx::IntPoint PageClient::page_did_request_reposition_window(Gfx::IntPoint position)
 {
 {
-    return client().did_request_reposition_window(position);
+    return client().did_request_reposition_window(m_id, position);
 }
 }
 
 
 void PageClient::page_did_request_restore_window()
 void PageClient::page_did_request_restore_window()
 {
 {
-    client().async_did_request_restore_window();
+    client().async_did_request_restore_window(m_id);
 }
 }
 
 
 Gfx::IntRect PageClient::page_did_request_maximize_window()
 Gfx::IntRect PageClient::page_did_request_maximize_window()
 {
 {
-    return client().did_request_maximize_window();
+    return client().did_request_maximize_window(m_id);
 }
 }
 
 
 Gfx::IntRect PageClient::page_did_request_minimize_window()
 Gfx::IntRect PageClient::page_did_request_minimize_window()
 {
 {
-    return client().did_request_minimize_window();
+    return client().did_request_minimize_window(m_id);
 }
 }
 
 
 Gfx::IntRect PageClient::page_did_request_fullscreen_window()
 Gfx::IntRect PageClient::page_did_request_fullscreen_window()
 {
 {
-    return client().did_request_fullscreen_window();
+    return client().did_request_fullscreen_window(m_id);
 }
 }
 
 
 void PageClient::page_did_request_scroll(i32 x_delta, i32 y_delta)
 void PageClient::page_did_request_scroll(i32 x_delta, i32 y_delta)
 {
 {
-    client().async_did_request_scroll(x_delta, y_delta);
+    client().async_did_request_scroll(m_id, x_delta, y_delta);
 }
 }
 
 
 void PageClient::page_did_request_scroll_to(Web::CSSPixelPoint scroll_position)
 void PageClient::page_did_request_scroll_to(Web::CSSPixelPoint scroll_position)
@@ -299,83 +310,83 @@ void PageClient::page_did_request_scroll_to(Web::CSSPixelPoint scroll_position)
     page().top_level_traversable()->set_viewport_rect(viewport);
     page().top_level_traversable()->set_viewport_rect(viewport);
 
 
     auto device_scroll_position = page().css_to_device_point(scroll_position);
     auto device_scroll_position = page().css_to_device_point(scroll_position);
-    client().async_did_request_scroll_to(device_scroll_position.to_type<int>());
+    client().async_did_request_scroll_to(m_id, device_scroll_position.to_type<int>());
 }
 }
 
 
 void PageClient::page_did_enter_tooltip_area(Web::CSSPixelPoint content_position, ByteString const& title)
 void PageClient::page_did_enter_tooltip_area(Web::CSSPixelPoint content_position, ByteString const& title)
 {
 {
-    client().async_did_enter_tooltip_area({ content_position.x().to_int(), content_position.y().to_int() }, title);
+    client().async_did_enter_tooltip_area(m_id, { content_position.x().to_int(), content_position.y().to_int() }, title);
 }
 }
 
 
 void PageClient::page_did_leave_tooltip_area()
 void PageClient::page_did_leave_tooltip_area()
 {
 {
-    client().async_did_leave_tooltip_area();
+    client().async_did_leave_tooltip_area(m_id);
 }
 }
 
 
 void PageClient::page_did_hover_link(const URL& url)
 void PageClient::page_did_hover_link(const URL& url)
 {
 {
-    client().async_did_hover_link(url);
+    client().async_did_hover_link(m_id, url);
 }
 }
 
 
 void PageClient::page_did_unhover_link()
 void PageClient::page_did_unhover_link()
 {
 {
-    client().async_did_unhover_link();
+    client().async_did_unhover_link(m_id);
 }
 }
 
 
 void PageClient::page_did_middle_click_link(const URL& url, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers)
 void PageClient::page_did_middle_click_link(const URL& url, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers)
 {
 {
-    client().async_did_middle_click_link(url, target, modifiers);
+    client().async_did_middle_click_link(m_id, url, target, modifiers);
 }
 }
 
 
 void PageClient::page_did_start_loading(const URL& url, bool is_redirect)
 void PageClient::page_did_start_loading(const URL& url, bool is_redirect)
 {
 {
-    client().async_did_start_loading(url, is_redirect);
+    client().async_did_start_loading(m_id, url, is_redirect);
 }
 }
 
 
 void PageClient::page_did_create_new_document(Web::DOM::Document& document)
 void PageClient::page_did_create_new_document(Web::DOM::Document& document)
 {
 {
-    client().initialize_js_console({}, document);
+    initialize_js_console(document);
 }
 }
 
 
 void PageClient::page_did_destroy_document(Web::DOM::Document& document)
 void PageClient::page_did_destroy_document(Web::DOM::Document& document)
 {
 {
-    client().destroy_js_console({}, document);
+    destroy_js_console(document);
 }
 }
 
 
 void PageClient::page_did_finish_loading(const URL& url)
 void PageClient::page_did_finish_loading(const URL& url)
 {
 {
-    client().async_did_finish_loading(url);
+    client().async_did_finish_loading(m_id, url);
 }
 }
 
 
 void PageClient::page_did_finish_text_test()
 void PageClient::page_did_finish_text_test()
 {
 {
-    client().async_did_finish_text_test();
+    client().async_did_finish_text_test(m_id);
 }
 }
 
 
 void PageClient::page_did_request_context_menu(Web::CSSPixelPoint content_position)
 void PageClient::page_did_request_context_menu(Web::CSSPixelPoint content_position)
 {
 {
-    client().async_did_request_context_menu(page().css_to_device_point(content_position).to_type<int>());
+    client().async_did_request_context_menu(m_id, page().css_to_device_point(content_position).to_type<int>());
 }
 }
 
 
 void PageClient::page_did_request_link_context_menu(Web::CSSPixelPoint content_position, URL const& url, ByteString const& target, unsigned modifiers)
 void PageClient::page_did_request_link_context_menu(Web::CSSPixelPoint content_position, URL const& url, ByteString const& target, unsigned modifiers)
 {
 {
-    client().async_did_request_link_context_menu(page().css_to_device_point(content_position).to_type<int>(), url, target, modifiers);
+    client().async_did_request_link_context_menu(m_id, page().css_to_device_point(content_position).to_type<int>(), url, target, modifiers);
 }
 }
 
 
 void PageClient::page_did_request_image_context_menu(Web::CSSPixelPoint content_position, URL const& url, ByteString const& target, unsigned modifiers, Gfx::Bitmap const* bitmap_pointer)
 void PageClient::page_did_request_image_context_menu(Web::CSSPixelPoint content_position, URL const& url, ByteString const& target, unsigned modifiers, Gfx::Bitmap const* bitmap_pointer)
 {
 {
     auto bitmap = bitmap_pointer ? bitmap_pointer->to_shareable_bitmap() : Gfx::ShareableBitmap();
     auto bitmap = bitmap_pointer ? bitmap_pointer->to_shareable_bitmap() : Gfx::ShareableBitmap();
-    client().async_did_request_image_context_menu(page().css_to_device_point(content_position).to_type<int>(), url, target, modifiers, bitmap);
+    client().async_did_request_image_context_menu(m_id, page().css_to_device_point(content_position).to_type<int>(), url, target, modifiers, bitmap);
 }
 }
 
 
 void PageClient::page_did_request_media_context_menu(Web::CSSPixelPoint content_position, ByteString const& target, unsigned modifiers, Web::Page::MediaContextMenu menu)
 void PageClient::page_did_request_media_context_menu(Web::CSSPixelPoint content_position, ByteString const& target, unsigned modifiers, Web::Page::MediaContextMenu menu)
 {
 {
-    client().async_did_request_media_context_menu(page().css_to_device_point(content_position).to_type<int>(), target, modifiers, move(menu));
+    client().async_did_request_media_context_menu(m_id, page().css_to_device_point(content_position).to_type<int>(), target, modifiers, move(menu));
 }
 }
 
 
 void PageClient::page_did_request_alert(String const& message)
 void PageClient::page_did_request_alert(String const& message)
 {
 {
-    client().async_did_request_alert(message);
+    client().async_did_request_alert(m_id, message);
 }
 }
 
 
 void PageClient::alert_closed()
 void PageClient::alert_closed()
@@ -385,7 +396,7 @@ void PageClient::alert_closed()
 
 
 void PageClient::page_did_request_confirm(String const& message)
 void PageClient::page_did_request_confirm(String const& message)
 {
 {
-    client().async_did_request_confirm(message);
+    client().async_did_request_confirm(m_id, message);
 }
 }
 
 
 void PageClient::confirm_closed(bool accepted)
 void PageClient::confirm_closed(bool accepted)
@@ -395,12 +406,12 @@ void PageClient::confirm_closed(bool accepted)
 
 
 void PageClient::page_did_request_prompt(String const& message, String const& default_)
 void PageClient::page_did_request_prompt(String const& message, String const& default_)
 {
 {
-    client().async_did_request_prompt(message, default_);
+    client().async_did_request_prompt(m_id, message, default_);
 }
 }
 
 
 void PageClient::page_did_request_set_prompt_text(String const& text)
 void PageClient::page_did_request_set_prompt_text(String const& text)
 {
 {
-    client().async_did_request_set_prompt_text(text);
+    client().async_did_request_set_prompt_text(m_id, text);
 }
 }
 
 
 void PageClient::prompt_closed(Optional<String> response)
 void PageClient::prompt_closed(Optional<String> response)
@@ -445,32 +456,32 @@ void PageClient::set_user_style(String source)
 
 
 void PageClient::page_did_request_accept_dialog()
 void PageClient::page_did_request_accept_dialog()
 {
 {
-    client().async_did_request_accept_dialog();
+    client().async_did_request_accept_dialog(m_id);
 }
 }
 
 
 void PageClient::page_did_request_dismiss_dialog()
 void PageClient::page_did_request_dismiss_dialog()
 {
 {
-    client().async_did_request_dismiss_dialog();
+    client().async_did_request_dismiss_dialog(m_id);
 }
 }
 
 
 void PageClient::page_did_change_favicon(Gfx::Bitmap const& favicon)
 void PageClient::page_did_change_favicon(Gfx::Bitmap const& favicon)
 {
 {
-    client().async_did_change_favicon(favicon.to_shareable_bitmap());
+    client().async_did_change_favicon(m_id, favicon.to_shareable_bitmap());
 }
 }
 
 
 Vector<Web::Cookie::Cookie> PageClient::page_did_request_all_cookies(URL const& url)
 Vector<Web::Cookie::Cookie> PageClient::page_did_request_all_cookies(URL const& url)
 {
 {
-    return client().did_request_all_cookies(url);
+    return client().did_request_all_cookies(m_id, url);
 }
 }
 
 
 Optional<Web::Cookie::Cookie> PageClient::page_did_request_named_cookie(URL const& url, String const& name)
 Optional<Web::Cookie::Cookie> PageClient::page_did_request_named_cookie(URL const& url, String const& name)
 {
 {
-    return client().did_request_named_cookie(url, name);
+    return client().did_request_named_cookie(m_id, url, name);
 }
 }
 
 
 String PageClient::page_did_request_cookie(const URL& url, Web::Cookie::Source source)
 String PageClient::page_did_request_cookie(const URL& url, Web::Cookie::Source source)
 {
 {
-    auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidRequestCookie>(move(url), source);
+    auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidRequestCookie>(m_id, move(url), source);
     if (!response) {
     if (!response) {
         dbgln("WebContent client disconnected during DidRequestCookie. Exiting peacefully.");
         dbgln("WebContent client disconnected during DidRequestCookie. Exiting peacefully.");
         exit(0);
         exit(0);
@@ -480,7 +491,7 @@ String PageClient::page_did_request_cookie(const URL& url, Web::Cookie::Source s
 
 
 void PageClient::page_did_set_cookie(const URL& url, Web::Cookie::ParsedCookie const& cookie, Web::Cookie::Source source)
 void PageClient::page_did_set_cookie(const URL& url, Web::Cookie::ParsedCookie const& cookie, Web::Cookie::Source source)
 {
 {
-    auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidSetCookie>(url, cookie, source);
+    auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidSetCookie>(m_id, url, cookie, source);
     if (!response) {
     if (!response) {
         dbgln("WebContent client disconnected during DidSetCookie. Exiting peacefully.");
         dbgln("WebContent client disconnected during DidSetCookie. Exiting peacefully.");
         exit(0);
         exit(0);
@@ -489,12 +500,12 @@ void PageClient::page_did_set_cookie(const URL& url, Web::Cookie::ParsedCookie c
 
 
 void PageClient::page_did_update_cookie(Web::Cookie::Cookie cookie)
 void PageClient::page_did_update_cookie(Web::Cookie::Cookie cookie)
 {
 {
-    client().async_did_update_cookie(move(cookie));
+    client().async_did_update_cookie(m_id, move(cookie));
 }
 }
 
 
 void PageClient::page_did_update_resource_count(i32 count_waiting)
 void PageClient::page_did_update_resource_count(i32 count_waiting)
 {
 {
-    client().async_did_update_resource_count(count_waiting);
+    client().async_did_update_resource_count(m_id, 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)
 PageClient::NewWebViewResult PageClient::page_did_request_new_web_view(Web::HTML::ActivateTab activate_tab, Web::HTML::WebViewHints hints, Web::HTML::TokenizedFeature::NoOpener no_opener)
@@ -509,7 +520,7 @@ PageClient::NewWebViewResult PageClient::page_did_request_new_web_view(Web::HTML
 
 
     page_id = new_client.m_id;
     page_id = new_client.m_id;
 
 
-    auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidRequestNewWebView>(activate_tab, hints, page_id);
+    auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::DidRequestNewWebView>(m_id, activate_tab, hints, page_id);
     if (!response) {
     if (!response) {
         dbgln("WebContent client disconnected during DidRequestNewWebView. Exiting peacefully.");
         dbgln("WebContent client disconnected during DidRequestNewWebView. Exiting peacefully.");
         exit(0);
         exit(0);
@@ -520,42 +531,47 @@ PageClient::NewWebViewResult PageClient::page_did_request_new_web_view(Web::HTML
 
 
 void PageClient::page_did_request_activate_tab()
 void PageClient::page_did_request_activate_tab()
 {
 {
-    client().async_did_request_activate_tab();
+    client().async_did_request_activate_tab(m_id);
 }
 }
 
 
-void PageClient::page_did_close_browsing_context(Web::HTML::BrowsingContext const&)
+void PageClient::page_did_close_top_level_traversable()
 {
 {
-    client().async_did_close_browsing_context();
+    // FIXME: Rename this IPC call
+    client().async_did_close_browsing_context(m_id);
+
+    // NOTE: This only removes the strong reference the PageHost has for this PageClient.
+    //       It will be GC'd 'later'.
+    m_owner.remove_page({}, m_id);
 }
 }
 
 
 void PageClient::request_file(Web::FileRequest file_request)
 void PageClient::request_file(Web::FileRequest file_request)
 {
 {
-    client().request_file(move(file_request));
+    client().request_file(m_id, move(file_request));
 }
 }
 
 
 void PageClient::page_did_request_color_picker(Color current_color)
 void PageClient::page_did_request_color_picker(Color current_color)
 {
 {
-    client().async_did_request_color_picker(current_color);
+    client().async_did_request_color_picker(m_id, current_color);
 }
 }
 
 
 void PageClient::page_did_request_select_dropdown(Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items)
 void PageClient::page_did_request_select_dropdown(Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items)
 {
 {
-    client().async_did_request_select_dropdown(page().css_to_device_point(content_position).to_type<int>(), minimum_width * device_pixels_per_css_pixel(), items);
+    client().async_did_request_select_dropdown(m_id, page().css_to_device_point(content_position).to_type<int>(), minimum_width * device_pixels_per_css_pixel(), items);
 }
 }
 
 
 void PageClient::page_did_change_theme_color(Gfx::Color color)
 void PageClient::page_did_change_theme_color(Gfx::Color color)
 {
 {
-    client().async_did_change_theme_color(color);
+    client().async_did_change_theme_color(m_id, color);
 }
 }
 
 
 void PageClient::page_did_insert_clipboard_entry(String data, String presentation_style, String mime_type)
 void PageClient::page_did_insert_clipboard_entry(String data, String presentation_style, String mime_type)
 {
 {
-    client().async_did_insert_clipboard_entry(move(data), move(presentation_style), move(mime_type));
+    client().async_did_insert_clipboard_entry(m_id, move(data), move(presentation_style), move(mime_type));
 }
 }
 
 
 WebView::SocketPair PageClient::request_worker_agent()
 WebView::SocketPair PageClient::request_worker_agent()
 {
 {
-    auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::RequestWorkerAgent>();
+    auto response = client().send_sync_but_allow_failure<Messages::WebContentClient::RequestWorkerAgent>(m_id);
     if (!response) {
     if (!response) {
         dbgln("WebContent client disconnected during RequestWorkerAgent. Exiting peacefully.");
         dbgln("WebContent client disconnected during RequestWorkerAgent. Exiting peacefully.");
         exit(0);
         exit(0);
@@ -566,22 +582,22 @@ WebView::SocketPair PageClient::request_worker_agent()
 
 
 void PageClient::inspector_did_load()
 void PageClient::inspector_did_load()
 {
 {
-    client().async_inspector_did_load();
+    client().async_inspector_did_load(m_id);
 }
 }
 
 
 void PageClient::inspector_did_select_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element)
 void PageClient::inspector_did_select_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> const& pseudo_element)
 {
 {
-    client().async_inspector_did_select_dom_node(node_id, pseudo_element);
+    client().async_inspector_did_select_dom_node(m_id, node_id, pseudo_element);
 }
 }
 
 
 void PageClient::inspector_did_set_dom_node_text(i32 node_id, String const& text)
 void PageClient::inspector_did_set_dom_node_text(i32 node_id, String const& text)
 {
 {
-    client().async_inspector_did_set_dom_node_text(node_id, text);
+    client().async_inspector_did_set_dom_node_text(m_id, node_id, text);
 }
 }
 
 
 void PageClient::inspector_did_set_dom_node_tag(i32 node_id, String const& tag)
 void PageClient::inspector_did_set_dom_node_tag(i32 node_id, String const& tag)
 {
 {
-    client().async_inspector_did_set_dom_node_tag(node_id, tag);
+    client().async_inspector_did_set_dom_node_tag(m_id, node_id, tag);
 }
 }
 
 
 static Vector<WebView::Attribute> named_node_map_to_vector(JS::NonnullGCPtr<Web::DOM::NamedNodeMap> map)
 static Vector<WebView::Attribute> named_node_map_to_vector(JS::NonnullGCPtr<Web::DOM::NamedNodeMap> map)
@@ -601,12 +617,12 @@ static Vector<WebView::Attribute> named_node_map_to_vector(JS::NonnullGCPtr<Web:
 
 
 void PageClient::inspector_did_add_dom_node_attributes(i32 node_id, JS::NonnullGCPtr<Web::DOM::NamedNodeMap> attributes)
 void PageClient::inspector_did_add_dom_node_attributes(i32 node_id, JS::NonnullGCPtr<Web::DOM::NamedNodeMap> attributes)
 {
 {
-    client().async_inspector_did_add_dom_node_attributes(node_id, named_node_map_to_vector(attributes));
+    client().async_inspector_did_add_dom_node_attributes(m_id, node_id, named_node_map_to_vector(attributes));
 }
 }
 
 
 void PageClient::inspector_did_replace_dom_node_attribute(i32 node_id, String const& name, JS::NonnullGCPtr<Web::DOM::NamedNodeMap> replacement_attributes)
 void PageClient::inspector_did_replace_dom_node_attribute(i32 node_id, String const& name, JS::NonnullGCPtr<Web::DOM::NamedNodeMap> replacement_attributes)
 {
 {
-    client().async_inspector_did_replace_dom_node_attribute(node_id, name, named_node_map_to_vector(replacement_attributes));
+    client().async_inspector_did_replace_dom_node_attribute(m_id, node_id, name, named_node_map_to_vector(replacement_attributes));
 }
 }
 
 
 void PageClient::inspector_did_request_dom_tree_context_menu(i32 node_id, Web::CSSPixelPoint position, String const& type, Optional<String> const& tag, Optional<String> const& attribute_name, Optional<String> const& attribute_value)
 void PageClient::inspector_did_request_dom_tree_context_menu(i32 node_id, Web::CSSPixelPoint position, String const& type, Optional<String> const& tag, Optional<String> const& attribute_name, Optional<String> const& attribute_value)
@@ -615,12 +631,12 @@ void PageClient::inspector_did_request_dom_tree_context_menu(i32 node_id, Web::C
     if (attribute_name.has_value() && attribute_value.has_value())
     if (attribute_name.has_value() && attribute_value.has_value())
         attribute = WebView::Attribute { *attribute_name, *attribute_value };
         attribute = WebView::Attribute { *attribute_name, *attribute_value };
 
 
-    client().async_inspector_did_request_dom_tree_context_menu(node_id, page().css_to_device_point(position).to_type<int>(), type, tag, move(attribute));
+    client().async_inspector_did_request_dom_tree_context_menu(m_id, node_id, page().css_to_device_point(position).to_type<int>(), type, tag, move(attribute));
 }
 }
 
 
 void PageClient::inspector_did_execute_console_script(String const& script)
 void PageClient::inspector_did_execute_console_script(String const& script)
 {
 {
-    client().async_inspector_did_execute_console_script(script);
+    client().async_inspector_did_execute_console_script(m_id, script);
 }
 }
 
 
 ErrorOr<void> PageClient::connect_to_webdriver(ByteString const& webdriver_ipc_path)
 ErrorOr<void> PageClient::connect_to_webdriver(ByteString const& webdriver_ipc_path)
@@ -634,4 +650,78 @@ ErrorOr<void> PageClient::connect_to_webdriver(ByteString const& webdriver_ipc_p
     return {};
     return {};
 }
 }
 
 
+void PageClient::initialize_js_console(Web::DOM::Document& document)
+{
+    auto& realm = document.realm();
+    auto console_object = realm.intrinsics().console_object();
+    auto console_client = make<WebContentConsoleClient>(console_object->console(), document.realm(), *this);
+    console_object->console().set_client(*console_client);
+
+    VERIFY(document.browsing_context());
+    if (document.browsing_context()->is_top_level()) {
+        m_top_level_document_console_client = console_client->make_weak_ptr();
+    }
+
+    m_console_clients.set(&document, move(console_client));
+}
+
+void PageClient::destroy_js_console(Web::DOM::Document& document)
+{
+    m_console_clients.remove(&document);
+}
+
+void PageClient::js_console_input(ByteString const& js_source)
+{
+    if (m_top_level_document_console_client)
+        m_top_level_document_console_client->handle_input(js_source);
+}
+
+void PageClient::run_javascript(ByteString const& js_source)
+{
+    auto* active_document = page().top_level_browsing_context().active_document();
+
+    if (!active_document)
+        return;
+
+    // This is partially based on "execute a javascript: URL request" https://html.spec.whatwg.org/multipage/browsing-the-web.html#javascript-protocol
+
+    // Let settings be browsingContext's active document's relevant settings object.
+    auto& settings = active_document->relevant_settings_object();
+
+    // Let baseURL be settings's API base URL.
+    auto base_url = settings.api_base_url();
+
+    // Let script be the result of creating a classic script given scriptSource, settings, baseURL, and the default classic script fetch options.
+    // FIXME: This doesn't pass in "default classic script fetch options"
+    // FIXME: What should the filename be here?
+    auto script = Web::HTML::ClassicScript::create("(client connection run_javascript)", js_source, settings, move(base_url));
+
+    // Let evaluationStatus be the result of running the classic script script.
+    auto evaluation_status = script->run();
+
+    if (evaluation_status.is_error())
+        dbgln("Exception :(");
+}
+
+void PageClient::js_console_request_messages(i32 start_index)
+{
+    if (m_top_level_document_console_client)
+        m_top_level_document_console_client->send_messages(start_index);
+}
+
+void PageClient::did_output_js_console_message(i32 message_index)
+{
+    client().async_did_output_js_console_message(m_id, message_index);
+}
+
+void PageClient::console_peer_did_misbehave(char const* reason)
+{
+    client().did_misbehave(reason);
+}
+
+void PageClient::did_get_js_console_messages(i32 start_index, Vector<ByteString> message_types, Vector<ByteString> messages)
+{
+    client().async_did_get_js_console_messages(m_id, start_index, move(message_types), move(messages));
+}
+
 }
 }

+ 25 - 1
Userland/Services/WebContent/PageClient.h

@@ -65,6 +65,17 @@ public:
 
 
     void ready_to_paint();
     void ready_to_paint();
 
 
+    void add_backing_store(i32 front_bitmap_id, Gfx::ShareableBitmap const& front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap const& back_bitmap);
+
+    void initialize_js_console(Web::DOM::Document& document);
+    void destroy_js_console(Web::DOM::Document& document);
+    void js_console_input(ByteString const& js_source);
+    void run_javascript(ByteString const& js_source);
+    void js_console_request_messages(i32 start_index);
+    void did_output_js_console_message(i32 message_index);
+    void console_peer_did_misbehave(char const* reason);
+    void did_get_js_console_messages(i32 start_index, Vector<ByteString> message_types, Vector<ByteString> messages);
+
     virtual double device_pixels_per_css_pixel() const override { return m_device_pixels_per_css_pixel; }
     virtual double device_pixels_per_css_pixel() const override { return m_device_pixels_per_css_pixel; }
 
 
 private:
 private:
@@ -120,7 +131,7 @@ private:
     virtual void page_did_update_resource_count(i32) override;
     virtual void page_did_update_resource_count(i32) override;
     virtual NewWebViewResult page_did_request_new_web_view(Web::HTML::ActivateTab, Web::HTML::WebViewHints, Web::HTML::TokenizedFeature::NoOpener) override;
     virtual NewWebViewResult page_did_request_new_web_view(Web::HTML::ActivateTab, Web::HTML::WebViewHints, Web::HTML::TokenizedFeature::NoOpener) override;
     virtual void page_did_request_activate_tab() override;
     virtual void page_did_request_activate_tab() override;
-    virtual void page_did_close_browsing_context(Web::HTML::BrowsingContext const&) override;
+    virtual void page_did_close_top_level_traversable() override;
     virtual void request_file(Web::FileRequest) override;
     virtual void request_file(Web::FileRequest) override;
     virtual void page_did_request_color_picker(Color current_color) override;
     virtual void page_did_request_color_picker(Color current_color) override;
     virtual void page_did_request_select_dropdown(Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items) override;
     virtual void page_did_request_select_dropdown(Web::CSSPixelPoint content_position, Web::CSSPixels minimum_width, Vector<Web::HTML::SelectItem> items) override;
@@ -167,6 +178,19 @@ private:
 #ifdef HAS_ACCELERATED_GRAPHICS
 #ifdef HAS_ACCELERATED_GRAPHICS
     OwnPtr<AccelGfx::Context> m_accelerated_graphics_context;
     OwnPtr<AccelGfx::Context> m_accelerated_graphics_context;
 #endif
 #endif
+
+    struct BackingStores {
+        i32 front_bitmap_id { -1 };
+        i32 back_bitmap_id { -1 };
+        RefPtr<Gfx::Bitmap> front_bitmap;
+        RefPtr<Gfx::Bitmap> back_bitmap;
+    };
+    BackingStores m_backing_stores;
+
+    HashMap<Web::DOM::Document*, NonnullOwnPtr<WebContentConsoleClient>> m_console_clients;
+    WeakPtr<WebContentConsoleClient> m_top_level_document_console_client;
+
+    JS::Handle<JS::GlobalObject> m_console_global_object;
 };
 };
 
 
 }
 }

+ 5 - 0
Userland/Services/WebContent/PageHost.cpp

@@ -29,6 +29,11 @@ PageClient& PageHost::create_page()
     return *m_pages.get(m_next_id - 1).value();
     return *m_pages.get(m_next_id - 1).value();
 }
 }
 
 
+void PageHost::remove_page(Badge<PageClient>, u64 index)
+{
+    m_pages.remove(index);
+}
+
 PageHost::~PageHost() = default;
 PageHost::~PageHost() = default;
 
 
 }
 }

+ 1 - 0
Userland/Services/WebContent/PageHost.h

@@ -28,6 +28,7 @@ public:
 
 
     PageClient& page(u64 index) { return *m_pages.find(index)->value; }
     PageClient& page(u64 index) { return *m_pages.find(index)->value; }
     PageClient& create_page();
     PageClient& create_page();
+    void remove_page(Badge<PageClient>, u64 index);
 
 
     ConnectionFromClient& client() const { return m_client; }
     ConnectionFromClient& client() const { return m_client; }
 
 

+ 69 - 69
Userland/Services/WebContent/WebContentClient.ipc

@@ -14,81 +14,81 @@
 
 
 endpoint WebContentClient
 endpoint WebContentClient
 {
 {
-    did_start_loading(URL url, bool is_redirect) =|
-    did_finish_loading(URL url) =|
-    did_request_navigate_back() =|
-    did_request_navigate_forward() =|
-    did_request_refresh() =|
-    did_paint(Gfx::IntRect content_rect, i32 bitmap_id) =|
-    did_request_cursor_change(i32 cursor_type) =|
-    did_layout(Gfx::IntSize content_size) =|
-    did_change_title(ByteString title) =|
-    did_request_scroll(i32 x_delta, i32 y_delta) =|
-    did_request_scroll_to(Gfx::IntPoint scroll_position) =|
-    did_enter_tooltip_area(Gfx::IntPoint content_position, ByteString title) =|
-    did_leave_tooltip_area() =|
-    did_hover_link(URL url) =|
-    did_unhover_link() =|
-    did_click_link(URL url, ByteString target, unsigned modifiers) =|
-    did_middle_click_link(URL url, ByteString target, unsigned modifiers) =|
-    did_request_context_menu(Gfx::IntPoint content_position) =|
-    did_request_link_context_menu(Gfx::IntPoint content_position, URL url, ByteString target, unsigned modifiers) =|
-    did_request_image_context_menu(Gfx::IntPoint content_position, URL url, ByteString target, unsigned modifiers, Gfx::ShareableBitmap bitmap) =|
-    did_request_media_context_menu(Gfx::IntPoint content_position, ByteString target, unsigned modifiers, Web::Page::MediaContextMenu menu) =|
-    did_request_alert(String message) =|
-    did_request_confirm(String message) =|
-    did_request_prompt(String message, String default_) =|
-    did_request_set_prompt_text(String message) =|
-    did_request_accept_dialog() =|
-    did_request_dismiss_dialog() =|
-    did_get_source(URL url, ByteString source) =|
+    did_start_loading(u64 page_id, URL url, bool is_redirect) =|
+    did_finish_loading(u64 page_id, URL url) =|
+    did_request_navigate_back(u64 page_id) =|
+    did_request_navigate_forward(u64 page_id) =|
+    did_request_refresh(u64 page_id) =|
+    did_paint(u64 page_id, Gfx::IntRect content_rect, i32 bitmap_id) =|
+    did_request_cursor_change(u64 page_id, i32 cursor_type) =|
+    did_layout(u64 page_id, Gfx::IntSize content_size) =|
+    did_change_title(u64 page_id, ByteString title) =|
+    did_request_scroll(u64 page_id, i32 x_delta, i32 y_delta) =|
+    did_request_scroll_to(u64 page_id, Gfx::IntPoint scroll_position) =|
+    did_enter_tooltip_area(u64 page_id, Gfx::IntPoint content_position, ByteString title) =|
+    did_leave_tooltip_area(u64 page_id) =|
+    did_hover_link(u64 page_id, URL url) =|
+    did_unhover_link(u64 page_id) =|
+    did_click_link(u64 page_id, URL url, ByteString target, unsigned modifiers) =|
+    did_middle_click_link(u64 page_id, URL url, ByteString target, unsigned modifiers) =|
+    did_request_context_menu(u64 page_id, Gfx::IntPoint content_position) =|
+    did_request_link_context_menu(u64 page_id, Gfx::IntPoint content_position, URL url, ByteString target, unsigned modifiers) =|
+    did_request_image_context_menu(u64 page_id, Gfx::IntPoint content_position, URL url, ByteString target, unsigned modifiers, Gfx::ShareableBitmap bitmap) =|
+    did_request_media_context_menu(u64 page_id, Gfx::IntPoint content_position, ByteString target, unsigned modifiers, Web::Page::MediaContextMenu menu) =|
+    did_request_alert(u64 page_id, String message) =|
+    did_request_confirm(u64 page_id, String message) =|
+    did_request_prompt(u64 page_id, String message, String default_) =|
+    did_request_set_prompt_text(u64 page_id, String message) =|
+    did_request_accept_dialog(u64 page_id) =|
+    did_request_dismiss_dialog(u64 page_id) =|
+    did_get_source(u64 page_id, URL url, ByteString source) =|
 
 
-    did_inspect_dom_tree(ByteString dom_tree) =|
-    did_inspect_dom_node(bool has_style, ByteString computed_style,  ByteString resolved_style,  ByteString custom_properties, ByteString node_box_sizing, ByteString aria_properties_state) =|
-    did_inspect_accessibility_tree(ByteString accessibility_tree) =|
-    did_get_hovered_node_id(i32 node_id) =|
-    did_finish_editing_dom_node(Optional<i32> node_id) =|
-    did_get_dom_node_html(String html) =|
+    did_inspect_dom_tree(u64 page_id, ByteString dom_tree) =|
+    did_inspect_dom_node(u64 page_id, bool has_style, ByteString computed_style,  ByteString resolved_style,  ByteString custom_properties, ByteString node_box_sizing, ByteString aria_properties_state) =|
+    did_inspect_accessibility_tree(u64 page_id, ByteString accessibility_tree) =|
+    did_get_hovered_node_id(u64 page_id, i32 node_id) =|
+    did_finish_editing_dom_node(u64 page_id, Optional<i32> node_id) =|
+    did_get_dom_node_html(u64 page_id, String html) =|
 
 
-    did_take_screenshot(Gfx::ShareableBitmap screenshot) =|
+    did_take_screenshot(u64 page_id, Gfx::ShareableBitmap screenshot) =|
 
 
-    did_change_favicon(Gfx::ShareableBitmap favicon) =|
-    did_request_all_cookies(URL url) => (Vector<Web::Cookie::Cookie> cookies)
-    did_request_named_cookie(URL url, String name) => (Optional<Web::Cookie::Cookie> cookie)
-    did_request_cookie(URL url, Web::Cookie::Source source) => (String cookie)
-    did_set_cookie(URL url, Web::Cookie::ParsedCookie cookie, Web::Cookie::Source source) => ()
-    did_update_cookie(Web::Cookie::Cookie cookie) =|
-    did_update_resource_count(i32 count_waiting) =|
-    did_request_new_web_view(Web::HTML::ActivateTab activate_tab, Web::HTML::WebViewHints hints, Optional<u64> page_index) => (String handle)
-    did_request_activate_tab() =|
-    did_close_browsing_context() =|
-    did_request_restore_window() =|
-    did_request_reposition_window(Gfx::IntPoint position) => (Gfx::IntPoint window_position)
-    did_request_resize_window(Gfx::IntSize size) => (Gfx::IntSize window_size)
-    did_request_maximize_window() => (Gfx::IntRect window_rect)
-    did_request_minimize_window() => (Gfx::IntRect window_rect)
-    did_request_fullscreen_window() => (Gfx::IntRect window_rect)
-    did_request_file(ByteString path, i32 request_id) =|
-    did_request_color_picker(Color current_color) =|
-    did_request_select_dropdown(Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> items) =|
-    did_finish_handling_input_event(bool event_was_accepted) =|
-    did_change_theme_color(Gfx::Color color) =|
-    did_insert_clipboard_entry(String data, String presentation_style, String mime_type) =|
+    did_change_favicon(u64 page_id, Gfx::ShareableBitmap favicon) =|
+    did_request_all_cookies(u64 page_id, URL url) => (Vector<Web::Cookie::Cookie> cookies)
+    did_request_named_cookie(u64 page_id, URL url, String name) => (Optional<Web::Cookie::Cookie> cookie)
+    did_request_cookie(u64 page_id, URL url, Web::Cookie::Source source) => (String cookie)
+    did_set_cookie(u64 page_id, URL url, Web::Cookie::ParsedCookie cookie, Web::Cookie::Source source) => ()
+    did_update_cookie(u64 page_id, Web::Cookie::Cookie cookie) =|
+    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<u64> page_index) => (String handle)
+    did_request_activate_tab(u64 page_id) =|
+    did_close_browsing_context(u64 page_id) =|
+    did_request_restore_window(u64 page_id) =|
+    did_request_reposition_window(u64 page_id, Gfx::IntPoint position) => (Gfx::IntPoint window_position)
+    did_request_resize_window(u64 page_id, Gfx::IntSize size) => (Gfx::IntSize window_size)
+    did_request_maximize_window(u64 page_id) => (Gfx::IntRect window_rect)
+    did_request_minimize_window(u64 page_id) => (Gfx::IntRect window_rect)
+    did_request_fullscreen_window(u64 page_id) => (Gfx::IntRect window_rect)
+    did_request_file(u64 page_id, ByteString path, i32 request_id) =|
+    did_request_color_picker(u64 page_id, Color current_color) =|
+    did_request_select_dropdown(u64 page_id, Gfx::IntPoint content_position, i32 minimum_width, Vector<Web::HTML::SelectItem> items) =|
+    did_finish_handling_input_event(u64 page_id, bool event_was_accepted) =|
+    did_change_theme_color(u64 page_id, Gfx::Color color) =|
+    did_insert_clipboard_entry(u64 page_id, String data, String presentation_style, String mime_type) =|
 
 
-    did_output_js_console_message(i32 message_index) =|
-    did_get_js_console_messages(i32 start_index, Vector<ByteString> message_types, Vector<ByteString> messages) =|
+    did_output_js_console_message(u64 page_id, i32 message_index) =|
+    did_get_js_console_messages(u64 page_id, i32 start_index, Vector<ByteString> message_types, Vector<ByteString> messages) =|
 
 
-    did_finish_text_test() =|
+    did_finish_text_test(u64 page_id) =|
 
 
-    request_worker_agent() => (WebView::SocketPair sockets) // FIXME: Add required attributes to select a SharedWorker Agent
+    request_worker_agent(u64 page_id) => (WebView::SocketPair sockets) // FIXME: Add required attributes to select a SharedWorker Agent
 
 
-    inspector_did_load() =|
-    inspector_did_select_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element) =|
-    inspector_did_set_dom_node_text(i32 node_id, String text) =|
-    inspector_did_set_dom_node_tag(i32 node_id, String tag) =|
-    inspector_did_add_dom_node_attributes(i32 node_id, Vector<WebView::Attribute> attributes) =|
-    inspector_did_replace_dom_node_attribute(i32 node_id, String name, Vector<WebView::Attribute> replacement_attributes) =|
-    inspector_did_request_dom_tree_context_menu(i32 node_id, Gfx::IntPoint position, String type, Optional<String> tag, Optional<WebView::Attribute> attribute) =|
-    inspector_did_execute_console_script(String script) =|
+    inspector_did_load(u64 page_id) =|
+    inspector_did_select_dom_node(u64 page_id, i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element) =|
+    inspector_did_set_dom_node_text(u64 page_id, i32 node_id, String text) =|
+    inspector_did_set_dom_node_tag(u64 page_id, i32 node_id, String tag) =|
+    inspector_did_add_dom_node_attributes(u64 page_id, i32 node_id, Vector<WebView::Attribute> attributes) =|
+    inspector_did_replace_dom_node_attribute(u64 page_id, i32 node_id, String name, Vector<WebView::Attribute> replacement_attributes) =|
+    inspector_did_request_dom_tree_context_menu(u64 page_id, i32 node_id, Gfx::IntPoint position, String type, Optional<String> tag, Optional<WebView::Attribute> attribute) =|
+    inspector_did_execute_console_script(u64 page_id, String script) =|
 
 
 }
 }

+ 9 - 8
Userland/Services/WebContent/WebContentConsoleClient.cpp

@@ -6,7 +6,6 @@
  * SPDX-License-Identifier: BSD-2-Clause
  * SPDX-License-Identifier: BSD-2-Clause
  */
  */
 
 
-#include "WebContentConsoleClient.h"
 #include <AK/StringBuilder.h>
 #include <AK/StringBuilder.h>
 #include <AK/TemporaryChange.h>
 #include <AK/TemporaryChange.h>
 #include <LibJS/MarkupGenerator.h>
 #include <LibJS/MarkupGenerator.h>
@@ -20,10 +19,12 @@
 #include <LibWeb/HTML/Scripting/Environments.h>
 #include <LibWeb/HTML/Scripting/Environments.h>
 #include <LibWeb/HTML/Window.h>
 #include <LibWeb/HTML/Window.h>
 #include <WebContent/ConsoleGlobalEnvironmentExtensions.h>
 #include <WebContent/ConsoleGlobalEnvironmentExtensions.h>
+#include <WebContent/PageClient.h>
+#include <WebContent/WebContentConsoleClient.h>
 
 
 namespace WebContent {
 namespace WebContent {
 
 
-WebContentConsoleClient::WebContentConsoleClient(JS::Console& console, JS::Realm& realm, ConnectionFromClient& client)
+WebContentConsoleClient::WebContentConsoleClient(JS::Console& console, JS::Realm& realm, PageClient& client)
     : ConsoleClient(console)
     : ConsoleClient(console)
     , m_client(client)
     , m_client(client)
 {
 {
@@ -58,25 +59,25 @@ void WebContentConsoleClient::report_exception(JS::Error const& exception, bool
 void WebContentConsoleClient::print_html(ByteString const& line)
 void WebContentConsoleClient::print_html(ByteString const& line)
 {
 {
     m_message_log.append({ .type = ConsoleOutput::Type::HTML, .data = line });
     m_message_log.append({ .type = ConsoleOutput::Type::HTML, .data = line });
-    m_client.async_did_output_js_console_message(m_message_log.size() - 1);
+    m_client.did_output_js_console_message(m_message_log.size() - 1);
 }
 }
 
 
 void WebContentConsoleClient::clear_output()
 void WebContentConsoleClient::clear_output()
 {
 {
     m_message_log.append({ .type = ConsoleOutput::Type::Clear, .data = "" });
     m_message_log.append({ .type = ConsoleOutput::Type::Clear, .data = "" });
-    m_client.async_did_output_js_console_message(m_message_log.size() - 1);
+    m_client.did_output_js_console_message(m_message_log.size() - 1);
 }
 }
 
 
 void WebContentConsoleClient::begin_group(ByteString const& label, bool start_expanded)
 void WebContentConsoleClient::begin_group(ByteString const& label, bool start_expanded)
 {
 {
     m_message_log.append({ .type = start_expanded ? ConsoleOutput::Type::BeginGroup : ConsoleOutput::Type::BeginGroupCollapsed, .data = label });
     m_message_log.append({ .type = start_expanded ? ConsoleOutput::Type::BeginGroup : ConsoleOutput::Type::BeginGroupCollapsed, .data = label });
-    m_client.async_did_output_js_console_message(m_message_log.size() - 1);
+    m_client.did_output_js_console_message(m_message_log.size() - 1);
 }
 }
 
 
 void WebContentConsoleClient::end_group()
 void WebContentConsoleClient::end_group()
 {
 {
     m_message_log.append({ .type = ConsoleOutput::Type::EndGroup, .data = "" });
     m_message_log.append({ .type = ConsoleOutput::Type::EndGroup, .data = "" });
-    m_client.async_did_output_js_console_message(m_message_log.size() - 1);
+    m_client.did_output_js_console_message(m_message_log.size() - 1);
 }
 }
 
 
 void WebContentConsoleClient::send_messages(i32 start_index)
 void WebContentConsoleClient::send_messages(i32 start_index)
@@ -88,7 +89,7 @@ void WebContentConsoleClient::send_messages(i32 start_index)
         // then, by requesting with start_index=0. If we don't have any messages at all, that
         // then, by requesting with start_index=0. If we don't have any messages at all, that
         // is still a valid request, and we can just ignore it.
         // is still a valid request, and we can just ignore it.
         if (start_index != 0)
         if (start_index != 0)
-            m_client.did_misbehave("Requested non-existent console message index.");
+            m_client.console_peer_did_misbehave("Requested non-existent console message index.");
         return;
         return;
     }
     }
 
 
@@ -121,7 +122,7 @@ void WebContentConsoleClient::send_messages(i32 start_index)
         messages.append(message.data);
         messages.append(message.data);
     }
     }
 
 
-    m_client.async_did_get_js_console_messages(start_index, message_types, messages);
+    m_client.did_get_js_console_messages(start_index, message_types, messages);
 }
 }
 
 
 void WebContentConsoleClient::clear()
 void WebContentConsoleClient::clear()

+ 5 - 3
Userland/Services/WebContent/WebContentConsoleClient.h

@@ -8,10 +8,12 @@
 
 
 #pragma once
 #pragma once
 
 
-#include "ConnectionFromClient.h"
+#include <AK/Vector.h>
+#include <AK/Weakable.h>
 #include <LibJS/Console.h>
 #include <LibJS/Console.h>
 #include <LibJS/Forward.h>
 #include <LibJS/Forward.h>
 #include <LibWeb/Forward.h>
 #include <LibWeb/Forward.h>
+#include <WebContent/ConsoleGlobalEnvironmentExtensions.h>
 #include <WebContent/Forward.h>
 #include <WebContent/Forward.h>
 
 
 namespace WebContent {
 namespace WebContent {
@@ -19,7 +21,7 @@ namespace WebContent {
 class WebContentConsoleClient final : public JS::ConsoleClient
 class WebContentConsoleClient final : public JS::ConsoleClient
     , public Weakable<WebContentConsoleClient> {
     , public Weakable<WebContentConsoleClient> {
 public:
 public:
-    WebContentConsoleClient(JS::Console&, JS::Realm&, ConnectionFromClient&);
+    WebContentConsoleClient(JS::Console&, JS::Realm&, PageClient&);
 
 
     void handle_input(ByteString const& js_source);
     void handle_input(ByteString const& js_source);
     void send_messages(i32 start_index);
     void send_messages(i32 start_index);
@@ -35,7 +37,7 @@ private:
         m_current_message_style.append(';');
         m_current_message_style.append(';');
     }
     }
 
 
-    ConnectionFromClient& m_client;
+    PageClient& m_client;
     JS::Handle<ConsoleGlobalEnvironmentExtensions> m_console_global_environment_extensions;
     JS::Handle<ConsoleGlobalEnvironmentExtensions> m_console_global_environment_extensions;
 
 
     void clear_output();
     void clear_output();

+ 69 - 69
Userland/Services/WebContent/WebContentServer.ipc

@@ -11,96 +11,96 @@
 
 
 endpoint WebContentServer
 endpoint WebContentServer
 {
 {
-    get_window_handle() => (String handle)
-    set_window_handle(String handle) =|
+    get_window_handle(u64 page_id) => (String handle)
+    set_window_handle(u64 page_id, String handle) =|
 
 
-    connect_to_webdriver(ByteString webdriver_ipc_path) =|
+    connect_to_webdriver(u64 page_id, ByteString webdriver_ipc_path) =|
 
 
-    update_system_theme(Core::AnonymousBuffer theme_buffer) =|
-    update_system_fonts(ByteString default_font_query, ByteString fixed_width_font_query, ByteString window_title_font_query) =|
-    update_screen_rects(Vector<Web::DevicePixelRect> rects, u32 main_screen_index) =|
+    update_system_theme(u64 page_id, Core::AnonymousBuffer theme_buffer) =|
+    update_system_fonts(u64 page_id, ByteString default_font_query, ByteString fixed_width_font_query, ByteString window_title_font_query) =|
+    update_screen_rects(u64 page_id, Vector<Web::DevicePixelRect> rects, u32 main_screen_index) =|
 
 
-    load_url(URL url) =|
-    load_html(ByteString html) =|
+    load_url(u64 page_id, URL url) =|
+    load_html(u64 page_id, ByteString html) =|
 
 
-    add_backing_store(i32 front_bitmap_id, Gfx::ShareableBitmap front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap back_bitmap) =|
-    ready_to_paint() =|
+    add_backing_store(u64 page_id, i32 front_bitmap_id, Gfx::ShareableBitmap front_bitmap, i32 back_bitmap_id, Gfx::ShareableBitmap back_bitmap) =|
+    ready_to_paint(u64 page_id) =|
 
 
-    set_viewport_rect(Web::DevicePixelRect rect) =|
+    set_viewport_rect(u64 page_id, Web::DevicePixelRect rect) =|
 
 
-    mouse_down(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers) =|
-    mouse_move(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers) =|
-    mouse_up(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers) =|
-    mouse_wheel(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, Web::DevicePixels wheel_delta_x, Web::DevicePixels wheel_delta_y) =|
-    doubleclick(Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers) =|
+    mouse_down(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers) =|
+    mouse_move(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers) =|
+    mouse_up(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers) =|
+    mouse_wheel(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers, Web::DevicePixels wheel_delta_x, Web::DevicePixels wheel_delta_y) =|
+    doubleclick(u64 page_id, Web::DevicePixelPoint position, Web::DevicePixelPoint screen_position, u32 button, u32 buttons, u32 modifiers) =|
 
 
-    key_down(i32 key, u32 modifiers, u32 code_point) =|
-    key_up(i32 key, u32 modifiers, u32 code_point) =|
+    key_down(u64 page_id, i32 key, u32 modifiers, u32 code_point) =|
+    key_up(u64 page_id, i32 key, u32 modifiers, u32 code_point) =|
 
 
-    debug_request(ByteString request, ByteString argument) =|
-    get_source() =|
-    inspect_dom_tree() =|
-    inspect_dom_node(i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element) =|
-    inspect_accessibility_tree() =|
-    get_hovered_node_id() =|
-    js_console_input(ByteString js_source) =|
-    js_console_request_messages(i32 start_index) =|
+    debug_request(u64 page_id, ByteString request, ByteString argument) =|
+    get_source(u64 page_id) =|
+    inspect_dom_tree(u64 page_id) =|
+    inspect_dom_node(u64 page_id, i32 node_id, Optional<Web::CSS::Selector::PseudoElement::Type> pseudo_element) =|
+    inspect_accessibility_tree(u64 page_id) =|
+    get_hovered_node_id(u64 page_id) =|
+    js_console_input(u64 page_id, ByteString js_source) =|
+    js_console_request_messages(u64 page_id, i32 start_index) =|
 
 
-    set_dom_node_text(i32 node_id, String text) =|
-    set_dom_node_tag(i32 node_id, String name) =|
-    add_dom_node_attributes(i32 node_id, Vector<WebView::Attribute> attributes) =|
-    replace_dom_node_attribute(i32 node_id, String name, Vector<WebView::Attribute> replacement_attributes) =|
-    create_child_element(i32 node_id) =|
-    create_child_text_node(i32 node_id) =|
-    clone_dom_node(i32 node_id) =|
-    remove_dom_node(i32 node_id) =|
-    get_dom_node_html(i32 node_id) =|
+    set_dom_node_text(u64 page_id, i32 node_id, String text) =|
+    set_dom_node_tag(u64 page_id, i32 node_id, String name) =|
+    add_dom_node_attributes(u64 page_id, i32 node_id, Vector<WebView::Attribute> attributes) =|
+    replace_dom_node_attribute(u64 page_id, i32 node_id, String name, Vector<WebView::Attribute> replacement_attributes) =|
+    create_child_element(u64 page_id, i32 node_id) =|
+    create_child_text_node(u64 page_id, i32 node_id) =|
+    clone_dom_node(u64 page_id, i32 node_id) =|
+    remove_dom_node(u64 page_id, i32 node_id) =|
+    get_dom_node_html(u64 page_id, i32 node_id) =|
 
 
-    take_document_screenshot() =|
-    take_dom_node_screenshot(i32 node_id) =|
+    take_document_screenshot(u64 page_id) =|
+    take_dom_node_screenshot(u64 page_id, i32 node_id) =|
 
 
-    dump_gc_graph() => (String json)
+    dump_gc_graph(u64 page_id) => (String json)
 
 
-    run_javascript(ByteString js_source) =|
+    run_javascript(u64 page_id, ByteString js_source) =|
 
 
-    dump_layout_tree() => (ByteString dump)
-    dump_paint_tree() => (ByteString dump)
-    dump_text() => (ByteString dump)
+    dump_layout_tree(u64 page_id) => (ByteString dump)
+    dump_paint_tree(u64 page_id) => (ByteString dump)
+    dump_text(u64 page_id) => (ByteString dump)
 
 
-    get_selected_text() => (ByteString selection)
-    select_all() =|
+    get_selected_text(u64 page_id) => (ByteString selection)
+    select_all(u64 page_id) =|
 
 
-    set_content_filters(Vector<String> filters) =|
-    set_autoplay_allowed_on_all_websites() =|
-    set_autoplay_allowlist(Vector<String> allowlist) =|
-    set_proxy_mappings(Vector<ByteString> proxies, HashMap<ByteString,size_t> mappings) =|
-    set_preferred_color_scheme(Web::CSS::PreferredColorScheme color_scheme) =|
-    set_has_focus(bool has_focus) =|
-    set_is_scripting_enabled(bool is_scripting_enabled) =|
-    set_device_pixels_per_css_pixel(float device_pixels_per_css_pixel) =|
+    set_content_filters(u64 page_id, Vector<String> filters) =|
+    set_autoplay_allowed_on_all_websites(u64 page_id) =|
+    set_autoplay_allowlist(u64 page_id, Vector<String> allowlist) =|
+    set_proxy_mappings(u64 page_id, Vector<ByteString> proxies, HashMap<ByteString,size_t> mappings) =|
+    set_preferred_color_scheme(u64 page_id, Web::CSS::PreferredColorScheme color_scheme) =|
+    set_has_focus(u64 page_id, bool has_focus) =|
+    set_is_scripting_enabled(u64 page_id, bool is_scripting_enabled) =|
+    set_device_pixels_per_css_pixel(u64 page_id, float device_pixels_per_css_pixel) =|
 
 
-    set_window_position(Web::DevicePixelPoint position) =|
-    set_window_size(Web::DevicePixelSize size) =|
+    set_window_position(u64 page_id, Web::DevicePixelPoint position) =|
+    set_window_size(u64 page_id, Web::DevicePixelSize size) =|
 
 
-    get_local_storage_entries() => (OrderedHashMap<String,String> entries)
-    get_session_storage_entries() => (OrderedHashMap<String,String> entries)
+    get_local_storage_entries(u64 page_id) => (OrderedHashMap<String,String> entries)
+    get_session_storage_entries(u64 page_id) => (OrderedHashMap<String,String> entries)
 
 
-    handle_file_return(i32 error, Optional<IPC::File> file, i32 request_id) =|
+    handle_file_return(u64 page_id, i32 error, Optional<IPC::File> file, i32 request_id) =|
 
 
-    set_system_visibility_state(bool visible) =|
+    set_system_visibility_state(u64 page_id, bool visible) =|
 
 
-    alert_closed() =|
-    confirm_closed(bool accepted) =|
-    prompt_closed(Optional<String> response) =|
-    color_picker_update(Optional<Color> picked_color, Web::HTML::ColorPickerUpdateState state) =|
-    select_dropdown_closed(Optional<String> value) =|
+    alert_closed(u64 page_id) =|
+    confirm_closed(u64 page_id, bool accepted) =|
+    prompt_closed(u64 page_id, Optional<String> response) =|
+    color_picker_update(u64 page_id, Optional<Color> picked_color, Web::HTML::ColorPickerUpdateState state) =|
+    select_dropdown_closed(u64 page_id, Optional<String> value) =|
 
 
-    toggle_media_play_state() =|
-    toggle_media_mute_state() =|
-    toggle_media_loop_state() =|
-    toggle_media_controls_state() =|
+    toggle_media_play_state(u64 page_id) =|
+    toggle_media_mute_state(u64 page_id) =|
+    toggle_media_loop_state(u64 page_id) =|
+    toggle_media_controls_state(u64 page_id) =|
 
 
-    set_user_style(String source) =|
+    set_user_style(u64 page_id, String source) =|
 
 
-    enable_inspector_prototype() =|
+    enable_inspector_prototype(u64 page_id) =|
 }
 }

+ 11 - 11
Userland/Utilities/headless-browser.cpp

@@ -90,15 +90,15 @@ public:
         view->m_client_state.client = TRY(launch_web_content_process(*view, candidate_web_content_paths, web_content_options));
         view->m_client_state.client = TRY(launch_web_content_process(*view, candidate_web_content_paths, web_content_options));
 #endif
 #endif
 
 
-        view->client().async_update_system_theme(move(theme));
-        view->client().async_update_system_fonts(Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query(), Gfx::FontDatabase::window_title_font_query());
+        view->client().async_update_system_theme(0, move(theme));
+        view->client().async_update_system_fonts(0, Gfx::FontDatabase::default_font_query(), Gfx::FontDatabase::fixed_width_font_query(), Gfx::FontDatabase::window_title_font_query());
 
 
         view->m_viewport_rect = { { 0, 0 }, window_size };
         view->m_viewport_rect = { { 0, 0 }, window_size };
-        view->client().async_set_viewport_rect(view->m_viewport_rect.to_type<Web::DevicePixels>());
-        view->client().async_set_window_size(window_size.to_type<Web::DevicePixels>());
+        view->client().async_set_viewport_rect(0, view->m_viewport_rect.to_type<Web::DevicePixels>());
+        view->client().async_set_window_size(0, window_size.to_type<Web::DevicePixels>());
 
 
         if (!web_driver_ipc_path.is_empty())
         if (!web_driver_ipc_path.is_empty())
-            view->client().async_connect_to_webdriver(web_driver_ipc_path);
+            view->client().async_connect_to_webdriver(0, web_driver_ipc_path);
 
 
         view->m_client_state.client->on_web_content_process_crash = [] {
         view->m_client_state.client->on_web_content_process_crash = [] {
             warnln("\033[31;1mWebContent Crashed!!\033[0m");
             warnln("\033[31;1mWebContent Crashed!!\033[0m");
@@ -116,7 +116,7 @@ public:
         VERIFY(!m_pending_screenshot);
         VERIFY(!m_pending_screenshot);
 
 
         m_pending_screenshot = Core::Promise<RefPtr<Gfx::Bitmap>>::construct();
         m_pending_screenshot = Core::Promise<RefPtr<Gfx::Bitmap>>::construct();
-        client().async_take_document_screenshot();
+        client().async_take_document_screenshot(0);
 
 
         auto screenshot = MUST(m_pending_screenshot->await());
         auto screenshot = MUST(m_pending_screenshot->await());
         m_pending_screenshot = nullptr;
         m_pending_screenshot = nullptr;
@@ -132,22 +132,22 @@ public:
 
 
     ErrorOr<String> dump_layout_tree()
     ErrorOr<String> dump_layout_tree()
     {
     {
-        return String::from_byte_string(client().dump_layout_tree());
+        return String::from_byte_string(client().dump_layout_tree(0));
     }
     }
 
 
     ErrorOr<String> dump_paint_tree()
     ErrorOr<String> dump_paint_tree()
     {
     {
-        return String::from_byte_string(client().dump_paint_tree());
+        return String::from_byte_string(client().dump_paint_tree(0));
     }
     }
 
 
     ErrorOr<String> dump_text()
     ErrorOr<String> dump_text()
     {
     {
-        return String::from_byte_string(client().dump_text());
+        return String::from_byte_string(client().dump_text(0));
     }
     }
 
 
     void clear_content_filters()
     void clear_content_filters()
     {
     {
-        client().async_set_content_filters({});
+        client().async_set_content_filters(0, {});
     }
     }
 
 
 private:
 private:
@@ -157,7 +157,7 @@ private:
     {
     {
         on_scroll_to_point = [this](auto position) {
         on_scroll_to_point = [this](auto position) {
             m_viewport_rect.set_location(position);
             m_viewport_rect.set_location(position);
-            client().async_set_viewport_rect(m_viewport_rect.to_type<Web::DevicePixels>());
+            client().async_set_viewport_rect(0, m_viewport_rect.to_type<Web::DevicePixels>());
         };
         };
 
 
         on_scroll_by_delta = [this](auto x_delta, auto y_delta) {
         on_scroll_by_delta = [this](auto x_delta, auto y_delta) {