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