1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/renderer/set_icon_natives.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "content/public/common/common_param_traits.h"
11 #include "extensions/renderer/request_sender.h"
12 #include "extensions/renderer/script_context.h"
13 #include "ipc/ipc_message_utils.h"
14 #include "third_party/WebKit/public/web/WebArrayBufferConverter.h"
15 #include "third_party/skia/include/core/SkBitmap.h"
16 #include "ui/gfx/ipc/gfx_param_traits.h"
20 const char* kImageSizeKeys
[] = {"19", "38"};
21 const char kInvalidDimensions
[] = "ImageData has invalid dimensions.";
22 const char kInvalidData
[] = "ImageData data length does not match dimensions.";
23 const char kNoMemory
[] = "Chrome was unable to initialize icon.";
27 namespace extensions
{
29 SetIconNatives::SetIconNatives(RequestSender
* request_sender
,
30 ScriptContext
* context
)
31 : ObjectBackedNativeHandler(context
), request_sender_(request_sender
) {
34 base::Bind(&SetIconNatives::SetIconCommon
, base::Unretained(this)));
37 bool SetIconNatives::ConvertImageDataToBitmapValue(
38 const v8::Local
<v8::Object
> image_data
,
39 v8::Local
<v8::Value
>* image_data_bitmap
) {
40 v8::Isolate
* isolate
= context()->v8_context()->GetIsolate();
41 v8::Local
<v8::Object
> data
=
42 image_data
->Get(v8::String::NewFromUtf8(isolate
, "data"))->ToObject();
44 image_data
->Get(v8::String::NewFromUtf8(isolate
, "width"))->Int32Value();
46 image_data
->Get(v8::String::NewFromUtf8(isolate
, "height"))->Int32Value();
48 if (width
<= 0 || height
<= 0) {
49 isolate
->ThrowException(v8::Exception::Error(
50 v8::String::NewFromUtf8(isolate
, kInvalidDimensions
)));
54 // We need to be able to safely check |data_length| == 4 * width * height
55 // without overflowing below.
56 int max_width
= (std::numeric_limits
<int>::max() / 4) / height
;
57 if (width
> max_width
) {
58 isolate
->ThrowException(v8::Exception::Error(
59 v8::String::NewFromUtf8(isolate
, kInvalidDimensions
)));
64 data
->Get(v8::String::NewFromUtf8(isolate
, "length"))->Int32Value();
65 if (data_length
!= 4 * width
* height
) {
66 isolate
->ThrowException(
67 v8::Exception::Error(v8::String::NewFromUtf8(isolate
, kInvalidData
)));
72 if (!bitmap
.tryAllocN32Pixels(width
, height
)) {
73 isolate
->ThrowException(
74 v8::Exception::Error(v8::String::NewFromUtf8(isolate
, kNoMemory
)));
77 bitmap
.eraseARGB(0, 0, 0, 0);
79 uint32_t* pixels
= bitmap
.getAddr32(0, 0);
80 for (int t
= 0; t
< width
* height
; t
++) {
81 // |data| is RGBA, pixels is ARGB.
82 pixels
[t
] = SkPreMultiplyColor(
83 ((data
->Get(v8::Integer::New(isolate
, 4 * t
+ 3))->Int32Value() & 0xFF)
85 ((data
->Get(v8::Integer::New(isolate
, 4 * t
+ 0))->Int32Value() & 0xFF)
87 ((data
->Get(v8::Integer::New(isolate
, 4 * t
+ 1))->Int32Value() & 0xFF)
89 ((data
->Get(v8::Integer::New(isolate
, 4 * t
+ 2))->Int32Value() & 0xFF)
93 // Construct the Value object.
94 IPC::Message bitmap_pickle
;
95 IPC::WriteParam(&bitmap_pickle
, bitmap
);
96 blink::WebArrayBuffer buffer
=
97 blink::WebArrayBuffer::create(bitmap_pickle
.size(), 1);
98 memcpy(buffer
.data(), bitmap_pickle
.data(), bitmap_pickle
.size());
99 *image_data_bitmap
= blink::WebArrayBufferConverter::toV8Value(
100 &buffer
, context()->v8_context()->Global(), isolate
);
105 bool SetIconNatives::ConvertImageDataSetToBitmapValueSet(
106 v8::Local
<v8::Object
>& details
,
107 v8::Local
<v8::Object
>* bitmap_set_value
) {
108 v8::Isolate
* isolate
= context()->v8_context()->GetIsolate();
109 v8::Local
<v8::Object
> image_data_set
=
110 details
->Get(v8::String::NewFromUtf8(isolate
, "imageData"))->ToObject();
112 DCHECK(bitmap_set_value
);
113 for (size_t i
= 0; i
< arraysize(kImageSizeKeys
); i
++) {
114 if (!image_data_set
->Has(
115 v8::String::NewFromUtf8(isolate
, kImageSizeKeys
[i
])))
117 v8::Local
<v8::Object
> image_data
=
118 image_data_set
->Get(v8::String::NewFromUtf8(isolate
, kImageSizeKeys
[i
]))
120 v8::Local
<v8::Value
> image_data_bitmap
;
121 if (!ConvertImageDataToBitmapValue(image_data
, &image_data_bitmap
))
123 (*bitmap_set_value
)->Set(
124 v8::String::NewFromUtf8(isolate
, kImageSizeKeys
[i
]), image_data_bitmap
);
129 void SetIconNatives::SetIconCommon(
130 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
131 CHECK_EQ(1, args
.Length());
132 CHECK(args
[0]->IsObject());
133 v8::Local
<v8::Object
> details
= args
[0]->ToObject();
134 v8::Local
<v8::Object
> bitmap_set_value(v8::Object::New(args
.GetIsolate()));
135 if (!ConvertImageDataSetToBitmapValueSet(details
, &bitmap_set_value
))
138 v8::Local
<v8::Object
> dict(v8::Object::New(args
.GetIsolate()));
139 dict
->Set(v8::String::NewFromUtf8(args
.GetIsolate(), "imageData"),
141 if (details
->Has(v8::String::NewFromUtf8(args
.GetIsolate(), "tabId"))) {
143 v8::String::NewFromUtf8(args
.GetIsolate(), "tabId"),
144 details
->Get(v8::String::NewFromUtf8(args
.GetIsolate(), "tabId")));
146 args
.GetReturnValue().Set(dict
);
149 } // namespace extensions