Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(320)

Side by Side Diff: content/child/notifications/notification_manager.cc

Issue 1847863002: Move notification resource loading from content/child to blink (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address peter's comments. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "content/child/notifications/notification_manager.h" 5 #include "content/child/notifications/notification_manager.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
11 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/threading/thread_local.h" 12 #include "base/threading/thread_local.h"
14 #include "content/child/notifications/notification_data_conversions.h" 13 #include "content/child/notifications/notification_data_conversions.h"
15 #include "content/child/notifications/notification_dispatcher.h" 14 #include "content/child/notifications/notification_dispatcher.h"
16 #include "content/child/service_worker/web_service_worker_registration_impl.h" 15 #include "content/child/service_worker/web_service_worker_registration_impl.h"
17 #include "content/child/thread_safe_sender.h" 16 #include "content/child/thread_safe_sender.h"
18 #include "content/common/notification_constants.h" 17 #include "content/common/notification_constants.h"
19 #include "content/public/common/notification_resources.h" 18 #include "content/public/common/notification_resources.h"
20 #include "content/public/common/platform_notification_data.h" 19 #include "content/public/common/platform_notification_data.h"
21 #include "third_party/WebKit/public/platform/URLConversion.h" 20 #include "third_party/WebKit/public/platform/URLConversion.h"
22 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" 21 #include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
23 #include "third_party/WebKit/public/platform/modules/notifications/WebNotificati onDelegate.h" 22 #include "third_party/WebKit/public/platform/modules/notifications/WebNotificati onDelegate.h"
24 23
25 using blink::WebNotificationPermission; 24 using blink::WebNotificationPermission;
26 25
27 namespace content { 26 namespace content {
28 namespace { 27 namespace {
29 28
30 int CurrentWorkerId() { 29 int CurrentWorkerId() {
31 return WorkerThread::GetCurrentId(); 30 return WorkerThread::GetCurrentId();
32 } 31 }
33 32
34 // Checks whether |notification_data| specifies any non-empty resources that 33 NotificationResources ToNotificationResources(
35 // need to be fetched. 34 std::unique_ptr<blink::WebNotificationResources> web_resources) {
36 bool HasResourcesToFetch(const blink::WebNotificationData& notification_data) { 35 NotificationResources resources;
37 if (!notification_data.icon.isEmpty()) 36 resources.notification_icon = web_resources->icon;
38 return true; 37 resources.badge = web_resources->badge;
39 if (!notification_data.badge.isEmpty()) 38 for (const auto& action_icon : web_resources->actionIcons)
40 return true; 39 resources.action_icons.push_back(action_icon);
41 for (const auto& action : notification_data.actions) { 40 return resources;
42 if (!action.icon.isEmpty())
43 return true;
44 }
45 return false;
46 } 41 }
47 42
48 } // namespace 43 } // namespace
49 44
50 static base::LazyInstance<base::ThreadLocalPointer<NotificationManager>>::Leaky 45 static base::LazyInstance<base::ThreadLocalPointer<NotificationManager>>::Leaky
51 g_notification_manager_tls = LAZY_INSTANCE_INITIALIZER; 46 g_notification_manager_tls = LAZY_INSTANCE_INITIALIZER;
52 47
53 NotificationManager::NotificationManager( 48 NotificationManager::NotificationManager(
54 ThreadSafeSender* thread_safe_sender, 49 ThreadSafeSender* thread_safe_sender,
55 base::SingleThreadTaskRunner* main_thread_task_runner,
56 NotificationDispatcher* notification_dispatcher) 50 NotificationDispatcher* notification_dispatcher)
57 : thread_safe_sender_(thread_safe_sender), 51 : thread_safe_sender_(thread_safe_sender),
58 notification_dispatcher_(notification_dispatcher), 52 notification_dispatcher_(notification_dispatcher) {
59 notifications_tracker_(main_thread_task_runner) {
60 g_notification_manager_tls.Pointer()->Set(this); 53 g_notification_manager_tls.Pointer()->Set(this);
61 } 54 }
62 55
63 NotificationManager::~NotificationManager() { 56 NotificationManager::~NotificationManager() {
64 g_notification_manager_tls.Pointer()->Set(nullptr); 57 g_notification_manager_tls.Pointer()->Set(nullptr);
65 } 58 }
66 59
67 NotificationManager* NotificationManager::ThreadSpecificInstance( 60 NotificationManager* NotificationManager::ThreadSpecificInstance(
68 ThreadSafeSender* thread_safe_sender, 61 ThreadSafeSender* thread_safe_sender,
69 base::SingleThreadTaskRunner* main_thread_task_runner,
70 NotificationDispatcher* notification_dispatcher) { 62 NotificationDispatcher* notification_dispatcher) {
71 if (g_notification_manager_tls.Pointer()->Get()) 63 if (g_notification_manager_tls.Pointer()->Get())
72 return g_notification_manager_tls.Pointer()->Get(); 64 return g_notification_manager_tls.Pointer()->Get();
73 65
74 NotificationManager* manager = new NotificationManager( 66 NotificationManager* manager =
75 thread_safe_sender, main_thread_task_runner, notification_dispatcher); 67 new NotificationManager(thread_safe_sender, notification_dispatcher);
76 if (CurrentWorkerId()) 68 if (CurrentWorkerId())
77 WorkerThread::AddObserver(manager); 69 WorkerThread::AddObserver(manager);
78 return manager; 70 return manager;
79 } 71 }
80 72
81 void NotificationManager::WillStopCurrentWorkerThread() { 73 void NotificationManager::WillStopCurrentWorkerThread() {
82 delete this; 74 delete this;
83 } 75 }
84 76
85 void NotificationManager::show( 77 void NotificationManager::show(
86 const blink::WebSecurityOrigin& origin, 78 const blink::WebSecurityOrigin& origin,
87 const blink::WebNotificationData& notification_data, 79 const blink::WebNotificationData& notification_data,
80 std::unique_ptr<blink::WebNotificationResources> notification_resources,
88 blink::WebNotificationDelegate* delegate) { 81 blink::WebNotificationDelegate* delegate) {
89 DCHECK_EQ(0u, notification_data.actions.size()); 82 DCHECK_EQ(0u, notification_data.actions.size());
83 DCHECK_EQ(0u, notification_resources->actionIcons.size());
90 84
91 if (!HasResourcesToFetch(notification_data)) { 85 int notification_id =
92 DisplayPageNotification(origin, notification_data, delegate, 86 notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
93 NotificationResources());
94 return;
95 }
96 87
97 notifications_tracker_.FetchResources( 88 active_page_notifications_[notification_id] = delegate;
98 notification_data, delegate, 89 // TODO(mkwst): This is potentially doing the wrong thing with unique
99 base::Bind(&NotificationManager::DisplayPageNotification, 90 // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
100 base::Unretained(this), // this owns |notifications_tracker_| 91 // https://crbug.com/490074 for detail.
101 origin, notification_data, delegate)); 92 thread_safe_sender_->Send(new PlatformNotificationHostMsg_Show(
93 notification_id, blink::WebStringToGURL(origin.toString()),
94 ToPlatformNotificationData(notification_data),
95 ToNotificationResources(std::move(notification_resources))));
102 } 96 }
103 97
104 void NotificationManager::showPersistent( 98 void NotificationManager::showPersistent(
105 const blink::WebSecurityOrigin& origin, 99 const blink::WebSecurityOrigin& origin,
106 const blink::WebNotificationData& notification_data, 100 const blink::WebNotificationData& notification_data,
101 std::unique_ptr<blink::WebNotificationResources> notification_resources,
107 blink::WebServiceWorkerRegistration* service_worker_registration, 102 blink::WebServiceWorkerRegistration* service_worker_registration,
108 blink::WebNotificationShowCallbacks* callbacks) { 103 blink::WebNotificationShowCallbacks* callbacks) {
109 DCHECK(service_worker_registration); 104 DCHECK(service_worker_registration);
105 DCHECK_EQ(notification_data.actions.size(),
106 notification_resources->actionIcons.size());
110 107
111 int64_t service_worker_registration_id = 108 int64_t service_worker_registration_id =
112 static_cast<WebServiceWorkerRegistrationImpl*>( 109 static_cast<WebServiceWorkerRegistrationImpl*>(
113 service_worker_registration) 110 service_worker_registration)
114 ->registration_id(); 111 ->registration_id();
115 112
116 std::unique_ptr<blink::WebNotificationShowCallbacks> owned_callbacks( 113 std::unique_ptr<blink::WebNotificationShowCallbacks> owned_callbacks(
117 callbacks); 114 callbacks);
118 115
119 // Verify that the author-provided payload size does not exceed our limit. 116 // Verify that the author-provided payload size does not exceed our limit.
120 // This is an implementation-defined limit to prevent abuse of notification 117 // This is an implementation-defined limit to prevent abuse of notification
121 // data as a storage mechanism. A UMA histogram records the requested sizes, 118 // data as a storage mechanism. A UMA histogram records the requested sizes,
122 // which enables us to track how much data authors are attempting to store. 119 // which enables us to track how much data authors are attempting to store.
123 // 120 //
124 // If the size exceeds this limit, reject the showNotification() promise. This 121 // If the size exceeds this limit, reject the showNotification() promise. This
125 // is outside of the boundaries set by the specification, but it gives authors 122 // is outside of the boundaries set by the specification, but it gives authors
126 // an indication that something has gone wrong. 123 // an indication that something has gone wrong.
127 size_t author_data_size = notification_data.data.size(); 124 size_t author_data_size = notification_data.data.size();
128 125
129 UMA_HISTOGRAM_COUNTS_1000("Notifications.AuthorDataSize", author_data_size); 126 UMA_HISTOGRAM_COUNTS_1000("Notifications.AuthorDataSize", author_data_size);
130 127
131 if (author_data_size > PlatformNotificationData::kMaximumDeveloperDataSize) { 128 if (author_data_size > PlatformNotificationData::kMaximumDeveloperDataSize) {
132 owned_callbacks->onError(); 129 owned_callbacks->onError();
133 return; 130 return;
134 } 131 }
135 132
136 if (!HasResourcesToFetch(notification_data)) { 133 // TODO(peter): GenerateNotificationId is more of a request id. Consider
137 NotificationResources notification_resources; 134 // renaming the method in the NotificationDispatcher if this makes sense.
135 int request_id =
136 notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
138 137
139 // Action indices are expected to have a corresponding icon bitmap, which 138 pending_show_notification_requests_.AddWithID(owned_callbacks.release(),
140 // may be empty when the developer provided no (or an invalid) icon. 139 request_id);
141 if (!notification_data.actions.isEmpty()) {
142 notification_resources.action_icons.resize(
143 notification_data.actions.size());
144 }
145 140
146 DisplayPersistentNotification( 141 // TODO(mkwst): This is potentially doing the wrong thing with unique
147 origin, notification_data, service_worker_registration_id, 142 // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
148 std::move(owned_callbacks), notification_resources); 143 // https://crbug.com/490074 for detail.
149 return; 144 thread_safe_sender_->Send(new PlatformNotificationHostMsg_ShowPersistent(
150 } 145 request_id, service_worker_registration_id,
151 146 blink::WebStringToGURL(origin.toString()),
152 notifications_tracker_.FetchResources( 147 ToPlatformNotificationData(notification_data),
153 notification_data, nullptr /* delegate */, 148 ToNotificationResources(std::move(notification_resources))));
154 base::Bind(&NotificationManager::DisplayPersistentNotification,
155 base::Unretained(this), // this owns |notifications_tracker_|
156 origin, notification_data, service_worker_registration_id,
157 base::Passed(&owned_callbacks)));
158 } 149 }
159 150
160 void NotificationManager::getNotifications( 151 void NotificationManager::getNotifications(
161 const blink::WebString& filter_tag, 152 const blink::WebString& filter_tag,
162 blink::WebServiceWorkerRegistration* service_worker_registration, 153 blink::WebServiceWorkerRegistration* service_worker_registration,
163 blink::WebNotificationGetCallbacks* callbacks) { 154 blink::WebNotificationGetCallbacks* callbacks) {
164 DCHECK(service_worker_registration); 155 DCHECK(service_worker_registration);
165 DCHECK(callbacks); 156 DCHECK(callbacks);
166 157
167 WebServiceWorkerRegistrationImpl* service_worker_registration_impl = 158 WebServiceWorkerRegistrationImpl* service_worker_registration_impl =
(...skipping 10 matching lines...) Expand all
178 notification_dispatcher_->GenerateNotificationId(CurrentWorkerId()); 169 notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
179 170
180 pending_get_notification_requests_.AddWithID(callbacks, request_id); 171 pending_get_notification_requests_.AddWithID(callbacks, request_id);
181 172
182 thread_safe_sender_->Send(new PlatformNotificationHostMsg_GetNotifications( 173 thread_safe_sender_->Send(new PlatformNotificationHostMsg_GetNotifications(
183 request_id, service_worker_registration_id, origin, 174 request_id, service_worker_registration_id, origin,
184 base::UTF16ToUTF8(base::StringPiece16(filter_tag)))); 175 base::UTF16ToUTF8(base::StringPiece16(filter_tag))));
185 } 176 }
186 177
187 void NotificationManager::close(blink::WebNotificationDelegate* delegate) { 178 void NotificationManager::close(blink::WebNotificationDelegate* delegate) {
188 if (notifications_tracker_.CancelResourceFetches(delegate))
189 return;
190
191 for (auto& iter : active_page_notifications_) { 179 for (auto& iter : active_page_notifications_) {
192 if (iter.second != delegate) 180 if (iter.second != delegate)
193 continue; 181 continue;
194 182
195 thread_safe_sender_->Send( 183 thread_safe_sender_->Send(
196 new PlatformNotificationHostMsg_Close(iter.first)); 184 new PlatformNotificationHostMsg_Close(iter.first));
197 active_page_notifications_.erase(iter.first); 185 active_page_notifications_.erase(iter.first);
198 return; 186 return;
199 } 187 }
200 188
201 // It should not be possible for Blink to call close() on a Notification which 189 // It should not be possible for Blink to call close() on a Notification which
202 // does not exist in either the pending or active notification lists. 190 // does not exist in either the pending or active notification lists.
203 NOTREACHED(); 191 NOTREACHED();
204 } 192 }
205 193
206 void NotificationManager::closePersistent( 194 void NotificationManager::closePersistent(
207 const blink::WebSecurityOrigin& origin, 195 const blink::WebSecurityOrigin& origin,
208 int64_t persistent_notification_id) { 196 int64_t persistent_notification_id) {
209 thread_safe_sender_->Send(new PlatformNotificationHostMsg_ClosePersistent( 197 thread_safe_sender_->Send(new PlatformNotificationHostMsg_ClosePersistent(
210 // TODO(mkwst): This is potentially doing the wrong thing with unique 198 // TODO(mkwst): This is potentially doing the wrong thing with unique
211 // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See 199 // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
212 // https://crbug.com/490074 for detail. 200 // https://crbug.com/490074 for detail.
213 blink::WebStringToGURL(origin.toString()), persistent_notification_id)); 201 blink::WebStringToGURL(origin.toString()), persistent_notification_id));
214 } 202 }
215 203
216 void NotificationManager::notifyDelegateDestroyed( 204 void NotificationManager::notifyDelegateDestroyed(
217 blink::WebNotificationDelegate* delegate) { 205 blink::WebNotificationDelegate* delegate) {
218 if (notifications_tracker_.CancelResourceFetches(delegate))
219 return;
220
221 for (auto& iter : active_page_notifications_) { 206 for (auto& iter : active_page_notifications_) {
222 if (iter.second != delegate) 207 if (iter.second != delegate)
223 continue; 208 continue;
224 209
225 active_page_notifications_.erase(iter.first); 210 active_page_notifications_.erase(iter.first);
226 return; 211 return;
227 } 212 }
228 } 213 }
229 214
230 WebNotificationPermission NotificationManager::checkPermission( 215 WebNotificationPermission NotificationManager::checkPermission(
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 ToWebNotificationData(notification_infos[i].second); 305 ToWebNotificationData(notification_infos[i].second);
321 306
322 notifications[i] = web_notification_info; 307 notifications[i] = web_notification_info;
323 } 308 }
324 309
325 callbacks->onSuccess(notifications); 310 callbacks->onSuccess(notifications);
326 311
327 pending_get_notification_requests_.Remove(request_id); 312 pending_get_notification_requests_.Remove(request_id);
328 } 313 }
329 314
330 void NotificationManager::DisplayPageNotification(
331 const blink::WebSecurityOrigin& origin,
332 const blink::WebNotificationData& notification_data,
333 blink::WebNotificationDelegate* delegate,
334 const NotificationResources& notification_resources) {
335 DCHECK_EQ(0u, notification_data.actions.size());
336 DCHECK_EQ(0u, notification_resources.action_icons.size());
337
338 int notification_id =
339 notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
340
341 active_page_notifications_[notification_id] = delegate;
342 // TODO(mkwst): This is potentially doing the wrong thing with unique
343 // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
344 // https://crbug.com/490074 for detail.
345 thread_safe_sender_->Send(new PlatformNotificationHostMsg_Show(
346 notification_id, blink::WebStringToGURL(origin.toString()),
347 ToPlatformNotificationData(notification_data), notification_resources));
348 }
349
350 void NotificationManager::DisplayPersistentNotification(
351 const blink::WebSecurityOrigin& origin,
352 const blink::WebNotificationData& notification_data,
353 int64_t service_worker_registration_id,
354 std::unique_ptr<blink::WebNotificationShowCallbacks> callbacks,
355 const NotificationResources& notification_resources) {
356 DCHECK_EQ(notification_data.actions.size(),
357 notification_resources.action_icons.size());
358
359 // TODO(peter): GenerateNotificationId is more of a request id. Consider
360 // renaming the method in the NotificationDispatcher if this makes sense.
361 int request_id =
362 notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
363
364 pending_show_notification_requests_.AddWithID(callbacks.release(),
365 request_id);
366
367 // TODO(mkwst): This is potentially doing the wrong thing with unique
368 // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
369 // https://crbug.com/490074 for detail.
370 thread_safe_sender_->Send(new PlatformNotificationHostMsg_ShowPersistent(
371 request_id, service_worker_registration_id,
372 blink::WebStringToGURL(origin.toString()),
373 ToPlatformNotificationData(notification_data), notification_resources));
374 }
375
376 } // namespace content 315 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698