#include "base/memory/scoped_ptr.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
-#include "chrome/browser/chrome_notification_types.h"
+#include "base/stl_util.h"
+#include "chrome/browser/extensions/api/notification_provider/notification_provider_api.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/notifications/desktop_notification_service_factory.h"
+#include "chrome/browser/notifications/extension_welcome_notification.h"
+#include "chrome/browser/notifications/extension_welcome_notification_factory.h"
#include "chrome/browser/notifications/fullscreen_notification_blocker.h"
#include "chrome/browser/notifications/message_center_settings_controller.h"
#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/notifications/notification_conversion_helper.h"
#include "chrome/browser/notifications/screen_lock_notification_blocker.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/chrome_pages.h"
-#include "chrome/browser/ui/host_desktop.h"
+#include "chrome/common/extensions/api/notification_provider.h"
#include "chrome/common/pref_names.h"
-#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/browser/info_map.h"
+#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension_set.h"
+#include "extensions/common/permissions/permissions_data.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/message_center_tray.h"
message_center_->SetNotifierSettingsProvider(settings_provider_.get());
#if defined(OS_CHROMEOS)
+#if !defined(USE_ATHENA)
+ // TODO(oshima|hashimoto): Support notification on athena. crbug.com/408755.
blockers_.push_back(
new LoginStateNotificationBlockerChromeOS(message_center));
+#endif
#else
blockers_.push_back(new ScreenLockNotificationBlocker(message_center));
#endif
blockers_.push_back(new FullscreenNotificationBlocker(message_center));
#if defined(OS_WIN) || defined(OS_MACOSX) \
- || (defined(USE_AURA) && !defined(USE_ASH))
+ || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
// On Windows, Linux and Mac, the notification manager owns the tray icon and
// views.Other platforms have global ownership and Create will return NULL.
tray_.reset(message_center::CreateMessageCenterTray());
#endif
- registrar_.Add(this,
- chrome::NOTIFICATION_FULLSCREEN_CHANGED,
- content::NotificationService::AllSources());
}
MessageCenterNotificationManager::~MessageCenterNotificationManager() {
+ message_center_->SetNotifierSettingsProvider(NULL);
message_center_->RemoveObserver(this);
+
+ STLDeleteContainerPairSecondPointers(profile_notifications_.begin(),
+ profile_notifications_.end());
+ profile_notifications_.clear();
}
void MessageCenterNotificationManager::RegisterPrefs(
if (Update(notification, profile))
return;
- DesktopNotificationServiceFactory::GetForProfile(profile)->
+ ExtensionWelcomeNotificationFactory::GetForBrowserContext(profile)->
ShowWelcomeNotificationIfNecessary(notification);
- AddProfileNotification(
+ // WARNING: You MUST update the message center via the notification within a
+ // ProfileNotification object or the profile ID will not be correctly set for
+ // ChromeOS.
+ ProfileNotification* profile_notification(
new ProfileNotification(profile, notification, message_center_));
+ AddProfileNotification(profile_notification);
+
+ // TODO(liyanhou): Change the logic to only send notifications to one party.
+ // Currently, if there is an app with notificationProvider permission,
+ // notifications will go to both message center and the app.
+ // Change it to send notifications to message center only when the user chose
+ // default message center (extension_id.empty()).
+
+ // If there exist apps/extensions that have notificationProvider permission,
+ // route notifications to one of the apps/extensions.
+ std::string extension_id = GetExtensionTakingOverNotifications(profile);
+ if (!extension_id.empty())
+ profile_notification->AddToAlternateProvider(extension_id);
+
+ message_center_->AddNotification(make_scoped_ptr(
+ new message_center::Notification(profile_notification->notification())));
+ profile_notification->StartDownloads();
}
bool MessageCenterNotificationManager::Update(const Notification& notification,
// Changing the type from non-progress to progress does not count towards
// the immediate update allowed in the message center.
std::string old_id =
- old_notification->notification().notification_id();
- DCHECK(message_center_->HasNotification(old_id));
+ old_notification->notification().delegate_id();
// Add/remove notification in the local list but just update the same
// one in MessageCenter.
profile_notifications_.erase(old_id);
ProfileNotification* new_notification =
new ProfileNotification(profile, notification, message_center_);
- profile_notifications_[notification.notification_id()] = new_notification;
+ profile_notifications_[notification.delegate_id()] = new_notification;
- // Now pass a copy to message center.
- scoped_ptr<message_center::Notification> message_center_notification(
- make_scoped_ptr(new message_center::Notification(notification)));
- message_center_->UpdateNotification(old_id,
- message_center_notification.Pass());
+ // TODO(liyanhou): Add routing updated notifications to alternative
+ // providers.
+
+ // WARNING: You MUST use AddProfileNotification or update the message
+ // center via the notification within a ProfileNotification object or the
+ // profile ID will not be correctly set for ChromeOS.
+ message_center_->UpdateNotification(
+ old_id,
+ make_scoped_ptr(new message_center::Notification(
+ new_notification->notification())));
new_notification->StartDownloads();
return true;
tray_.reset(delegate);
}
-void MessageCenterNotificationManager::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- if (type == chrome::NOTIFICATION_FULLSCREEN_CHANGED) {
- const bool is_fullscreen = *content::Details<bool>(details).ptr();
-
- if (is_fullscreen && tray_.get() && tray_->GetMessageCenterTray())
- tray_->GetMessageCenterTray()->HidePopupBubble();
- }
-}
-
////////////////////////////////////////////////////////////////////////////////
// ImageDownloads
notification.icon_url(),
base::Bind(&message_center::MessageCenter::SetNotificationIcon,
base::Unretained(message_center_),
- notification.notification_id()));
+ notification.delegate_id()));
// Notification image.
StartDownloadWithImage(
notification.image_url(),
base::Bind(&message_center::MessageCenter::SetNotificationImage,
base::Unretained(message_center_),
- notification.notification_id()));
+ notification.delegate_id()));
// Notification button icons.
StartDownloadWithImage(
notification.button_one_icon_url(),
base::Bind(&message_center::MessageCenter::SetNotificationButtonIcon,
base::Unretained(message_center_),
- notification.notification_id(),
+ notification.delegate_id(),
0));
StartDownloadWithImage(
notification,
notification.button_two_icon_url(),
base::Bind(&message_center::MessageCenter::SetNotificationButtonIcon,
base::Unretained(message_center_),
- notification.notification_id(),
+ notification.delegate_id(),
1));
// This should tell the observer we're done if everything was synchronous.
if (url.is_empty())
return;
- content::WebContents* contents = notification.GetWebContents();
+ content::WebContents* contents = notification.delegate()->GetWebContents();
if (!contents) {
LOG(WARNING) << "Notification needs an image but has no WebContents";
return;
void
MessageCenterNotificationManager::ProfileNotification::OnDownloadsCompleted() {
- notification_.DoneRendering();
+ notification_.delegate()->ReleaseRenderViewHost();
}
-std::string
- MessageCenterNotificationManager::ProfileNotification::GetExtensionId() {
- extensions::InfoMap* extension_info_map =
- extensions::ExtensionSystem::Get(profile())->info_map();
- extensions::ExtensionSet extensions;
- extension_info_map->GetExtensionsWithAPIPermissionForSecurityOrigin(
- notification().origin_url(), notification().process_id(),
- extensions::APIPermission::kNotification, &extensions);
-
- DesktopNotificationService* desktop_service =
- DesktopNotificationServiceFactory::GetForProfile(profile());
- for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
- iter != extensions.end(); ++iter) {
- if (desktop_service->IsNotifierEnabled(message_center::NotifierId(
- message_center::NotifierId::APPLICATION, (*iter)->id()))) {
- return (*iter)->id();
- }
- }
- return std::string();
+void
+MessageCenterNotificationManager::ProfileNotification::AddToAlternateProvider(
+ const std::string extension_id) {
+ // Convert data from Notification type to NotificationOptions type.
+ extensions::api::notifications::NotificationOptions options;
+ NotificationConversionHelper::NotificationToNotificationOptions(notification_,
+ &options);
+
+ // Send the notification to the alternate provider extension/app.
+ extensions::NotificationProviderEventRouter event_router(profile_);
+ event_router.CreateNotification(extension_id,
+ notification_.notifier_id().id,
+ notification_.delegate_id(),
+ options);
}
////////////////////////////////////////////////////////////////////////////////
void MessageCenterNotificationManager::AddProfileNotification(
ProfileNotification* profile_notification) {
- const Notification& notification = profile_notification->notification();
- std::string id = notification.notification_id();
+ std::string id = profile_notification->notification().delegate_id();
// Notification ids should be unique.
DCHECK(profile_notifications_.find(id) == profile_notifications_.end());
profile_notifications_[id] = profile_notification;
-
- // Create the copy for message center, and ensure the extension ID is correct.
- scoped_ptr<message_center::Notification> message_center_notification(
- new message_center::Notification(notification));
- message_center_->AddNotification(message_center_notification.Pass());
-
- profile_notification->StartDownloads();
}
void MessageCenterNotificationManager::RemoveProfileNotification(
ProfileNotification* profile_notification) {
- std::string id = profile_notification->notification().notification_id();
+ std::string id = profile_notification->notification().delegate_id();
profile_notifications_.erase(id);
delete profile_notification;
}
return (*iter).second;
}
+
+std::string
+MessageCenterNotificationManager::GetExtensionTakingOverNotifications(
+ Profile* profile) {
+ // TODO(liyanhou): When additional settings in Chrome Settings is implemented,
+ // change choosing the last app with permission to a user selected app.
+ extensions::ExtensionRegistry* registry =
+ extensions::ExtensionRegistry::Get(profile);
+ DCHECK(registry);
+ std::string extension_id;
+ for (extensions::ExtensionSet::const_iterator it =
+ registry->enabled_extensions().begin();
+ it != registry->enabled_extensions().end();
+ ++it) {
+ if ((*it->get()).permissions_data()->HasAPIPermission(
+ extensions::APIPermission::ID::kNotificationProvider)) {
+ extension_id = (*it->get()).id();
+ return extension_id;
+ }
+ }
+ return extension_id;
+}