Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / content / child / notifications / notification_manager.cc
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
3 // found in the LICENSE file.
4
5 #include "content/child/notifications/notification_manager.h"
6
7 #include "base/lazy_instance.h"
8 #include "base/threading/thread_local.h"
9 #include "content/child/notifications/notification_dispatcher.h"
10 #include "content/child/thread_safe_sender.h"
11 #include "content/child/worker_task_runner.h"
12 #include "content/common/platform_notification_messages.h"
13 #include "content/public/common/show_desktop_notification_params.h"
14 #include "third_party/WebKit/public/platform/WebNotificationData.h"
15 #include "third_party/WebKit/public/platform/WebNotificationDelegate.h"
16 #include "third_party/WebKit/public/platform/WebSerializedOrigin.h"
17 #include "third_party/skia/include/core/SkBitmap.h"
18
19 using blink::WebNotificationPermission;
20
21 namespace content {
22 namespace {
23
24 int CurrentWorkerId() {
25   return WorkerTaskRunner::Instance()->CurrentWorkerId();
26 }
27
28 }  // namespace
29
30 static base::LazyInstance<base::ThreadLocalPointer<NotificationManager>>::Leaky
31     g_notification_manager_tls = LAZY_INSTANCE_INITIALIZER;
32
33 NotificationManager::NotificationManager(
34     ThreadSafeSender* thread_safe_sender,
35     NotificationDispatcher* notification_dispatcher)
36     : thread_safe_sender_(thread_safe_sender),
37       notification_dispatcher_(notification_dispatcher) {
38   g_notification_manager_tls.Pointer()->Set(this);
39 }
40
41 NotificationManager::~NotificationManager() {
42   g_notification_manager_tls.Pointer()->Set(nullptr);
43 }
44
45 NotificationManager* NotificationManager::ThreadSpecificInstance(
46     ThreadSafeSender* thread_safe_sender,
47     NotificationDispatcher* notification_dispatcher) {
48   if (g_notification_manager_tls.Pointer()->Get())
49     return g_notification_manager_tls.Pointer()->Get();
50
51   NotificationManager* manager = new NotificationManager(
52       thread_safe_sender, notification_dispatcher);
53   if (WorkerTaskRunner::Instance()->CurrentWorkerId())
54     WorkerTaskRunner::Instance()->AddStopObserver(manager);
55   return manager;
56 }
57
58 void NotificationManager::OnWorkerRunLoopStopped() {
59   delete this;
60 }
61
62 void NotificationManager::show(
63     const blink::WebSerializedOrigin& origin,
64     const blink::WebNotificationData& notification_data,
65     blink::WebNotificationDelegate* delegate) {
66   int notification_id =
67       notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
68
69   active_notifications_[notification_id] = delegate;
70
71   ShowDesktopNotificationHostMsgParams params;
72   params.origin = GURL(origin.string());
73
74   // TODO(peter): Move the notification_icon_loader to //content/child/ and use
75   // it to download Notification icons here.
76   params.icon = SkBitmap();
77   params.title = notification_data.title;
78   params.body = notification_data.body;
79
80   // TODO(peter): Remove the usage of the Blink WebTextDirection enumeration for
81   // the text direction of notifications throughout Chrome.
82   params.direction = blink::WebTextDirectionLeftToRight;
83   params.replace_id = notification_data.tag;
84
85   thread_safe_sender_->Send(new PlatformNotificationHostMsg_Show(
86       notification_id, params));
87 }
88
89 void NotificationManager::close(blink::WebNotificationDelegate* delegate) {
90   auto iter = active_notifications_.begin();
91   for (; iter != active_notifications_.end(); ++iter) {
92     if (iter->second != delegate)
93       continue;
94
95     thread_safe_sender_->Send(
96         new PlatformNotificationHostMsg_Close(iter->first));
97     active_notifications_.erase(iter);
98
99     delegate->dispatchCloseEvent();
100     return;
101   }
102
103   // It should not be possible for Blink to call close() on a Notification which
104   // does not exist anymore in the manager.
105   NOTREACHED();
106 }
107
108 void NotificationManager::notifyDelegateDestroyed(
109     blink::WebNotificationDelegate* delegate) {
110   auto iter = active_notifications_.begin();
111   for (; iter != active_notifications_.end(); ++iter) {
112     if (iter->second != delegate)
113       continue;
114
115     active_notifications_.erase(iter);
116     return;
117   }
118 }
119
120 WebNotificationPermission NotificationManager::checkPermission(
121     const blink::WebSerializedOrigin& origin) {
122   WebNotificationPermission permission =
123       blink::WebNotificationPermissionAllowed;
124   thread_safe_sender_->Send(new PlatformNotificationHostMsg_CheckPermission(
125       GURL(origin.string()), &permission));
126
127   return permission;
128 }
129
130 bool NotificationManager::OnMessageReceived(const IPC::Message& message) {
131   bool handled = true;
132   IPC_BEGIN_MESSAGE_MAP(NotificationManager, message)
133     IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidShow, OnShow);
134     IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClose, OnClose);
135     IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClick, OnClick);
136     IPC_MESSAGE_UNHANDLED(handled = false)
137   IPC_END_MESSAGE_MAP()
138
139   return handled;
140 }
141
142 void NotificationManager::OnShow(int id) {
143   const auto& iter = active_notifications_.find(id);
144   if (iter == active_notifications_.end())
145     return;
146
147   iter->second->dispatchShowEvent();
148 }
149
150 void NotificationManager::OnClose(int id) {
151   const auto& iter = active_notifications_.find(id);
152   if (iter == active_notifications_.end())
153     return;
154
155   iter->second->dispatchCloseEvent();
156   active_notifications_.erase(iter);
157 }
158
159 void NotificationManager::OnClick(int id) {
160   const auto& iter = active_notifications_.find(id);
161   if (iter == active_notifications_.end())
162     return;
163
164   iter->second->dispatchClickEvent();
165 }
166
167 }  // namespace content