1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_MESSAGE_CENTER_PUBLIC_CPP_NOTIFICATION_H_ 6 #define UI_MESSAGE_CENTER_PUBLIC_CPP_NOTIFICATION_H_ 7 8 #include <stddef.h> 9 10 #include <string> 11 #include <vector> 12 13 #include "base/memory/ref_counted.h" 14 #include "base/optional.h" 15 #include "base/strings/string16.h" 16 #include "base/time/time.h" 17 #include "base/values.h" 18 #include "third_party/skia/include/core/SkColor.h" 19 #include "ui/gfx/color_palette.h" 20 #include "ui/gfx/image/image.h" 21 #include "ui/gfx/paint_vector_icon.h" 22 #include "ui/gfx/skia_util.h" 23 #include "ui/gfx/vector_icon_types.h" 24 #include "ui/message_center/public/cpp/message_center_public_export.h" 25 #include "ui/message_center/public/cpp/notification_delegate.h" 26 #include "ui/message_center/public/cpp/notification_types.h" 27 #include "ui/message_center/public/cpp/notifier_id.h" 28 #include "url/gurl.h" 29 30 namespace gfx { 31 struct VectorIcon; 32 } // namespace gfx 33 34 namespace message_center { 35 36 // Represents an individual item in NOTIFICATION_TYPE_MULTIPLE notifications. 37 struct MESSAGE_CENTER_PUBLIC_EXPORT NotificationItem { 38 base::string16 title; 39 base::string16 message; 40 }; 41 42 enum class SettingsButtonHandler { 43 NONE = 0, // No button. This is the default. Does not affect native 44 // settings button (like on Android). 45 INLINE = 1, // Button shown, settings inline. 46 DELEGATE = 2, // Button shown, notification's delegate handles action. 47 }; 48 49 enum class SystemNotificationWarningLevel { NORMAL, WARNING, CRITICAL_WARNING }; 50 51 // Represents a button to be shown as part of a notification. 52 struct MESSAGE_CENTER_PUBLIC_EXPORT ButtonInfo { 53 explicit ButtonInfo(const base::string16& title); 54 ButtonInfo(const ButtonInfo& other); 55 ButtonInfo(); 56 ~ButtonInfo(); 57 ButtonInfo& operator=(const ButtonInfo& other); 58 59 // Title that should be displayed on the notification button. 60 base::string16 title; 61 62 // Icon that should be displayed on the notification button. Optional. On some 63 // platforms, a mask will be applied to the icon, to match the visual 64 // requirements of the notification. As with Android, MD notifications don't 65 // display this icon. 66 gfx::Image icon; 67 68 // The placeholder string that should be displayed in the input field for 69 // text input type buttons until the user has entered a response themselves. 70 // If the value is null, there is no input field associated with the button. 71 base::Optional<base::string16> placeholder; 72 }; 73 74 enum class FullscreenVisibility { 75 NONE = 0, // Don't show the notification over fullscreen (default). 76 OVER_USER = 1, // Show over the current fullscreened client window. 77 // windows (like Chrome OS login). 78 }; 79 80 // Represents rich features available for notifications. 81 class MESSAGE_CENTER_PUBLIC_EXPORT RichNotificationData { 82 public: 83 RichNotificationData(); 84 RichNotificationData(const RichNotificationData& other); 85 ~RichNotificationData(); 86 87 // Priority of the notification. This must be one of the NotificationPriority 88 // values defined in notification_types.h. 89 int priority = DEFAULT_PRIORITY; 90 91 // Whether the notification should remain on screen indefinitely. 92 bool never_timeout = false; 93 94 // Time indicating when the notification was shown. Defaults to the time at 95 // which the RichNotificationData instance is constructed. 96 base::Time timestamp; 97 98 // Context message to display below the notification's content. Optional. May 99 // not be used for notifications that have an explicit origin URL set. 100 base::string16 context_message; 101 102 // Large image to display on the notification. Optional. 103 gfx::Image image; 104 105 // Small badge to display on the notification to illustrate the source of the 106 // notification. Optional. 107 gfx::Image small_image; 108 109 // Vector version of |small_image|. 110 // Used by Notification::GenerateMaskedSmallIcon. 111 // If not available, |small_image| will be used by the method. Optional. 112 // 113 // Due to the restriction of CreateVectorIcon, this should be a pointer to 114 // globally defined VectorIcon instance e.g. kNotificationCapsLockIcon. 115 // gfx::Image created by gfx::CreateVectorIcon internally stores reference to 116 // VectorIcon, so the VectorIcon should live longer than gfx::Image instance. 117 // As a temporary solution to this problem, we make this variable a pointer 118 // and only pass globally defined constants. 119 // TODO(tetsui): Remove the pointer, after fixing VectorIconSource not to 120 // retain VectorIcon reference. https://crbug.com/760866 121 const gfx::VectorIcon* vector_small_image = &gfx::kNoneIcon; 122 123 // Items to display on the notification. Only applicable for notifications 124 // that have type NOTIFICATION_TYPE_MULTIPLE. 125 std::vector<NotificationItem> items; 126 127 // Progress, in range of [0-100], of NOTIFICATION_TYPE_PROGRESS notifications. 128 // Values outside of the range (e.g. -1) will show an infinite loading 129 // progress bar. 130 int progress = 0; 131 132 // Status text string shown in NOTIFICATION_TYPE_PROGRESS notifications. 133 // If MD style notification is not enabled, this attribute is ignored. 134 base::string16 progress_status; 135 136 // Buttons that should show up on the notification. A maximum of 16 buttons 137 // is supported by the current implementation, but this may differ between 138 // platforms. 139 std::vector<ButtonInfo> buttons; 140 141 // Whether updates to the visible notification should be announced to users 142 // depending on visual assistance systems. 143 bool should_make_spoken_feedback_for_popup_updates = true; 144 145 #if defined(OS_CHROMEOS) 146 // Flag if the notification is pinned. If true, the notification is pinned 147 // and the user can't remove it. 148 bool pinned = false; 149 #endif // defined(OS_CHROMEOS) 150 151 // Vibration pattern to play when displaying the notification. There must be 152 // an odd number of entries in this pattern when it's set: numbers of 153 // milliseconds to vibrate separated by numbers of milliseconds to pause. 154 std::vector<int> vibration_pattern; 155 156 // Whether the vibration pattern and other applicable announcement mechanisms 157 // should be considered when updating the notification. 158 bool renotify = false; 159 160 // Whether all announcement mechansims should be suppressed when displaying 161 // the notification. 162 bool silent = false; 163 164 // An accessible description of the notification's contents. 165 base::string16 accessible_name; 166 167 // Unified theme color used in new style notification. 168 // Usually, it should not be set directly. 169 // For system notification, ash::CreateSystemNotification with 170 // SystemNotificationWarningLevel should be used. 171 SkColor accent_color = SK_ColorTRANSPARENT; 172 173 // Controls whether a settings button should appear on the notification. See 174 // enum definition. TODO(estade): turn this into a boolean. See 175 // crbug.com/780342 176 SettingsButtonHandler settings_button_handler = SettingsButtonHandler::NONE; 177 178 // Controls whether a snooze button should appear on the notification. 179 bool should_show_snooze_button = false; 180 181 FullscreenVisibility fullscreen_visibility = FullscreenVisibility::NONE; 182 }; 183 184 class MESSAGE_CENTER_PUBLIC_EXPORT Notification { 185 public: 186 // Creates a new notification. 187 // 188 // |type|: Type of the notification that dictates the layout. 189 // |id|: Identifier of the notification. Showing a notification that shares 190 // its profile and identifier with an already visible notification will 191 // replace the former one 192 // |title|: Title of the notification. 193 // |message|: Body text of the notification. May not be used for certain 194 // values of |type|, for example list-style notifications. 195 // |icon|: Icon to show alongside of the notification. 196 // |display_source|: Textual representation of who's shown the notification. 197 // |origin_url|: URL of the website responsible for showing the notification. 198 // |notifier_id|: NotifierId instance representing the system responsible for 199 // showing the notification. 200 // |optional_fields|: Rich data that can be used to assign more elaborate 201 // features to notifications. 202 // |delegate|: Delegate that will influence the behaviour of this notification 203 // and receives events on its behalf. May be omitted. 204 Notification(NotificationType type, 205 const std::string& id, 206 const base::string16& title, 207 const base::string16& message, 208 const gfx::Image& icon, 209 const base::string16& display_source, 210 const GURL& origin_url, 211 const NotifierId& notifier_id, 212 const RichNotificationData& optional_fields, 213 scoped_refptr<NotificationDelegate> delegate); 214 215 // Creates a copy of the |other| notification. The delegate, if any, will be 216 // identical for both the Notification instances. The |id| of the notification 217 // will be replaced by the given value. 218 Notification(const std::string& id, const Notification& other); 219 220 // Creates a copy of the |other| notification. The delegate will be replaced 221 // by |delegate|. 222 Notification(scoped_refptr<NotificationDelegate> delegate, 223 const Notification& other); 224 225 // Creates a copy of the |other| notification. The delegate, if any, will be 226 // identical for both the Notification instances. 227 Notification(const Notification& other); 228 229 Notification& operator=(const Notification& other); 230 231 virtual ~Notification(); 232 233 // Performs a deep copy of |notification|, including images and (optionally) 234 // the body image, small image, and icon images which are not supported on all 235 // platforms. 236 static std::unique_ptr<Notification> DeepCopy( 237 const Notification& notification, 238 bool include_body_image, 239 bool include_small_image, 240 bool include_icon_images); 241 type()242 NotificationType type() const { return type_; } set_type(NotificationType type)243 void set_type(NotificationType type) { type_ = type; } 244 245 // Uniquely identifies a notification in the message center. For 246 // notification front ends that support multiple profiles, this id should 247 // identify a unique profile + frontend_notification_id combination. You can 248 // Use this id against the MessageCenter interface but not the 249 // NotificationUIManager interface. id()250 const std::string& id() const { return id_; } 251 title()252 const base::string16& title() const { return title_; } set_title(const base::string16 & title)253 void set_title(const base::string16& title) { title_ = title; } 254 message()255 const base::string16& message() const { return message_; } set_message(const base::string16 & message)256 void set_message(const base::string16& message) { message_ = message; } 257 258 // The origin URL of the script which requested the notification. 259 // Can be empty if the notification is requested by an extension or 260 // Chrome app. origin_url()261 const GURL& origin_url() const { return origin_url_; } set_origin_url(const GURL & origin_url)262 void set_origin_url(const GURL& origin_url) { origin_url_ = origin_url; } 263 264 // A display string for the source of the notification. display_source()265 const base::string16& display_source() const { return display_source_; } 266 notifier_id()267 const NotifierId& notifier_id() const { return notifier_id_; } 268 set_profile_id(const std::string & profile_id)269 void set_profile_id(const std::string& profile_id) { 270 notifier_id_.profile_id = profile_id; 271 } 272 273 // Begin unpacked values from optional_fields. priority()274 int priority() const { return optional_fields_.priority; } set_priority(int priority)275 void set_priority(int priority) { optional_fields_.priority = priority; } 276 277 // This vibration_pattern property currently has no effect on 278 // non-Android platforms. vibration_pattern()279 const std::vector<int>& vibration_pattern() const { 280 return optional_fields_.vibration_pattern; 281 } set_vibration_pattern(const std::vector<int> & vibration_pattern)282 void set_vibration_pattern(const std::vector<int>& vibration_pattern) { 283 optional_fields_.vibration_pattern = vibration_pattern; 284 } 285 286 // This property currently only works in platforms that support native 287 // notifications. 288 // It determines whether the sound and vibration effects should signal 289 // if the notification is replacing another notification. renotify()290 bool renotify() const { return optional_fields_.renotify; } set_renotify(bool renotify)291 void set_renotify(bool renotify) { optional_fields_.renotify = renotify; } 292 293 // This property currently has no effect on non-Android platforms. silent()294 bool silent() const { return optional_fields_.silent; } set_silent(bool silent)295 void set_silent(bool silent) { optional_fields_.silent = silent; } 296 timestamp()297 base::Time timestamp() const { return optional_fields_.timestamp; } set_timestamp(const base::Time & timestamp)298 void set_timestamp(const base::Time& timestamp) { 299 optional_fields_.timestamp = timestamp; 300 } 301 context_message()302 const base::string16 context_message() const { 303 return optional_fields_.context_message; 304 } 305 set_context_message(const base::string16 & context_message)306 void set_context_message(const base::string16& context_message) { 307 optional_fields_.context_message = context_message; 308 } 309 310 // Decides if the notification origin should be used as a context message 311 bool UseOriginAsContextMessage() const; 312 items()313 const std::vector<NotificationItem>& items() const { 314 return optional_fields_.items; 315 } set_items(const std::vector<NotificationItem> & items)316 void set_items(const std::vector<NotificationItem>& items) { 317 optional_fields_.items = items; 318 } 319 progress()320 int progress() const { return optional_fields_.progress; } set_progress(int progress)321 void set_progress(int progress) { optional_fields_.progress = progress; } 322 progress_status()323 base::string16 progress_status() const { 324 return optional_fields_.progress_status; 325 } set_progress_status(const base::string16 & progress_status)326 void set_progress_status(const base::string16& progress_status) { 327 optional_fields_.progress_status = progress_status; 328 } 329 330 // End unpacked values. 331 332 // Images fetched asynchronously. icon()333 const gfx::Image& icon() const { return icon_; } set_icon(const gfx::Image & icon)334 void set_icon(const gfx::Image& icon) { icon_ = icon; } 335 image()336 const gfx::Image& image() const { return optional_fields_.image; } set_image(const gfx::Image & image)337 void set_image(const gfx::Image& image) { optional_fields_.image = image; } 338 small_image()339 const gfx::Image& small_image() const { return optional_fields_.small_image; } set_small_image(const gfx::Image & image)340 void set_small_image(const gfx::Image& image) { 341 optional_fields_.small_image = image; 342 } 343 vector_small_image()344 const gfx::VectorIcon& vector_small_image() const { 345 return *optional_fields_.vector_small_image; 346 } 347 // Due to the restriction of CreateVectorIcon, this should be a pointer to 348 // globally defined VectorIcon instance e.g. kNotificationCapsLockIcon. 349 // See detailed comment in RichNotificationData::vector_small_image. set_vector_small_image(const gfx::VectorIcon & image)350 void set_vector_small_image(const gfx::VectorIcon& image) { 351 optional_fields_.vector_small_image = ℑ 352 } 353 354 // Mask the color of |small_image| to the given |color|. 355 // If |vector_small_image| is available, it returns the vector image 356 // filled by the |color|. 357 // Otherwise, it uses alpha channel of the rasterized |small_image| for 358 // masking. 359 gfx::Image GenerateMaskedSmallIcon(int dip_size, SkColor color) const; 360 361 // Buttons, with icons fetched asynchronously. buttons()362 const std::vector<ButtonInfo>& buttons() const { 363 return optional_fields_.buttons; 364 } set_buttons(const std::vector<ButtonInfo> & buttons)365 void set_buttons(const std::vector<ButtonInfo>& buttons) { 366 optional_fields_.buttons = buttons; 367 } 368 void SetButtonIcon(size_t index, const gfx::Image& icon); 369 370 // Used to keep the order of notifications with the same timestamp. 371 // The notification with lesser serial_number is considered 'older'. serial_number()372 unsigned serial_number() { return serial_number_; } 373 374 // Gets and sets whether the notifiction should remain onscreen permanently. never_timeout()375 bool never_timeout() const { return optional_fields_.never_timeout; } set_never_timeout(bool never_timeout)376 void set_never_timeout(bool never_timeout) { 377 optional_fields_.never_timeout = never_timeout; 378 } 379 pinned()380 bool pinned() const { 381 #if defined(OS_CHROMEOS) 382 return optional_fields_.pinned; 383 #else 384 return false; 385 #endif // defined(OS_CHROMEOS) 386 } 387 #if defined(OS_CHROMEOS) set_pinned(bool pinned)388 void set_pinned(bool pinned) { optional_fields_.pinned = pinned; } 389 #endif // defined(OS_CHROMEOS) 390 391 // Gets a text for spoken feedback. accessible_name()392 const base::string16& accessible_name() const { 393 return optional_fields_.accessible_name; 394 } 395 accent_color()396 SkColor accent_color() const { return optional_fields_.accent_color; } set_accent_color(SkColor accent_color)397 void set_accent_color(SkColor accent_color) { 398 optional_fields_.accent_color = accent_color; 399 } 400 should_show_settings_button()401 bool should_show_settings_button() const { 402 return optional_fields_.settings_button_handler != 403 SettingsButtonHandler::NONE; 404 } 405 set_settings_button_handler(SettingsButtonHandler handler)406 void set_settings_button_handler(SettingsButtonHandler handler) { 407 optional_fields_.settings_button_handler = handler; 408 } 409 should_show_snooze_button()410 bool should_show_snooze_button() const { 411 return optional_fields_.should_show_snooze_button; 412 } 413 fullscreen_visibility()414 FullscreenVisibility fullscreen_visibility() const { 415 return optional_fields_.fullscreen_visibility; 416 } set_fullscreen_visibility(FullscreenVisibility visibility)417 void set_fullscreen_visibility(FullscreenVisibility visibility) { 418 optional_fields_.fullscreen_visibility = visibility; 419 } 420 delegate()421 NotificationDelegate* delegate() const { return delegate_.get(); } 422 rich_notification_data()423 const RichNotificationData& rich_notification_data() const { 424 return optional_fields_; 425 } 426 set_delegate(scoped_refptr<NotificationDelegate> delegate)427 void set_delegate(scoped_refptr<NotificationDelegate> delegate) { 428 DCHECK(!delegate_); 429 delegate_ = delegate; 430 } 431 432 // Set the priority to SYSTEM. The system priority user needs to call this 433 // method explicitly, to avoid setting it accidentally. 434 void SetSystemPriority(); 435 custom_view_type()436 const std::string& custom_view_type() const { return custom_view_type_; } set_custom_view_type(const std::string & custom_view_type)437 void set_custom_view_type(const std::string& custom_view_type) { 438 DCHECK_EQ(type(), NotificationType::NOTIFICATION_TYPE_CUSTOM); 439 custom_view_type_ = custom_view_type; 440 } 441 442 protected: 443 // The type of notification we'd like displayed. 444 NotificationType type_; 445 446 std::string id_; 447 base::string16 title_; 448 base::string16 message_; 449 450 // Image data for the associated icon, used by Ash when available. 451 gfx::Image icon_; 452 453 // The display string for the source of the notification. Could be 454 // the same as |origin_url_|, or the name of an extension. 455 // Expected to be a localized user facing string. 456 base::string16 display_source_; 457 458 private: 459 // The origin URL of the script which requested the notification. 460 // Can be empty if requested through a chrome app or extension or if 461 // it's a system notification. 462 GURL origin_url_; 463 NotifierId notifier_id_; 464 RichNotificationData optional_fields_; 465 466 // TODO(estade): these book-keeping fields should be moved into 467 // NotificationList. 468 unsigned serial_number_; 469 470 // A proxy object that allows access back to the JavaScript object that 471 // represents the notification, for firing events. 472 scoped_refptr<NotificationDelegate> delegate_; 473 474 // For custom notifications this determines which factory will be used for 475 // creating the view for this notification. The type should match the type 476 // used to register the factory in MessageViewFactory. 477 std::string custom_view_type_; 478 }; 479 480 } // namespace message_center 481 482 #endif // UI_MESSAGE_CENTER_PUBLIC_CPP_NOTIFICATION_H_ 483