Index: components/mus/public/cpp/lib/property_type_converters.cc |
diff --git a/components/mus/public/cpp/lib/property_type_converters.cc b/components/mus/public/cpp/lib/property_type_converters.cc |
index 2e1ff65818c014d568d7f3f3fddcd1b4bea7b94a..a64b0f1da6ec52476b5bba910914b55c3a195be5 100644 |
--- a/components/mus/public/cpp/lib/property_type_converters.cc |
+++ b/components/mus/public/cpp/lib/property_type_converters.cc |
@@ -7,9 +7,19 @@ |
#include <stdint.h> |
#include "base/strings/utf_string_conversions.h" |
+#include "third_party/skia/include/core/SkBitmap.h" |
#include "ui/gfx/geometry/rect.h" |
#include "ui/gfx/geometry/size.h" |
+namespace { |
+ |
+// Maximum allowed height or width of a bitmap, in pixels. This limit prevents |
+// malformed bitmap headers from causing arbitrarily large memory allocations |
+// for pixel data. |
+const int kMaxBitmapSize = 4096; |
+ |
+} // namespace |
+ |
namespace mojo { |
// static |
@@ -73,7 +83,7 @@ gfx::Size TypeConverter<gfx::Size, const std::vector<uint8_t>>::Convert( |
const std::vector<uint8_t> |
TypeConverter<const std::vector<uint8_t>, int32_t>::Convert( |
const int32_t& input) { |
- std::vector<uint8_t> vec(8); |
+ std::vector<uint8_t> vec(4); |
vec[0] = (input >> 24) & 0xFF; |
vec[1] = (input >> 16) & 0xFF; |
vec[2] = (input >> 8) & 0xFF; |
@@ -118,5 +128,74 @@ TypeConverter<std::string, const std::vector<uint8_t>>::Convert( |
return std::string(input.begin(), input.end()); |
} |
-} // namespace mojo |
+// static |
+const std::vector<uint8_t> |
+TypeConverter<const std::vector<uint8_t>, SkBitmap>::Convert( |
+ const SkBitmap& input) { |
+ // Empty images are valid to serialize and are represented by an empty vector. |
+ if (input.isNull()) |
+ return std::vector<uint8_t>(); |
+ |
+ // Only RGBA 8888 bitmaps with premultiplied alpha are supported. |
+ if (input.colorType() != kBGRA_8888_SkColorType || |
+ input.alphaType() != kPremul_SkAlphaType) { |
+ NOTREACHED(); |
+ return std::vector<uint8_t>(); |
+ } |
+ |
+ // Sanity check the bitmap size. |
+ int width = input.width(); |
+ int height = input.height(); |
+ if (width < 0 || width > kMaxBitmapSize || height < 0 || |
+ height > kMaxBitmapSize) { |
+ NOTREACHED(); |
+ return std::vector<uint8_t>(); |
+ } |
+ |
+ // Serialize the bitmap. The size is restricted so only 2 bytes are required |
+ // per dimension. |
+ std::vector<uint8_t> vec(4 + input.getSize()); |
+ vec[0] = (width >> 8) & 0xFF; |
+ vec[1] = width & 0xFF; |
+ vec[2] = (height >> 8) & 0xFF; |
+ vec[3] = height & 0xFF; |
+ if (!input.copyPixelsTo(&vec[4], input.getSize())) |
+ return std::vector<uint8_t>(); |
+ return vec; |
+} |
+// static |
+SkBitmap TypeConverter<SkBitmap, const std::vector<uint8_t>>::Convert( |
+ const std::vector<uint8_t>& input) { |
+ // Empty images are represented by empty vectors. |
+ if (input.empty()) |
+ return SkBitmap(); |
+ |
+ // Read and sanity check size. |
+ int width = input[0] << 8 | input[1]; |
+ int height = input[2] << 8 | input[3]; |
+ if (width < 0 || width > kMaxBitmapSize || height < 0 || |
+ height > kMaxBitmapSize) { |
+ NOTREACHED(); |
+ return SkBitmap(); |
+ } |
+ |
+ // Try to allocate a bitmap of the appropriate size. |
+ SkBitmap bitmap; |
+ if (!bitmap.tryAllocPixels(SkImageInfo::Make( |
+ width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType))) { |
+ return SkBitmap(); |
+ } |
+ |
+ // Ensure the vector contains the right amount of data. |
+ if (input.size() != bitmap.getSize() + 4) { |
+ NOTREACHED(); |
+ return SkBitmap(); |
+ } |
+ |
+ // Read the pixel data. |
+ memcpy(bitmap.getPixels(), &input[4], bitmap.getSize()); |
sky
2016/03/25 15:56:34
Do you need to lock and unlock the pixels here?
James Cook
2016/03/25 16:52:39
Done.
|
+ return bitmap; |
+} |
+ |
+} // namespace mojo |