blob: ab6f3af2f67c5540fb3a336c9631538e56cd4122 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "skia/ext/skia_utils_base.h"
#include "base/memory/ptr_util.h"
#include "base/test/gtest_util.h"
#include "base/test/test_discardable_memory_allocator.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkFlattenableSerialization.h"
#include "third_party/skia/include/core/SkImageGenerator.h"
#include "third_party/skia/include/core/SkPixelSerializer.h"
#include "third_party/skia/include/core/SkWriteBuffer.h"
#include "third_party/skia/include/effects/SkImageSource.h"
#include "third_party/skia/include/effects/SkPaintImageFilter.h"
namespace skia {
namespace {
// Raw data for a PNG file with 1x1 white pixels.
const unsigned char kWhitePNG[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, 0xde, 0x00, 0x00, 0x00,
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00,
0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x49,
0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x05,
0xfe, 0x02, 0xfe, 0xdc, 0xcc, 0x59, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x49,
0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
};
class FakeImageGenerator : public SkImageGenerator {
public:
FakeImageGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(10, 10)) {}
~FakeImageGenerator() override { EXPECT_TRUE(decoded_); }
SkData* onRefEncodedData() override {
// Use a generator that lets the caller encode it.
return SkData::MakeWithCString("evilimage").release();
}
bool onGetPixels(const SkImageInfo& info,
void* pixels,
size_t,
const Options&) override {
decoded_ = true;
memset(pixels, 0, info.computeMinByteSize());
return true;
}
private:
bool decoded_ = false;
};
class PixelSerializer : public SkPixelSerializer {
public:
bool onUseEncodedData(const void* data, size_t len) override {
CHECK(false);
return false;
}
SkData* onEncode(const SkPixmap&) override {
EXPECT_TRUE(has_decoded_images_);
return nullptr;
}
bool has_decoded_images_ = false;
};
TEST(SkiaUtilsBaseTest, ImageSerializationDecodesImage) {
base::TestDiscardableMemoryAllocator allocator;
base::DiscardableMemoryAllocator::SetInstance(&allocator);
auto image =
SkImage::MakeFromGenerator(base::MakeUnique<FakeImageGenerator>());
auto filter = SkImageSource::Make(image);
// Serialize the filter. This decodes the image.
sk_sp<SkData> data = ValidatingSerializeFlattenable(filter.get());
// Deserialize.
auto deserialized_filter =
sk_sp<SkImageFilter>((SkImageFilter*)ValidatingDeserializeFlattenable(
data->data(), data->size(), SkImageFilter::GetFlattenableType()));
// Now serialize again to ensure that the deserialized filter did not have any
// encoded images. Serialization is the only way to deep inspect the filter.
SkBinaryWriteBuffer writer;
auto pixel_serializer = sk_make_sp<PixelSerializer>();
pixel_serializer->has_decoded_images_ = true;
writer.setPixelSerializer(pixel_serializer);
writer.writeFlattenable(deserialized_filter.get());
EXPECT_GT(writer.bytesWritten(), 0u);
base::DiscardableMemoryAllocator::SetInstance(nullptr);
}
TEST(SkiaUtilsBaseTest, DeserializationWithEncodedImagesFails) {
base::TestDiscardableMemoryAllocator allocator;
base::DiscardableMemoryAllocator::SetInstance(&allocator);
auto image = SkImage::MakeFromGenerator(SkImageGenerator::MakeFromEncoded(
SkData::MakeWithoutCopy(kWhitePNG, sizeof(kWhitePNG))));
auto filter = SkImageSource::Make(image);
// Serialize the filter using default serialization.
sk_sp<SkData> data(SkValidatingSerializeFlattenable(filter.get()));
// Deserialize with images disabled.
auto deserialized_filter =
sk_sp<SkImageFilter>((SkImageFilter*)ValidatingDeserializeFlattenable(
data->data(), data->size(), SkImageFilter::GetFlattenableType()));
// Now serialize again to make sure that all encoded images were rejected
// during serialization.
SkBinaryWriteBuffer writer;
auto pixel_serializer = sk_make_sp<PixelSerializer>();
writer.setPixelSerializer(pixel_serializer);
writer.writeFlattenable(deserialized_filter.get());
EXPECT_GT(writer.bytesWritten(), 0u);
base::DiscardableMemoryAllocator::SetInstance(nullptr);
}
} // namespace
} // namespace skia