OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/notifications/platform_notification_service_impl.h" | 5 #include "chrome/browser/notifications/platform_notification_service_impl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" |
12 #include "base/metrics/user_metrics_action.h" | 12 #include "base/metrics/user_metrics_action.h" |
13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "build/build_config.h" | 15 #include "build/build_config.h" |
16 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
17 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 17 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
18 #include "chrome/browser/notifications/desktop_notification_profile_util.h" | 18 #include "chrome/browser/notifications/desktop_notification_profile_util.h" |
| 19 #include "chrome/browser/notifications/notification_display_service_factory.h" |
19 #include "chrome/browser/notifications/notification_object_proxy.h" | 20 #include "chrome/browser/notifications/notification_object_proxy.h" |
20 #include "chrome/browser/notifications/notification_ui_manager.h" | 21 #include "chrome/browser/notifications/notification_ui_manager.h" |
21 #include "chrome/browser/notifications/persistent_notification_delegate.h" | 22 #include "chrome/browser/notifications/persistent_notification_delegate.h" |
22 #include "chrome/browser/profiles/profile.h" | 23 #include "chrome/browser/profiles/profile.h" |
23 #include "chrome/browser/profiles/profile_io_data.h" | 24 #include "chrome/browser/profiles/profile_io_data.h" |
24 #include "chrome/browser/profiles/profile_manager.h" | 25 #include "chrome/browser/profiles/profile_manager.h" |
25 #include "chrome/browser/ui/browser.h" | 26 #include "chrome/browser/ui/browser.h" |
26 #include "chrome/browser/ui/chrome_pages.h" | 27 #include "chrome/browser/ui/chrome_pages.h" |
27 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" | 28 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" |
28 #include "chrome/common/chrome_switches.h" | 29 #include "chrome/common/chrome_switches.h" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 } | 83 } |
83 | 84 |
84 void OnCloseEventDispatchComplete( | 85 void OnCloseEventDispatchComplete( |
85 content::PersistentNotificationStatus status) { | 86 content::PersistentNotificationStatus status) { |
86 UMA_HISTOGRAM_ENUMERATION( | 87 UMA_HISTOGRAM_ENUMERATION( |
87 "Notifications.PersistentWebNotificationCloseResult", status, | 88 "Notifications.PersistentWebNotificationCloseResult", status, |
88 content::PersistentNotificationStatus:: | 89 content::PersistentNotificationStatus:: |
89 PERSISTENT_NOTIFICATION_STATUS_MAX); | 90 PERSISTENT_NOTIFICATION_STATUS_MAX); |
90 } | 91 } |
91 | 92 |
92 void CancelNotification(const std::string& id, ProfileID profile_id) { | 93 void OnCloseNonPersistentNotificationProfileLoaded( |
| 94 const std::string& notification_id, |
| 95 Profile* profile) { |
93 PlatformNotificationServiceImpl::GetInstance() | 96 PlatformNotificationServiceImpl::GetInstance() |
94 ->GetNotificationUIManager()->CancelById(id, profile_id); | 97 ->GetNotificationDisplayService(profile) |
| 98 ->Close(notification_id); |
95 } | 99 } |
96 | 100 |
97 // Callback to run once the profile has been loaded in order to perform a | 101 // Callback to run once the profile has been loaded in order to perform a |
98 // given |operation| in a notification. | 102 // given |operation| in a notification. |
99 void ProfileLoadedCallback( | 103 void ProfileLoadedCallback( |
100 PlatformNotificationServiceImpl::NotificationOperation operation, | 104 PlatformNotificationServiceImpl::NotificationOperation operation, |
101 const GURL& origin, | 105 const GURL& origin, |
102 int64_t persistent_notification_id, | 106 int64_t persistent_notification_id, |
103 int action_index, | 107 int action_index, |
104 Profile* profile) { | 108 Profile* profile) { |
(...skipping 15 matching lines...) Expand all Loading... |
120 ->OnPersistentNotificationClose(profile, persistent_notification_id, | 124 ->OnPersistentNotificationClose(profile, persistent_notification_id, |
121 origin, true); | 125 origin, true); |
122 break; | 126 break; |
123 case PlatformNotificationServiceImpl::NOTIFICATION_SETTINGS: | 127 case PlatformNotificationServiceImpl::NOTIFICATION_SETTINGS: |
124 PlatformNotificationServiceImpl::GetInstance()->OpenNotificationSettings( | 128 PlatformNotificationServiceImpl::GetInstance()->OpenNotificationSettings( |
125 profile); | 129 profile); |
126 break; | 130 break; |
127 } | 131 } |
128 } | 132 } |
129 | 133 |
| 134 // Callback used to close an non-persistent notification from blink. |
| 135 void CancelNotification(const std::string& notification_id, |
| 136 std::string profile_id, |
| 137 bool incognito) { |
| 138 ProfileManager* profile_manager = g_browser_process->profile_manager(); |
| 139 DCHECK(profile_manager); |
| 140 profile_manager->LoadProfile( |
| 141 profile_id, incognito, |
| 142 base::Bind(&OnCloseNonPersistentNotificationProfileLoaded, |
| 143 notification_id)); |
| 144 } |
| 145 |
130 } // namespace | 146 } // namespace |
131 | 147 |
132 // static | 148 // static |
133 PlatformNotificationServiceImpl* | 149 PlatformNotificationServiceImpl* |
134 PlatformNotificationServiceImpl::GetInstance() { | 150 PlatformNotificationServiceImpl::GetInstance() { |
135 return base::Singleton<PlatformNotificationServiceImpl>::get(); | 151 return base::Singleton<PlatformNotificationServiceImpl>::get(); |
136 } | 152 } |
137 | 153 |
138 PlatformNotificationServiceImpl::PlatformNotificationServiceImpl() | 154 PlatformNotificationServiceImpl::PlatformNotificationServiceImpl() |
139 : native_notification_ui_manager_( | 155 : test_display_service_(nullptr) {} |
140 NotificationUIManager::CreateNativeNotificationManager()), | |
141 notification_ui_manager_for_tests_(nullptr) {} | |
142 | 156 |
143 PlatformNotificationServiceImpl::~PlatformNotificationServiceImpl() {} | 157 PlatformNotificationServiceImpl::~PlatformNotificationServiceImpl() {} |
144 | 158 |
145 void PlatformNotificationServiceImpl::ProcessPersistentNotificationOperation( | 159 void PlatformNotificationServiceImpl::ProcessPersistentNotificationOperation( |
146 NotificationOperation operation, | 160 NotificationOperation operation, |
147 const std::string& profile_id, | 161 const std::string& profile_id, |
148 bool incognito, | 162 bool incognito, |
149 const GURL& origin, | 163 const GURL& origin, |
150 int64_t persistent_notification_id, | 164 int64_t persistent_notification_id, |
151 int action_index) { | 165 int action_index) { |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 | 336 |
323 Profile* profile = Profile::FromBrowserContext(browser_context); | 337 Profile* profile = Profile::FromBrowserContext(browser_context); |
324 DCHECK(profile); | 338 DCHECK(profile); |
325 DCHECK_EQ(0u, notification_data.actions.size()); | 339 DCHECK_EQ(0u, notification_data.actions.size()); |
326 DCHECK_EQ(0u, notification_resources.action_icons.size()); | 340 DCHECK_EQ(0u, notification_resources.action_icons.size()); |
327 | 341 |
328 NotificationObjectProxy* proxy = | 342 NotificationObjectProxy* proxy = |
329 new NotificationObjectProxy(browser_context, std::move(delegate)); | 343 new NotificationObjectProxy(browser_context, std::move(delegate)); |
330 Notification notification = CreateNotificationFromData( | 344 Notification notification = CreateNotificationFromData( |
331 profile, origin, notification_data, notification_resources, proxy); | 345 profile, origin, notification_data, notification_resources, proxy); |
332 | 346 GetNotificationDisplayService(profile)->Display(notification.delegate_id(), |
333 GetNotificationUIManager()->Add(notification, profile); | 347 notification); |
334 if (cancel_callback) | 348 if (cancel_callback) { |
| 349 #if defined(OS_WIN) |
| 350 std::string profile_id = |
| 351 base::WideToUTF8(profile->GetPath().BaseName().value()); |
| 352 #elif defined(OS_POSIX) |
| 353 std::string profile_id = profile->GetPath().BaseName().value(); |
| 354 #endif |
335 *cancel_callback = | 355 *cancel_callback = |
336 base::Bind(&CancelNotification, | 356 base::Bind(&CancelNotification, notification.delegate_id(), profile_id, |
337 notification.delegate_id(), | 357 profile->IsOffTheRecord()); |
338 NotificationUIManager::GetProfileID(profile)); | 358 } |
339 | 359 |
340 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( | 360 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( |
341 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 361 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
342 } | 362 } |
343 | 363 |
344 void PlatformNotificationServiceImpl::DisplayPersistentNotification( | 364 void PlatformNotificationServiceImpl::DisplayPersistentNotification( |
345 BrowserContext* browser_context, | 365 BrowserContext* browser_context, |
346 int64_t persistent_notification_id, | 366 int64_t persistent_notification_id, |
347 const GURL& origin, | 367 const GURL& origin, |
348 const content::PlatformNotificationData& notification_data, | 368 const content::PlatformNotificationData& notification_data, |
(...skipping 10 matching lines...) Expand all Loading... |
359 browser_context, persistent_notification_id, origin, | 379 browser_context, persistent_notification_id, origin, |
360 settings_button_index); | 380 settings_button_index); |
361 | 381 |
362 Notification notification = CreateNotificationFromData( | 382 Notification notification = CreateNotificationFromData( |
363 profile, origin, notification_data, notification_resources, delegate); | 383 profile, origin, notification_data, notification_resources, delegate); |
364 | 384 |
365 // TODO(peter): Remove this mapping when we have reliable id generation for | 385 // TODO(peter): Remove this mapping when we have reliable id generation for |
366 // the message_center::Notification objects. | 386 // the message_center::Notification objects. |
367 persistent_notifications_[persistent_notification_id] = notification.id(); | 387 persistent_notifications_[persistent_notification_id] = notification.id(); |
368 | 388 |
369 GetNotificationUIManager()->Add(notification, profile); | 389 GetNotificationDisplayService(profile)->Display( |
| 390 base::Int64ToString(delegate->persistent_notification_id()), |
| 391 notification); |
370 content::RecordAction( | 392 content::RecordAction( |
371 base::UserMetricsAction("Notifications.Persistent.Shown")); | 393 base::UserMetricsAction("Notifications.Persistent.Shown")); |
372 | 394 |
373 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( | 395 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( |
374 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 396 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
375 } | 397 } |
376 | 398 |
377 void PlatformNotificationServiceImpl::ClosePersistentNotification( | 399 void PlatformNotificationServiceImpl::ClosePersistentNotification( |
378 BrowserContext* browser_context, | 400 BrowserContext* browser_context, |
379 int64_t persistent_notification_id) { | 401 int64_t persistent_notification_id) { |
380 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 402 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
381 | 403 |
382 Profile* profile = Profile::FromBrowserContext(browser_context); | 404 Profile* profile = Profile::FromBrowserContext(browser_context); |
383 DCHECK(profile); | 405 DCHECK(profile); |
384 | 406 |
385 closed_notifications_.insert(persistent_notification_id); | 407 closed_notifications_.insert(persistent_notification_id); |
386 | 408 |
387 #if defined(OS_ANDROID) | 409 #if defined(OS_ANDROID) |
388 bool cancel_by_persistent_id = true; | 410 bool cancel_by_persistent_id = true; |
389 #else | 411 #else |
390 bool cancel_by_persistent_id = (native_notification_ui_manager_ != nullptr); | 412 bool cancel_by_persistent_id = |
| 413 GetNotificationDisplayService(profile)->SupportsNotificationCenter(); |
391 #endif | 414 #endif |
392 | 415 |
393 if (cancel_by_persistent_id) { | 416 if (cancel_by_persistent_id) { |
394 // TODO(peter): Remove this conversion when the notification ids are being | 417 // TODO(peter): Remove this conversion when the notification ids are being |
395 // generated by the caller of this method. | 418 // generated by the caller of this method. |
396 GetNotificationUIManager()->CancelById( | 419 GetNotificationDisplayService(profile)->Close( |
397 base::Int64ToString(persistent_notification_id), | 420 base::Int64ToString(persistent_notification_id)); |
398 NotificationUIManager::GetProfileID(profile)); | |
399 } | 421 } |
400 | 422 |
401 auto iter = persistent_notifications_.find(persistent_notification_id); | 423 auto iter = persistent_notifications_.find(persistent_notification_id); |
402 if (iter == persistent_notifications_.end()) | 424 if (iter == persistent_notifications_.end()) |
403 return; | 425 return; |
404 | 426 |
405 GetNotificationUIManager()->CancelById( | 427 GetNotificationDisplayService(profile)->Close(iter->second); |
406 iter->second, NotificationUIManager::GetProfileID(profile)); | |
407 | 428 |
408 persistent_notifications_.erase(iter); | 429 persistent_notifications_.erase(iter); |
409 } | 430 } |
410 | 431 |
411 bool PlatformNotificationServiceImpl::GetDisplayedPersistentNotifications( | 432 bool PlatformNotificationServiceImpl::GetDisplayedPersistentNotifications( |
412 BrowserContext* browser_context, | 433 BrowserContext* browser_context, |
413 std::set<std::string>* displayed_notifications) { | 434 std::set<std::string>* displayed_notifications) { |
414 DCHECK(displayed_notifications); | 435 DCHECK(displayed_notifications); |
415 | 436 |
416 #if !defined(OS_ANDROID) | |
417 Profile* profile = Profile::FromBrowserContext(browser_context); | 437 Profile* profile = Profile::FromBrowserContext(browser_context); |
418 if (!profile || profile->AsTestingProfile()) | 438 if (!profile || profile->AsTestingProfile()) |
419 return false; // Tests will not have a message center. | 439 return false; // Tests will not have a message center. |
420 | 440 |
421 NotificationUIManager* ui_manager = GetNotificationUIManager(); | |
422 DCHECK(ui_manager); | |
423 | |
424 // TODO(peter): Filter for persistent notifications only. | 441 // TODO(peter): Filter for persistent notifications only. |
425 *displayed_notifications = ui_manager->GetAllIdsByProfile( | 442 return GetNotificationDisplayService(profile)->GetDisplayed( |
426 NotificationUIManager::GetProfileID(profile)); | 443 displayed_notifications); |
427 | |
428 return true; | |
429 #else | |
430 // Android cannot reliably return the notifications that are currently being | |
431 // displayed on the platform, see the comment in NotificationUIManagerAndroid. | |
432 return false; | |
433 #endif // !defined(OS_ANDROID) | |
434 } | 444 } |
435 | 445 |
436 Notification PlatformNotificationServiceImpl::CreateNotificationFromData( | 446 Notification PlatformNotificationServiceImpl::CreateNotificationFromData( |
437 Profile* profile, | 447 Profile* profile, |
438 const GURL& origin, | 448 const GURL& origin, |
439 const content::PlatformNotificationData& notification_data, | 449 const content::PlatformNotificationData& notification_data, |
440 const content::NotificationResources& notification_resources, | 450 const content::NotificationResources& notification_resources, |
441 NotificationDelegate* delegate) const { | 451 NotificationDelegate* delegate) const { |
442 DCHECK_EQ(notification_data.actions.size(), | 452 DCHECK_EQ(notification_data.actions.size(), |
443 notification_resources.action_icons.size()); | 453 notification_resources.action_icons.size()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 | 488 |
479 // On desktop, notifications with require_interaction==true stay on-screen | 489 // On desktop, notifications with require_interaction==true stay on-screen |
480 // rather than minimizing to the notification center after a timeout. | 490 // rather than minimizing to the notification center after a timeout. |
481 // On mobile, this is ignored (notifications are minimized at all times). | 491 // On mobile, this is ignored (notifications are minimized at all times). |
482 if (notification_data.require_interaction) | 492 if (notification_data.require_interaction) |
483 notification.set_never_timeout(true); | 493 notification.set_never_timeout(true); |
484 | 494 |
485 return notification; | 495 return notification; |
486 } | 496 } |
487 | 497 |
488 NotificationUIManager* | 498 NotificationDisplayService* |
489 PlatformNotificationServiceImpl::GetNotificationUIManager() const { | 499 PlatformNotificationServiceImpl::GetNotificationDisplayService( |
490 if (notification_ui_manager_for_tests_) | 500 Profile* profile) { |
491 return notification_ui_manager_for_tests_; | 501 if (test_display_service_ != nullptr) |
492 | 502 return test_display_service_; |
493 if (native_notification_ui_manager_) { | 503 return NotificationDisplayServiceFactory::GetForProfile(profile); |
494 return native_notification_ui_manager_.get(); | |
495 } | |
496 | |
497 return g_browser_process->notification_ui_manager(); | |
498 } | 504 } |
499 | 505 |
500 void PlatformNotificationServiceImpl::OpenNotificationSettings( | 506 void PlatformNotificationServiceImpl::OpenNotificationSettings( |
501 BrowserContext* browser_context) { | 507 BrowserContext* browser_context) { |
502 #if defined(OS_ANDROID) | 508 #if defined(OS_ANDROID) |
503 NOTIMPLEMENTED(); | 509 NOTIMPLEMENTED(); |
504 #else | 510 #else |
505 | 511 |
506 Profile* profile = Profile::FromBrowserContext(browser_context); | 512 Profile* profile = Profile::FromBrowserContext(browser_context); |
507 DCHECK(profile); | 513 DCHECK(profile); |
508 | 514 |
509 if (switches::SettingsWindowEnabled()) { | 515 if (switches::SettingsWindowEnabled()) { |
510 chrome::ShowContentSettingsExceptionsInWindow( | 516 chrome::ShowContentSettingsExceptionsInWindow( |
511 profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 517 profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
512 } else { | 518 } else { |
513 chrome::ScopedTabbedBrowserDisplayer browser_displayer(profile); | 519 chrome::ScopedTabbedBrowserDisplayer browser_displayer(profile); |
514 chrome::ShowContentSettingsExceptions(browser_displayer.browser(), | 520 chrome::ShowContentSettingsExceptions(browser_displayer.browser(), |
515 CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 521 CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
516 } | 522 } |
517 | 523 |
518 #endif // defined(OS_ANDROID) | 524 #endif // defined(OS_ANDROID) |
519 } | 525 } |
520 | 526 |
521 void PlatformNotificationServiceImpl::SetNotificationUIManagerForTesting( | |
522 NotificationUIManager* manager) { | |
523 notification_ui_manager_for_tests_ = manager; | |
524 } | |
525 | |
526 base::string16 PlatformNotificationServiceImpl::DisplayNameForContextMessage( | 527 base::string16 PlatformNotificationServiceImpl::DisplayNameForContextMessage( |
527 Profile* profile, | 528 Profile* profile, |
528 const GURL& origin) const { | 529 const GURL& origin) const { |
529 #if defined(ENABLE_EXTENSIONS) | 530 #if defined(ENABLE_EXTENSIONS) |
530 // If the source is an extension, lookup the display name. | 531 // If the source is an extension, lookup the display name. |
531 if (origin.SchemeIs(extensions::kExtensionScheme)) { | 532 if (origin.SchemeIs(extensions::kExtensionScheme)) { |
532 const extensions::Extension* extension = | 533 const extensions::Extension* extension = |
533 extensions::ExtensionRegistry::Get(profile)->GetExtensionById( | 534 extensions::ExtensionRegistry::Get(profile)->GetExtensionById( |
534 origin.host(), extensions::ExtensionRegistry::EVERYTHING); | 535 origin.host(), extensions::ExtensionRegistry::EVERYTHING); |
535 DCHECK(extension); | 536 DCHECK(extension); |
536 | 537 |
537 return base::UTF8ToUTF16(extension->name()); | 538 return base::UTF8ToUTF16(extension->name()); |
538 } | 539 } |
539 #endif | 540 #endif |
540 | 541 |
541 return base::string16(); | 542 return base::string16(); |
542 } | 543 } |
| 544 |
| 545 void PlatformNotificationServiceImpl::SetNotificationDisplayServiceForTesting( |
| 546 NotificationDisplayService* display_service) { |
| 547 test_display_service_ = display_service; |
| 548 } |
OLD | NEW |