Bug 1695381 - Refactor GTK icon processing in preparation for remoting. r=tnikkel

Differential Revision: https://phabricator.services.mozilla.com/D118595
This commit is contained in:
Jed Davis 2021-06-26 01:15:00 +00:00
Родитель 552c921cc3
Коммит 7011e9f0bc
2 изменённых файлов: 57 добавлений и 17 удалений

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/NullPrincipal.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/gfx/Swizzle.h"
#include "mozilla/ipc/ByteBuf.h"
#include <algorithm>
#include <gio/gio.h>
@ -33,11 +34,11 @@
#include "gfxPlatform.h"
using mozilla::CheckedInt32;
using mozilla::ipc::ByteBuf;
NS_IMPL_ISUPPORTS(nsIconChannel, nsIRequest, nsIChannel)
static nsresult moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI* aURI,
nsIChannel** aChannel) {
static nsresult MozGdkPixbufToByteBuf(GdkPixbuf* aPixbuf, ByteBuf* aByteBuf) {
int width = gdk_pixbuf_get_width(aPixbuf);
int height = gdk_pixbuf_get_height(aPixbuf);
NS_ENSURE_TRUE(height < 256 && width < 256 && height > 0 && width > 0 &&
@ -73,31 +74,43 @@ static nsresult moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI* aURI,
outstride, mozilla::gfx::SurfaceFormat::OS_RGBA,
mozilla::gfx::IntSize(width, height));
*aByteBuf = ByteBuf(buf, buf_size.value(), buf_size.value());
return NS_OK;
}
static nsresult ByteBufToStream(ByteBuf&& aBuf, nsIInputStream** aStream) {
nsresult rv;
nsCOMPtr<nsIStringInputStream> stream =
do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
// Prevent the leaking of buf
if (NS_WARN_IF(NS_FAILED(rv))) {
free(buf);
return rv;
}
// stream takes ownership of buf and will free it on destruction.
// This function cannot fail.
rv = stream->AdoptData((char*)buf, buf_size.value());
rv = stream->AdoptData(reinterpret_cast<char*>(aBuf.mData), aBuf.mLen);
MOZ_ASSERT(CheckedInt32(aBuf.mLen).isValid(),
"aBuf.mLen should fit in int32_t");
aBuf.mData = nullptr;
// If this no longer holds then re-examine buf's lifetime.
MOZ_ASSERT(NS_SUCCEEDED(rv));
NS_ENSURE_SUCCESS(rv, rv);
stream.forget(aStream);
return NS_OK;
}
static nsresult StreamToChannel(already_AddRefed<nsIInputStream> aStream,
nsIURI* aURI, nsIChannel** aChannel) {
// nsIconProtocolHandler::NewChannel will provide the correct loadInfo for
// this iconChannel. Use the most restrictive security settings for the
// temporary loadInfo to make sure the channel can not be opened.
nsCOMPtr<nsIPrincipal> nullPrincipal =
mozilla::NullPrincipal::CreateWithoutOriginAttributes();
return NS_NewInputStreamChannel(
aChannel, aURI, stream.forget(), nullPrincipal,
aChannel, aURI, std::move(aStream), nullPrincipal,
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
nsIContentPolicy::TYPE_INTERNAL_IMAGE, nsLiteralCString(IMAGE_ICON_MS));
}
@ -182,7 +195,9 @@ static nsresult ScaleIconBuf(GdkPixbuf** aBuf, int32_t iconSize) {
return NS_OK;
}
nsresult nsIconChannel::InitWithGIO(nsIMozIconURI* aIconURI) {
/* static */
nsresult nsIconChannel::GetIconWithGIO(nsIMozIconURI* aIconURI,
ByteBuf* aDataOut) {
GIcon* icon = nullptr;
nsCOMPtr<nsIURL> fileURI;
@ -265,12 +280,13 @@ nsresult nsIconChannel::InitWithGIO(nsIMozIconURI* aIconURI) {
nsresult rv = ScaleIconBuf(&buf, iconSize);
NS_ENSURE_SUCCESS(rv, rv);
rv = moz_gdk_pixbuf_to_channel(buf, aIconURI, getter_AddRefs(mRealChannel));
rv = MozGdkPixbufToByteBuf(buf, aDataOut);
g_object_unref(buf);
return rv;
}
nsresult nsIconChannel::Init(nsIURI* aURI) {
/* static */
nsresult nsIconChannel::GetIcon(nsIURI* aURI, ByteBuf* aDataOut) {
nsCOMPtr<nsIMozIconURI> iconURI = do_QueryInterface(aURI);
NS_ASSERTION(iconURI, "URI is not an nsIMozIconURI");
@ -281,7 +297,7 @@ nsresult nsIconChannel::Init(nsIURI* aURI) {
nsAutoCString stockIcon;
iconURI->GetStockIcon(stockIcon);
if (stockIcon.IsEmpty()) {
return InitWithGIO(iconURI);
return GetIconWithGIO(iconURI, aDataOut);
}
// Search for stockIcon
@ -373,14 +389,27 @@ nsresult nsIconChannel::Init(nsIURI* aURI) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv =
moz_gdk_pixbuf_to_channel(icon, iconURI, getter_AddRefs(mRealChannel));
nsresult rv = MozGdkPixbufToByteBuf(icon, aDataOut);
g_object_unref(icon);
return rv;
}
nsresult nsIconChannel::Init(nsIURI* aURI) {
nsresult rv;
nsCOMPtr<nsIInputStream> stream;
ByteBuf bytebuf;
rv = GetIcon(aURI, &bytebuf);
NS_ENSURE_SUCCESS(rv, rv);
rv = ByteBufToStream(std::move(bytebuf), getter_AddRefs(stream));
NS_ENSURE_SUCCESS(rv, rv);
return StreamToChannel(stream.forget(), aURI, getter_AddRefs(mRealChannel));
}
void nsIconChannel::Shutdown() {
if (gProtoWindow) {
gtk_widget_destroy(gProtoWindow);

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -12,9 +13,14 @@
#include "nsIIconURI.h"
#include "nsCOMPtr.h"
/// This class is the gnome implementation of nsIconChannel. It basically asks
/// gtk/gnome for an icon, saves it as a tmp icon, and creates a new channel for
/// that file to which all calls will be proxied.
namespace mozilla::ipc {
class ByteBuf;
}
/// This class is the GTK implementation of nsIconChannel. It asks
/// GTK for the icon, translates the pixel data in-memory into
/// nsIconDecoder format, and proxies the nsChannel interface to a new
/// channel returning that image.
class nsIconChannel final : public nsIChannel {
public:
NS_DECL_ISUPPORTS
@ -30,13 +36,18 @@ class nsIconChannel final : public nsIChannel {
/// If this method fails, no other function must be called on this object.
nsresult Init(nsIURI* aURI);
/// Obtains an icon, in nsIconDecoder format, as a ByteBuf instead
/// of a channel. For use with IPC.
static nsresult GetIcon(nsIURI* aURI, mozilla::ipc::ByteBuf* aDataOut);
private:
~nsIconChannel() {}
/// The channel to the temp icon file (e.g. to /tmp/2qy9wjqw.html).
/// The input stream channel which will yield the image.
/// Will always be non-null after a successful Init.
nsCOMPtr<nsIChannel> mRealChannel;
nsresult InitWithGIO(nsIMozIconURI* aIconURI);
static nsresult GetIconWithGIO(nsIMozIconURI* aIconURI,
mozilla::ipc::ByteBuf* aDataOut);
};
#endif // mozilla_image_decoders_icon_gtk_nsIconChannel_h