Index: trunk/src/chrome/browser/extensions/api/notifications/notifications_api.cc |
=================================================================== |
--- trunk/src/chrome/browser/extensions/api/notifications/notifications_api.cc (revision 289543) |
+++ trunk/src/chrome/browser/extensions/api/notifications/notifications_api.cc (working copy) |
@@ -14,7 +14,6 @@ |
#include "chrome/browser/notifications/desktop_notification_service.h" |
#include "chrome/browser/notifications/desktop_notification_service_factory.h" |
#include "chrome/browser/notifications/notification.h" |
-#include "chrome/browser/notifications/notification_conversion_helper.h" |
#include "chrome/browser/notifications/notification_ui_manager.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/common/chrome_version_info.h" |
@@ -54,6 +53,68 @@ |
const char kExtraImageProvided[] = |
"Image resource provided for notification type != image"; |
+// Converts an object with width, height, and data in RGBA format into an |
+// gfx::Image (in ARGB format). |
+bool NotificationBitmapToGfxImage( |
+ float max_scale, |
+ const gfx::Size& target_size_dips, |
+ api::notifications::NotificationBitmap* notification_bitmap, |
+ gfx::Image* return_image) { |
+ if (!notification_bitmap) |
+ return false; |
+ |
+ const int max_device_pixel_width = target_size_dips.width() * max_scale; |
+ const int max_device_pixel_height = target_size_dips.height() * max_scale; |
+ |
+ const int BYTES_PER_PIXEL = 4; |
+ |
+ const int width = notification_bitmap->width; |
+ const int height = notification_bitmap->height; |
+ |
+ if (width < 0 || height < 0 || width > max_device_pixel_width || |
+ height > max_device_pixel_height) |
+ return false; |
+ |
+ // Ensure we have rgba data. |
+ std::string* rgba_data = notification_bitmap->data.get(); |
+ if (!rgba_data) |
+ return false; |
+ |
+ const size_t rgba_data_length = rgba_data->length(); |
+ const size_t rgba_area = width * height; |
+ |
+ if (rgba_data_length != rgba_area * BYTES_PER_PIXEL) |
+ return false; |
+ |
+ SkBitmap bitmap; |
+ // Allocate the actual backing store with the sanitized dimensions. |
+ if (!bitmap.allocN32Pixels(width, height)) |
+ return false; |
+ |
+ // Ensure that our bitmap and our data now refer to the same number of pixels. |
+ if (rgba_data_length != bitmap.getSafeSize()) |
+ return false; |
+ |
+ uint32_t* pixels = bitmap.getAddr32(0, 0); |
+ const char* c_rgba_data = rgba_data->data(); |
+ |
+ for (size_t t = 0; t < rgba_area; ++t) { |
+ // |c_rgba_data| is RGBA, pixels is ARGB. |
+ size_t rgba_index = t * BYTES_PER_PIXEL; |
+ pixels[t] = SkPreMultiplyColor( |
+ ((c_rgba_data[rgba_index + 3] & 0xFF) << 24) | |
+ ((c_rgba_data[rgba_index + 0] & 0xFF) << 16) | |
+ ((c_rgba_data[rgba_index + 1] & 0xFF) << 8) | |
+ ((c_rgba_data[rgba_index + 2] & 0xFF) << 0)); |
+ } |
+ |
+ // TODO(dewittj): Handle HiDPI images with more than one scale factor |
+ // representation. |
+ gfx::ImageSkia skia(gfx::ImageSkiaRep(bitmap, 1.0f)); |
+ *return_image = gfx::Image(skia); |
+ return true; |
+} |
+ |
// Given an extension id and another id, returns an id that is unique |
// relative to other extensions. |
std::string CreateScopedIdentifier(const std::string& extension_id, |
@@ -214,11 +275,10 @@ |
const base::string16 message(base::UTF8ToUTF16(*options->message)); |
gfx::Image icon; |
- if (!NotificationConversionHelper::NotificationBitmapToGfxImage( |
- image_scale, |
- bitmap_sizes.icon_size, |
- options->icon_bitmap.get(), |
- &icon)) { |
+ if (!NotificationBitmapToGfxImage(image_scale, |
+ bitmap_sizes.icon_size, |
+ options->icon_bitmap.get(), |
+ &icon)) { |
SetError(kUnableToDecodeIconError); |
return false; |
} |
@@ -226,11 +286,10 @@ |
// Then, handle any optional data that's been provided. |
message_center::RichNotificationData optional_fields; |
if (options->app_icon_mask_url.get()) { |
- if (!NotificationConversionHelper::NotificationBitmapToGfxImage( |
- image_scale, |
- bitmap_sizes.app_icon_mask_size, |
- options->app_icon_mask_bitmap.get(), |
- &optional_fields.small_image)) { |
+ if (!NotificationBitmapToGfxImage(image_scale, |
+ bitmap_sizes.app_icon_mask_size, |
+ options->app_icon_mask_bitmap.get(), |
+ &optional_fields.small_image)) { |
SetError(kUnableToDecodeIconError); |
return false; |
} |
@@ -250,11 +309,10 @@ |
for (size_t i = 0; i < number_of_buttons; i++) { |
message_center::ButtonInfo info( |
base::UTF8ToUTF16((*options->buttons)[i]->title)); |
- NotificationConversionHelper::NotificationBitmapToGfxImage( |
- image_scale, |
- bitmap_sizes.button_icon_size, |
- (*options->buttons)[i]->icon_bitmap.get(), |
- &info.icon); |
+ NotificationBitmapToGfxImage(image_scale, |
+ bitmap_sizes.button_icon_size, |
+ (*options->buttons)[i]->icon_bitmap.get(), |
+ &info.icon); |
optional_fields.buttons.push_back(info); |
} |
} |
@@ -264,11 +322,10 @@ |
base::UTF8ToUTF16(*options->context_message); |
} |
- bool has_image = NotificationConversionHelper::NotificationBitmapToGfxImage( |
- image_scale, |
- bitmap_sizes.image_size, |
- options->image_bitmap.get(), |
- &optional_fields.image); |
+ bool has_image = NotificationBitmapToGfxImage(image_scale, |
+ bitmap_sizes.image_size, |
+ options->image_bitmap.get(), |
+ &optional_fields.image); |
// We should have an image if and only if the type is an image type. |
if (has_image != (type == message_center::NOTIFICATION_TYPE_IMAGE)) { |
SetError(kExtraImageProvided); |
@@ -350,17 +407,16 @@ |
// TODO(dewittj): Return error if this fails. |
if (options->icon_bitmap) { |
gfx::Image icon; |
- NotificationConversionHelper::NotificationBitmapToGfxImage( |
+ NotificationBitmapToGfxImage( |
image_scale, bitmap_sizes.icon_size, options->icon_bitmap.get(), &icon); |
notification->set_icon(icon); |
} |
gfx::Image app_icon_mask; |
- if (NotificationConversionHelper::NotificationBitmapToGfxImage( |
- image_scale, |
- bitmap_sizes.app_icon_mask_size, |
- options->app_icon_mask_bitmap.get(), |
- &app_icon_mask)) { |
+ if (NotificationBitmapToGfxImage(image_scale, |
+ bitmap_sizes.app_icon_mask_size, |
+ options->app_icon_mask_bitmap.get(), |
+ &app_icon_mask)) { |
notification->set_small_image(app_icon_mask); |
} |
@@ -379,11 +435,10 @@ |
for (size_t i = 0; i < number_of_buttons; i++) { |
message_center::ButtonInfo button( |
base::UTF8ToUTF16((*options->buttons)[i]->title)); |
- NotificationConversionHelper::NotificationBitmapToGfxImage( |
- image_scale, |
- bitmap_sizes.button_icon_size, |
- (*options->buttons)[i]->icon_bitmap.get(), |
- &button.icon); |
+ NotificationBitmapToGfxImage(image_scale, |
+ bitmap_sizes.button_icon_size, |
+ (*options->buttons)[i]->icon_bitmap.get(), |
+ &button.icon); |
buttons.push_back(button); |
} |
notification->set_buttons(buttons); |
@@ -395,11 +450,10 @@ |
} |
gfx::Image image; |
- bool has_image = NotificationConversionHelper::NotificationBitmapToGfxImage( |
- image_scale, |
- bitmap_sizes.image_size, |
- options->image_bitmap.get(), |
- &image); |
+ bool has_image = NotificationBitmapToGfxImage(image_scale, |
+ bitmap_sizes.image_size, |
+ options->image_bitmap.get(), |
+ &image); |
if (has_image) { |
// We should have an image if and only if the type is an image type. |
if (notification->type() != message_center::NOTIFICATION_TYPE_IMAGE) { |