From 6a7c5c176a3a73c1395a92928a20244e68502056 Mon Sep 17 00:00:00 2001 From: Patrick Griffis Date: Tue, 2 Apr 2024 17:41:01 -0700 Subject: [PATCH] [GTK] Implement WebAutomationSession::platformGetBase64EncodedPNGData on GTK4 and Skia https://bugs.webkit.org/show_bug.cgi?id=271985 Reviewed by Adrian Perez de Castro. For the variant of platformGetBase64EncodedPNGData that takes a ShareableBitmap this adds a Skia implementation. For the variant that takes a ViewSnapshot a GTK4 implementation was added. * Source/WebKit/PlatformWPE.cmake: * Source/WebKit/SourcesGTK.txt: * Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp: * Source/WebKit/UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp: (WebKit::WebAutomationSession::platformGetBase64EncodedPNGData): * Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp: (WebKit::base64EncodedPNGData): (WebKit::WebAutomationSession::platformGetBase64EncodedPNGData): * Source/WebKit/UIProcess/Automation/skia/WebAutomationSessionSkia.cpp: Copied from Source/WebKit/UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp. (WebKit::base64EncodedPNGData): (WebKit::WebAutomationSession::platformGetBase64EncodedPNGData): Canonical link: https://commits.webkit.org/276982@main --- Source/WebKit/SourcesGTK.txt | 4 +- Source/WebKit/SourcesWPE.txt | 1 + .../Automation/WebAutomationSession.cpp | 4 +- .../cairo/WebAutomationSessionCairo.cpp | 10 +-- .../gtk/WebAutomationSessionGtk.cpp | 43 +++++++++++ .../skia/WebAutomationSessionSkia.cpp | 72 +++++++++++++++++++ 6 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 Source/WebKit/UIProcess/Automation/skia/WebAutomationSessionSkia.cpp diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt index 1c85e0e031ee..71c916278d7e 100644 --- a/Source/WebKit/SourcesGTK.txt +++ b/Source/WebKit/SourcesGTK.txt @@ -229,8 +229,8 @@ UIProcess/API/gtk/WebKitWebViewGtk4.cpp @no-unify UIProcess/API/soup/HTTPCookieStoreSoup.cpp UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp - -UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp +UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp @no-unify +UIProcess/Automation/skia/WebAutomationSessionSkia.cpp UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt index 7ec9045f8db4..871b16039677 100644 --- a/Source/WebKit/SourcesWPE.txt +++ b/Source/WebKit/SourcesWPE.txt @@ -217,6 +217,7 @@ UIProcess/API/wpe/WebKitWebViewWPE.cpp @no-unify UIProcess/API/wpe/WPEWebView.cpp @no-unify UIProcess/Automation/libwpe/WebAutomationSessionLibWPE.cpp +UIProcess/Automation/skia/WebAutomationSessionSkia.cpp UIProcess/CoordinatedGraphics/DrawingAreaProxyCoordinatedGraphics.cpp diff --git a/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp b/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp index 1ff6fc6fd5fe..3619d8e49549 100644 --- a/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp +++ b/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp @@ -2456,7 +2456,7 @@ void WebAutomationSession::didTakeScreenshot(uint64_t callbackID, std::optional< callback->sendSuccess(base64EncodedData.value()); } -#if !PLATFORM(COCOA) && !USE(CAIRO) +#if !PLATFORM(COCOA) && !USE(CAIRO) && !USE(SKIA) std::optional WebAutomationSession::platformGetBase64EncodedPNGData(ShareableBitmap::Handle&&) { return std::nullopt; @@ -2466,7 +2466,7 @@ std::optional WebAutomationSession::platformGetBase64EncodedPNGData(cons { return std::nullopt; } -#endif // !PLATFORM(COCOA) && !USE(CAIRO) +#endif // !PLATFORM(COCOA) && !USE(CAIRO) && !USE(SKIA) #if !PLATFORM(COCOA) std::optional WebAutomationSession::platformGenerateLocalFilePathForRemoteFile(const String&, const String&) diff --git a/Source/WebKit/UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp b/Source/WebKit/UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp index 38995bd43016..cb9240d1a3f7 100644 --- a/Source/WebKit/UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp +++ b/Source/WebKit/UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp @@ -29,6 +29,7 @@ #if USE(CAIRO) #include "ViewSnapshotStore.h" +#include #include #include #include @@ -64,14 +65,13 @@ std::optional WebAutomationSession::platformGetBase64EncodedPNGData(Shar return base64EncodedPNGData(surface.get()); } -std::optional WebAutomationSession::platformGetBase64EncodedPNGData(const ViewSnapshot& snapshot) +#if !PLATFORM(GTK) +std::optional WebAutomationSession::platformGetBase64EncodedPNGData(const ViewSnapshot&) { -#if PLATFORM(GTK) && !USE(GTK4) - return base64EncodedPNGData(snapshot.surface()); -#else + notImplemented(); return std::nullopt; -#endif } +#endif } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp b/Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp index 64874f2afbfd..1f2bf07979a4 100644 --- a/Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp +++ b/Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp @@ -26,12 +26,14 @@ #include "config.h" #include "WebAutomationSession.h" +#include "ViewSnapshotStore.h" #include "WebAutomationSessionMacros.h" #include "WebKitWebViewBaseInternal.h" #include "WebPageProxy.h" #include #include #include +#include namespace WebKit { using namespace WebCore; @@ -336,4 +338,45 @@ void WebAutomationSession::platformSimulateWheelInteraction(WebPageProxy& page, } #endif // ENABLE(WEBDRIVER_WHEEL_INTERACTIONS) +#if USE(GTK4) +static std::optional base64EncodedPNGData(GdkTexture* texture) +{ + if (!texture) + return std::nullopt; + + GRefPtr pngBytes = adoptGRef(gdk_texture_save_to_png_bytes(texture)); + size_t pngSize; + auto* pngData = static_cast(g_bytes_get_data(pngBytes.get(), &pngSize)); + + return base64EncodeToString(std::span(pngData, pngSize)); +} +#else +static std::optional base64EncodedPNGData(cairo_surface_t* surface) +{ + if (!surface) + return std::nullopt; + + Vector pngData; + cairo_surface_write_to_png_stream(surface, [](void* userData, const unsigned char* data, unsigned length) -> cairo_status_t { + auto* pngData = static_cast*>(userData); + pngData->append(std::span { data, length }); + return CAIRO_STATUS_SUCCESS; + }, &pngData); + + if (pngData.isEmpty()) + return std::nullopt; + + return base64EncodeToString(pngData); +} +#endif // USE(GTK4) + +std::optional WebAutomationSession::platformGetBase64EncodedPNGData(const ViewSnapshot& snapshot) +{ +#if USE(GTK4) + return base64EncodedPNGData(snapshot.texture()); +#else + return base64EncodedPNGData(snapshot.surface()); +#endif +} + } // namespace WebKit diff --git a/Source/WebKit/UIProcess/Automation/skia/WebAutomationSessionSkia.cpp b/Source/WebKit/UIProcess/Automation/skia/WebAutomationSessionSkia.cpp new file mode 100644 index 000000000000..22ad53fd68dc --- /dev/null +++ b/Source/WebKit/UIProcess/Automation/skia/WebAutomationSessionSkia.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2024 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebAutomationSession.h" + +#if USE(SKIA) + +#include "ViewSnapshotStore.h" +#include +#include +IGNORE_CLANG_WARNINGS_BEGIN("cast-align") +#include +IGNORE_CLANG_WARNINGS_END +#include +#include + +namespace WebKit { +using namespace WebCore; + +static std::optional base64EncodedPNGData(SkImage& image) +{ + auto data = SkPngEncoder::Encode(nullptr, &image, { }); + if (!data) + return std::nullopt; + + return base64EncodeToString(std::span(data->bytes(), data->size())); +} + +std::optional WebAutomationSession::platformGetBase64EncodedPNGData(ShareableBitmap::Handle&& handle) +{ + auto bitmap = ShareableBitmap::create(WTFMove(handle), SharedMemory::Protection::ReadOnly); + if (!bitmap) + return std::nullopt; + + auto image = bitmap->createPlatformImage(); + return base64EncodedPNGData(*image.get()); +} + +#if !PLATFORM(GTK) +std::optional WebAutomationSession::platformGetBase64EncodedPNGData(const ViewSnapshot&) +{ + notImplemented(); + return std::nullopt; +} +#endif + +} // namespace WebKit + +#endif // USE(SKIA)