Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / notifications / message_center_notification_manager.cc
index c06040a..5ea8d24 100644 (file)
@@ -8,24 +8,25 @@
 #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"
@@ -70,26 +71,31 @@ MessageCenterNotificationManager::MessageCenterNotificationManager(
   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(
@@ -108,11 +114,31 @@ void MessageCenterNotificationManager::Add(const Notification& notification,
   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,
@@ -136,8 +162,7 @@ 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.
@@ -145,13 +170,18 @@ bool MessageCenterNotificationManager::Update(const Notification& notification,
       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;
@@ -285,18 +315,6 @@ void MessageCenterNotificationManager::SetMessageCenterTrayDelegateForTest(
   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
 
@@ -322,7 +340,7 @@ void MessageCenterNotificationManager::ImageDownloads::StartDownloads(
       notification.icon_url(),
       base::Bind(&message_center::MessageCenter::SetNotificationIcon,
                  base::Unretained(message_center_),
-                 notification.notification_id()));
+                 notification.delegate_id()));
 
   // Notification image.
   StartDownloadWithImage(
@@ -331,7 +349,7 @@ void MessageCenterNotificationManager::ImageDownloads::StartDownloads(
       notification.image_url(),
       base::Bind(&message_center::MessageCenter::SetNotificationImage,
                  base::Unretained(message_center_),
-                 notification.notification_id()));
+                 notification.delegate_id()));
 
   // Notification button icons.
   StartDownloadWithImage(
@@ -340,7 +358,7 @@ void MessageCenterNotificationManager::ImageDownloads::StartDownloads(
       notification.button_one_icon_url(),
       base::Bind(&message_center::MessageCenter::SetNotificationButtonIcon,
                  base::Unretained(message_center_),
-                 notification.notification_id(),
+                 notification.delegate_id(),
                  0));
   StartDownloadWithImage(
       notification,
@@ -348,7 +366,7 @@ void MessageCenterNotificationManager::ImageDownloads::StartDownloads(
       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.
@@ -370,7 +388,7 @@ void MessageCenterNotificationManager::ImageDownloads::StartDownloadWithImage(
   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;
@@ -441,28 +459,23 @@ void MessageCenterNotificationManager::ProfileNotification::StartDownloads() {
 
 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);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -470,23 +483,15 @@ std::string
 
 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;
 }
@@ -500,3 +505,25 @@ MessageCenterNotificationManager::ProfileNotification*
 
   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;
+}