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

Side by Side Diff: chrome/browser/extensions/api/notifications/notifications_api.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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/notifications/notifications_api.h" 5 #include "chrome/browser/extensions/api/notifications/notifications_api.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/guid.h" 8 #include "base/guid.h"
9 #include "base/rand_util.h" 9 #include "base/rand_util.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/notifications/desktop_notification_service.h" 14 #include "chrome/browser/notifications/desktop_notification_service.h"
15 #include "chrome/browser/notifications/desktop_notification_service_factory.h" 15 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
16 #include "chrome/browser/notifications/notification.h" 16 #include "chrome/browser/notifications/notification.h"
17 #include "chrome/browser/notifications/notification_conversion_helper.h"
17 #include "chrome/browser/notifications/notification_ui_manager.h" 18 #include "chrome/browser/notifications/notification_ui_manager.h"
18 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/chrome_version_info.h" 20 #include "chrome/common/chrome_version_info.h"
20 #include "chrome/common/extensions/api/notifications/notification_style.h" 21 #include "chrome/common/extensions/api/notifications/notification_style.h"
21 #include "content/public/browser/render_process_host.h" 22 #include "content/public/browser/render_process_host.h"
22 #include "content/public/browser/render_view_host.h" 23 #include "content/public/browser/render_view_host.h"
23 #include "content/public/browser/web_contents.h" 24 #include "content/public/browser/web_contents.h"
24 #include "extensions/browser/event_router.h" 25 #include "extensions/browser/event_router.h"
25 #include "extensions/common/extension.h" 26 #include "extensions/common/extension.h"
26 #include "extensions/common/features/feature.h" 27 #include "extensions/common/features/feature.h"
(...skipping 19 matching lines...) Expand all
46 "Unable to successfully use the provided image."; 47 "Unable to successfully use the provided image.";
47 const char kUnexpectedProgressValueForNonProgressType[] = 48 const char kUnexpectedProgressValueForNonProgressType[] =
48 "The progress value should not be specified for non-progress notification"; 49 "The progress value should not be specified for non-progress notification";
49 const char kInvalidProgressValue[] = 50 const char kInvalidProgressValue[] =
50 "The progress value should range from 0 to 100"; 51 "The progress value should range from 0 to 100";
51 const char kExtraListItemsProvided[] = 52 const char kExtraListItemsProvided[] =
52 "List items provided for notification type != list"; 53 "List items provided for notification type != list";
53 const char kExtraImageProvided[] = 54 const char kExtraImageProvided[] =
54 "Image resource provided for notification type != image"; 55 "Image resource provided for notification type != image";
55 56
56 // Converts an object with width, height, and data in RGBA format into an
57 // gfx::Image (in ARGB format).
58 bool NotificationBitmapToGfxImage(
59 float max_scale,
60 const gfx::Size& target_size_dips,
61 api::notifications::NotificationBitmap* notification_bitmap,
62 gfx::Image* return_image) {
63 if (!notification_bitmap)
64 return false;
65
66 const int max_device_pixel_width = target_size_dips.width() * max_scale;
67 const int max_device_pixel_height = target_size_dips.height() * max_scale;
68
69 const int BYTES_PER_PIXEL = 4;
70
71 const int width = notification_bitmap->width;
72 const int height = notification_bitmap->height;
73
74 if (width < 0 || height < 0 || width > max_device_pixel_width ||
75 height > max_device_pixel_height)
76 return false;
77
78 // Ensure we have rgba data.
79 std::string* rgba_data = notification_bitmap->data.get();
80 if (!rgba_data)
81 return false;
82
83 const size_t rgba_data_length = rgba_data->length();
84 const size_t rgba_area = width * height;
85
86 if (rgba_data_length != rgba_area * BYTES_PER_PIXEL)
87 return false;
88
89 SkBitmap bitmap;
90 // Allocate the actual backing store with the sanitized dimensions.
91 if (!bitmap.allocN32Pixels(width, height))
92 return false;
93
94 // Ensure that our bitmap and our data now refer to the same number of pixels.
95 if (rgba_data_length != bitmap.getSafeSize())
96 return false;
97
98 uint32_t* pixels = bitmap.getAddr32(0, 0);
99 const char* c_rgba_data = rgba_data->data();
100
101 for (size_t t = 0; t < rgba_area; ++t) {
102 // |c_rgba_data| is RGBA, pixels is ARGB.
103 size_t rgba_index = t * BYTES_PER_PIXEL;
104 pixels[t] = SkPreMultiplyColor(
105 ((c_rgba_data[rgba_index + 3] & 0xFF) << 24) |
106 ((c_rgba_data[rgba_index + 0] & 0xFF) << 16) |
107 ((c_rgba_data[rgba_index + 1] & 0xFF) << 8) |
108 ((c_rgba_data[rgba_index + 2] & 0xFF) << 0));
109 }
110
111 // TODO(dewittj): Handle HiDPI images with more than one scale factor
112 // representation.
113 gfx::ImageSkia skia(gfx::ImageSkiaRep(bitmap, 1.0f));
114 *return_image = gfx::Image(skia);
115 return true;
116 }
117
118 // Given an extension id and another id, returns an id that is unique 57 // Given an extension id and another id, returns an id that is unique
119 // relative to other extensions. 58 // relative to other extensions.
120 std::string CreateScopedIdentifier(const std::string& extension_id, 59 std::string CreateScopedIdentifier(const std::string& extension_id,
121 const std::string& id) { 60 const std::string& id) {
122 return extension_id + "-" + id; 61 return extension_id + "-" + id;
123 } 62 }
124 63
125 // Removes the unique internal identifier to send the ID as the 64 // Removes the unique internal identifier to send the ID as the
126 // extension expects it. 65 // extension expects it.
127 std::string StripScopeFromIdentifier(const std::string& extension_id, 66 std::string StripScopeFromIdentifier(const std::string& extension_id,
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 float image_scale = 207 float image_scale =
269 ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactors().back()); 208 ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactors().back());
270 209
271 // Extract required fields: type, title, message, and icon. 210 // Extract required fields: type, title, message, and icon.
272 message_center::NotificationType type = 211 message_center::NotificationType type =
273 MapApiTemplateTypeToType(options->type); 212 MapApiTemplateTypeToType(options->type);
274 const base::string16 title(base::UTF8ToUTF16(*options->title)); 213 const base::string16 title(base::UTF8ToUTF16(*options->title));
275 const base::string16 message(base::UTF8ToUTF16(*options->message)); 214 const base::string16 message(base::UTF8ToUTF16(*options->message));
276 gfx::Image icon; 215 gfx::Image icon;
277 216
278 if (!NotificationBitmapToGfxImage(image_scale, 217 if (!NotificationConversionHelper::NotificationBitmapToGfxImage(
279 bitmap_sizes.icon_size, 218 image_scale,
280 options->icon_bitmap.get(), 219 bitmap_sizes.icon_size,
281 &icon)) { 220 options->icon_bitmap.get(),
221 &icon)) {
282 SetError(kUnableToDecodeIconError); 222 SetError(kUnableToDecodeIconError);
283 return false; 223 return false;
284 } 224 }
285 225
286 // Then, handle any optional data that's been provided. 226 // Then, handle any optional data that's been provided.
287 message_center::RichNotificationData optional_fields; 227 message_center::RichNotificationData optional_fields;
288 if (options->app_icon_mask_url.get()) { 228 if (options->app_icon_mask_url.get()) {
289 if (!NotificationBitmapToGfxImage(image_scale, 229 if (!NotificationConversionHelper::NotificationBitmapToGfxImage(
290 bitmap_sizes.app_icon_mask_size, 230 image_scale,
291 options->app_icon_mask_bitmap.get(), 231 bitmap_sizes.app_icon_mask_size,
292 &optional_fields.small_image)) { 232 options->app_icon_mask_bitmap.get(),
233 &optional_fields.small_image)) {
293 SetError(kUnableToDecodeIconError); 234 SetError(kUnableToDecodeIconError);
294 return false; 235 return false;
295 } 236 }
296 } 237 }
297 238
298 if (options->priority.get()) 239 if (options->priority.get())
299 optional_fields.priority = *options->priority; 240 optional_fields.priority = *options->priority;
300 241
301 if (options->event_time.get()) 242 if (options->event_time.get())
302 optional_fields.timestamp = base::Time::FromJsTime(*options->event_time); 243 optional_fields.timestamp = base::Time::FromJsTime(*options->event_time);
303 244
304 if (options->buttons.get()) { 245 if (options->buttons.get()) {
305 // Currently we allow up to 2 buttons. 246 // Currently we allow up to 2 buttons.
306 size_t number_of_buttons = options->buttons->size(); 247 size_t number_of_buttons = options->buttons->size();
307 number_of_buttons = number_of_buttons > 2 ? 2 : number_of_buttons; 248 number_of_buttons = number_of_buttons > 2 ? 2 : number_of_buttons;
308 249
309 for (size_t i = 0; i < number_of_buttons; i++) { 250 for (size_t i = 0; i < number_of_buttons; i++) {
310 message_center::ButtonInfo info( 251 message_center::ButtonInfo info(
311 base::UTF8ToUTF16((*options->buttons)[i]->title)); 252 base::UTF8ToUTF16((*options->buttons)[i]->title));
312 NotificationBitmapToGfxImage(image_scale, 253 NotificationConversionHelper::NotificationBitmapToGfxImage(
313 bitmap_sizes.button_icon_size, 254 image_scale,
314 (*options->buttons)[i]->icon_bitmap.get(), 255 bitmap_sizes.button_icon_size,
315 &info.icon); 256 (*options->buttons)[i]->icon_bitmap.get(),
257 &info.icon);
316 optional_fields.buttons.push_back(info); 258 optional_fields.buttons.push_back(info);
317 } 259 }
318 } 260 }
319 261
320 if (options->context_message) { 262 if (options->context_message) {
321 optional_fields.context_message = 263 optional_fields.context_message =
322 base::UTF8ToUTF16(*options->context_message); 264 base::UTF8ToUTF16(*options->context_message);
323 } 265 }
324 266
325 bool has_image = NotificationBitmapToGfxImage(image_scale, 267 bool has_image = NotificationConversionHelper::NotificationBitmapToGfxImage(
326 bitmap_sizes.image_size, 268 image_scale,
327 options->image_bitmap.get(), 269 bitmap_sizes.image_size,
328 &optional_fields.image); 270 options->image_bitmap.get(),
271 &optional_fields.image);
329 // We should have an image if and only if the type is an image type. 272 // We should have an image if and only if the type is an image type.
330 if (has_image != (type == message_center::NOTIFICATION_TYPE_IMAGE)) { 273 if (has_image != (type == message_center::NOTIFICATION_TYPE_IMAGE)) {
331 SetError(kExtraImageProvided); 274 SetError(kExtraImageProvided);
332 return false; 275 return false;
333 } 276 }
334 277
335 // We should have list items if and only if the type is a multiple type. 278 // We should have list items if and only if the type is a multiple type.
336 bool has_list_items = options->items.get() && options->items->size() > 0; 279 bool has_list_items = options->items.get() && options->items->size() > 0;
337 if (has_list_items != (type == message_center::NOTIFICATION_TYPE_MULTIPLE)) { 280 if (has_list_items != (type == message_center::NOTIFICATION_TYPE_MULTIPLE)) {
338 SetError(kExtraListItemsProvided); 281 SetError(kExtraListItemsProvided);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 if (options->type != api::notifications::TEMPLATE_TYPE_NONE) 343 if (options->type != api::notifications::TEMPLATE_TYPE_NONE)
401 notification->set_type(MapApiTemplateTypeToType(options->type)); 344 notification->set_type(MapApiTemplateTypeToType(options->type));
402 if (options->title) 345 if (options->title)
403 notification->set_title(base::UTF8ToUTF16(*options->title)); 346 notification->set_title(base::UTF8ToUTF16(*options->title));
404 if (options->message) 347 if (options->message)
405 notification->set_message(base::UTF8ToUTF16(*options->message)); 348 notification->set_message(base::UTF8ToUTF16(*options->message));
406 349
407 // TODO(dewittj): Return error if this fails. 350 // TODO(dewittj): Return error if this fails.
408 if (options->icon_bitmap) { 351 if (options->icon_bitmap) {
409 gfx::Image icon; 352 gfx::Image icon;
410 NotificationBitmapToGfxImage( 353 NotificationConversionHelper::NotificationBitmapToGfxImage(
411 image_scale, bitmap_sizes.icon_size, options->icon_bitmap.get(), &icon); 354 image_scale, bitmap_sizes.icon_size, options->icon_bitmap.get(), &icon);
412 notification->set_icon(icon); 355 notification->set_icon(icon);
413 } 356 }
414 357
415 gfx::Image app_icon_mask; 358 gfx::Image app_icon_mask;
416 if (NotificationBitmapToGfxImage(image_scale, 359 if (NotificationConversionHelper::NotificationBitmapToGfxImage(
417 bitmap_sizes.app_icon_mask_size, 360 image_scale,
418 options->app_icon_mask_bitmap.get(), 361 bitmap_sizes.app_icon_mask_size,
419 &app_icon_mask)) { 362 options->app_icon_mask_bitmap.get(),
363 &app_icon_mask)) {
420 notification->set_small_image(app_icon_mask); 364 notification->set_small_image(app_icon_mask);
421 } 365 }
422 366
423 if (options->priority) 367 if (options->priority)
424 notification->set_priority(*options->priority); 368 notification->set_priority(*options->priority);
425 369
426 if (options->event_time) 370 if (options->event_time)
427 notification->set_timestamp(base::Time::FromJsTime(*options->event_time)); 371 notification->set_timestamp(base::Time::FromJsTime(*options->event_time));
428 372
429 if (options->buttons) { 373 if (options->buttons) {
430 // Currently we allow up to 2 buttons. 374 // Currently we allow up to 2 buttons.
431 size_t number_of_buttons = options->buttons->size(); 375 size_t number_of_buttons = options->buttons->size();
432 number_of_buttons = number_of_buttons > 2 ? 2 : number_of_buttons; 376 number_of_buttons = number_of_buttons > 2 ? 2 : number_of_buttons;
433 377
434 std::vector<message_center::ButtonInfo> buttons; 378 std::vector<message_center::ButtonInfo> buttons;
435 for (size_t i = 0; i < number_of_buttons; i++) { 379 for (size_t i = 0; i < number_of_buttons; i++) {
436 message_center::ButtonInfo button( 380 message_center::ButtonInfo button(
437 base::UTF8ToUTF16((*options->buttons)[i]->title)); 381 base::UTF8ToUTF16((*options->buttons)[i]->title));
438 NotificationBitmapToGfxImage(image_scale, 382 NotificationConversionHelper::NotificationBitmapToGfxImage(
439 bitmap_sizes.button_icon_size, 383 image_scale,
440 (*options->buttons)[i]->icon_bitmap.get(), 384 bitmap_sizes.button_icon_size,
441 &button.icon); 385 (*options->buttons)[i]->icon_bitmap.get(),
386 &button.icon);
442 buttons.push_back(button); 387 buttons.push_back(button);
443 } 388 }
444 notification->set_buttons(buttons); 389 notification->set_buttons(buttons);
445 } 390 }
446 391
447 if (options->context_message) { 392 if (options->context_message) {
448 notification->set_context_message( 393 notification->set_context_message(
449 base::UTF8ToUTF16(*options->context_message)); 394 base::UTF8ToUTF16(*options->context_message));
450 } 395 }
451 396
452 gfx::Image image; 397 gfx::Image image;
453 bool has_image = NotificationBitmapToGfxImage(image_scale, 398 bool has_image = NotificationConversionHelper::NotificationBitmapToGfxImage(
454 bitmap_sizes.image_size, 399 image_scale,
455 options->image_bitmap.get(), 400 bitmap_sizes.image_size,
456 &image); 401 options->image_bitmap.get(),
402 &image);
457 if (has_image) { 403 if (has_image) {
458 // We should have an image if and only if the type is an image type. 404 // We should have an image if and only if the type is an image type.
459 if (notification->type() != message_center::NOTIFICATION_TYPE_IMAGE) { 405 if (notification->type() != message_center::NOTIFICATION_TYPE_IMAGE) {
460 SetError(kExtraImageProvided); 406 SetError(kExtraImageProvided);
461 return false; 407 return false;
462 } 408 }
463 notification->set_image(image); 409 notification->set_image(image);
464 } 410 }
465 411
466 if (options->progress) { 412 if (options->progress) {
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 ? api::notifications::PERMISSION_LEVEL_GRANTED 630 ? api::notifications::PERMISSION_LEVEL_GRANTED
685 : api::notifications::PERMISSION_LEVEL_DENIED; 631 : api::notifications::PERMISSION_LEVEL_DENIED;
686 632
687 SetResult(new base::StringValue(api::notifications::ToString(result))); 633 SetResult(new base::StringValue(api::notifications::ToString(result)));
688 SendResponse(true); 634 SendResponse(true);
689 635
690 return true; 636 return true;
691 } 637 }
692 638
693 } // namespace extensions 639 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698