OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/message_center_settings_controller.h" | 5 #include "chrome/browser/notifications/message_center_settings_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/i18n/string_compare.h" | 10 #include "base/i18n/string_compare.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 12 #include "chrome/browser/chrome_notification_types.h" |
12 #include "chrome/browser/extensions/app_icon_loader_impl.h" | 13 #include "chrome/browser/extensions/app_icon_loader_impl.h" |
13 #include "chrome/browser/extensions/extension_service.h" | 14 #include "chrome/browser/extensions/extension_service.h" |
14 #include "chrome/browser/favicon/favicon_service.h" | 15 #include "chrome/browser/favicon/favicon_service.h" |
15 #include "chrome/browser/favicon/favicon_service_factory.h" | 16 #include "chrome/browser/favicon/favicon_service_factory.h" |
16 #include "chrome/browser/history/history_types.h" | 17 #include "chrome/browser/history/history_types.h" |
17 #include "chrome/browser/notifications/desktop_notification_service.h" | 18 #include "chrome/browser/notifications/desktop_notification_service.h" |
18 #include "chrome/browser/notifications/desktop_notification_service_factory.h" | 19 #include "chrome/browser/notifications/desktop_notification_service_factory.h" |
19 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h" | 20 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h" |
20 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_fac
tory.h" | 21 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_fac
tory.h" |
21 #include "chrome/browser/profiles/profile.h" | |
22 #include "chrome/browser/profiles/profile_manager.h" | 22 #include "chrome/browser/profiles/profile_manager.h" |
23 #include "chrome/common/cancelable_task_tracker.h" | 23 #include "chrome/common/cancelable_task_tracker.h" |
24 #include "chrome/common/extensions/extension_constants.h" | 24 #include "chrome/common/extensions/extension_constants.h" |
25 #include "chrome/common/favicon/favicon_types.h" | 25 #include "chrome/common/favicon/favicon_types.h" |
| 26 #include "content/public/browser/notification_service.h" |
| 27 #include "content/public/browser/notification_source.h" |
26 #include "grit/theme_resources.h" | 28 #include "grit/theme_resources.h" |
27 #include "grit/ui_strings.h" | 29 #include "grit/ui_strings.h" |
28 #include "ui/base/l10n/l10n_util.h" | 30 #include "ui/base/l10n/l10n_util.h" |
29 #include "ui/base/resource/resource_bundle.h" | 31 #include "ui/base/resource/resource_bundle.h" |
30 #include "ui/gfx/image/image.h" | 32 #include "ui/gfx/image/image.h" |
31 #include "ui/message_center/message_center_style.h" | 33 #include "ui/message_center/message_center_style.h" |
32 | 34 |
33 #if defined(USE_ASH) | 35 #if defined(USE_ASH) |
34 #include "ash/shell.h" | 36 #include "ash/shell.h" |
35 #include "ash/system/web_notification/web_notification_tray.h" | 37 #include "ash/system/web_notification/web_notification_tray.h" |
(...skipping 16 matching lines...) Expand all Loading... |
52 private: | 54 private: |
53 icu::Collator* collator_; | 55 icu::Collator* collator_; |
54 }; | 56 }; |
55 | 57 |
56 bool SimpleCompareNotifiers(Notifier* n1, Notifier* n2) { | 58 bool SimpleCompareNotifiers(Notifier* n1, Notifier* n2) { |
57 return n1->name < n2->name; | 59 return n1->name < n2->name; |
58 } | 60 } |
59 | 61 |
60 } // namespace | 62 } // namespace |
61 | 63 |
62 MessageCenterSettingsController::MessageCenterSettingsController() { | 64 MessageCenterSettingsController::MessageCenterSettingsController() |
| 65 : profile_(NULL) { |
| 66 // We set the profile associated with the settings at the beginning and fail |
| 67 // silently if this profile is destroyed later. This is a temporary fix for |
| 68 // http://crbug.com/263193 |
| 69 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 70 content::NotificationService::AllSources()); |
63 } | 71 } |
64 | 72 |
65 MessageCenterSettingsController::~MessageCenterSettingsController() { | 73 MessageCenterSettingsController::~MessageCenterSettingsController() { |
66 } | 74 } |
67 | 75 |
68 void MessageCenterSettingsController::AddObserver( | 76 void MessageCenterSettingsController::AddObserver( |
69 message_center::NotifierSettingsObserver* observer) { | 77 message_center::NotifierSettingsObserver* observer) { |
70 observers_.AddObserver(observer); | 78 observers_.AddObserver(observer); |
71 } | 79 } |
72 | 80 |
73 void MessageCenterSettingsController::RemoveObserver( | 81 void MessageCenterSettingsController::RemoveObserver( |
74 message_center::NotifierSettingsObserver* observer) { | 82 message_center::NotifierSettingsObserver* observer) { |
75 observers_.RemoveObserver(observer); | 83 observers_.RemoveObserver(observer); |
76 } | 84 } |
77 | 85 |
78 void MessageCenterSettingsController::GetNotifierList( | 86 void MessageCenterSettingsController::GetNotifierList( |
79 std::vector<Notifier*>* notifiers) { | 87 std::vector<Notifier*>* notifiers) { |
80 DCHECK(notifiers); | 88 DCHECK(notifiers); |
81 // TODO(mukai): Fix this for multi-profile. | 89 // TODO(mukai): Fix this for multi-profile. |
82 // Temporarily use the last used profile to prevent chrome from crashing when | 90 // Temporarily use the last used profile to prevent chrome from crashing when |
83 // the default profile is not loaded. | 91 // the default profile is not loaded. |
84 Profile* profile = ProfileManager::GetLastUsedProfileAllowedByPolicy(); | 92 profile_ = ProfileManager::GetLastUsedProfileAllowedByPolicy(); |
85 DesktopNotificationService* notification_service = | 93 DesktopNotificationService* notification_service = |
86 DesktopNotificationServiceFactory::GetForProfile(profile); | 94 DesktopNotificationServiceFactory::GetForProfile(profile_); |
87 | 95 |
88 UErrorCode error; | 96 UErrorCode error; |
89 scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(error)); | 97 scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(error)); |
90 scoped_ptr<NotifierComparator> comparator; | 98 scoped_ptr<NotifierComparator> comparator; |
91 if (!U_FAILURE(error)) | 99 if (!U_FAILURE(error)) |
92 comparator.reset(new NotifierComparator(collator.get())); | 100 comparator.reset(new NotifierComparator(collator.get())); |
93 | 101 |
94 ExtensionService* extension_service = profile->GetExtensionService(); | 102 ExtensionService* extension_service = profile_->GetExtensionService(); |
95 const ExtensionSet* extension_set = extension_service->extensions(); | 103 const ExtensionSet* extension_set = extension_service->extensions(); |
96 // The extension icon size has to be 32x32 at least to load bigger icons if | 104 // The extension icon size has to be 32x32 at least to load bigger icons if |
97 // the icon doesn't exist for the specified size, and in that case it falls | 105 // the icon doesn't exist for the specified size, and in that case it falls |
98 // back to the default icon. The fetched icon will be resized in the settings | 106 // back to the default icon. The fetched icon will be resized in the settings |
99 // dialog. See chrome/browser/extensions/extension_icon_image.cc and | 107 // dialog. See chrome/browser/extensions/extension_icon_image.cc and |
100 // crbug.com/222931 | 108 // crbug.com/222931 |
101 app_icon_loader_.reset(new extensions::AppIconLoaderImpl( | 109 app_icon_loader_.reset(new extensions::AppIconLoaderImpl( |
102 profile, extension_misc::EXTENSION_ICON_SMALL, this)); | 110 profile_, extension_misc::EXTENSION_ICON_SMALL, this)); |
103 for (ExtensionSet::const_iterator iter = extension_set->begin(); | 111 for (ExtensionSet::const_iterator iter = extension_set->begin(); |
104 iter != extension_set->end(); ++iter) { | 112 iter != extension_set->end(); ++iter) { |
105 const extensions::Extension* extension = iter->get(); | 113 const extensions::Extension* extension = iter->get(); |
106 if (!extension->HasAPIPermission( | 114 if (!extension->HasAPIPermission( |
107 extensions::APIPermission::kNotification)) { | 115 extensions::APIPermission::kNotification)) { |
108 continue; | 116 continue; |
109 } | 117 } |
110 | 118 |
111 NotifierId notifier_id(NotifierId::APPLICATION, extension->id()); | 119 NotifierId notifier_id(NotifierId::APPLICATION, extension->id()); |
112 notifiers->push_back(new Notifier( | 120 notifiers->push_back(new Notifier( |
113 notifier_id, | 121 notifier_id, |
114 UTF8ToUTF16(extension->name()), | 122 UTF8ToUTF16(extension->name()), |
115 notification_service->IsNotifierEnabled(notifier_id))); | 123 notification_service->IsNotifierEnabled(notifier_id))); |
116 app_icon_loader_->FetchImage(extension->id()); | 124 app_icon_loader_->FetchImage(extension->id()); |
117 } | 125 } |
118 | 126 |
119 if (notifier::ChromeNotifierServiceFactory::UseSyncedNotifications( | 127 if (notifier::ChromeNotifierServiceFactory::UseSyncedNotifications( |
120 CommandLine::ForCurrentProcess())) { | 128 CommandLine::ForCurrentProcess())) { |
121 notifier::ChromeNotifierService* sync_notifier_service = | 129 notifier::ChromeNotifierService* sync_notifier_service = |
122 notifier::ChromeNotifierServiceFactory::GetInstance()->GetForProfile( | 130 notifier::ChromeNotifierServiceFactory::GetInstance()->GetForProfile( |
123 profile, Profile::EXPLICIT_ACCESS); | 131 profile_, Profile::EXPLICIT_ACCESS); |
124 sync_notifier_service->GetSyncedNotificationServices(notifiers); | 132 sync_notifier_service->GetSyncedNotificationServices(notifiers); |
125 | 133 |
126 if (comparator) | 134 if (comparator) |
127 std::sort(notifiers->begin(), notifiers->end(), *comparator); | 135 std::sort(notifiers->begin(), notifiers->end(), *comparator); |
128 else | 136 else |
129 std::sort(notifiers->begin(), notifiers->end(), SimpleCompareNotifiers); | 137 std::sort(notifiers->begin(), notifiers->end(), SimpleCompareNotifiers); |
130 } | 138 } |
131 | 139 |
132 int app_count = notifiers->size(); | 140 int app_count = notifiers->size(); |
133 | 141 |
134 ContentSettingsForOneType settings; | 142 ContentSettingsForOneType settings; |
135 notification_service->GetNotificationsSettings(&settings); | 143 notification_service->GetNotificationsSettings(&settings); |
136 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( | 144 FaviconService* favicon_service = FaviconServiceFactory::GetForProfile( |
137 profile, Profile::EXPLICIT_ACCESS); | 145 profile_, Profile::EXPLICIT_ACCESS); |
138 favicon_tracker_.reset(new CancelableTaskTracker()); | 146 favicon_tracker_.reset(new CancelableTaskTracker()); |
139 patterns_.clear(); | 147 patterns_.clear(); |
140 for (ContentSettingsForOneType::const_iterator iter = settings.begin(); | 148 for (ContentSettingsForOneType::const_iterator iter = settings.begin(); |
141 iter != settings.end(); ++iter) { | 149 iter != settings.end(); ++iter) { |
142 if (iter->primary_pattern == ContentSettingsPattern::Wildcard() && | 150 if (iter->primary_pattern == ContentSettingsPattern::Wildcard() && |
143 iter->secondary_pattern == ContentSettingsPattern::Wildcard() && | 151 iter->secondary_pattern == ContentSettingsPattern::Wildcard() && |
144 iter->source != "preference") { | 152 iter->source != "preference") { |
145 continue; | 153 continue; |
146 } | 154 } |
147 | 155 |
148 std::string url_pattern = iter->primary_pattern.ToString(); | 156 std::string url_pattern = iter->primary_pattern.ToString(); |
149 string16 name = UTF8ToUTF16(url_pattern); | 157 string16 name = UTF8ToUTF16(url_pattern); |
150 GURL url(url_pattern); | 158 GURL url(url_pattern); |
151 NotifierId notifier_id(url); | 159 NotifierId notifier_id(url); |
152 notifiers->push_back(new Notifier( | 160 notifiers->push_back(new Notifier( |
153 notifier_id, | 161 notifier_id, |
154 name, | 162 name, |
155 notification_service->IsNotifierEnabled(notifier_id))); | 163 notification_service->IsNotifierEnabled(notifier_id))); |
156 patterns_[name] = iter->primary_pattern; | 164 patterns_[name] = iter->primary_pattern; |
157 FaviconService::FaviconForURLParams favicon_params( | 165 FaviconService::FaviconForURLParams favicon_params( |
158 profile, url, chrome::FAVICON | chrome::TOUCH_ICON, | 166 profile_, url, chrome::FAVICON | chrome::TOUCH_ICON, |
159 message_center::kSettingsIconSize); | 167 message_center::kSettingsIconSize); |
160 // Note that favicon service obtains the favicon from history. This means | 168 // Note that favicon service obtains the favicon from history. This means |
161 // that it will fail to obtain the image if there are no history data for | 169 // that it will fail to obtain the image if there are no history data for |
162 // that URL. | 170 // that URL. |
163 favicon_service->GetFaviconImageForURL( | 171 favicon_service->GetFaviconImageForURL( |
164 favicon_params, | 172 favicon_params, |
165 base::Bind(&MessageCenterSettingsController::OnFaviconLoaded, | 173 base::Bind(&MessageCenterSettingsController::OnFaviconLoaded, |
166 base::Unretained(this), url), | 174 base::Unretained(this), url), |
167 favicon_tracker_.get()); | 175 favicon_tracker_.get()); |
168 } | 176 } |
(...skipping 18 matching lines...) Expand all Loading... |
187 } else { | 195 } else { |
188 std::sort(notifiers->begin() + app_count, notifiers->end(), | 196 std::sort(notifiers->begin() + app_count, notifiers->end(), |
189 SimpleCompareNotifiers); | 197 SimpleCompareNotifiers); |
190 } | 198 } |
191 } | 199 } |
192 | 200 |
193 void MessageCenterSettingsController::SetNotifierEnabled( | 201 void MessageCenterSettingsController::SetNotifierEnabled( |
194 const Notifier& notifier, | 202 const Notifier& notifier, |
195 bool enabled) { | 203 bool enabled) { |
196 // TODO(mukai): Fix this for multi-profile. | 204 // TODO(mukai): Fix this for multi-profile. |
197 Profile* profile = ProfileManager::GetDefaultProfile(); | 205 // If the profile has been destroyed, fail silently. |
| 206 if (!profile_) |
| 207 return; |
198 DesktopNotificationService* notification_service = | 208 DesktopNotificationService* notification_service = |
199 DesktopNotificationServiceFactory::GetForProfile(profile); | 209 DesktopNotificationServiceFactory::GetForProfile(profile_); |
200 | 210 |
201 if (notifier.notifier_id.type == NotifierId::WEB_PAGE) { | 211 if (notifier.notifier_id.type == NotifierId::WEB_PAGE) { |
202 // WEB_PAGE notifier cannot handle in DesktopNotificationService | 212 // WEB_PAGE notifier cannot handle in DesktopNotificationService |
203 // since it has the exact URL pattern. | 213 // since it has the exact URL pattern. |
204 // TODO(mukai): fix this. | 214 // TODO(mukai): fix this. |
205 ContentSetting default_setting = | 215 ContentSetting default_setting = |
206 notification_service->GetDefaultContentSetting(NULL); | 216 notification_service->GetDefaultContentSetting(NULL); |
207 DCHECK(default_setting == CONTENT_SETTING_ALLOW || | 217 DCHECK(default_setting == CONTENT_SETTING_ALLOW || |
208 default_setting == CONTENT_SETTING_BLOCK || | 218 default_setting == CONTENT_SETTING_BLOCK || |
209 default_setting == CONTENT_SETTING_ASK); | 219 default_setting == CONTENT_SETTING_ASK); |
(...skipping 16 matching lines...) Expand all Loading... |
226 } else { | 236 } else { |
227 LOG(ERROR) << "Invalid url pattern: " | 237 LOG(ERROR) << "Invalid url pattern: " |
228 << notifier.notifier_id.url.spec(); | 238 << notifier.notifier_id.url.spec(); |
229 } | 239 } |
230 } | 240 } |
231 } else { | 241 } else { |
232 notification_service->SetNotifierEnabled(notifier.notifier_id, enabled); | 242 notification_service->SetNotifierEnabled(notifier.notifier_id, enabled); |
233 if (notifier.notifier_id.type == NotifierId::SYNCED_NOTIFICATION_SERVICE) { | 243 if (notifier.notifier_id.type == NotifierId::SYNCED_NOTIFICATION_SERVICE) { |
234 notifier::ChromeNotifierService* notifier_service = | 244 notifier::ChromeNotifierService* notifier_service = |
235 notifier::ChromeNotifierServiceFactory::GetInstance()->GetForProfile( | 245 notifier::ChromeNotifierServiceFactory::GetInstance()->GetForProfile( |
236 profile, Profile::EXPLICIT_ACCESS); | 246 profile_, Profile::EXPLICIT_ACCESS); |
237 notifier_service->OnSyncedNotificationServiceEnabled( | 247 notifier_service->OnSyncedNotificationServiceEnabled( |
238 notifier.notifier_id.id, enabled); | 248 notifier.notifier_id.id, enabled); |
239 } | 249 } |
240 } | 250 } |
241 } | 251 } |
242 | 252 |
243 void MessageCenterSettingsController::OnNotifierSettingsClosing() { | 253 void MessageCenterSettingsController::OnNotifierSettingsClosing() { |
244 DCHECK(favicon_tracker_.get()); | 254 DCHECK(favicon_tracker_.get()); |
245 favicon_tracker_->TryCancelAll(); | 255 favicon_tracker_->TryCancelAll(); |
246 patterns_.clear(); | 256 patterns_.clear(); |
247 } | 257 } |
248 | 258 |
| 259 void MessageCenterSettingsController::Observe( |
| 260 int type, |
| 261 const content::NotificationSource& source, |
| 262 const content::NotificationDetails& details) { |
| 263 if (type == chrome::NOTIFICATION_PROFILE_DESTROYED && |
| 264 content::Source<Profile>(source).ptr() == profile_) { |
| 265 // Our profile just got destroyed, so we delete our pointer to it. |
| 266 profile_ = NULL; |
| 267 } |
| 268 } |
| 269 |
249 void MessageCenterSettingsController::OnFaviconLoaded( | 270 void MessageCenterSettingsController::OnFaviconLoaded( |
250 const GURL& url, | 271 const GURL& url, |
251 const chrome::FaviconImageResult& favicon_result) { | 272 const chrome::FaviconImageResult& favicon_result) { |
252 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, | 273 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, |
253 observers_, | 274 observers_, |
254 UpdateIconImage(NotifierId(url), favicon_result.image)); | 275 UpdateIconImage(NotifierId(url), favicon_result.image)); |
255 } | 276 } |
256 | 277 |
257 | 278 |
258 void MessageCenterSettingsController::SetAppImage(const std::string& id, | 279 void MessageCenterSettingsController::SetAppImage(const std::string& id, |
259 const gfx::ImageSkia& image) { | 280 const gfx::ImageSkia& image) { |
260 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, | 281 FOR_EACH_OBSERVER(message_center::NotifierSettingsObserver, |
261 observers_, | 282 observers_, |
262 UpdateIconImage(NotifierId(NotifierId::APPLICATION, id), | 283 UpdateIconImage(NotifierId(NotifierId::APPLICATION, id), |
263 gfx::Image(image))); | 284 gfx::Image(image))); |
264 } | 285 } |
OLD | NEW |