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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/notifications/notification_conversion_helper.cc
diff --git a/chrome/browser/notifications/notification_conversion_helper.cc b/chrome/browser/notifications/notification_conversion_helper.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0c70de6ea47a23ed8c11cc4bf9be432874145116
--- /dev/null
+++ b/chrome/browser/notifications/notification_conversion_helper.cc
@@ -0,0 +1,211 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/notification_conversion_helper.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/common/extensions/api/notification_provider.h"
+#include "chrome/common/extensions/api/notifications/notification_style.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_rep.h"
+#include "ui/gfx/skia_util.h"
+
+void NotificationConversionHelper::NotificationToNotificationOptions(
+ const Notification& notification,
+ extensions::api::notifications::NotificationOptions* options) {
+ // Extract required fields: type, title, message, and icon.
+ std::string type = MapTypeToString(notification.type());
+ options->type = extensions::api::notifications::ParseTemplateType(type);
+
+ if (!notification.icon().IsEmpty()) {
+ scoped_ptr<extensions::api::notifications::NotificationBitmap> icon(
+ new extensions::api::notifications::NotificationBitmap());
+ GfxImageToNotificationBitmap(&notification.icon(), icon.get());
+ options->icon_bitmap = icon.Pass();
+ }
+
+ options->title.reset(
+ new std::string(base::UTF16ToUTF8(notification.title())));
+ options->message.reset(
+ new std::string(base::UTF16ToUTF8(notification.message())));
+
+ // Handle optional data provided.
+ const message_center::RichNotificationData* rich_data =
+ &notification.rich_notification_data();
+
+ if (!rich_data->small_image.IsEmpty()) {
+ scoped_ptr<extensions::api::notifications::NotificationBitmap> icon_mask(
+ new extensions::api::notifications::NotificationBitmap());
+ GfxImageToNotificationBitmap(&rich_data->small_image, icon_mask.get());
+ options->app_icon_mask_bitmap = icon_mask.Pass();
+ }
+
+ options->priority.reset(new int(rich_data->priority));
+
+ options->is_clickable.reset(new bool(rich_data->clickable));
+
+ options->event_time.reset(new double(rich_data->timestamp.ToDoubleT()));
+
+ if (!rich_data->context_message.empty())
+ options->context_message.reset(
+ new std::string(base::UTF16ToUTF8(rich_data->context_message)));
+
+ if (!rich_data->buttons.empty()) {
+ scoped_ptr<std::vector<
+ linked_ptr<extensions::api::notifications::NotificationButton> > >
+ button_list(new std::vector<
+ linked_ptr<extensions::api::notifications::NotificationButton> >);
+ for (size_t i = 0; i < rich_data->buttons.size(); i++) {
+ linked_ptr<extensions::api::notifications::NotificationButton> button(
+ new extensions::api::notifications::NotificationButton);
+ button->title = base::UTF16ToUTF8(rich_data->buttons[i].title);
+
+ if (!rich_data->buttons[i].icon.IsEmpty()) {
+ scoped_ptr<extensions::api::notifications::NotificationBitmap> icon(
+ new extensions::api::notifications::NotificationBitmap());
+ GfxImageToNotificationBitmap(&rich_data->buttons[i].icon, icon.get());
+ button->icon_bitmap = icon.Pass();
+ }
+ button_list->push_back(button);
+ }
+ options->buttons = button_list.Pass();
+ }
+
+ // Only image type notifications should have images.
+ if (type == "image" && !rich_data->image.IsEmpty()) {
+ scoped_ptr<extensions::api::notifications::NotificationBitmap> image(
+ new extensions::api::notifications::NotificationBitmap());
+ GfxImageToNotificationBitmap(&notification.image(), image.get());
+ options->image_bitmap = image.Pass();
+ } else if (type != "image" && !rich_data->image.IsEmpty()) {
+ DVLOG(1) << "Only image type notifications should have images.";
+ }
+
+ // Only progress type notifications should have progress bars.
+ if (type == "progress")
+ options->progress.reset(new int(rich_data->progress));
+ else if (rich_data->progress != 0)
+ DVLOG(1) << "Only progress type notifications should have progress.";
+
+ // Only list type notifications should have lists.
+ if (type == "list" && !rich_data->items.empty()) {
+ scoped_ptr<std::vector<
+ linked_ptr<extensions::api::notifications::NotificationItem> > >
+ list(new std::vector<
+ linked_ptr<extensions::api::notifications::NotificationItem> >);
+ for (size_t j = 0; j < rich_data->items.size(); j++) {
+ linked_ptr<extensions::api::notifications::NotificationItem> item(
+ new extensions::api::notifications::NotificationItem);
+ item->title = base::UTF16ToUTF8(rich_data->items[j].title);
+ item->message = base::UTF16ToUTF8(rich_data->items[j].message);
+ list->push_back(item);
+ }
+ options->items = list.Pass();
+ } else if (type != "list" && !rich_data->items.empty()) {
+ DVLOG(1) << "Only list type notifications should have lists.";
+ }
+}
+
+void NotificationConversionHelper::GfxImageToNotificationBitmap(
+ const gfx::Image* gfx_image,
+ extensions::api::notifications::NotificationBitmap* notification_bitmap) {
+ SkBitmap sk_bitmap = gfx_image->AsBitmap();
+ sk_bitmap.lockPixels();
+
+ notification_bitmap->width = sk_bitmap.width();
+ notification_bitmap->height = sk_bitmap.height();
+ int pixel_count = sk_bitmap.width() * sk_bitmap.height();
+ const int BYTES_PER_PIXEL = 4;
+
+ uint32_t* bitmap_pixels = sk_bitmap.getAddr32(0, 0);
+ const unsigned char* bitmap =
+ reinterpret_cast<const unsigned char*>(bitmap_pixels);
+ unsigned char* bitmap_data(new unsigned char[pixel_count * BYTES_PER_PIXEL]);
+
+ gfx::ConvertSkiaToRGBA(bitmap, pixel_count, bitmap_data);
+ sk_bitmap.unlockPixels();
+
+ notification_bitmap->data.reset(new std::string(
+ bitmap_data, (bitmap_data + pixel_count * BYTES_PER_PIXEL)));
+ return;
+}
+
+bool NotificationConversionHelper::NotificationBitmapToGfxImage(
+ float max_scale,
+ const gfx::Size& target_size_dips,
+ extensions::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;
+}
+
+std::string NotificationConversionHelper::MapTypeToString(
+ message_center::NotificationType type) {
+ switch (type) {
+ case message_center::NOTIFICATION_TYPE_BASE_FORMAT:
+ return "basic";
+ case message_center::NOTIFICATION_TYPE_IMAGE:
+ return "image";
+ case message_center::NOTIFICATION_TYPE_MULTIPLE:
+ return "list";
+ case message_center::NOTIFICATION_TYPE_PROGRESS:
+ return "progress";
+ default:
+ NOTREACHED();
+ return "";
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698