| 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 CancelNotification(const std::string& notification_id, |
| 93 PlatformNotificationServiceImpl::GetInstance() | 94 std::string profile_id, |
| 94 ->GetNotificationUIManager()->CancelById(id, profile_id); | 95 bool incognito) { |
| 96 // We are going to need to load the profile from the id and call close |
| 97 // NotificationDisplayServiceFactory::GetForProfile(profile)->Close(id); |
| 95 } | 98 } |
| 96 | 99 |
| 97 // Callback to run once the profile has been loaded in order to perform a | 100 // Callback to run once the profile has been loaded in order to perform a |
| 98 // given |operation| in a notification. | 101 // given |operation| in a notification. |
| 99 void ProfileLoadedCallback( | 102 void ProfileLoadedCallback( |
| 100 PlatformNotificationServiceImpl::NotificationOperation operation, | 103 PlatformNotificationServiceImpl::NotificationOperation operation, |
| 101 const GURL& origin, | 104 const GURL& origin, |
| 102 int64_t persistent_notification_id, | 105 int64_t persistent_notification_id, |
| 103 int action_index, | 106 int action_index, |
| 104 bool incognito, | 107 bool incognito, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 } | 139 } |
| 137 | 140 |
| 138 } // namespace | 141 } // namespace |
| 139 | 142 |
| 140 // static | 143 // static |
| 141 PlatformNotificationServiceImpl* | 144 PlatformNotificationServiceImpl* |
| 142 PlatformNotificationServiceImpl::GetInstance() { | 145 PlatformNotificationServiceImpl::GetInstance() { |
| 143 return base::Singleton<PlatformNotificationServiceImpl>::get(); | 146 return base::Singleton<PlatformNotificationServiceImpl>::get(); |
| 144 } | 147 } |
| 145 | 148 |
| 146 PlatformNotificationServiceImpl::PlatformNotificationServiceImpl() | 149 PlatformNotificationServiceImpl::PlatformNotificationServiceImpl() {} |
| 147 : native_notification_ui_manager_( | |
| 148 NotificationUIManager::CreateNativeNotificationManager()), | |
| 149 notification_ui_manager_for_tests_(nullptr) {} | |
| 150 | 150 |
| 151 PlatformNotificationServiceImpl::~PlatformNotificationServiceImpl() {} | 151 PlatformNotificationServiceImpl::~PlatformNotificationServiceImpl() {} |
| 152 | 152 |
| 153 void PlatformNotificationServiceImpl::ProcessPersistentNotificationOperation( | 153 void PlatformNotificationServiceImpl::ProcessPersistentNotificationOperation( |
| 154 NotificationOperation operation, | 154 NotificationOperation operation, |
| 155 const std::string& profile_id, | 155 const std::string& profile_id, |
| 156 bool incognito, | 156 bool incognito, |
| 157 const GURL& origin, | 157 const GURL& origin, |
| 158 int64_t persistent_notification_id, | 158 int64_t persistent_notification_id, |
| 159 int action_index) { | 159 int action_index) { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 | 345 |
| 346 Profile* profile = Profile::FromBrowserContext(browser_context); | 346 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 347 DCHECK(profile); | 347 DCHECK(profile); |
| 348 DCHECK_EQ(0u, notification_data.actions.size()); | 348 DCHECK_EQ(0u, notification_data.actions.size()); |
| 349 DCHECK_EQ(0u, notification_resources.action_icons.size()); | 349 DCHECK_EQ(0u, notification_resources.action_icons.size()); |
| 350 | 350 |
| 351 NotificationObjectProxy* proxy = | 351 NotificationObjectProxy* proxy = |
| 352 new NotificationObjectProxy(browser_context, std::move(delegate)); | 352 new NotificationObjectProxy(browser_context, std::move(delegate)); |
| 353 Notification notification = CreateNotificationFromData( | 353 Notification notification = CreateNotificationFromData( |
| 354 profile, origin, notification_data, notification_resources, proxy); | 354 profile, origin, notification_data, notification_resources, proxy); |
| 355 NotificationDisplayServiceFactory::GetForProfile(profile)->Display( |
| 356 notification); |
| 355 | 357 |
| 356 GetNotificationUIManager()->Add(notification, profile); | |
| 357 if (cancel_callback) | 358 if (cancel_callback) |
| 358 *cancel_callback = | 359 *cancel_callback = base::Bind( |
| 359 base::Bind(&CancelNotification, | 360 &CancelNotification, notification.delegate_id(), |
| 360 notification.delegate_id(), | 361 profile->GetPath().BaseName().value(), // This will fail on Windows |
| 361 NotificationUIManager::GetProfileID(profile)); | 362 profile->IsOffTheRecord()); |
| 362 | 363 |
| 363 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( | 364 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( |
| 364 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 365 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
| 365 } | 366 } |
| 366 | 367 |
| 367 void PlatformNotificationServiceImpl::DisplayPersistentNotification( | 368 void PlatformNotificationServiceImpl::DisplayPersistentNotification( |
| 368 BrowserContext* browser_context, | 369 BrowserContext* browser_context, |
| 369 int64_t persistent_notification_id, | 370 int64_t persistent_notification_id, |
| 370 const GURL& origin, | 371 const GURL& origin, |
| 371 const content::PlatformNotificationData& notification_data, | 372 const content::PlatformNotificationData& notification_data, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 382 browser_context, persistent_notification_id, origin, | 383 browser_context, persistent_notification_id, origin, |
| 383 settings_button_index); | 384 settings_button_index); |
| 384 | 385 |
| 385 Notification notification = CreateNotificationFromData( | 386 Notification notification = CreateNotificationFromData( |
| 386 profile, origin, notification_data, notification_resources, delegate); | 387 profile, origin, notification_data, notification_resources, delegate); |
| 387 | 388 |
| 388 // TODO(peter): Remove this mapping when we have reliable id generation for | 389 // TODO(peter): Remove this mapping when we have reliable id generation for |
| 389 // the message_center::Notification objects. | 390 // the message_center::Notification objects. |
| 390 persistent_notifications_[persistent_notification_id] = notification.id(); | 391 persistent_notifications_[persistent_notification_id] = notification.id(); |
| 391 | 392 |
| 392 GetNotificationUIManager()->Add(notification, profile); | 393 NotificationDisplayServiceFactory::GetForProfile(profile)->Display( |
| 394 notification); |
| 395 |
| 393 content::RecordAction( | 396 content::RecordAction( |
| 394 base::UserMetricsAction("Notifications.Persistent.Shown")); | 397 base::UserMetricsAction("Notifications.Persistent.Shown")); |
| 395 | 398 |
| 396 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( | 399 HostContentSettingsMapFactory::GetForProfile(profile)->UpdateLastUsage( |
| 397 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 400 origin, origin, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
| 398 } | 401 } |
| 399 | 402 |
| 400 void PlatformNotificationServiceImpl::ClosePersistentNotification( | 403 void PlatformNotificationServiceImpl::ClosePersistentNotification( |
| 401 BrowserContext* browser_context, | 404 BrowserContext* browser_context, |
| 402 int64_t persistent_notification_id) { | 405 int64_t persistent_notification_id) { |
| 403 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 406 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 404 | 407 |
| 405 Profile* profile = Profile::FromBrowserContext(browser_context); | 408 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 406 DCHECK(profile); | 409 DCHECK(profile); |
| 407 | 410 |
| 408 closed_notifications_.insert(persistent_notification_id); | 411 closed_notifications_.insert(persistent_notification_id); |
| 409 | 412 |
| 410 #if defined(OS_ANDROID) | 413 #if defined(OS_ANDROID) |
| 411 bool cancel_by_persistent_id = true; | 414 bool cancel_by_persistent_id = true; |
| 412 #else | 415 #else |
| 413 bool cancel_by_persistent_id = (native_notification_ui_manager_ != nullptr); | 416 bool cancel_by_persistent_id = |
| 417 NotificationDisplayServiceFactory::GetForProfile(profile) |
| 418 ->SupportsNotificationCenter(); |
| 414 #endif | 419 #endif |
| 415 | 420 |
| 416 if (cancel_by_persistent_id) { | 421 if (cancel_by_persistent_id) { |
| 417 // TODO(peter): Remove this conversion when the notification ids are being | 422 // TODO(peter): Remove this conversion when the notification ids are being |
| 418 // generated by the caller of this method. | 423 // generated by the caller of this method. |
| 419 GetNotificationUIManager()->CancelById( | 424 NotificationDisplayServiceFactory::GetForProfile(profile)->Close( |
| 420 base::Int64ToString(persistent_notification_id), | 425 base::Int64ToString(persistent_notification_id)); |
| 421 NotificationUIManager::GetProfileID(profile)); | |
| 422 } | 426 } |
| 423 | 427 |
| 424 auto iter = persistent_notifications_.find(persistent_notification_id); | 428 auto iter = persistent_notifications_.find(persistent_notification_id); |
| 425 if (iter == persistent_notifications_.end()) | 429 if (iter == persistent_notifications_.end()) |
| 426 return; | 430 return; |
| 427 | 431 |
| 428 GetNotificationUIManager()->CancelById( | 432 NotificationDisplayServiceFactory::GetForProfile(profile)->Close( |
| 429 iter->second, NotificationUIManager::GetProfileID(profile)); | 433 iter->second); |
| 430 | 434 |
| 431 persistent_notifications_.erase(iter); | 435 persistent_notifications_.erase(iter); |
| 432 } | 436 } |
| 433 | 437 |
| 434 bool PlatformNotificationServiceImpl::GetDisplayedPersistentNotifications( | 438 bool PlatformNotificationServiceImpl::GetDisplayedPersistentNotifications( |
| 435 BrowserContext* browser_context, | 439 BrowserContext* browser_context, |
| 436 std::set<std::string>* displayed_notifications) { | 440 std::set<std::string>* displayed_notifications) { |
| 437 DCHECK(displayed_notifications); | 441 DCHECK(displayed_notifications); |
| 438 | 442 |
| 439 #if !defined(OS_ANDROID) | 443 #if !defined(OS_ANDROID) |
| 440 Profile* profile = Profile::FromBrowserContext(browser_context); | 444 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 441 if (!profile || profile->AsTestingProfile()) | 445 if (!profile || profile->AsTestingProfile()) |
| 442 return false; // Tests will not have a message center. | 446 return false; // Tests will not have a message center. |
| 443 | 447 |
| 444 // There may not be a notification ui manager when another feature erroneously | |
| 445 // instantiates a storage partition when the browser process is shutting down. | |
| 446 // TODO(peter): Remove in favor of a DCHECK when crbug.com/546745 is fixed. | |
| 447 NotificationUIManager* ui_manager = GetNotificationUIManager(); | |
| 448 if (!ui_manager) | |
| 449 return false; | |
| 450 | |
| 451 // TODO(peter): Filter for persistent notifications only. | 448 // TODO(peter): Filter for persistent notifications only. |
| 452 *displayed_notifications = ui_manager->GetAllIdsByProfile( | 449 *displayed_notifications = |
| 453 NotificationUIManager::GetProfileID(profile)); | 450 NotificationDisplayServiceFactory::GetForProfile(profile)->GetDisplayed(); |
| 454 | 451 |
| 455 return true; | 452 return true; |
| 456 #else | 453 #else |
| 457 // Android cannot reliably return the notifications that are currently being | 454 // Android cannot reliably return the notifications that are currently being |
| 458 // displayed on the platform, see the comment in NotificationUIManagerAndroid. | 455 // displayed on the platform, see the comment in NotificationUIManagerAndroid. |
| 459 return false; | 456 return false; |
| 460 #endif // !defined(OS_ANDROID) | 457 #endif // !defined(OS_ANDROID) |
| 461 } | 458 } |
| 462 | 459 |
| 463 Notification PlatformNotificationServiceImpl::CreateNotificationFromData( | 460 Notification PlatformNotificationServiceImpl::CreateNotificationFromData( |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 | 502 |
| 506 // On desktop, notifications with require_interaction==true stay on-screen | 503 // On desktop, notifications with require_interaction==true stay on-screen |
| 507 // rather than minimizing to the notification center after a timeout. | 504 // rather than minimizing to the notification center after a timeout. |
| 508 // On mobile, this is ignored (notifications are minimized at all times). | 505 // On mobile, this is ignored (notifications are minimized at all times). |
| 509 if (notification_data.require_interaction) | 506 if (notification_data.require_interaction) |
| 510 notification.set_never_timeout(true); | 507 notification.set_never_timeout(true); |
| 511 | 508 |
| 512 return notification; | 509 return notification; |
| 513 } | 510 } |
| 514 | 511 |
| 515 NotificationUIManager* | |
| 516 PlatformNotificationServiceImpl::GetNotificationUIManager() const { | |
| 517 if (notification_ui_manager_for_tests_) | |
| 518 return notification_ui_manager_for_tests_; | |
| 519 | |
| 520 if (native_notification_ui_manager_) { | |
| 521 return native_notification_ui_manager_.get(); | |
| 522 } | |
| 523 | |
| 524 return g_browser_process->notification_ui_manager(); | |
| 525 } | |
| 526 | |
| 527 void PlatformNotificationServiceImpl::OpenNotificationSettings( | 512 void PlatformNotificationServiceImpl::OpenNotificationSettings( |
| 528 BrowserContext* browser_context) { | 513 BrowserContext* browser_context) { |
| 529 #if defined(OS_ANDROID) | 514 #if defined(OS_ANDROID) |
| 530 NOTIMPLEMENTED(); | 515 NOTIMPLEMENTED(); |
| 531 #else | 516 #else |
| 532 | 517 |
| 533 Profile* profile = Profile::FromBrowserContext(browser_context); | 518 Profile* profile = Profile::FromBrowserContext(browser_context); |
| 534 DCHECK(profile); | 519 DCHECK(profile); |
| 535 | 520 |
| 536 if (switches::SettingsWindowEnabled()) { | 521 if (switches::SettingsWindowEnabled()) { |
| 537 chrome::ShowContentSettingsExceptionsInWindow( | 522 chrome::ShowContentSettingsExceptionsInWindow( |
| 538 profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 523 profile, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
| 539 } else { | 524 } else { |
| 540 chrome::ScopedTabbedBrowserDisplayer browser_displayer(profile); | 525 chrome::ScopedTabbedBrowserDisplayer browser_displayer(profile); |
| 541 chrome::ShowContentSettingsExceptions(browser_displayer.browser(), | 526 chrome::ShowContentSettingsExceptions(browser_displayer.browser(), |
| 542 CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | 527 CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
| 543 } | 528 } |
| 544 | 529 |
| 545 #endif // defined(OS_ANDROID) | 530 #endif // defined(OS_ANDROID) |
| 546 } | 531 } |
| 547 | 532 |
| 548 void PlatformNotificationServiceImpl::SetNotificationUIManagerForTesting( | |
| 549 NotificationUIManager* manager) { | |
| 550 notification_ui_manager_for_tests_ = manager; | |
| 551 } | |
| 552 | |
| 553 base::string16 PlatformNotificationServiceImpl::DisplayNameForContextMessage( | 533 base::string16 PlatformNotificationServiceImpl::DisplayNameForContextMessage( |
| 554 Profile* profile, | 534 Profile* profile, |
| 555 const GURL& origin) const { | 535 const GURL& origin) const { |
| 556 #if defined(ENABLE_EXTENSIONS) | 536 #if defined(ENABLE_EXTENSIONS) |
| 557 // If the source is an extension, lookup the display name. | 537 // If the source is an extension, lookup the display name. |
| 558 if (origin.SchemeIs(extensions::kExtensionScheme)) { | 538 if (origin.SchemeIs(extensions::kExtensionScheme)) { |
| 559 const extensions::Extension* extension = | 539 const extensions::Extension* extension = |
| 560 extensions::ExtensionRegistry::Get(profile)->GetExtensionById( | 540 extensions::ExtensionRegistry::Get(profile)->GetExtensionById( |
| 561 origin.host(), extensions::ExtensionRegistry::EVERYTHING); | 541 origin.host(), extensions::ExtensionRegistry::EVERYTHING); |
| 562 DCHECK(extension); | 542 DCHECK(extension); |
| 563 | 543 |
| 564 return base::UTF8ToUTF16(extension->name()); | 544 return base::UTF8ToUTF16(extension->name()); |
| 565 } | 545 } |
| 566 #endif | 546 #endif |
| 567 | 547 |
| 568 return base::string16(); | 548 return base::string16(); |
| 569 } | 549 } |
| OLD | NEW |