1 // Copyright (c) 2012 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 "chrome/renderer/extensions/set_icon_natives.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "chrome/common/render_messages.h"
11 #include "chrome/renderer/extensions/request_sender.h"
12 #include "third_party/skia/include/core/SkBitmap.h"
13 #include "third_party/skia/include/core/SkColor.h"
17 const char* kImageSizeKeys
[] = { "19", "38" };
18 const char kInvalidDimensions
[] = "ImageData has invalid dimensions.";
19 const char kInvalidData
[] = "ImageData data length does not match dimensions.";
20 const char kNoMemory
[] = "Chrome was unable to initialize icon.";
24 namespace extensions
{
26 SetIconNatives::SetIconNatives(Dispatcher
* dispatcher
,
27 RequestSender
* request_sender
,
28 ChromeV8Context
* context
)
29 : ChromeV8Extension(dispatcher
, context
),
30 request_sender_(request_sender
) {
33 base::Bind(&SetIconNatives::SetIconCommon
, base::Unretained(this)));
36 bool SetIconNatives::ConvertImageDataToBitmapValue(
37 const v8::Local
<v8::Object
> image_data
,
38 base::Value
** bitmap_value
) {
39 v8::Isolate
* isolate
= context()->v8_context()->GetIsolate();
40 v8::Local
<v8::Object
> data
=
41 image_data
->Get(v8::String::NewFromUtf8(isolate
, "data"))->ToObject();
43 image_data
->Get(v8::String::NewFromUtf8(isolate
, "width"))->Int32Value();
45 image_data
->Get(v8::String::NewFromUtf8(isolate
, "height"))->Int32Value();
47 if (width
<= 0 || height
<= 0) {
48 isolate
->ThrowException(v8::Exception::Error(
49 v8::String::NewFromUtf8(isolate
, kInvalidDimensions
)));
53 // We need to be able to safely check |data_length| == 4 * width * height
54 // without overflowing below.
55 int max_width
= (std::numeric_limits
<int>::max() / 4) / height
;
56 if (width
> max_width
) {
57 isolate
->ThrowException(v8::Exception::Error(
58 v8::String::NewFromUtf8(isolate
, kInvalidDimensions
)));
63 data
->Get(v8::String::NewFromUtf8(isolate
, "length"))->Int32Value();
64 if (data_length
!= 4 * width
* height
) {
65 isolate
->ThrowException(
66 v8::Exception::Error(v8::String::NewFromUtf8(isolate
, kInvalidData
)));
71 bitmap
.setConfig(SkBitmap::kARGB_8888_Config
, width
, height
);
72 if (!bitmap
.allocPixels()) {
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 *bitmap_value
= base::BinaryValue::CreateWithCopiedBuffer(
97 static_cast<const char*>(bitmap_pickle
.data()), bitmap_pickle
.size());
102 bool SetIconNatives::ConvertImageDataSetToBitmapValueSet(
103 const v8::FunctionCallbackInfo
<v8::Value
>& args
,
104 base::DictionaryValue
* bitmap_set_value
) {
105 v8::Local
<v8::Object
> extension_args
= args
[1]->ToObject();
106 v8::Local
<v8::Object
> details
= extension_args
107 ->Get(v8::String::NewFromUtf8(args
.GetIsolate(), "0"))->ToObject();
108 v8::Local
<v8::Object
> image_data_set
=
109 details
->Get(v8::String::NewFromUtf8(args
.GetIsolate(), "imageData"))
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(args
.GetIsolate(), kImageSizeKeys
[i
])))
117 v8::Local
<v8::Object
> image_data
= image_data_set
118 ->Get(v8::String::NewFromUtf8(args
.GetIsolate(), kImageSizeKeys
[i
]))
120 base::Value
* image_data_bitmap
= NULL
;
121 if (!ConvertImageDataToBitmapValue(image_data
, &image_data_bitmap
))
123 bitmap_set_value
->Set(kImageSizeKeys
[i
], image_data_bitmap
);
128 void SetIconNatives::SetIconCommon(
129 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
130 scoped_ptr
<base::DictionaryValue
> bitmap_set_value(
131 new base::DictionaryValue());
132 if (!ConvertImageDataSetToBitmapValueSet(args
, bitmap_set_value
.get()))
135 v8::Local
<v8::Object
> extension_args
= args
[1]->ToObject();
136 v8::Local
<v8::Object
> details
= extension_args
137 ->Get(v8::String::NewFromUtf8(args
.GetIsolate(), "0"))->ToObject();
139 base::DictionaryValue
* dict
= new base::DictionaryValue();
140 dict
->Set("imageData", bitmap_set_value
.release());
142 if (details
->Has(v8::String::NewFromUtf8(args
.GetIsolate(), "tabId"))) {
143 dict
->SetInteger("tabId",
144 details
->Get(v8::String::NewFromUtf8(
145 args
.GetIsolate(), "tabId"))->Int32Value());
148 base::ListValue list_value
;
149 list_value
.Append(dict
);
151 std::string name
= *v8::String::Utf8Value(args
[0]);
152 int request_id
= args
[2]->Int32Value();
153 bool has_callback
= args
[3]->BooleanValue();
154 bool for_io_thread
= args
[4]->BooleanValue();
156 request_sender_
->StartRequest(context(),
164 } // namespace extensions