ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / content / child / notifications / notification_manager.cc
blobcccece9ab427f168892c70e95d9464961a37106e
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.
5 #include "content/child/notifications/notification_manager.h"
7 #include "base/lazy_instance.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "base/threading/thread_local.h"
11 #include "content/child/notifications/notification_data_conversions.h"
12 #include "content/child/notifications/notification_dispatcher.h"
13 #include "content/child/service_worker/web_service_worker_registration_impl.h"
14 #include "content/child/thread_safe_sender.h"
15 #include "content/child/worker_task_runner.h"
16 #include "content/common/platform_notification_messages.h"
17 #include "content/public/common/platform_notification_data.h"
18 #include "third_party/WebKit/public/platform/WebSerializedOrigin.h"
19 #include "third_party/WebKit/public/platform/modules/notifications/WebNotificationDelegate.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
22 using blink::WebNotificationPermission;
24 namespace content {
25 namespace {
27 int CurrentWorkerId() {
28 return WorkerTaskRunner::Instance()->CurrentWorkerId();
31 } // namespace
33 static base::LazyInstance<base::ThreadLocalPointer<NotificationManager>>::Leaky
34 g_notification_manager_tls = LAZY_INSTANCE_INITIALIZER;
36 NotificationManager::NotificationManager(
37 ThreadSafeSender* thread_safe_sender,
38 base::SingleThreadTaskRunner* main_thread_task_runner,
39 NotificationDispatcher* notification_dispatcher)
40 : thread_safe_sender_(thread_safe_sender),
41 notification_dispatcher_(notification_dispatcher),
42 pending_notifications_(main_thread_task_runner) {
43 g_notification_manager_tls.Pointer()->Set(this);
46 NotificationManager::~NotificationManager() {
47 g_notification_manager_tls.Pointer()->Set(nullptr);
50 NotificationManager* NotificationManager::ThreadSpecificInstance(
51 ThreadSafeSender* thread_safe_sender,
52 base::SingleThreadTaskRunner* main_thread_task_runner,
53 NotificationDispatcher* notification_dispatcher) {
54 if (g_notification_manager_tls.Pointer()->Get())
55 return g_notification_manager_tls.Pointer()->Get();
57 NotificationManager* manager = new NotificationManager(
58 thread_safe_sender, main_thread_task_runner, notification_dispatcher);
59 if (CurrentWorkerId())
60 WorkerTaskRunner::Instance()->AddStopObserver(manager);
61 return manager;
64 void NotificationManager::OnWorkerRunLoopStopped() {
65 delete this;
68 void NotificationManager::show(
69 const blink::WebSerializedOrigin& origin,
70 const blink::WebNotificationData& notification_data,
71 blink::WebNotificationDelegate* delegate) {
72 if (notification_data.icon.isEmpty()) {
73 DisplayPageNotification(origin, notification_data, delegate, SkBitmap());
74 return;
77 pending_notifications_.FetchPageNotificationResources(
78 notification_data,
79 delegate,
80 base::Bind(&NotificationManager::DisplayPageNotification,
81 base::Unretained(this), // this owns |pending_notifications_|
82 origin,
83 notification_data,
84 delegate));
87 void NotificationManager::showPersistent(
88 const blink::WebSerializedOrigin& origin,
89 const blink::WebNotificationData& notification_data,
90 blink::WebServiceWorkerRegistration* service_worker_registration,
91 blink::WebNotificationShowCallbacks* callbacks) {
92 DCHECK(service_worker_registration);
93 int64 service_worker_registration_id =
94 static_cast<WebServiceWorkerRegistrationImpl*>(
95 service_worker_registration)->registration_id();
97 scoped_ptr<blink::WebNotificationShowCallbacks> owned_callbacks(callbacks);
98 if (notification_data.icon.isEmpty()) {
99 DisplayPersistentNotification(origin,
100 notification_data,
101 service_worker_registration_id,
102 owned_callbacks.Pass(),
103 SkBitmap());
104 return;
107 pending_notifications_.FetchPersistentNotificationResources(
108 notification_data,
109 base::Bind(&NotificationManager::DisplayPersistentNotification,
110 base::Unretained(this), // this owns |pending_notifications_|
111 origin,
112 notification_data,
113 service_worker_registration_id,
114 base::Passed(&owned_callbacks)));
117 void NotificationManager::close(blink::WebNotificationDelegate* delegate) {
118 if (pending_notifications_.CancelPageNotificationFetches(delegate))
119 return;
121 for (auto& iter : active_page_notifications_) {
122 if (iter.second != delegate)
123 continue;
125 thread_safe_sender_->Send(
126 new PlatformNotificationHostMsg_Close(iter.first));
127 active_page_notifications_.erase(iter.first);
128 return;
131 // It should not be possible for Blink to call close() on a Notification which
132 // does not exist in either the pending or active notification lists.
133 NOTREACHED();
136 void NotificationManager::closePersistent(
137 const blink::WebString& persistent_notification_id) {
138 thread_safe_sender_->Send(new PlatformNotificationHostMsg_ClosePersistent(
139 base::UTF16ToUTF8(persistent_notification_id)));
142 void NotificationManager::notifyDelegateDestroyed(
143 blink::WebNotificationDelegate* delegate) {
144 if (pending_notifications_.CancelPageNotificationFetches(delegate))
145 return;
147 for (auto& iter : active_page_notifications_) {
148 if (iter.second != delegate)
149 continue;
151 active_page_notifications_.erase(iter.first);
152 return;
156 WebNotificationPermission NotificationManager::checkPermission(
157 const blink::WebSerializedOrigin& origin) {
158 WebNotificationPermission permission =
159 blink::WebNotificationPermissionAllowed;
160 thread_safe_sender_->Send(new PlatformNotificationHostMsg_CheckPermission(
161 GURL(origin.string()), &permission));
163 return permission;
166 bool NotificationManager::OnMessageReceived(const IPC::Message& message) {
167 bool handled = true;
168 IPC_BEGIN_MESSAGE_MAP(NotificationManager, message)
169 IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidShow, OnDidShow);
170 IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClose, OnDidClose);
171 IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClick, OnDidClick);
172 IPC_MESSAGE_UNHANDLED(handled = false)
173 IPC_END_MESSAGE_MAP()
175 return handled;
178 void NotificationManager::OnDidShow(int notification_id) {
179 const auto& iter = active_page_notifications_.find(notification_id);
180 if (iter == active_page_notifications_.end())
181 return;
183 iter->second->dispatchShowEvent();
186 void NotificationManager::OnDidClose(int notification_id) {
187 const auto& iter = active_page_notifications_.find(notification_id);
188 if (iter == active_page_notifications_.end())
189 return;
191 iter->second->dispatchCloseEvent();
192 active_page_notifications_.erase(iter);
195 void NotificationManager::OnDidClick(int notification_id) {
196 const auto& iter = active_page_notifications_.find(notification_id);
197 if (iter == active_page_notifications_.end())
198 return;
200 iter->second->dispatchClickEvent();
203 void NotificationManager::DisplayPageNotification(
204 const blink::WebSerializedOrigin& origin,
205 const blink::WebNotificationData& notification_data,
206 blink::WebNotificationDelegate* delegate,
207 const SkBitmap& icon) {
208 int notification_id =
209 notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
211 active_page_notifications_[notification_id] = delegate;
212 thread_safe_sender_->Send(
213 new PlatformNotificationHostMsg_Show(
214 notification_id,
215 GURL(origin.string()),
216 icon,
217 ToPlatformNotificationData(notification_data)));
220 void NotificationManager::DisplayPersistentNotification(
221 const blink::WebSerializedOrigin& origin,
222 const blink::WebNotificationData& notification_data,
223 int64 service_worker_registration_id,
224 scoped_ptr<blink::WebNotificationShowCallbacks> callbacks,
225 const SkBitmap& icon) {
226 thread_safe_sender_->Send(
227 new PlatformNotificationHostMsg_ShowPersistent(
228 service_worker_registration_id,
229 GURL(origin.string()),
230 icon,
231 ToPlatformNotificationData(notification_data)));
233 // There currently isn't a case in which the promise would be rejected per
234 // our implementation, so always resolve it here.
235 callbacks->onSuccess();
238 } // namespace content