Browse Source

LibWebView+WebContent: Add a WebContent IPC to take DOM node screenshots

Timothy Flynn 1 year ago
parent
commit
f7de1369d2

+ 23 - 9
Userland/Libraries/LibWebView/ViewImplementation.cpp

@@ -374,6 +374,22 @@ void ViewImplementation::handle_web_content_process_crash()
     load_html(builder.to_deprecated_string());
     load_html(builder.to_deprecated_string());
 }
 }
 
 
+static ErrorOr<void> save_screenshot(Gfx::ShareableBitmap const& bitmap)
+{
+    if (!bitmap.is_valid())
+        return Error::from_string_view("Failed to take a screenshot"sv);
+
+    LexicalPath path { Core::StandardPaths::downloads_directory() };
+    path = path.append(TRY(Core::DateTime::now().to_string("screenshot-%Y-%m-%d-%H-%M-%S.png"sv)));
+
+    auto encoded = TRY(Gfx::PNGWriter::encode(*bitmap.bitmap()));
+
+    auto screenshot_file = TRY(Core::File::open(path.string(), Core::File::OpenMode::Write));
+    TRY(screenshot_file->write_until_depleted(encoded));
+
+    return {};
+}
+
 ErrorOr<void> ViewImplementation::take_screenshot(ScreenshotType type)
 ErrorOr<void> ViewImplementation::take_screenshot(ScreenshotType type)
 {
 {
     Gfx::ShareableBitmap bitmap;
     Gfx::ShareableBitmap bitmap;
@@ -388,16 +404,14 @@ ErrorOr<void> ViewImplementation::take_screenshot(ScreenshotType type)
         break;
         break;
     }
     }
 
 
-    if (!bitmap.is_valid())
-        return Error::from_string_view("Failed to take a screenshot of the current tab"sv);
-
-    LexicalPath path { Core::StandardPaths::downloads_directory() };
-    path = path.append(TRY(Core::DateTime::now().to_string("screenshot-%Y-%m-%d-%H-%M-%S.png"sv)));
-
-    auto encoded = TRY(Gfx::PNGWriter::encode(*bitmap.bitmap()));
+    TRY(save_screenshot(bitmap));
+    return {};
+}
 
 
-    auto screenshot_file = TRY(Core::File::open(path.string(), Core::File::OpenMode::Write));
-    TRY(screenshot_file->write_until_depleted(encoded));
+ErrorOr<void> ViewImplementation::take_dom_node_screenshot(i32 node_id)
+{
+    auto bitmap = client().take_dom_node_screenshot(node_id);
+    TRY(save_screenshot(bitmap));
 
 
     return {};
     return {};
 }
 }

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

@@ -91,6 +91,7 @@ public:
         Full,
         Full,
     };
     };
     ErrorOr<void> take_screenshot(ScreenshotType);
     ErrorOr<void> take_screenshot(ScreenshotType);
+    ErrorOr<void> take_dom_node_screenshot(i32);
 
 
     void set_user_style_sheet(String source);
     void set_user_style_sheet(String source);
     // Load Native.css as the User style sheet, which attempts to make WebView content look as close to
     // Load Native.css as the User style sheet, which attempts to make WebView content look as close to

+ 14 - 0
Userland/Services/WebContent/ConnectionFromClient.cpp

@@ -825,6 +825,20 @@ Messages::WebContentServer::TakeDocumentScreenshotResponse ConnectionFromClient:
     return { bitmap->to_shareable_bitmap() };
     return { bitmap->to_shareable_bitmap() };
 }
 }
 
 
+Messages::WebContentServer::TakeDomNodeScreenshotResponse ConnectionFromClient::take_dom_node_screenshot(i32 node_id)
+{
+    auto* dom_node = Web::DOM::Node::from_unique_id(node_id);
+    if (!dom_node || !dom_node->paintable_box())
+        return { {} };
+
+    auto rect = page().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();
+    page().paint(rect, *bitmap, { .paint_overlay = Web::PaintOptions::PaintOverlay::No });
+
+    return { bitmap->to_shareable_bitmap() };
+}
+
 Messages::WebContentServer::GetSelectedTextResponse ConnectionFromClient::get_selected_text()
 Messages::WebContentServer::GetSelectedTextResponse ConnectionFromClient::get_selected_text()
 {
 {
     return page().page().focused_context().selected_text();
     return page().page().focused_context().selected_text();

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

@@ -118,6 +118,7 @@ private:
     virtual void enable_inspector_prototype() override;
     virtual void enable_inspector_prototype() override;
 
 
     virtual Messages::WebContentServer::TakeDocumentScreenshotResponse take_document_screenshot() override;
     virtual Messages::WebContentServer::TakeDocumentScreenshotResponse take_document_screenshot() override;
+    virtual Messages::WebContentServer::TakeDomNodeScreenshotResponse take_dom_node_screenshot(i32 node_id) override;
 
 
     virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override;
     virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override;
     virtual Messages::WebContentServer::GetSessionStorageEntriesResponse get_session_storage_entries() override;
     virtual Messages::WebContentServer::GetSessionStorageEntriesResponse get_session_storage_entries() override;

+ 1 - 0
Userland/Services/WebContent/WebContentServer.ipc

@@ -54,6 +54,7 @@ endpoint WebContentServer
     get_dom_node_html(i32 node_id) => (Optional<String> html)
     get_dom_node_html(i32 node_id) => (Optional<String> html)
 
 
     take_document_screenshot() => (Gfx::ShareableBitmap data)
     take_document_screenshot() => (Gfx::ShareableBitmap data)
+    take_dom_node_screenshot(i32 node_id) => (Gfx::ShareableBitmap data)
 
 
     run_javascript(DeprecatedString js_source) =|
     run_javascript(DeprecatedString js_source) =|