Update mojo surfaces bindings and mojo/cc/ glue
[chromium-blink-merge.git] / chrome / browser / notifications / notification_conversion_helper.cc
blob800adc11c620a685ea9f8a419625689ed5fe9a3e
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 "chrome/browser/notifications/notification_conversion_helper.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/common/extensions/api/notification_provider.h"
11 #include "chrome/common/extensions/api/notifications/notification_style.h"
12 #include "ui/gfx/image/image_skia.h"
13 #include "ui/gfx/image/image_skia_rep.h"
14 #include "ui/gfx/skia_util.h"
16 void NotificationConversionHelper::NotificationToNotificationOptions(
17 const Notification& notification,
18 extensions::api::notifications::NotificationOptions* options) {
19 // Extract required fields: type, title, message, and icon.
20 std::string type = MapTypeToString(notification.type());
21 options->type = extensions::api::notifications::ParseTemplateType(type);
23 if (!notification.icon().IsEmpty()) {
24 scoped_ptr<extensions::api::notifications::NotificationBitmap> icon(
25 new extensions::api::notifications::NotificationBitmap());
26 GfxImageToNotificationBitmap(&notification.icon(), icon.get());
27 options->icon_bitmap = icon.Pass();
30 options->title.reset(
31 new std::string(base::UTF16ToUTF8(notification.title())));
32 options->message.reset(
33 new std::string(base::UTF16ToUTF8(notification.message())));
35 // Handle optional data provided.
36 const message_center::RichNotificationData* rich_data =
37 &notification.rich_notification_data();
39 if (!rich_data->small_image.IsEmpty()) {
40 scoped_ptr<extensions::api::notifications::NotificationBitmap> icon_mask(
41 new extensions::api::notifications::NotificationBitmap());
42 GfxImageToNotificationBitmap(&rich_data->small_image, icon_mask.get());
43 options->app_icon_mask_bitmap = icon_mask.Pass();
46 options->priority.reset(new int(rich_data->priority));
48 options->is_clickable.reset(new bool(rich_data->clickable));
50 options->event_time.reset(new double(rich_data->timestamp.ToDoubleT()));
52 if (!rich_data->context_message.empty())
53 options->context_message.reset(
54 new std::string(base::UTF16ToUTF8(rich_data->context_message)));
56 if (!rich_data->buttons.empty()) {
57 scoped_ptr<std::vector<
58 linked_ptr<extensions::api::notifications::NotificationButton> > >
59 button_list(new std::vector<
60 linked_ptr<extensions::api::notifications::NotificationButton> >);
61 for (size_t i = 0; i < rich_data->buttons.size(); i++) {
62 linked_ptr<extensions::api::notifications::NotificationButton> button(
63 new extensions::api::notifications::NotificationButton);
64 button->title = base::UTF16ToUTF8(rich_data->buttons[i].title);
66 if (!rich_data->buttons[i].icon.IsEmpty()) {
67 scoped_ptr<extensions::api::notifications::NotificationBitmap> icon(
68 new extensions::api::notifications::NotificationBitmap());
69 GfxImageToNotificationBitmap(&rich_data->buttons[i].icon, icon.get());
70 button->icon_bitmap = icon.Pass();
72 button_list->push_back(button);
74 options->buttons = button_list.Pass();
77 // Only image type notifications should have images.
78 if (type == "image" && !rich_data->image.IsEmpty()) {
79 scoped_ptr<extensions::api::notifications::NotificationBitmap> image(
80 new extensions::api::notifications::NotificationBitmap());
81 GfxImageToNotificationBitmap(&notification.image(), image.get());
82 options->image_bitmap = image.Pass();
83 } else if (type != "image" && !rich_data->image.IsEmpty()) {
84 DVLOG(1) << "Only image type notifications should have images.";
87 // Only progress type notifications should have progress bars.
88 if (type == "progress")
89 options->progress.reset(new int(rich_data->progress));
90 else if (rich_data->progress != 0)
91 DVLOG(1) << "Only progress type notifications should have progress.";
93 // Only list type notifications should have lists.
94 if (type == "list" && !rich_data->items.empty()) {
95 scoped_ptr<std::vector<
96 linked_ptr<extensions::api::notifications::NotificationItem> > >
97 list(new std::vector<
98 linked_ptr<extensions::api::notifications::NotificationItem> >);
99 for (size_t j = 0; j < rich_data->items.size(); j++) {
100 linked_ptr<extensions::api::notifications::NotificationItem> item(
101 new extensions::api::notifications::NotificationItem);
102 item->title = base::UTF16ToUTF8(rich_data->items[j].title);
103 item->message = base::UTF16ToUTF8(rich_data->items[j].message);
104 list->push_back(item);
106 options->items = list.Pass();
107 } else if (type != "list" && !rich_data->items.empty()) {
108 DVLOG(1) << "Only list type notifications should have lists.";
112 void NotificationConversionHelper::GfxImageToNotificationBitmap(
113 const gfx::Image* gfx_image,
114 extensions::api::notifications::NotificationBitmap* notification_bitmap) {
115 SkBitmap sk_bitmap = gfx_image->AsBitmap();
116 sk_bitmap.lockPixels();
118 notification_bitmap->width = sk_bitmap.width();
119 notification_bitmap->height = sk_bitmap.height();
120 int pixel_count = sk_bitmap.width() * sk_bitmap.height();
121 const int BYTES_PER_PIXEL = 4;
123 uint32_t* bitmap_pixels = sk_bitmap.getAddr32(0, 0);
124 const unsigned char* bitmap =
125 reinterpret_cast<const unsigned char*>(bitmap_pixels);
126 scoped_ptr<unsigned char[]> rgba_bitmap_data(
127 new unsigned char[pixel_count * BYTES_PER_PIXEL]);
129 gfx::ConvertSkiaToRGBA(bitmap, pixel_count, rgba_bitmap_data.get());
130 sk_bitmap.unlockPixels();
132 notification_bitmap->data.reset(new std::string(
133 rgba_bitmap_data.get(),
134 (rgba_bitmap_data.get() + pixel_count * BYTES_PER_PIXEL)));
135 return;
138 bool NotificationConversionHelper::NotificationBitmapToGfxImage(
139 float max_scale,
140 const gfx::Size& target_size_dips,
141 extensions::api::notifications::NotificationBitmap* notification_bitmap,
142 gfx::Image* return_image) {
143 if (!notification_bitmap)
144 return false;
146 const int max_device_pixel_width = target_size_dips.width() * max_scale;
147 const int max_device_pixel_height = target_size_dips.height() * max_scale;
149 const int BYTES_PER_PIXEL = 4;
151 const int width = notification_bitmap->width;
152 const int height = notification_bitmap->height;
154 if (width < 0 || height < 0 || width > max_device_pixel_width ||
155 height > max_device_pixel_height)
156 return false;
158 // Ensure we have rgba data.
159 std::string* rgba_data = notification_bitmap->data.get();
160 if (!rgba_data)
161 return false;
163 const size_t rgba_data_length = rgba_data->length();
164 const size_t rgba_area = width * height;
166 if (rgba_data_length != rgba_area * BYTES_PER_PIXEL)
167 return false;
169 SkBitmap bitmap;
170 // Allocate the actual backing store with the sanitized dimensions.
171 if (!bitmap.allocN32Pixels(width, height))
172 return false;
174 // Ensure that our bitmap and our data now refer to the same number of pixels.
175 if (rgba_data_length != bitmap.getSafeSize())
176 return false;
178 uint32_t* pixels = bitmap.getAddr32(0, 0);
179 const char* c_rgba_data = rgba_data->data();
181 for (size_t t = 0; t < rgba_area; ++t) {
182 // |c_rgba_data| is RGBA, pixels is ARGB.
183 size_t rgba_index = t * BYTES_PER_PIXEL;
184 pixels[t] =
185 SkPreMultiplyColor(((c_rgba_data[rgba_index + 3] & 0xFF) << 24) |
186 ((c_rgba_data[rgba_index + 0] & 0xFF) << 16) |
187 ((c_rgba_data[rgba_index + 1] & 0xFF) << 8) |
188 ((c_rgba_data[rgba_index + 2] & 0xFF) << 0));
191 // TODO(dewittj): Handle HiDPI images with more than one scale factor
192 // representation.
193 gfx::ImageSkia skia(gfx::ImageSkiaRep(bitmap, 1.0f));
194 *return_image = gfx::Image(skia);
195 return true;
198 std::string NotificationConversionHelper::MapTypeToString(
199 message_center::NotificationType type) {
200 switch (type) {
201 case message_center::NOTIFICATION_TYPE_BASE_FORMAT:
202 return "basic";
203 case message_center::NOTIFICATION_TYPE_IMAGE:
204 return "image";
205 case message_center::NOTIFICATION_TYPE_MULTIPLE:
206 return "list";
207 case message_center::NOTIFICATION_TYPE_PROGRESS:
208 return "progress";
209 default:
210 NOTREACHED();
211 return "";