OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/renderer/extensions/set_icon_natives.h" | |
6 | |
7 #include <limits> | |
8 | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "chrome/common/render_messages.h" | |
11 #include "extensions/renderer/request_sender.h" | |
12 #include "third_party/skia/include/core/SkBitmap.h" | |
13 #include "third_party/skia/include/core/SkColor.h" | |
14 | |
15 namespace { | |
16 | |
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."; | |
21 | |
22 } // namespace | |
23 | |
24 namespace extensions { | |
25 | |
26 SetIconNatives::SetIconNatives(Dispatcher* dispatcher, | |
27 RequestSender* request_sender, | |
28 ChromeV8Context* context) | |
29 : ChromeV8Extension(dispatcher, context), | |
30 request_sender_(request_sender) { | |
31 RouteFunction( | |
32 "SetIconCommon", | |
33 base::Bind(&SetIconNatives::SetIconCommon, base::Unretained(this))); | |
34 } | |
35 | |
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(); | |
42 int width = | |
43 image_data->Get(v8::String::NewFromUtf8(isolate, "width"))->Int32Value(); | |
44 int height = | |
45 image_data->Get(v8::String::NewFromUtf8(isolate, "height"))->Int32Value(); | |
46 | |
47 if (width <= 0 || height <= 0) { | |
48 isolate->ThrowException(v8::Exception::Error( | |
49 v8::String::NewFromUtf8(isolate, kInvalidDimensions))); | |
50 return false; | |
51 } | |
52 | |
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))); | |
59 return false; | |
60 } | |
61 | |
62 int data_length = | |
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))); | |
67 return false; | |
68 } | |
69 | |
70 SkBitmap bitmap; | |
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))); | |
75 return false; | |
76 } | |
77 bitmap.eraseARGB(0, 0, 0, 0); | |
78 | |
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) | |
84 << 24) | | |
85 ((data->Get(v8::Integer::New(isolate, 4*t + 0))->Int32Value() & 0xFF) | |
86 << 16) | | |
87 ((data->Get(v8::Integer::New(isolate, 4*t + 1))->Int32Value() & 0xFF) | |
88 << 8) | | |
89 ((data->Get(v8::Integer::New(isolate, 4*t + 2))->Int32Value() & 0xFF) | |
90 << 0)); | |
91 } | |
92 | |
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()); | |
98 | |
99 return true; | |
100 } | |
101 | |
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")) | |
110 ->ToObject(); | |
111 | |
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]))) | |
116 continue; | |
117 v8::Local<v8::Object> image_data = image_data_set | |
118 ->Get(v8::String::NewFromUtf8(args.GetIsolate(), kImageSizeKeys[i])) | |
119 ->ToObject(); | |
120 base::Value* image_data_bitmap = NULL; | |
121 if (!ConvertImageDataToBitmapValue(image_data, &image_data_bitmap)) | |
122 return false; | |
123 bitmap_set_value->Set(kImageSizeKeys[i], image_data_bitmap); | |
124 } | |
125 return true; | |
126 } | |
127 | |
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())) | |
133 return; | |
134 | |
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(); | |
138 | |
139 base::DictionaryValue* dict = new base::DictionaryValue(); | |
140 dict->Set("imageData", bitmap_set_value.release()); | |
141 | |
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()); | |
146 } | |
147 | |
148 base::ListValue list_value; | |
149 list_value.Append(dict); | |
150 | |
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(); | |
155 | |
156 request_sender_->StartRequest(context(), | |
157 name, | |
158 request_id, | |
159 has_callback, | |
160 for_io_thread, | |
161 &list_value); | |
162 } | |
163 | |
164 } // namespace extensions | |
OLD | NEW |