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

Side by Side Diff: chrome/browser/notifications/notification_ui_manager_android.cc

Issue 1072043003: Clean up the NotificationUIManagerAndroid. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@n-db-Integrate
Patch Set: Created 5 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 "chrome/browser/notifications/notification_ui_manager_android.h" 5 #include "chrome/browser/notifications/notification_ui_manager_android.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/android/jni_array.h" 9 #include "base/android/jni_array.h"
10 #include "base/android/jni_string.h" 10 #include "base/android/jni_string.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/notifications/notification.h" 14 #include "chrome/browser/notifications/notification.h"
15 #include "chrome/browser/notifications/persistent_notification_delegate.h" 15 #include "chrome/browser/notifications/persistent_notification_delegate.h"
16 #include "chrome/browser/notifications/platform_notification_service_impl.h" 16 #include "chrome/browser/notifications/platform_notification_service_impl.h"
17 #include "chrome/browser/notifications/profile_notification.h"
18 #include "chrome/browser/profiles/profile_manager.h" 17 #include "chrome/browser/profiles/profile_manager.h"
19 #include "content/public/common/persistent_notification_status.h" 18 #include "content/public/common/persistent_notification_status.h"
20 #include "content/public/common/platform_notification_data.h" 19 #include "content/public/common/platform_notification_data.h"
21 #include "jni/NotificationUIManager_jni.h" 20 #include "jni/NotificationUIManager_jni.h"
22 #include "ui/gfx/android/java_bitmap.h" 21 #include "ui/gfx/android/java_bitmap.h"
23 #include "ui/gfx/image/image.h" 22 #include "ui/gfx/image/image.h"
24 23
25 using base::android::AttachCurrentThread; 24 using base::android::AttachCurrentThread;
26 using base::android::ConvertJavaStringToUTF8; 25 using base::android::ConvertJavaStringToUTF8;
27 using base::android::ConvertUTF16ToJavaString; 26 using base::android::ConvertUTF16ToJavaString;
28 using base::android::ConvertUTF8ToJavaString; 27 using base::android::ConvertUTF8ToJavaString;
29 28
30 namespace {
31
32 // Called when the "notificationclick" event in the Service Worker has finished
33 // executing for a notification that was created in a previous instance of the
34 // browser.
35 void OnEventDispatchComplete(content::PersistentNotificationStatus status) {
36 // TODO(peter): Add UMA statistics based on |status|.
37 // TODO(peter): Decide if we want to forcefully shut down the browser process
38 // if we're confident it was created for delivering this event.
39 }
40
41 } // namespace
42
43 // Called by the Java side when a notification event has been received, but the 29 // Called by the Java side when a notification event has been received, but the
44 // NotificationUIManager has not been initialized yet. Enforce initialization of 30 // NotificationUIManager has not been initialized yet. Enforce initialization of
45 // the class. 31 // the class.
46 static void InitializeNotificationUIManager(JNIEnv* env, jclass clazz) { 32 static void InitializeNotificationUIManager(JNIEnv* env, jclass clazz) {
47 g_browser_process->notification_ui_manager(); 33 g_browser_process->notification_ui_manager();
48 } 34 }
49 35
50 // static 36 // static
51 NotificationUIManager* NotificationUIManager::Create(PrefService* local_state) { 37 NotificationUIManager* NotificationUIManager::Create(PrefService* local_state) {
52 return new NotificationUIManagerAndroid(); 38 return new NotificationUIManagerAndroid();
(...skipping 23 matching lines...) Expand all
76 62
77 regenerated_notification_infos_[persistent_notification_id] = 63 regenerated_notification_infos_[persistent_notification_id] =
78 std::make_pair(origin.spec(), tag); 64 std::make_pair(origin.spec(), tag);
79 65
80 // TODO(peter): Rather than assuming that the last used profile is the 66 // TODO(peter): Rather than assuming that the last used profile is the
81 // appropriate one for this notification, the used profile should be 67 // appropriate one for this notification, the used profile should be
82 // stored as part of the notification's data. See https://crbug.com/437574. 68 // stored as part of the notification's data. See https://crbug.com/437574.
83 PlatformNotificationServiceImpl::GetInstance()->OnPersistentNotificationClick( 69 PlatformNotificationServiceImpl::GetInstance()->OnPersistentNotificationClick(
84 ProfileManager::GetLastUsedProfile(), 70 ProfileManager::GetLastUsedProfile(),
85 persistent_notification_id, 71 persistent_notification_id,
86 origin, 72 origin);
87 base::Bind(&OnEventDispatchComplete));
88 73
89 return true; 74 return true;
90 } 75 }
91 76
92 bool NotificationUIManagerAndroid::OnNotificationClosed( 77 bool NotificationUIManagerAndroid::OnNotificationClosed(
93 JNIEnv* env, 78 JNIEnv* env,
94 jobject java_object, 79 jobject java_object,
95 jlong persistent_notification_id, 80 jlong persistent_notification_id,
96 jstring java_origin, 81 jstring java_origin,
97 jstring java_tag) { 82 jstring java_tag) {
98 // TODO(peter): Implement handling when a notification has been closed. The 83 // TODO(peter): Implement handling when a notification has been closed. The
99 // notification database has to reflect this in its own state. 84 // notification database has to reflect this in its own state.
100 return true; 85 return true;
101 } 86 }
102 87
103 void NotificationUIManagerAndroid::Add(const Notification& notification, 88 void NotificationUIManagerAndroid::Add(const Notification& notification,
104 Profile* profile) { 89 Profile* profile) {
105 // If the given notification is replacing an older one, drop its associated
106 // profile notification object without closing the platform notification.
107 // We'll use the native Android system to perform a smoother replacement.
108 ProfileNotification* notification_to_replace =
109 FindNotificationToReplace(notification, profile);
110 if (notification_to_replace)
111 RemoveProfileNotification(notification_to_replace, false /* close */);
112
113 ProfileNotification* profile_notification =
114 new ProfileNotification(profile, notification);
115
116 // Takes ownership of |profile_notification|.
117 AddProfileNotification(profile_notification);
118
119 JNIEnv* env = AttachCurrentThread(); 90 JNIEnv* env = AttachCurrentThread();
120 91
92 // The Android notification UI manager only supports Web Notifications, which
93 // have a PersistentNotificationDelegate. The persistent id of the
94 // notification is exposed through it's interface.
95 //
96 // TODO(peter): When content/ passes a message_center::Notification to the
97 // chrome/ layer, the persistent notification id should be captured as a
98 // property on that object instead, making this cast unnecessary.
121 PersistentNotificationDelegate* delegate = 99 PersistentNotificationDelegate* delegate =
122 static_cast<PersistentNotificationDelegate*>(notification.delegate()); 100 static_cast<PersistentNotificationDelegate*>(notification.delegate());
123 DCHECK(delegate); 101 DCHECK(delegate);
124 102
125 int64_t persistent_notification_id = delegate->persistent_notification_id(); 103 int64_t persistent_notification_id = delegate->persistent_notification_id();
126 GURL origin_url(notification.origin_url().GetOrigin()); 104 GURL origin_url(notification.origin_url().GetOrigin());
127 105
128 ScopedJavaLocalRef<jstring> origin = ConvertUTF8ToJavaString( 106 ScopedJavaLocalRef<jstring> origin = ConvertUTF8ToJavaString(
129 env, origin_url.spec()); 107 env, origin_url.spec());
130 ScopedJavaLocalRef<jstring> tag = 108 ScopedJavaLocalRef<jstring> tag =
(...skipping 21 matching lines...) Expand all
152 notification.silent()); 130 notification.silent());
153 131
154 regenerated_notification_infos_[persistent_notification_id] = 132 regenerated_notification_infos_[persistent_notification_id] =
155 std::make_pair(origin_url.spec(), notification.tag()); 133 std::make_pair(origin_url.spec(), notification.tag());
156 134
157 notification.delegate()->Display(); 135 notification.delegate()->Display();
158 } 136 }
159 137
160 bool NotificationUIManagerAndroid::Update(const Notification& notification, 138 bool NotificationUIManagerAndroid::Update(const Notification& notification,
161 Profile* profile) { 139 Profile* profile) {
162 // This method is currently only called from extensions and local discovery,
163 // both of which are not supported on Android.
164 NOTIMPLEMENTED(); 140 NOTIMPLEMENTED();
165 return false; 141 return false;
166 } 142 }
167 143
168 const Notification* NotificationUIManagerAndroid::FindById( 144 const Notification* NotificationUIManagerAndroid::FindById(
169 const std::string& delegate_id, 145 const std::string& delegate_id,
170 ProfileID profile_id) const { 146 ProfileID profile_id) const {
171 std::string profile_notification_id = 147 NOTIMPLEMENTED();
172 ProfileNotification::GetProfileNotificationId(delegate_id, profile_id); 148 return nullptr;
173 ProfileNotification* profile_notification =
174 FindProfileNotification(profile_notification_id);
175 if (!profile_notification)
176 return 0;
177
178 return &profile_notification->notification();
179 } 149 }
180 150
181 bool NotificationUIManagerAndroid::CancelById(const std::string& delegate_id, 151 bool NotificationUIManagerAndroid::CancelById(const std::string& delegate_id,
182 ProfileID profile_id) { 152 ProfileID profile_id) {
183 std::string profile_notification_id = 153 int64_t persistent_notification_id = 0;
184 ProfileNotification::GetProfileNotificationId(delegate_id, profile_id);
185 ProfileNotification* profile_notification =
186 FindProfileNotification(profile_notification_id);
187 if (profile_notification) {
188 RemoveProfileNotification(profile_notification, true /* close */);
189 return true;
190 }
191 154
192 // On Android, it's still possible that the notification can be closed in case 155 // TODO(peter): Use the |delegate_id| directly when notification ids are being
193 // the platform Id is known, even if no delegate exists. This happens when the 156 // generated by content/ instead of us.
194 // browser process is started because of interaction with a Notification. 157 if (!base::StringToInt64(delegate_id, &persistent_notification_id))
195 PlatformCloseNotification(delegate_id); 158 return false;
196 return true;
197 }
198
199 std::set<std::string>
200 NotificationUIManagerAndroid::GetAllIdsByProfileAndSourceOrigin(
201 Profile* profile,
202 const GURL& source) {
203 // |profile| may be invalid, so no calls must be made based on the instance.
204 std::set<std::string> delegate_ids;
205
206 for (auto iterator : profile_notifications_) {
207 ProfileNotification* profile_notification = iterator.second;
208 if (profile_notification->notification().origin_url() == source &&
209 profile_notification->profile() == profile)
210 delegate_ids.insert(profile_notification->notification().id());
211 }
212
213 return delegate_ids;
214 }
215
216 bool NotificationUIManagerAndroid::CancelAllBySourceOrigin(
217 const GURL& source_origin) {
218 bool removed = true;
219
220 for (auto iterator = profile_notifications_.begin();
221 iterator != profile_notifications_.end();) {
222 auto current_iterator = iterator++;
223
224 ProfileNotification* profile_notification = current_iterator->second;
225 if (profile_notification->notification().origin_url() == source_origin) {
226 RemoveProfileNotification(profile_notification, true /* close */);
227 removed = true;
228 }
229 }
230
231 return removed;
232 }
233
234 bool NotificationUIManagerAndroid::CancelAllByProfile(ProfileID profile_id) {
235 bool removed = true;
236
237 for (auto iterator = profile_notifications_.begin();
238 iterator != profile_notifications_.end();) {
239 auto current_iterator = iterator++;
240
241 ProfileNotification* profile_notification = current_iterator->second;
242 ProfileID current_profile_id =
243 NotificationUIManager::GetProfileID(profile_notification->profile());
244 if (current_profile_id == profile_id) {
245 RemoveProfileNotification(profile_notification, true /* close */);
246 removed = true;
247 }
248 }
249
250 return removed;
251 }
252
253 void NotificationUIManagerAndroid::CancelAll() {
254 for (auto iterator : profile_notifications_) {
255 ProfileNotification* profile_notification = iterator.second;
256
257 PlatformCloseNotification(profile_notification->notification().id());
258 delete profile_notification;
259 }
260
261 profile_notifications_.clear();
262 }
263
264 bool NotificationUIManagerAndroid::RegisterNotificationUIManager(JNIEnv* env) {
265 return RegisterNativesImpl(env);
266 }
267
268 void NotificationUIManagerAndroid::PlatformCloseNotification(
269 const std::string& notification_id) {
270 int64_t persistent_notification_id = 0;
271 if (!base::StringToInt64(notification_id, &persistent_notification_id))
272 return;
273 159
274 const auto iterator = 160 const auto iterator =
275 regenerated_notification_infos_.find(persistent_notification_id); 161 regenerated_notification_infos_.find(persistent_notification_id);
276 if (iterator == regenerated_notification_infos_.end()) 162 if (iterator == regenerated_notification_infos_.end())
277 return; 163 return false;
278 164
279 RegeneratedNotificationInfo notification_info = iterator->second; 165 const RegeneratedNotificationInfo& notification_info = iterator->second;
166
280 JNIEnv* env = AttachCurrentThread(); 167 JNIEnv* env = AttachCurrentThread();
281 168
282 ScopedJavaLocalRef<jstring> origin = 169 ScopedJavaLocalRef<jstring> origin =
283 ConvertUTF8ToJavaString(env, notification_info.first); 170 ConvertUTF8ToJavaString(env, notification_info.first);
284 ScopedJavaLocalRef<jstring> tag = 171 ScopedJavaLocalRef<jstring> tag =
285 ConvertUTF8ToJavaString(env, notification_info.second); 172 ConvertUTF8ToJavaString(env, notification_info.second);
286 173
287 regenerated_notification_infos_.erase(iterator); 174 regenerated_notification_infos_.erase(iterator);
288 175
289 Java_NotificationUIManager_closeNotification(env, 176 Java_NotificationUIManager_closeNotification(env,
290 java_object_.obj(), 177 java_object_.obj(),
291 persistent_notification_id, 178 persistent_notification_id,
292 origin.obj(), 179 origin.obj(),
293 tag.obj()); 180 tag.obj());
181 return true;
294 } 182 }
295 183
296 void NotificationUIManagerAndroid::AddProfileNotification( 184 std::set<std::string>
297 ProfileNotification* profile_notification) { 185 NotificationUIManagerAndroid::GetAllIdsByProfileAndSourceOrigin(
298 std::string id = profile_notification->notification().id(); 186 Profile* profile,
299 187 const GURL& source) {
300 // Notification ids should be unique. 188 NOTIMPLEMENTED();
dewittj 2015/04/10 17:06:59 I wonder if we should be harsher about these metho
Peter Beverloo 2015/04/14 17:53:40 That sounds good to me. Changed them to NOTREACHED
301 DCHECK(profile_notifications_.find(id) == profile_notifications_.end()); 189 return std::set<std::string>();
302
303 profile_notifications_[id] = profile_notification;
304 } 190 }
305 191
306 void NotificationUIManagerAndroid::RemoveProfileNotification( 192 bool NotificationUIManagerAndroid::CancelAllBySourceOrigin(
307 ProfileNotification* profile_notification, bool close) { 193 const GURL& source_origin) {
308 std::string notification_id = profile_notification->notification().id(); 194 NOTIMPLEMENTED();
309 if (close) 195 return false;
310 PlatformCloseNotification(notification_id);
311
312 profile_notifications_.erase(notification_id);
313 delete profile_notification;
314 } 196 }
315 197
316 ProfileNotification* NotificationUIManagerAndroid::FindProfileNotification( 198 bool NotificationUIManagerAndroid::CancelAllByProfile(ProfileID profile_id) {
317 const std::string& id) const { 199 NOTIMPLEMENTED();
318 auto iter = profile_notifications_.find(id); 200 return false;
319 if (iter == profile_notifications_.end())
320 return nullptr;
321
322 return iter->second;
323 } 201 }
324 202
325 ProfileNotification* NotificationUIManagerAndroid::FindNotificationToReplace( 203 void NotificationUIManagerAndroid::CancelAll() {
326 const Notification& notification, Profile* profile) const { 204 NOTIMPLEMENTED();
327 const std::string& tag = notification.tag(); 205 }
328 if (tag.empty())
329 return nullptr;
330 206
331 const GURL origin_url = notification.origin_url(); 207 bool NotificationUIManagerAndroid::RegisterNotificationUIManager(JNIEnv* env) {
332 DCHECK(origin_url.is_valid()); 208 return RegisterNativesImpl(env);
333
334 for (const auto& iterator : profile_notifications_) {
335 ProfileNotification* profile_notification = iterator.second;
336 if (profile_notification->notification().tag() == tag ||
337 profile_notification->notification().origin_url() == origin_url ||
338 profile_notification->profile() == profile) {
339 return profile_notification;
340 }
341 }
342 return nullptr;
343 } 209 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698