Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(744)

Side by Side Diff: chrome/browser/notifications/notification_conversion_helper.cc

Issue 441753002: Route newly created notifications to notification provider API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed comments, deleted browser tests for onUpdated and onCleared Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/notifications/notification_conversion_helper.h"
6
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"
15
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);
22
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();
28 }
29
30 options->title.reset(
31 new std::string(base::UTF16ToUTF8(notification.title())));
32 options->message.reset(
33 new std::string(base::UTF16ToUTF8(notification.message())));
34
35 // Handle optional data provided.
36 const message_center::RichNotificationData* rich_data =
37 &notification.rich_notification_data();
38
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();
44 }
45
46 options->priority.reset(new int(rich_data->priority));
47
48 options->is_clickable.reset(new bool(rich_data->clickable));
49
50 options->event_time.reset(new double(rich_data->timestamp.ToDoubleT()));
51
52 if (!rich_data->context_message.empty())
53 options->context_message.reset(
54 new std::string(base::UTF16ToUTF8(rich_data->context_message)));
55
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);
65
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();
71 }
72 button_list->push_back(button);
73 }
74 options->buttons = button_list.Pass();
75 }
76
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.";
85 }
86
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.";
92
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);
105 }
106 options->items = list.Pass();
107 } else if (type != "list" && !rich_data->items.empty()) {
108 DVLOG(1) << "Only list type notifications should have lists.";
109 }
110 }
111
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();
117
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;
122
123 uint32_t* bitmap_pixels = sk_bitmap.getAddr32(0, 0);
124 const unsigned char* bitmap =
125 reinterpret_cast<const unsigned char*>(bitmap_pixels);
126 unsigned char* bitmap_data(new unsigned char[pixel_count * BYTES_PER_PIXEL]);
127
128 gfx::ConvertSkiaToRGBA(bitmap, pixel_count, bitmap_data);
129 sk_bitmap.unlockPixels();
130
131 notification_bitmap->data.reset(new std::string(
132 bitmap_data, (bitmap_data + pixel_count * BYTES_PER_PIXEL)));
133 return;
134 }
135
136 bool NotificationConversionHelper::NotificationBitmapToGfxImage(
137 float max_scale,
138 const gfx::Size& target_size_dips,
139 extensions::api::notifications::NotificationBitmap* notification_bitmap,
140 gfx::Image* return_image) {
141 if (!notification_bitmap)
142 return false;
143
144 const int max_device_pixel_width = target_size_dips.width() * max_scale;
145 const int max_device_pixel_height = target_size_dips.height() * max_scale;
146
147 const int BYTES_PER_PIXEL = 4;
148
149 const int width = notification_bitmap->width;
150 const int height = notification_bitmap->height;
151
152 if (width < 0 || height < 0 || width > max_device_pixel_width ||
153 height > max_device_pixel_height)
154 return false;
155
156 // Ensure we have rgba data.
157 std::string* rgba_data = notification_bitmap->data.get();
158 if (!rgba_data)
159 return false;
160
161 const size_t rgba_data_length = rgba_data->length();
162 const size_t rgba_area = width * height;
163
164 if (rgba_data_length != rgba_area * BYTES_PER_PIXEL)
165 return false;
166
167 SkBitmap bitmap;
168 // Allocate the actual backing store with the sanitized dimensions.
169 if (!bitmap.allocN32Pixels(width, height))
170 return false;
171
172 // Ensure that our bitmap and our data now refer to the same number of pixels.
173 if (rgba_data_length != bitmap.getSafeSize())
174 return false;
175
176 uint32_t* pixels = bitmap.getAddr32(0, 0);
177 const char* c_rgba_data = rgba_data->data();
178
179 for (size_t t = 0; t < rgba_area; ++t) {
180 // |c_rgba_data| is RGBA, pixels is ARGB.
181 size_t rgba_index = t * BYTES_PER_PIXEL;
182 pixels[t] =
183 SkPreMultiplyColor(((c_rgba_data[rgba_index + 3] & 0xFF) << 24) |
184 ((c_rgba_data[rgba_index + 0] & 0xFF) << 16) |
185 ((c_rgba_data[rgba_index + 1] & 0xFF) << 8) |
186 ((c_rgba_data[rgba_index + 2] & 0xFF) << 0));
187 }
188
189 // TODO(dewittj): Handle HiDPI images with more than one scale factor
190 // representation.
191 gfx::ImageSkia skia(gfx::ImageSkiaRep(bitmap, 1.0f));
192 *return_image = gfx::Image(skia);
193 return true;
194 }
195
196 std::string NotificationConversionHelper::MapTypeToString(
197 message_center::NotificationType type) {
198 switch (type) {
199 case message_center::NOTIFICATION_TYPE_BASE_FORMAT:
200 return "basic";
201 case message_center::NOTIFICATION_TYPE_IMAGE:
202 return "image";
203 case message_center::NOTIFICATION_TYPE_MULTIPLE:
204 return "list";
205 case message_center::NOTIFICATION_TYPE_PROGRESS:
206 return "progress";
207 default:
208 NOTREACHED();
209 return "";
210 }
211 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698