Chromium Code Reviews| 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 OnCloseEphimeralNotificationProfileLoaded( |
| 93 PlatformNotificationServiceImpl::GetInstance() | 94 const std::string& notification_id, |
| 94 ->GetNotificationUIManager()->CancelById(id, profile_id); | 95 Profile* profile) { |
| 96 PlatformNotificationServiceImpl::GetInstance()->GetNotificationDisplayService( | |
|
Peter Beverloo
2016/04/18 14:57:10
NotificationDisplayServiceFactory::GetForProfile(p
Miguel Garcia
2016/04/21 14:32:10
The follow up CL I noted does this.
https://codere
| |
| 97 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 ephimeral 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(); | |
|
Peter Beverloo
2016/04/18 14:57:10
To confirm, we imagine all of this moving to the N
Miguel Garcia
2016/04/21 14:32:10
Yes, once ids are generated in content.
| |
| 139 DCHECK(profile_manager); | |
| 140 profile_manager->LoadProfile( | |
| 141 profile_id, incognito, | |
| 142 base::Bind(&OnCloseEphimeralNotificationProfileLoaded, notification_id)); | |
| 143 } | |
| 144 | |
| 130 } // namespace | 145 } // namespace |
| 131 | 146 |
| 132 // static | 147 // static |
| 133 PlatformNotificationServiceImpl* | 148 PlatformNotificationServiceImpl* |
| 134 PlatformNotificationServiceImpl::GetInstance() { | 149 PlatformNotificationServiceImpl::GetInstance() { |
| 135 return base::Singleton<PlatformNotificationServiceImpl>::get(); | 150 return base::Singleton<PlatformNotificationServiceImpl>::get(); |
| 136 } | 151 } |
| 137 | 152 |
| 138 PlatformNotificationServiceImpl::PlatformNotificationServiceImpl() | 153 PlatformNotificationServiceImpl::PlatformNotificationServiceImpl() |
| 139 : native_notification_ui_manager_( | 154 : test_display_service_(nullptr) {} |
| 140 NotificationUIManager::CreateNativeNotificationManager()), | |
| 141 notification_ui_manager_for_tests_(nullptr) {} | |
| 142 | 155 |
| 143 PlatformNotificationServiceImpl::~PlatformNotificationServiceImpl() {} | 156 PlatformNotificationServiceImpl::~PlatformNotificationServiceImpl() {} |
| 144 | 157 |
| 145 void PlatformNotificationServiceImpl::ProcessPersistentNotificationOperation( | 158 void PlatformNotificationServiceImpl::ProcessPersistentNotificationOperation( |
| 146 NotificationOperation operation, | 159 NotificationOperation operation, |
| 147 const std::string& profile_id, | 160 const std::string& profile_id, |
| 148 bool incognito, | 161 bool incognito, |
| 149 const GURL& origin, | 162 const GURL& origin, |
| 150 int64_t persistent_notification_id, | 163 int64_t persistent_notification_id, |
| 151 int action_index) { | 164 int action_index) { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 322 | 335 |
| 323 Profile* profile = Profile::FromBrowserContext(browser_context); | 336 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 324 DCHECK(profile); | 337 DCHECK(profile); |
| 325 DCHECK_EQ(0u, notification_data.actions.size()); | 338 DCHECK_EQ(0u, notification_data.actions.size()); |
| 326 DCHECK_EQ(0u, notification_resources.action_icons.size()); | 339 DCHECK_EQ(0u, notification_resources.action_icons.size()); |
| 327 | 340 |
| 328 NotificationObjectProxy* proxy = | 341 NotificationObjectProxy* proxy = |
| 329 new NotificationObjectProxy(browser_context, std::move(delegate)); | 342 new NotificationObjectProxy(browser_context, std::move(delegate)); |
| 330 Notification notification = CreateNotificationFromData( | 343 Notification notification = CreateNotificationFromData( |
| 331 profile, origin, notification_data, notification_resources, proxy); | 344 profile, origin, notification_data, notification_resources, proxy); |
| 332 | 345 GetNotificationDisplayService(profile)->Display(notification.delegate_id(), |
| 333 GetNotificationUIManager()->Add(notification, profile); | 346 notification); |
| 334 if (cancel_callback) | 347 if (cancel_callback) { |
| 348 #if defined(OS_WIN) | |
| 349 std::string profile_id = | |
| 350 base::WideToUTF8(profile->GetPath().BaseName().value()); | |
| 351 #elif defined(OS_POSIX) | |
| 352 std::string profile_id = profile->GetPath().BaseName().value(); | |
| 353 #endif | |
| 335 *cancel_callback = | 354 *cancel_callback = |
| 336 base::Bind(&CancelNotification, | 355 base::Bind(&CancelNotification, notification.delegate_id(), profile_id, |
| 337 notification.delegate_id(), | 356 profile->IsOffTheRecord()); |
| 338 NotificationUIManager::GetProfileID(profile)); | 357 } |
| 339 | 358 |
| 340 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( | 359 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( |
| 341 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 360 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
| 342 } | 361 } |
| 343 | 362 |
| 344 void PlatformNotificationServiceImpl::DisplayPersistentNotification( | 363 void PlatformNotificationServiceImpl::DisplayPersistentNotification( |
| 345 BrowserContext* browser_context, | 364 BrowserContext* browser_context, |
| 346 int64_t persistent_notification_id, | 365 int64_t persistent_notification_id, |
| 347 const GURL& origin, | 366 const GURL& origin, |
| 348 const content::PlatformNotificationData& notification_data, | 367 const content::PlatformNotificationData& notification_data, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 359 browser_context, persistent_notification_id, origin, | 378 browser_context, persistent_notification_id, origin, |
| 360 settings_button_index); | 379 settings_button_index); |
| 361 | 380 |
| 362 Notification notification = CreateNotificationFromData( | 381 Notification notification = CreateNotificationFromData( |
| 363 profile, origin, notification_data, notification_resources, delegate); | 382 profile, origin, notification_data, notification_resources, delegate); |
| 364 | 383 |
| 365 // TODO(peter): Remove this mapping when we have reliable id generation for | 384 // TODO(peter): Remove this mapping when we have reliable id generation for |
| 366 // the message_center::Notification objects. | 385 // the message_center::Notification objects. |
| 367 persistent_notifications_[persistent_notification_id] = notification.id(); | 386 persistent_notifications_[persistent_notification_id] = notification.id(); |
| 368 | 387 |
| 369 GetNotificationUIManager()->Add(notification, profile); | 388 GetNotificationDisplayService(profile)->Display( |
| 389 base::Int64ToString(delegate->persistent_notification_id()), | |
| 390 notification); | |
| 370 content::RecordAction( | 391 content::RecordAction( |
| 371 base::UserMetricsAction("Notifications.Persistent.Shown")); | 392 base::UserMetricsAction("Notifications.Persistent.Shown")); |
| 372 | 393 |
| 373 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( | 394 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( |
| 374 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 395 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
| 375 } | 396 } |
| 376 | 397 |
| 377 void PlatformNotificationServiceImpl::ClosePersistentNotification( | 398 void PlatformNotificationServiceImpl::ClosePersistentNotification( |
| 378 BrowserContext* browser_context, | 399 BrowserContext* browser_context, |
| 379 int64_t persistent_notification_id) { | 400 int64_t persistent_notification_id) { |
| 380 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 401 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 381 | 402 |
| 382 Profile* profile = Profile::FromBrowserContext(browser_context); | 403 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 383 DCHECK(profile); | 404 DCHECK(profile); |
| 384 | 405 |
| 385 closed_notifications_.insert(persistent_notification_id); | 406 closed_notifications_.insert(persistent_notification_id); |
| 386 | 407 |
| 387 #if defined(OS_ANDROID) | 408 #if defined(OS_ANDROID) |
| 388 bool cancel_by_persistent_id = true; | 409 bool cancel_by_persistent_id = true; |
| 389 #else | 410 #else |
| 390 bool cancel_by_persistent_id = (native_notification_ui_manager_ != nullptr); | 411 bool cancel_by_persistent_id = |
| 412 GetNotificationDisplayService(profile)->SupportsNotificationCenter(); | |
| 391 #endif | 413 #endif |
| 392 | 414 |
| 393 if (cancel_by_persistent_id) { | 415 if (cancel_by_persistent_id) { |
| 394 // TODO(peter): Remove this conversion when the notification ids are being | 416 // TODO(peter): Remove this conversion when the notification ids are being |
| 395 // generated by the caller of this method. | 417 // generated by the caller of this method. |
| 396 GetNotificationUIManager()->CancelById( | 418 GetNotificationDisplayService(profile)->Close( |
| 397 base::Int64ToString(persistent_notification_id), | 419 base::Int64ToString(persistent_notification_id)); |
| 398 NotificationUIManager::GetProfileID(profile)); | |
| 399 } | 420 } |
| 400 | 421 |
| 401 auto iter = persistent_notifications_.find(persistent_notification_id); | 422 auto iter = persistent_notifications_.find(persistent_notification_id); |
| 402 if (iter == persistent_notifications_.end()) | 423 if (iter == persistent_notifications_.end()) |
| 403 return; | 424 return; |
| 404 | 425 |
| 405 GetNotificationUIManager()->CancelById( | 426 GetNotificationDisplayService(profile)->Close(iter->second); |
| 406 iter->second, NotificationUIManager::GetProfileID(profile)); | |
| 407 | 427 |
| 408 persistent_notifications_.erase(iter); | 428 persistent_notifications_.erase(iter); |
| 409 } | 429 } |
| 410 | 430 |
| 411 bool PlatformNotificationServiceImpl::GetDisplayedPersistentNotifications( | 431 bool PlatformNotificationServiceImpl::GetDisplayedPersistentNotifications( |
| 412 BrowserContext* browser_context, | 432 BrowserContext* browser_context, |
| 413 std::set<std::string>* displayed_notifications) { | 433 std::set<std::string>* displayed_notifications) { |
| 414 DCHECK(displayed_notifications); | 434 DCHECK(displayed_notifications); |
| 415 | 435 |
| 416 #if !defined(OS_ANDROID) | |
| 417 Profile* profile = Profile::FromBrowserContext(browser_context); | 436 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 418 if (!profile || profile->AsTestingProfile()) | 437 if (!profile || profile->AsTestingProfile()) |
| 419 return false; // Tests will not have a message center. | 438 return false; // Tests will not have a message center. |
| 420 | 439 |
| 421 NotificationUIManager* ui_manager = GetNotificationUIManager(); | |
| 422 DCHECK(ui_manager); | |
| 423 | |
| 424 // TODO(peter): Filter for persistent notifications only. | 440 // TODO(peter): Filter for persistent notifications only. |
| 425 *displayed_notifications = ui_manager->GetAllIdsByProfile( | 441 return GetNotificationDisplayService(profile)->GetDisplayed( |
| 426 NotificationUIManager::GetProfileID(profile)); | 442 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 } | 443 } |
| 435 | 444 |
| 436 Notification PlatformNotificationServiceImpl::CreateNotificationFromData( | 445 Notification PlatformNotificationServiceImpl::CreateNotificationFromData( |
| 437 Profile* profile, | 446 Profile* profile, |
| 438 const GURL& origin, | 447 const GURL& origin, |
| 439 const content::PlatformNotificationData& notification_data, | 448 const content::PlatformNotificationData& notification_data, |
| 440 const content::NotificationResources& notification_resources, | 449 const content::NotificationResources& notification_resources, |
| 441 NotificationDelegate* delegate) const { | 450 NotificationDelegate* delegate) const { |
| 442 DCHECK_EQ(notification_data.actions.size(), | 451 DCHECK_EQ(notification_data.actions.size(), |
| 443 notification_resources.action_icons.size()); | 452 notification_resources.action_icons.size()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 | 487 |
| 479 // On desktop, notifications with require_interaction==true stay on-screen | 488 // On desktop, notifications with require_interaction==true stay on-screen |
| 480 // rather than minimizing to the notification center after a timeout. | 489 // rather than minimizing to the notification center after a timeout. |
| 481 // On mobile, this is ignored (notifications are minimized at all times). | 490 // On mobile, this is ignored (notifications are minimized at all times). |
| 482 if (notification_data.require_interaction) | 491 if (notification_data.require_interaction) |
| 483 notification.set_never_timeout(true); | 492 notification.set_never_timeout(true); |
| 484 | 493 |
| 485 return notification; | 494 return notification; |
| 486 } | 495 } |
| 487 | 496 |
| 488 NotificationUIManager* | 497 NotificationDisplayService* |
| 489 PlatformNotificationServiceImpl::GetNotificationUIManager() const { | 498 PlatformNotificationServiceImpl::GetNotificationDisplayService( |
| 490 if (notification_ui_manager_for_tests_) | 499 Profile* profile) { |
| 491 return notification_ui_manager_for_tests_; | 500 if (test_display_service_ != nullptr) |
| 492 | 501 return test_display_service_; |
| 493 if (native_notification_ui_manager_) { | 502 return NotificationDisplayServiceFactory::GetForProfile(profile); |
| 494 return native_notification_ui_manager_.get(); | |
| 495 } | |
| 496 | |
| 497 return g_browser_process->notification_ui_manager(); | |
| 498 } | 503 } |
| 499 | 504 |
| 500 void PlatformNotificationServiceImpl::OpenNotificationSettings( | 505 void PlatformNotificationServiceImpl::OpenNotificationSettings( |
| 501 BrowserContext* browser_context) { | 506 BrowserContext* browser_context) { |
| 502 #if defined(OS_ANDROID) | 507 #if defined(OS_ANDROID) |
| 503 NOTIMPLEMENTED(); | 508 NOTIMPLEMENTED(); |
| 504 #else | 509 #else |
| 505 | 510 |
| 506 Profile* profile = Profile::FromBrowserContext(browser_context); | 511 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 507 DCHECK(profile); | 512 DCHECK(profile); |
| 508 | 513 |
| 509 if (switches::SettingsWindowEnabled()) { | 514 if (switches::SettingsWindowEnabled()) { |
| 510 chrome::ShowContentSettingsExceptionsInWindow( | 515 chrome::ShowContentSettingsExceptionsInWindow( |
| 511 profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 516 profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
| 512 } else { | 517 } else { |
| 513 chrome::ScopedTabbedBrowserDisplayer browser_displayer(profile); | 518 chrome::ScopedTabbedBrowserDisplayer browser_displayer(profile); |
| 514 chrome::ShowContentSettingsExceptions(browser_displayer.browser(), | 519 chrome::ShowContentSettingsExceptions(browser_displayer.browser(), |
| 515 CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 520 CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
| 516 } | 521 } |
| 517 | 522 |
| 518 #endif // defined(OS_ANDROID) | 523 #endif // defined(OS_ANDROID) |
| 519 } | 524 } |
| 520 | 525 |
| 521 void PlatformNotificationServiceImpl::SetNotificationUIManagerForTesting( | |
| 522 NotificationUIManager* manager) { | |
| 523 notification_ui_manager_for_tests_ = manager; | |
| 524 } | |
| 525 | |
| 526 base::string16 PlatformNotificationServiceImpl::DisplayNameForContextMessage( | 526 base::string16 PlatformNotificationServiceImpl::DisplayNameForContextMessage( |
| 527 Profile* profile, | 527 Profile* profile, |
| 528 const GURL& origin) const { | 528 const GURL& origin) const { |
| 529 #if defined(ENABLE_EXTENSIONS) | 529 #if defined(ENABLE_EXTENSIONS) |
| 530 // If the source is an extension, lookup the display name. | 530 // If the source is an extension, lookup the display name. |
| 531 if (origin.SchemeIs(extensions::kExtensionScheme)) { | 531 if (origin.SchemeIs(extensions::kExtensionScheme)) { |
| 532 const extensions::Extension* extension = | 532 const extensions::Extension* extension = |
| 533 extensions::ExtensionRegistry::Get(profile)->GetExtensionById( | 533 extensions::ExtensionRegistry::Get(profile)->GetExtensionById( |
| 534 origin.host(), extensions::ExtensionRegistry::EVERYTHING); | 534 origin.host(), extensions::ExtensionRegistry::EVERYTHING); |
| 535 DCHECK(extension); | 535 DCHECK(extension); |
| 536 | 536 |
| 537 return base::UTF8ToUTF16(extension->name()); | 537 return base::UTF8ToUTF16(extension->name()); |
| 538 } | 538 } |
| 539 #endif | 539 #endif |
| 540 | 540 |
| 541 return base::string16(); | 541 return base::string16(); |
| 542 } | 542 } |
| 543 | |
| 544 void PlatformNotificationServiceImpl::SetNotificationDisplayServiceForTesting( | |
| 545 NotificationDisplayService* display_service) { | |
| 546 test_display_service_ = display_service; | |
| 547 } | |
| OLD | NEW |