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

Side by Side Diff: trunk/src/chrome/browser/extensions/api/notifications/notifications_api.cc

Issue 296113009: Revert 272211 "Allow high-res bitmaps to be passed in from notif..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 years, 7 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
« no previous file with comments | « no previous file | trunk/src/chrome/browser/extensions/api/notifications/notifications_apitest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_ui_manager.h" 17 #include "chrome/browser/notifications/notification_ui_manager.h"
18 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/chrome_version_info.h" 19 #include "chrome/common/chrome_version_info.h"
20 #include "chrome/common/extensions/api/notifications/notification_style.h"
21 #include "content/public/browser/render_process_host.h" 20 #include "content/public/browser/render_process_host.h"
22 #include "content/public/browser/render_view_host.h" 21 #include "content/public/browser/render_view_host.h"
23 #include "content/public/browser/web_contents.h" 22 #include "content/public/browser/web_contents.h"
24 #include "extensions/browser/event_router.h" 23 #include "extensions/browser/event_router.h"
25 #include "extensions/common/extension.h" 24 #include "extensions/common/extension.h"
26 #include "extensions/common/features/feature.h" 25 #include "extensions/common/features/feature.h"
27 #include "third_party/skia/include/core/SkBitmap.h" 26 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "ui/base/layout.h"
29 #include "ui/gfx/image/image.h" 27 #include "ui/gfx/image/image.h"
30 #include "ui/gfx/image/image_skia.h" 28 #include "ui/gfx/image/image_skia.h"
31 #include "ui/gfx/image/image_skia_rep.h" 29 #include "ui/gfx/image/image_skia_rep.h"
32 #include "ui/message_center/message_center_style.h" 30 #include "ui/message_center/message_center_style.h"
33 #include "ui/message_center/notifier_settings.h" 31 #include "ui/message_center/notifier_settings.h"
34 #include "url/gurl.h" 32 #include "url/gurl.h"
35 33
36 namespace extensions { 34 namespace extensions {
37 35
38 namespace notifications = api::notifications; 36 namespace notifications = api::notifications;
39 37
40 namespace { 38 namespace {
41 39
42 const char kMissingRequiredPropertiesForCreateNotification[] = 40 const char kMissingRequiredPropertiesForCreateNotification[] =
43 "Some of the required properties are missing: type, iconUrl, title and " 41 "Some of the required properties are missing: type, iconUrl, title and "
44 "message."; 42 "message.";
45 const char kUnableToDecodeIconError[] =
46 "Unable to successfully use the provided image.";
47 const char kUnexpectedProgressValueForNonProgressType[] = 43 const char kUnexpectedProgressValueForNonProgressType[] =
48 "The progress value should not be specified for non-progress notification"; 44 "The progress value should not be specified for non-progress notification";
49 const char kInvalidProgressValue[] = 45 const char kInvalidProgressValue[] =
50 "The progress value should range from 0 to 100"; 46 "The progress value should range from 0 to 100";
51 const char kExtraListItemsProvided[] =
52 "List items provided for notification type != list";
53 const char kExtraImageProvided[] =
54 "Image resource provided for notification type != image";
55 47
56 // Converts an object with width, height, and data in RGBA format into an 48 // Converts an object with width, height, and data in RGBA format into an
57 // gfx::Image (in ARGB format). 49 // gfx::Image (in ARGB format).
58 bool NotificationBitmapToGfxImage( 50 bool NotificationBitmapToGfxImage(
59 float max_scale,
60 const gfx::Size& target_size_dips,
61 api::notifications::NotificationBitmap* notification_bitmap, 51 api::notifications::NotificationBitmap* notification_bitmap,
62 gfx::Image* return_image) { 52 gfx::Image* return_image) {
63 if (!notification_bitmap) 53 if (!notification_bitmap)
64 return false; 54 return false;
65 55
66 const int max_device_pixel_width = target_size_dips.width() * max_scale; 56 // Ensure a sane set of dimensions.
67 const int max_device_pixel_height = target_size_dips.height() * max_scale; 57 const int max_width = message_center::kNotificationPreferredImageWidth;
68 58 const int max_height = message_center::kNotificationPreferredImageHeight;
69 const int BYTES_PER_PIXEL = 4; 59 const int BYTES_PER_PIXEL = 4;
70 60
71 const int width = notification_bitmap->width; 61 const int width = notification_bitmap->width;
72 const int height = notification_bitmap->height; 62 const int height = notification_bitmap->height;
73 63
74 if (width < 0 || height < 0 || width > max_device_pixel_width || 64 if (width < 0 || height < 0 || width > max_width || height > max_height)
75 height > max_device_pixel_height)
76 return false; 65 return false;
77 66
78 // Ensure we have rgba data. 67 // Ensure we have rgba data.
79 std::string* rgba_data = notification_bitmap->data.get(); 68 std::string* rgba_data = notification_bitmap->data.get();
80 if (!rgba_data) 69 if (!rgba_data)
81 return false; 70 return false;
82 71
83 const size_t rgba_data_length = rgba_data->length(); 72 const size_t rgba_data_length = rgba_data->length();
84 const size_t rgba_area = width * height; 73 const size_t rgba_area = width * height;
85 74
(...skipping 18 matching lines...) Expand all
104 for (size_t t = 0; t < rgba_area; ++t) { 93 for (size_t t = 0; t < rgba_area; ++t) {
105 // |c_rgba_data| is RGBA, pixels is ARGB. 94 // |c_rgba_data| is RGBA, pixels is ARGB.
106 size_t rgba_index = t * BYTES_PER_PIXEL; 95 size_t rgba_index = t * BYTES_PER_PIXEL;
107 pixels[t] = SkPreMultiplyColor( 96 pixels[t] = SkPreMultiplyColor(
108 ((c_rgba_data[rgba_index + 3] & 0xFF) << 24) | 97 ((c_rgba_data[rgba_index + 3] & 0xFF) << 24) |
109 ((c_rgba_data[rgba_index + 0] & 0xFF) << 16) | 98 ((c_rgba_data[rgba_index + 0] & 0xFF) << 16) |
110 ((c_rgba_data[rgba_index + 1] & 0xFF) << 8) | 99 ((c_rgba_data[rgba_index + 1] & 0xFF) << 8) |
111 ((c_rgba_data[rgba_index + 2] & 0xFF) << 0)); 100 ((c_rgba_data[rgba_index + 2] & 0xFF) << 0));
112 } 101 }
113 102
114 // TODO(dewittj): Handle HiDPI images with more than one scale factor 103 // TODO(dewittj): Handle HiDPI images.
115 // representation.
116 gfx::ImageSkia skia(gfx::ImageSkiaRep(bitmap, 1.0f)); 104 gfx::ImageSkia skia(gfx::ImageSkiaRep(bitmap, 1.0f));
117 *return_image = gfx::Image(skia); 105 *return_image = gfx::Image(skia);
118 return true; 106 return true;
119 } 107 }
120 108
121 // Given an extension id and another id, returns an id that is unique 109 // Given an extension id and another id, returns an id that is unique
122 // relative to other extensions. 110 // relative to other extensions.
123 std::string CreateScopedIdentifier(const std::string& extension_id, 111 std::string CreateScopedIdentifier(const std::string& extension_id,
124 const std::string& id) { 112 const std::string& id) {
125 return extension_id + "-" + id; 113 return extension_id + "-" + id;
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 // First, make sure the required fields exist: type, title, message, icon. 237 // First, make sure the required fields exist: type, title, message, icon.
250 // These fields are defined as optional in IDL such that they can be used as 238 // These fields are defined as optional in IDL such that they can be used as
251 // optional for notification updates. But for notification creations, they 239 // optional for notification updates. But for notification creations, they
252 // should be present. 240 // should be present.
253 if (options->type == api::notifications::TEMPLATE_TYPE_NONE || 241 if (options->type == api::notifications::TEMPLATE_TYPE_NONE ||
254 !options->icon_url || !options->title || !options->message) { 242 !options->icon_url || !options->title || !options->message) {
255 SetError(kMissingRequiredPropertiesForCreateNotification); 243 SetError(kMissingRequiredPropertiesForCreateNotification);
256 return false; 244 return false;
257 } 245 }
258 246
259 NotificationBitmapSizes bitmap_sizes = GetNotificationBitmapSizes();
260
261 float image_scale =
262 ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactors().back());
263
264 // Extract required fields: type, title, message, and icon. 247 // Extract required fields: type, title, message, and icon.
265 message_center::NotificationType type = 248 message_center::NotificationType type =
266 MapApiTemplateTypeToType(options->type); 249 MapApiTemplateTypeToType(options->type);
267 const base::string16 title(base::UTF8ToUTF16(*options->title)); 250 const base::string16 title(base::UTF8ToUTF16(*options->title));
268 const base::string16 message(base::UTF8ToUTF16(*options->message)); 251 const base::string16 message(base::UTF8ToUTF16(*options->message));
269 gfx::Image icon; 252 gfx::Image icon;
270 253
271 if (!NotificationBitmapToGfxImage(image_scale, 254 // TODO(dewittj): Return error if this fails.
272 bitmap_sizes.icon_size, 255 NotificationBitmapToGfxImage(options->icon_bitmap.get(), &icon);
273 options->icon_bitmap.get(),
274 &icon)) {
275 SetError(kUnableToDecodeIconError);
276 return false;
277 }
278 256
279 // Then, handle any optional data that's been provided. 257 // Then, handle any optional data that's been provided.
280 message_center::RichNotificationData optional_fields; 258 message_center::RichNotificationData optional_fields;
281 if (options->priority.get()) 259 if (options->priority.get())
282 optional_fields.priority = *options->priority; 260 optional_fields.priority = *options->priority;
283 261
284 if (options->event_time.get()) 262 if (options->event_time.get())
285 optional_fields.timestamp = base::Time::FromJsTime(*options->event_time); 263 optional_fields.timestamp = base::Time::FromJsTime(*options->event_time);
286 264
287 if (options->buttons.get()) { 265 if (options->buttons.get()) {
288 // Currently we allow up to 2 buttons. 266 // Currently we allow up to 2 buttons.
289 size_t number_of_buttons = options->buttons->size(); 267 size_t number_of_buttons = options->buttons->size();
290 number_of_buttons = number_of_buttons > 2 ? 2 : number_of_buttons; 268 number_of_buttons = number_of_buttons > 2 ? 2 : number_of_buttons;
291 269
292 for (size_t i = 0; i < number_of_buttons; i++) { 270 for (size_t i = 0; i < number_of_buttons; i++) {
293 message_center::ButtonInfo info( 271 message_center::ButtonInfo info(
294 base::UTF8ToUTF16((*options->buttons)[i]->title)); 272 base::UTF8ToUTF16((*options->buttons)[i]->title));
295 NotificationBitmapToGfxImage(image_scale, 273 NotificationBitmapToGfxImage((*options->buttons)[i]->icon_bitmap.get(),
296 bitmap_sizes.button_icon_size, 274 &info.icon);
297 (*options->buttons)[i]->icon_bitmap.get(),
298 &info.icon);
299 optional_fields.buttons.push_back(info); 275 optional_fields.buttons.push_back(info);
300 } 276 }
301 } 277 }
302 278
303 if (options->context_message) { 279 if (options->context_message) {
304 optional_fields.context_message = 280 optional_fields.context_message =
305 base::UTF8ToUTF16(*options->context_message); 281 base::UTF8ToUTF16(*options->context_message);
306 } 282 }
307 283
308 bool has_image = NotificationBitmapToGfxImage(image_scale, 284 bool has_image = NotificationBitmapToGfxImage(options->image_bitmap.get(),
309 bitmap_sizes.image_size,
310 options->image_bitmap.get(),
311 &optional_fields.image); 285 &optional_fields.image);
312 // We should have an image if and only if the type is an image type. 286 // We should have an image if and only if the type is an image type.
313 if (has_image != (type == message_center::NOTIFICATION_TYPE_IMAGE)) { 287 if (has_image != (type == message_center::NOTIFICATION_TYPE_IMAGE))
314 SetError(kExtraImageProvided);
315 return false; 288 return false;
316 }
317 289
318 // We should have list items if and only if the type is a multiple type. 290 // We should have list items if and only if the type is a multiple type.
319 bool has_list_items = options->items.get() && options->items->size() > 0; 291 bool has_list_items = options->items.get() && options->items->size() > 0;
320 if (has_list_items != (type == message_center::NOTIFICATION_TYPE_MULTIPLE)) { 292 if (has_list_items != (type == message_center::NOTIFICATION_TYPE_MULTIPLE))
321 SetError(kExtraListItemsProvided);
322 return false; 293 return false;
323 }
324 294
325 if (options->progress.get() != NULL) { 295 if (options->progress.get() != NULL) {
326 // We should have progress if and only if the type is a progress type. 296 // We should have progress if and only if the type is a progress type.
327 if (type != message_center::NOTIFICATION_TYPE_PROGRESS) { 297 if (type != message_center::NOTIFICATION_TYPE_PROGRESS) {
328 SetError(kUnexpectedProgressValueForNonProgressType); 298 SetError(kUnexpectedProgressValueForNonProgressType);
329 return false; 299 return false;
330 } 300 }
331 optional_fields.progress = *options->progress; 301 optional_fields.progress = *options->progress;
332 // Progress value should range from 0 to 100. 302 // Progress value should range from 0 to 100.
333 if (optional_fields.progress < 0 || optional_fields.progress > 100) { 303 if (optional_fields.progress < 0 || optional_fields.progress > 100) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 api_delegate); 338 api_delegate);
369 339
370 g_browser_process->notification_ui_manager()->Add(notification, GetProfile()); 340 g_browser_process->notification_ui_manager()->Add(notification, GetProfile());
371 return true; 341 return true;
372 } 342 }
373 343
374 bool NotificationsApiFunction::UpdateNotification( 344 bool NotificationsApiFunction::UpdateNotification(
375 const std::string& id, 345 const std::string& id,
376 api::notifications::NotificationOptions* options, 346 api::notifications::NotificationOptions* options,
377 Notification* notification) { 347 Notification* notification) {
378 NotificationBitmapSizes bitmap_sizes = GetNotificationBitmapSizes();
379 float image_scale =
380 ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactors().back());
381
382 // Update optional fields if provided. 348 // Update optional fields if provided.
383 if (options->type != api::notifications::TEMPLATE_TYPE_NONE) 349 if (options->type != api::notifications::TEMPLATE_TYPE_NONE)
384 notification->set_type(MapApiTemplateTypeToType(options->type)); 350 notification->set_type(MapApiTemplateTypeToType(options->type));
385 if (options->title) 351 if (options->title)
386 notification->set_title(base::UTF8ToUTF16(*options->title)); 352 notification->set_title(base::UTF8ToUTF16(*options->title));
387 if (options->message) 353 if (options->message)
388 notification->set_message(base::UTF8ToUTF16(*options->message)); 354 notification->set_message(base::UTF8ToUTF16(*options->message));
389 355
390 // TODO(dewittj): Return error if this fails. 356 // TODO(dewittj): Return error if this fails.
391 if (options->icon_bitmap) { 357 if (options->icon_bitmap) {
392 gfx::Image icon; 358 gfx::Image icon;
393 NotificationBitmapToGfxImage( 359 NotificationBitmapToGfxImage(options->icon_bitmap.get(), &icon);
394 image_scale, bitmap_sizes.icon_size, options->icon_bitmap.get(), &icon);
395 notification->set_icon(icon); 360 notification->set_icon(icon);
396 } 361 }
397 362
398 if (options->priority) 363 if (options->priority)
399 notification->set_priority(*options->priority); 364 notification->set_priority(*options->priority);
400 365
401 if (options->event_time) 366 if (options->event_time)
402 notification->set_timestamp(base::Time::FromJsTime(*options->event_time)); 367 notification->set_timestamp(base::Time::FromJsTime(*options->event_time));
403 368
404 if (options->buttons) { 369 if (options->buttons) {
405 // Currently we allow up to 2 buttons. 370 // Currently we allow up to 2 buttons.
406 size_t number_of_buttons = options->buttons->size(); 371 size_t number_of_buttons = options->buttons->size();
407 number_of_buttons = number_of_buttons > 2 ? 2 : number_of_buttons; 372 number_of_buttons = number_of_buttons > 2 ? 2 : number_of_buttons;
408 373
409 std::vector<message_center::ButtonInfo> buttons; 374 std::vector<message_center::ButtonInfo> buttons;
410 for (size_t i = 0; i < number_of_buttons; i++) { 375 for (size_t i = 0; i < number_of_buttons; i++) {
411 message_center::ButtonInfo button( 376 message_center::ButtonInfo button(
412 base::UTF8ToUTF16((*options->buttons)[i]->title)); 377 base::UTF8ToUTF16((*options->buttons)[i]->title));
413 NotificationBitmapToGfxImage(image_scale, 378 NotificationBitmapToGfxImage((*options->buttons)[i]->icon_bitmap.get(),
414 bitmap_sizes.button_icon_size, 379 &button.icon);
415 (*options->buttons)[i]->icon_bitmap.get(),
416 &button.icon);
417 buttons.push_back(button); 380 buttons.push_back(button);
418 } 381 }
419 notification->set_buttons(buttons); 382 notification->set_buttons(buttons);
420 } 383 }
421 384
422 if (options->context_message) { 385 if (options->context_message) {
423 notification->set_context_message( 386 notification->set_context_message(
424 base::UTF8ToUTF16(*options->context_message)); 387 base::UTF8ToUTF16(*options->context_message));
425 } 388 }
426 389
427 gfx::Image image; 390 gfx::Image image;
428 bool has_image = NotificationBitmapToGfxImage(image_scale, 391 if (NotificationBitmapToGfxImage(options->image_bitmap.get(), &image)) {
429 bitmap_sizes.image_size,
430 options->image_bitmap.get(),
431 &image);
432 if (has_image) {
433 // We should have an image if and only if the type is an image type. 392 // We should have an image if and only if the type is an image type.
434 if (notification->type() != message_center::NOTIFICATION_TYPE_IMAGE) { 393 if (notification->type() != message_center::NOTIFICATION_TYPE_IMAGE)
435 SetError(kExtraImageProvided);
436 return false; 394 return false;
437 }
438 notification->set_image(image); 395 notification->set_image(image);
439 } 396 }
440 397
441 if (options->progress) { 398 if (options->progress) {
442 // We should have progress if and only if the type is a progress type. 399 // We should have progress if and only if the type is a progress type.
443 if (notification->type() != message_center::NOTIFICATION_TYPE_PROGRESS) { 400 if (notification->type() != message_center::NOTIFICATION_TYPE_PROGRESS) {
444 SetError(kUnexpectedProgressValueForNonProgressType); 401 SetError(kUnexpectedProgressValueForNonProgressType);
445 return false; 402 return false;
446 } 403 }
447 int progress = *options->progress; 404 int progress = *options->progress;
448 // Progress value should range from 0 to 100. 405 // Progress value should range from 0 to 100.
449 if (progress < 0 || progress > 100) { 406 if (progress < 0 || progress > 100) {
450 SetError(kInvalidProgressValue); 407 SetError(kInvalidProgressValue);
451 return false; 408 return false;
452 } 409 }
453 notification->set_progress(progress); 410 notification->set_progress(progress);
454 } 411 }
455 412
456 if (options->items.get() && options->items->size() > 0) { 413 if (options->items.get() && options->items->size() > 0) {
457 // We should have list items if and only if the type is a multiple type. 414 // We should have list items if and only if the type is a multiple type.
458 if (notification->type() != message_center::NOTIFICATION_TYPE_MULTIPLE) { 415 if (notification->type() != message_center::NOTIFICATION_TYPE_MULTIPLE)
459 SetError(kExtraListItemsProvided);
460 return false; 416 return false;
461 }
462 417
463 std::vector<message_center::NotificationItem> items; 418 std::vector<message_center::NotificationItem> items;
464 using api::notifications::NotificationItem; 419 using api::notifications::NotificationItem;
465 std::vector<linked_ptr<NotificationItem> >::iterator i; 420 std::vector<linked_ptr<NotificationItem> >::iterator i;
466 for (i = options->items->begin(); i != options->items->end(); ++i) { 421 for (i = options->items->begin(); i != options->items->end(); ++i) {
467 message_center::NotificationItem item( 422 message_center::NotificationItem item(
468 base::UTF8ToUTF16(i->get()->title), 423 base::UTF8ToUTF16(i->get()->title),
469 base::UTF8ToUTF16(i->get()->message)); 424 base::UTF8ToUTF16(i->get()->message));
470 items.push_back(item); 425 items.push_back(item);
471 } 426 }
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 ? api::notifications::PERMISSION_LEVEL_GRANTED 614 ? api::notifications::PERMISSION_LEVEL_GRANTED
660 : api::notifications::PERMISSION_LEVEL_DENIED; 615 : api::notifications::PERMISSION_LEVEL_DENIED;
661 616
662 SetResult(new base::StringValue(api::notifications::ToString(result))); 617 SetResult(new base::StringValue(api::notifications::ToString(result)));
663 SendResponse(true); 618 SendResponse(true);
664 619
665 return true; 620 return true;
666 } 621 }
667 622
668 } // namespace extensions 623 } // namespace extensions
OLDNEW
« no previous file with comments | « no previous file | trunk/src/chrome/browser/extensions/api/notifications/notifications_apitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698