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

Side by Side Diff: chrome/browser/notifications/notification_ui_manager_mac.mm

Issue 1814923002: Nuke NotificationUIManager from PlatformNotificationServiceImpl (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@profile_manager_load
Patch Set: 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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_mac.h" 5 #include "chrome/browser/notifications/notification_ui_manager_mac.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/command_line.h"
10 #include "base/mac/foundation_util.h" 9 #include "base/mac/foundation_util.h"
11 #include "base/mac/mac_util.h" 10 #include "base/mac/mac_util.h"
12 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/sys_string_conversions.h" 12 #include "base/strings/sys_string_conversions.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/notification_display_service_factory.h"
15 #include "chrome/browser/notifications/persistent_notification_delegate.h" 16 #include "chrome/browser/notifications/persistent_notification_delegate.h"
16 #include "chrome/browser/notifications/platform_notification_service_impl.h" 17 #include "chrome/browser/notifications/platform_notification_service_impl.h"
17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/profiles/profile_manager.h" 19 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/grit/generated_resources.h" 20 #include "chrome/grit/generated_resources.h"
21 #include "ui/base/l10n/l10n_util_mac.h" 21 #include "ui/base/l10n/l10n_util_mac.h"
22 #include "url/gurl.h" 22 #include "url/gurl.h"
23 23
24 @class NSUserNotification; 24 @class NSUserNotification;
25 @class NSUserNotificationCenter; 25 @class NSUserNotificationCenter;
26 26
27 // The mapping from web notifications to NsUserNotification works as follows 27 // The mapping from web notifications to NsUserNotification works as follows
28 28
29 // notification#title in NSUserNotification.title 29 // notification#title in NSUserNotification.title
30 // notification#message in NSUserNotification.subtitle 30 // notification#message in NSUserNotification.subtitle
31 // notification#context_message in NSUserNotification.informativeText 31 // notification#context_message in NSUserNotification.informativeText
32 // notification#tag in NSUserNotification.identifier (10.9) 32 // notification#tag in NSUserNotification.identifier (10.9)
33 // notification#icon in NSUserNotification.contentImage (10.9) 33 // notification#icon in NSUserNotification.contentImage (10.9)
34 // Site settings button is implemented as NSUserNotification's action button 34 // Site settings button is implemented as NSUserNotification's action button
35 // Not possible to implement: 35 // Not possible to implement:
36 // -notification.requireInteraction 36 // -notification.requireInteraction
37 // -The event associated to the close button 37 // -The event associated to the close button
38 38
39 // TODO(miguelg) implement the following features 39 // TODO(miguelg) implement the following features
40 // - Sound names can be implemented by setting soundName in NSUserNotification 40 // - Sound names can be implemented by setting soundName in NSUserNotification
41 // NSUserNotificationDefaultSoundName gives you the platform default. 41 // NSUserNotificationDefaultSoundName gives you the platform default.
42 42
43 namespace { 43 namespace {
44 44
45 // Keys in NSUserNotification.userInfo to map chrome notifications to 45 // Keys in NSUserNotification.userInfo to map chrome notifications to
46 // native ones. 46 // native ones.
47 NSString* const kNotificationOriginKey = @"notification_origin"; 47 NSString* const kNotificationOriginKey = @"notification_origin";
48 NSString* const kNotificationPersistentIdKey = @"notification_persistent_id"; 48 NSString* const kNotificationPersistentIdKey = @"notification_persistent_id";
49 NSString* const kNotificationDelegateIdKey = @"notification_delegate_id";
50 49
51 // TODO(miguelg) get rid of this key once ProfileID has been ported
52 // from the void* it is today to the stable identifier provided
53 // in kNotificationProfilePersistentIdKey.
54 NSString* const kNotificationProfileIdKey = @"notification_profile_id";
55 NSString* const kNotificationProfilePersistentIdKey = 50 NSString* const kNotificationProfilePersistentIdKey =
56 @"notification_profile_persistent_id"; 51 @"notification_profile_persistent_id";
57 NSString* const kNotificationIncognitoKey = @"notification_incognito"; 52 NSString* const kNotificationIncognitoKey = @"notification_incognito";
58 53
59 } // namespace 54 } // namespace
60 55
61 // Only use native notifications for web, behind a flag and on 10.8+
62 // static 56 // static
63 NotificationUIManager* 57 NotificationPlatformBridge* NotificationPlatformBridge::Create() {
64 NotificationUIManager::CreateNativeNotificationManager() { 58 return new NotificationUIManagerMac(
65 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 59 [NSUserNotificationCenter defaultUserNotificationCenter]);
66 switches::kEnableNativeNotifications) &&
67 base::mac::IsOSMountainLionOrLater()) {
68 return new NotificationUIManagerMac();
69 }
70 return nullptr;
71 } 60 }
72 61
73 // A Cocoa class that represents the delegate of NSUserNotificationCenter and 62 // A Cocoa class that represents the delegate of NSUserNotificationCenter and
74 // can forward commands to C++. 63 // can forward commands to C++.
75 @interface NotificationCenterDelegate 64 @interface NotificationCenterDelegate
76 : NSObject<NSUserNotificationCenterDelegate> { 65 : NSObject<NSUserNotificationCenterDelegate> {
77 @private
78 NotificationUIManagerMac* manager_; // Weak, owns self.
79 } 66 }
80 - (id)initWithManager:(NotificationUIManagerMac*)manager;
81 @end 67 @end
82 68
83 // ///////////////////////////////////////////////////////////////////////////// 69 // /////////////////////////////////////////////////////////////////////////////
84 70
85 NotificationUIManagerMac::NotificationUIManagerMac() 71 NotificationUIManagerMac::NotificationUIManagerMac(
86 : delegate_([[NotificationCenterDelegate alloc] initWithManager:this]) { 72 NSUserNotificationCenter* notification_center)
87 [[NSUserNotificationCenter defaultUserNotificationCenter] 73 : delegate_([NotificationCenterDelegate alloc]),
88 setDelegate:delegate_.get()]; 74 notification_center_(notification_center) {
75 [notification_center_ setDelegate:delegate_.get()];
89 } 76 }
90 77
91 NotificationUIManagerMac::~NotificationUIManagerMac() { 78 NotificationUIManagerMac::~NotificationUIManagerMac() {
92 [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil]; 79 [notification_center_ setDelegate:nil];
93 CancelAll(); 80
81 // TODO(miguelg) lift this restriction if possible.
82 [notification_center_ removeAllDeliveredNotifications];
94 } 83 }
95 84
96 void NotificationUIManagerMac::Add(const Notification& notification, 85 void NotificationUIManagerMac::Display(const std::string& notification_id,
97 Profile* profile) { 86 const std::string& profile_id,
98 // The Mac notification UI manager only supports Web Notifications, which 87 bool incognito,
99 // have a PersistentNotificationDelegate. The persistent id of the 88 const Notification& notification) {
100 // notification is exposed through it's interface.
101 PersistentNotificationDelegate* delegate =
102 static_cast<PersistentNotificationDelegate*>(notification.delegate());
103 DCHECK(delegate);
104
105 base::scoped_nsobject<NSUserNotification> toast( 89 base::scoped_nsobject<NSUserNotification> toast(
106 [[NSUserNotification alloc] init]); 90 [[NSUserNotification alloc] init]);
107 [toast setTitle:base::SysUTF16ToNSString(notification.title())]; 91 [toast setTitle:base::SysUTF16ToNSString(notification.title())];
108 [toast setSubtitle:base::SysUTF16ToNSString(notification.message())]; 92 [toast setSubtitle:base::SysUTF16ToNSString(notification.message())];
109 93
110 // TODO(miguelg): try to elide the origin perhaps See NSString 94 // TODO(miguelg): try to elide the origin perhaps See NSString
111 // stringWithFormat. It seems that the informativeText font is constant. 95 // stringWithFormat. It seems that the informativeText font is constant.
112 NSString* informativeText = 96 NSString* informative_text =
113 notification.context_message().empty() 97 notification.context_message().empty()
114 ? base::SysUTF8ToNSString(notification.origin_url().spec()) 98 ? base::SysUTF8ToNSString(notification.origin_url().spec())
115 : base::SysUTF16ToNSString(notification.context_message()); 99 : base::SysUTF16ToNSString(notification.context_message());
116 [toast setInformativeText:informativeText]; 100 [toast setInformativeText:informative_text];
117 101
118 // Some functionality is only available in 10.9+ or requires private APIs 102 // Some functionality requires private APIs
119 // Icon 103 // Icon
120 if ([toast respondsToSelector:@selector(_identityImage)] && 104 if ([toast respondsToSelector:@selector(_identityImage)] &&
121 !notification.icon().IsEmpty()) { 105 !notification.icon().IsEmpty()) {
122 [toast setValue:notification.icon().ToNSImage() forKey:@"_identityImage"]; 106 [toast setValue:notification.icon().ToNSImage() forKey:@"_identityImage"];
123 [toast setValue:@NO forKey:@"_identityImageHasBorder"]; 107 [toast setValue:@NO forKey:@"_identityImageHasBorder"];
124 } 108 }
125 109
126 // Buttons 110 // Buttons
127 if ([toast respondsToSelector:@selector(_showsButtons)]) { 111 if ([toast respondsToSelector:@selector(_showsButtons)]) {
128 [toast setValue:@YES forKey:@"_showsButtons"]; 112 [toast setValue:@YES forKey:@"_showsButtons"];
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 [existing_notification valueForKey:@"identifier"]; 163 [existing_notification valueForKey:@"identifier"];
180 if ([identifier isEqual:base::SysUTF8ToNSString(notification.tag())]) { 164 if ([identifier isEqual:base::SysUTF8ToNSString(notification.tag())]) {
181 [notification_center 165 [notification_center
182 removeDeliveredNotification:existing_notification]; 166 removeDeliveredNotification:existing_notification];
183 break; 167 break;
184 } 168 }
185 } 169 }
186 } 170 }
187 } 171 }
188 172
189 int64_t persistent_notification_id = delegate->persistent_notification_id();
190 int64_t profile_id = reinterpret_cast<int64_t>(GetProfileID(profile));
191
192 toast.get().userInfo = @{ 173 toast.get().userInfo = @{
193 kNotificationOriginKey : 174 kNotificationOriginKey :
194 base::SysUTF8ToNSString(notification.origin_url().spec()), 175 base::SysUTF8ToNSString(notification.origin_url().spec()),
195 kNotificationPersistentIdKey : 176 kNotificationPersistentIdKey : base::SysUTF8ToNSString(notification_id),
196 [NSNumber numberWithLongLong:persistent_notification_id], 177 kNotificationProfilePersistentIdKey : base::SysUTF8ToNSString(profile_id),
197 kNotificationDelegateIdKey : 178 kNotificationIncognitoKey : [NSNumber numberWithBool:incognito]
198 base::SysUTF8ToNSString(notification.delegate_id()),
199 kNotificationProfileIdKey : [NSNumber numberWithLongLong:profile_id],
200 kNotificationProfilePersistentIdKey :
201 base::SysUTF8ToNSString(profile->GetPath().BaseName().value()),
202 kNotificationIncognitoKey :
203 [NSNumber numberWithBool:profile->IsOffTheRecord()]
204 }; 179 };
205 180
206 [[NSUserNotificationCenter defaultUserNotificationCenter] 181 [notification_center_ deliverNotification:toast];
207 deliverNotification:toast]; 182 notification.delegate()->Display();
208 } 183 }
209 184
210 bool NotificationUIManagerMac::Update(const Notification& notification, 185 void NotificationUIManagerMac::Close(const std::string& profile_id,
211 Profile* profile) { 186 const std::string& notification_id) {
212 NOTREACHED(); 187 NSString* candidate_id = base::SysUTF8ToNSString(notification_id);
213 return false; 188
189 NSString* current_profile_id = base::SysUTF8ToNSString(profile_id);
190 for (NSUserNotification* toast in
191 [notification_center_ deliveredNotifications]) {
192 NSString* toast_id =
193 [toast.userInfo objectForKey:kNotificationPersistentIdKey];
194
195 NSString* persistent_profile_id =
196 [toast.userInfo objectForKey:kNotificationProfilePersistentIdKey];
197
198 if (toast_id == candidate_id &&
199 persistent_profile_id == current_profile_id) {
200 [notification_center_ removeDeliveredNotification:toast];
201 }
202 }
214 } 203 }
215 204
216 const Notification* NotificationUIManagerMac::FindById( 205 bool NotificationUIManagerMac::GetDisplayed(
217 const std::string& delegate_id, 206 const std::string& profile_id,
218 ProfileID profile_id) const { 207 bool incognito,
219 NOTREACHED(); 208 std::set<std::string>* notifications) const {
220 return nil; 209 DCHECK(notifications);
210 NSString* current_profile_id = base::SysUTF8ToNSString(profile_id);
211 for (NSUserNotification* toast in
212 [notification_center_ deliveredNotifications]) {
213 NSString* toast_profile_id =
214 [toast.userInfo objectForKey:kNotificationProfilePersistentIdKey];
215 if (toast_profile_id == current_profile_id) {
216 notifications->insert(base::SysNSStringToUTF8(
217 [toast.userInfo objectForKey:kNotificationPersistentIdKey]));
218 }
219 }
220 return true;
221 } 221 }
222 222
223 bool NotificationUIManagerMac::CancelById(const std::string& delegate_id, 223 bool NotificationUIManagerMac::SupportsNotificationCenter() const {
224 ProfileID profile_id) { 224 return true;
225 int64_t persistent_notification_id = 0;
226 // TODO(peter): Use the |delegate_id| directly when notification ids are being
227 // generated by content/ instead of us.
228 if (!base::StringToInt64(delegate_id, &persistent_notification_id))
229 return false;
230
231 NSUserNotificationCenter* notificationCenter =
232 [NSUserNotificationCenter defaultUserNotificationCenter];
233 for (NSUserNotification* toast in
234 [notificationCenter deliveredNotifications]) {
235 NSNumber* toast_id =
236 [toast.userInfo objectForKey:kNotificationPersistentIdKey];
237 if (toast_id.longLongValue == persistent_notification_id) {
238 [notificationCenter removeDeliveredNotification:toast];
239 return true;
240 }
241 }
242
243 return false;
244 }
245
246 std::set<std::string>
247 NotificationUIManagerMac::GetAllIdsByProfileAndSourceOrigin(
248 ProfileID profile_id,
249 const GURL& source) {
250 NOTREACHED();
251 return std::set<std::string>();
252 }
253
254 std::set<std::string> NotificationUIManagerMac::GetAllIdsByProfile(
255 ProfileID profile_id) {
256 // ProfileID in mac is not safe to use across browser restarts
257 // Therefore because when chrome quits we cancel all pending notifications.
258 // TODO(miguelg) get rid of ProfileID as a void* for native notifications.
259 std::set<std::string> delegate_ids;
260 NSUserNotificationCenter* notificationCenter =
261 [NSUserNotificationCenter defaultUserNotificationCenter];
262 for (NSUserNotification* toast in
263 [notificationCenter deliveredNotifications]) {
264 NSNumber* toast_profile_id =
265 [toast.userInfo objectForKey:kNotificationProfileIdKey];
266 if (toast_profile_id.longLongValue ==
267 reinterpret_cast<int64_t>(profile_id)) {
268 delegate_ids.insert(base::SysNSStringToUTF8(
269 [toast.userInfo objectForKey:kNotificationDelegateIdKey]));
270 }
271 }
272 return delegate_ids;
273 }
274
275 bool NotificationUIManagerMac::CancelAllBySourceOrigin(
276 const GURL& source_origin) {
277 NOTREACHED();
278 return false;
279 }
280
281 bool NotificationUIManagerMac::CancelAllByProfile(ProfileID profile_id) {
282 NOTREACHED();
283 return false;
284 }
285
286 void NotificationUIManagerMac::CancelAll() {
287 [[NSUserNotificationCenter defaultUserNotificationCenter]
288 removeAllDeliveredNotifications];
289 } 225 }
290 226
291 // ///////////////////////////////////////////////////////////////////////////// 227 // /////////////////////////////////////////////////////////////////////////////
292 228
293 @implementation NotificationCenterDelegate 229 @implementation NotificationCenterDelegate
294
295 - (id)initWithManager:(NotificationUIManagerMac*)manager {
296 if ((self = [super init])) {
297 DCHECK(manager);
298 manager_ = manager;
299 }
300 return self;
301 }
302
303 - (void)userNotificationCenter:(NSUserNotificationCenter*)center 230 - (void)userNotificationCenter:(NSUserNotificationCenter*)center
304 didActivateNotification:(NSUserNotification*)notification { 231 didActivateNotification:(NSUserNotification*)notification {
305 std::string notificationOrigin = base::SysNSStringToUTF8( 232 std::string notificationOrigin = base::SysNSStringToUTF8(
306 [notification.userInfo objectForKey:kNotificationOriginKey]); 233 [notification.userInfo objectForKey:kNotificationOriginKey]);
307 NSNumber* persistentNotificationId = 234 NSNumber* persistentNotificationId =
308 [notification.userInfo objectForKey:kNotificationPersistentIdKey]; 235 [notification.userInfo objectForKey:kNotificationPersistentIdKey];
309 NSString* persistentProfileId = 236 NSString* persistentProfileId =
310 [notification.userInfo objectForKey:kNotificationProfilePersistentIdKey]; 237 [notification.userInfo objectForKey:kNotificationProfilePersistentIdKey];
311 NSNumber* isIncognito = 238 NSNumber* isIncognito =
312 [notification.userInfo objectForKey:kNotificationIncognitoKey]; 239 [notification.userInfo objectForKey:kNotificationIncognitoKey];
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 persistentNotificationId.longLongValue, buttonIndex); 287 persistentNotificationId.longLongValue, buttonIndex);
361 } 288 }
362 289
363 - (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center 290 - (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center
364 shouldPresentNotification:(NSUserNotification*)nsNotification { 291 shouldPresentNotification:(NSUserNotification*)nsNotification {
365 // Always display notifications, regardless of whether the app is foreground. 292 // Always display notifications, regardless of whether the app is foreground.
366 return YES; 293 return YES;
367 } 294 }
368 295
369 @end 296 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698