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
->v8_context()),
30 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 Value
** bitmap_value
) {
40 v8::Local
<v8::Object
> data
=
41 image_data
->Get(v8::String::New("data"))->ToObject();
42 int width
= image_data
->Get(v8::String::New("width"))->Int32Value();
43 int height
= image_data
->Get(v8::String::New("height"))->Int32Value();
45 if (width
<= 0 || height
<= 0) {
47 v8::Exception::Error(v8::String::New(kInvalidDimensions
)));
51 // We need to be able to safely check |data_length| == 4 * width * height
52 // without overflowing below.
53 int max_width
= (std::numeric_limits
<int>::max() / 4) / height
;
54 if (width
> max_width
) {
56 v8::Exception::Error(v8::String::New(kInvalidDimensions
)));
60 int data_length
= data
->Get(v8::String::New("length"))->Int32Value();
61 if (data_length
!= 4 * width
* height
) {
62 v8::ThrowException(v8::Exception::Error(v8::String::New(kInvalidData
)));
67 bitmap
.setConfig(SkBitmap::kARGB_8888_Config
, width
, height
);
68 if (!bitmap
.allocPixels()) {
69 v8::ThrowException(v8::Exception::Error(v8::String::New(kNoMemory
)));
72 bitmap
.eraseARGB(0, 0, 0, 0);
74 uint32_t* pixels
= bitmap
.getAddr32(0, 0);
75 for (int t
= 0; t
< width
*height
; t
++) {
76 // |data| is RGBA, pixels is ARGB.
77 pixels
[t
] = SkPreMultiplyColor(
78 ((data
->Get(v8::Integer::New(4*t
+ 3))->Int32Value() & 0xFF) << 24) |
79 ((data
->Get(v8::Integer::New(4*t
+ 0))->Int32Value() & 0xFF) << 16) |
80 ((data
->Get(v8::Integer::New(4*t
+ 1))->Int32Value() & 0xFF) << 8) |
81 ((data
->Get(v8::Integer::New(4*t
+ 2))->Int32Value() & 0xFF) << 0));
84 // Construct the Value object.
85 IPC::Message bitmap_pickle
;
86 IPC::WriteParam(&bitmap_pickle
, bitmap
);
87 *bitmap_value
= base::BinaryValue::CreateWithCopiedBuffer(
88 static_cast<const char*>(bitmap_pickle
.data()), bitmap_pickle
.size());
93 bool SetIconNatives::ConvertImageDataSetToBitmapValueSet(
94 const v8::Arguments
& args
, DictionaryValue
* bitmap_set_value
) {
95 v8::Local
<v8::Object
> extension_args
= args
[1]->ToObject();
96 v8::Local
<v8::Object
> details
=
97 extension_args
->Get(v8::String::New("0"))->ToObject();
98 v8::Local
<v8::Object
> image_data_set
=
99 details
->Get(v8::String::New("imageData"))->ToObject();
101 DCHECK(bitmap_set_value
);
102 for (size_t i
= 0; i
< arraysize(kImageSizeKeys
); i
++) {
103 if (!image_data_set
->Has(v8::String::New(kImageSizeKeys
[i
])))
105 v8::Local
<v8::Object
> image_data
=
106 image_data_set
->Get(v8::String::New(kImageSizeKeys
[i
]))->ToObject();
107 Value
* image_data_bitmap
= NULL
;
108 if (!ConvertImageDataToBitmapValue(image_data
, &image_data_bitmap
))
110 bitmap_set_value
->Set(kImageSizeKeys
[i
], image_data_bitmap
);
115 v8::Handle
<v8::Value
> SetIconNatives::SetIconCommon(
116 const v8::Arguments
& args
) {
117 scoped_ptr
<DictionaryValue
> bitmap_set_value(new DictionaryValue());
118 if (!ConvertImageDataSetToBitmapValueSet(args
, bitmap_set_value
.get()))
119 return v8::Undefined();
121 v8::Local
<v8::Object
> extension_args
= args
[1]->ToObject();
122 v8::Local
<v8::Object
> details
=
123 extension_args
->Get(v8::String::New("0"))->ToObject();
125 DictionaryValue
* dict
= new DictionaryValue();
126 dict
->Set("imageData", bitmap_set_value
.release());
128 if (details
->Has(v8::String::New("tabId"))) {
129 dict
->SetInteger("tabId",
130 details
->Get(v8::String::New("tabId"))->Int32Value());
133 ListValue list_value
;
134 list_value
.Append(dict
);
136 std::string name
= *v8::String::AsciiValue(args
[0]);
137 int request_id
= args
[2]->Int32Value();
138 bool has_callback
= args
[3]->BooleanValue();
139 bool for_io_thread
= args
[4]->BooleanValue();
141 request_sender_
->StartRequest(context_
,
147 return v8::Undefined();
150 } // namespace extensions