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

Side by Side Diff: chrome/browser/chromeos/extensions/file_browser_notifications.cc

Issue 14020002: chromeos: Move chrome/browser/chromeos/extensions/file_browser* to chrome/browser/chromeos/file_man… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sort Created 7 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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.
4
5 #include "chrome/browser/chromeos/extensions/file_browser_notifications.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop.h"
9 #include "base/stl_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/chromeos/extensions/file_manager/file_manager_util.h"
13 #include "chrome/browser/notifications/desktop_notification_service.h"
14 #include "chrome/browser/notifications/notification_delegate.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_list.h"
18 #include "grit/generated_resources.h"
19 #include "grit/theme_resources.h"
20 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "ui/webui/web_ui_util.h"
23
24 namespace {
25
26 struct NotificationTypeInfo {
27 FileBrowserNotifications::NotificationType type;
28 const char* notification_id_prefix;
29 int icon_id;
30 int title_id;
31 int message_id;
32 };
33
34 // Information about notification types.
35 // The order of notification types in the array must match the order of types in
36 // NotificationType enum (i.e. the following MUST be satisfied:
37 // kNotificationTypes[type].type == type).
38 const NotificationTypeInfo kNotificationTypes[] = {
39 {
40 FileBrowserNotifications::DEVICE, // type
41 "Device_", // notification_id_prefix
42 IDR_FILES_APP_ICON, // icon_id
43 IDS_REMOVABLE_DEVICE_DETECTION_TITLE, // title_id
44 IDS_REMOVABLE_DEVICE_SCANNING_MESSAGE // message_id
45 },
46 {
47 FileBrowserNotifications::DEVICE_FAIL, // type
48 "DeviceFail_", // notification_id_prefix
49 IDR_FILES_APP_ICON, // icon_id
50 IDS_REMOVABLE_DEVICE_DETECTION_TITLE, // title_id
51 IDS_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE // message_id
52 },
53 {
54 FileBrowserNotifications::DEVICE_EXTERNAL_STORAGE_DISABLED, // type
55 "DeviceFail_", // nottification_id_prefix; same as for DEVICE_FAIL.
56 IDR_FILES_APP_ICON, // icon_id
57 IDS_REMOVABLE_DEVICE_DETECTION_TITLE, // title_id
58 IDS_EXTERNAL_STORAGE_DISABLED_MESSAGE // message_id
59 },
60 {
61 FileBrowserNotifications::FORMAT_START, // type
62 "FormatStart_", // notification_id_prefix
63 IDR_FILES_APP_ICON, // icon_id
64 IDS_FORMATTING_OF_DEVICE_PENDING_TITLE, // title_id
65 IDS_FORMATTING_OF_DEVICE_PENDING_MESSAGE // message_id
66 },
67 {
68 FileBrowserNotifications::FORMAT_START_FAIL, // type
69 "FormatComplete_", // notification_id_prefix
70 IDR_FILES_APP_ICON, // icon_id
71 IDS_FORMATTING_OF_DEVICE_FAILED_TITLE, // title_id
72 IDS_FORMATTING_STARTED_FAILURE_MESSAGE // message_id
73 },
74 {
75 FileBrowserNotifications::FORMAT_SUCCESS, // type
76 "FormatComplete_", // notification_id_prefix
77 IDR_FILES_APP_ICON, // icon_id
78 IDS_FORMATTING_OF_DEVICE_FINISHED_TITLE, // title_id
79 IDS_FORMATTING_FINISHED_SUCCESS_MESSAGE // message_id
80 },
81 {
82 FileBrowserNotifications::FORMAT_FAIL, // type
83 "FormatComplete_", // notifications_id_prefix
84 IDR_FILES_APP_ICON, // icon_id
85 IDS_FORMATTING_OF_DEVICE_FAILED_TITLE, // title_id
86 IDS_FORMATTING_FINISHED_FAILURE_MESSAGE // message_id
87 },
88 };
89
90 int GetIconId(FileBrowserNotifications::NotificationType type) {
91 DCHECK_GE(type, 0);
92 DCHECK_LT(static_cast<size_t>(type), arraysize(kNotificationTypes));
93 DCHECK(kNotificationTypes[type].type == type);
94
95 return kNotificationTypes[type].icon_id;
96 }
97
98 string16 GetTitle(FileBrowserNotifications::NotificationType type) {
99 DCHECK_GE(type, 0);
100 DCHECK_LT(static_cast<size_t>(type), arraysize(kNotificationTypes));
101 DCHECK(kNotificationTypes[type].type == type);
102
103 int id = kNotificationTypes[type].title_id;
104 if (id < 0)
105 return string16();
106 return l10n_util::GetStringUTF16(id);
107 }
108
109 string16 GetMessage(FileBrowserNotifications::NotificationType type) {
110 DCHECK_GE(type, 0);
111 DCHECK_LT(static_cast<size_t>(type), arraysize(kNotificationTypes));
112 DCHECK(kNotificationTypes[type].type == type);
113
114 int id = kNotificationTypes[type].message_id;
115 if (id < 0)
116 return string16();
117 return l10n_util::GetStringUTF16(id);
118 }
119
120 std::string GetNotificationId(FileBrowserNotifications::NotificationType type,
121 const std::string& path) {
122 DCHECK_GE(type, 0);
123 DCHECK_LT(static_cast<size_t>(type), arraysize(kNotificationTypes));
124 DCHECK(kNotificationTypes[type].type == type);
125
126 std::string id_prefix(kNotificationTypes[type].notification_id_prefix);
127 return id_prefix.append(path);
128 }
129
130 } // namespace
131
132 // Manages file browser notifications. Generates a desktop notification on
133 // construction and removes it from the host when closed. Owned by the host.
134 class FileBrowserNotifications::NotificationMessage {
135 public:
136 class Delegate : public NotificationDelegate {
137 public:
138 Delegate(const base::WeakPtr<FileBrowserNotifications>& host,
139 const std::string& id)
140 : host_(host),
141 id_(id) {}
142 virtual void Display() OVERRIDE {}
143 virtual void Error() OVERRIDE {}
144 virtual void Close(bool by_user) OVERRIDE {
145 if (host_)
146 host_->RemoveNotificationById(id_);
147 }
148 virtual void Click() OVERRIDE {
149 // TODO(tbarzic): Show more info page once we have one.
150 }
151 virtual std::string id() const OVERRIDE { return id_; }
152 virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
153 return NULL;
154 }
155
156 private:
157 virtual ~Delegate() {}
158
159 base::WeakPtr<FileBrowserNotifications> host_;
160 std::string id_;
161
162 DISALLOW_COPY_AND_ASSIGN(Delegate);
163 };
164
165 NotificationMessage(FileBrowserNotifications* host,
166 Profile* profile,
167 NotificationType type,
168 const std::string& notification_id,
169 const string16& message)
170 : message_(message) {
171 const gfx::Image& icon =
172 ResourceBundle::GetSharedInstance().GetNativeImageNamed(
173 GetIconId(type));
174 // TODO(mukai): refactor here to invoke NotificationUIManager directly.
175 const string16 replace_id = UTF8ToUTF16(notification_id);
176 DesktopNotificationService::AddIconNotification(
177 file_manager_util::GetFileBrowserExtensionUrl(), GetTitle(type),
178 message, icon, replace_id,
179 new Delegate(host->AsWeakPtr(), notification_id), profile);
180 }
181
182 ~NotificationMessage() {}
183
184 // Used in test.
185 string16 message() { return message_; }
186
187 private:
188 string16 message_;
189
190 DISALLOW_COPY_AND_ASSIGN(NotificationMessage);
191 };
192
193 struct FileBrowserNotifications::MountRequestsInfo {
194 bool mount_success_exists;
195 bool fail_message_finalized;
196 bool fail_notification_shown;
197 bool non_parent_device_failed;
198 bool device_notification_hidden;
199
200 MountRequestsInfo() : mount_success_exists(false),
201 fail_message_finalized(false),
202 fail_notification_shown(false),
203 non_parent_device_failed(false),
204 device_notification_hidden(false) {
205 }
206 };
207
208 FileBrowserNotifications::FileBrowserNotifications(Profile* profile)
209 : profile_(profile) {
210 }
211
212 FileBrowserNotifications::~FileBrowserNotifications() {
213 STLDeleteContainerPairSecondPointers(notification_map_.begin(),
214 notification_map_.end());
215 }
216
217 void FileBrowserNotifications::RegisterDevice(const std::string& path) {
218 mount_requests_.insert(MountRequestsMap::value_type(path,
219 MountRequestsInfo()));
220 }
221
222 void FileBrowserNotifications::UnregisterDevice(const std::string& path) {
223 mount_requests_.erase(path);
224 }
225
226 void FileBrowserNotifications::ManageNotificationsOnMountCompleted(
227 const std::string& system_path, const std::string& label, bool is_parent,
228 bool success, bool is_unsupported) {
229 MountRequestsMap::iterator it = mount_requests_.find(system_path);
230 if (it == mount_requests_.end())
231 return;
232
233 // We have to hide device scanning notification if we haven't done it already.
234 if (!it->second.device_notification_hidden) {
235 HideNotification(DEVICE, system_path);
236 it->second.device_notification_hidden = true;
237 }
238
239 // Check if there is fail notification for parent device. If so, disregard it.
240 // (parent device contains partition table, which is unmountable).
241 if (!is_parent && it->second.fail_notification_shown &&
242 !it->second.non_parent_device_failed) {
243 HideNotification(DEVICE_FAIL, system_path);
244 it->second.fail_notification_shown = false;
245 }
246
247 // If notification can't change any more, no need to continue.
248 if (it->second.fail_message_finalized)
249 return;
250
251 int notification_message_id = 0;
252
253 // Do we have a multi-partition device for which at least one mount failed.
254 bool fail_on_multipartition_device =
255 success ? it->second.non_parent_device_failed
256 : it->second.mount_success_exists ||
257 it->second.non_parent_device_failed;
258
259 if (fail_on_multipartition_device) {
260 it->second.fail_message_finalized = true;
261 notification_message_id =
262 label.empty() ? IDS_MULTIPART_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE
263 : IDS_MULTIPART_DEVICE_UNSUPPORTED_MESSAGE;
264 } else if (!success) {
265 // First device failed.
266 if (!is_unsupported) {
267 notification_message_id =
268 label.empty() ? IDS_DEVICE_UNKNOWN_DEFAULT_MESSAGE
269 : IDS_DEVICE_UNKNOWN_MESSAGE;
270 } else {
271 notification_message_id =
272 label.empty() ? IDS_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE
273 : IDS_DEVICE_UNSUPPORTED_MESSAGE;
274 }
275 }
276
277 if (success) {
278 it->second.mount_success_exists = true;
279 } else {
280 it->second.non_parent_device_failed |= !is_parent;
281 }
282
283 if (notification_message_id == 0)
284 return;
285
286 if (it->second.fail_notification_shown) {
287 HideNotification(DEVICE_FAIL, system_path);
288 } else {
289 it->second.fail_notification_shown = true;
290 }
291
292 if (!label.empty()) {
293 ShowNotificationWithMessage(DEVICE_FAIL, system_path,
294 l10n_util::GetStringFUTF16(notification_message_id,
295 ASCIIToUTF16(label)));
296 } else {
297 ShowNotificationWithMessage(DEVICE_FAIL, system_path,
298 l10n_util::GetStringUTF16(notification_message_id));
299 }
300 }
301
302 void FileBrowserNotifications::ShowNotification(NotificationType type,
303 const std::string& path) {
304 ShowNotificationWithMessage(type, path, GetMessage(type));
305 }
306
307 void FileBrowserNotifications::ShowNotificationWithMessage(
308 NotificationType type,
309 const std::string& path,
310 const string16& message) {
311 std::string notification_id = GetNotificationId(type, path);
312 hidden_notifications_.erase(notification_id);
313 ShowNotificationById(type, notification_id, message);
314 }
315
316 void FileBrowserNotifications::ShowNotificationDelayed(
317 NotificationType type,
318 const std::string& path,
319 base::TimeDelta delay) {
320 std::string notification_id = GetNotificationId(type, path);
321 hidden_notifications_.erase(notification_id);
322 MessageLoop::current()->PostDelayedTask(
323 FROM_HERE,
324 base::Bind(&FileBrowserNotifications::ShowNotificationById, AsWeakPtr(),
325 type, notification_id, GetMessage(type)),
326 delay);
327 }
328
329 void FileBrowserNotifications::HideNotification(NotificationType type,
330 const std::string& path) {
331 std::string notification_id = GetNotificationId(type, path);
332 HideNotificationById(notification_id);
333 }
334
335 void FileBrowserNotifications::HideNotificationDelayed(
336 NotificationType type, const std::string& path, base::TimeDelta delay) {
337 MessageLoop::current()->PostDelayedTask(
338 FROM_HERE,
339 base::Bind(&FileBrowserNotifications::HideNotification, AsWeakPtr(),
340 type, path),
341 delay);
342 }
343
344 void FileBrowserNotifications::ShowNotificationById(
345 NotificationType type,
346 const std::string& notification_id,
347 const string16& message) {
348 if (hidden_notifications_.find(notification_id) !=
349 hidden_notifications_.end()) {
350 // Notification was hidden after a delayed show was requested.
351 hidden_notifications_.erase(notification_id);
352 return;
353 }
354 if (notification_map_.find(notification_id) != notification_map_.end()) {
355 // Remove any existing notification with |notification_id|.
356 // Will trigger Delegate::Close which will call RemoveNotificationById.
357 DesktopNotificationService::RemoveNotification(notification_id);
358 DCHECK(notification_map_.find(notification_id) == notification_map_.end());
359 }
360 // Create a new notification with |notification_id|.
361 NotificationMessage* new_message =
362 new NotificationMessage(this, profile_, type, notification_id, message);
363 notification_map_[notification_id] = new_message;
364 }
365
366 void FileBrowserNotifications::HideNotificationById(
367 const std::string& notification_id) {
368 NotificationMap::iterator it = notification_map_.find(notification_id);
369 if (it != notification_map_.end()) {
370 // Will trigger Delegate::Close which will call RemoveNotificationById.
371 DesktopNotificationService::RemoveNotification(notification_id);
372 } else {
373 // Mark as hidden so it does not get shown from a delayed task.
374 hidden_notifications_.insert(notification_id);
375 }
376 }
377
378 void FileBrowserNotifications::RemoveNotificationById(
379 const std::string& notification_id) {
380 NotificationMap::iterator it = notification_map_.find(notification_id);
381 if (it != notification_map_.end()) {
382 NotificationMessage* notification = it->second;
383 notification_map_.erase(it);
384 delete notification;
385 }
386 }
387
388 string16 FileBrowserNotifications::GetNotificationMessageForTest(
389 const std::string& id) const {
390 NotificationMap::const_iterator it = notification_map_.find(id);
391 if (it == notification_map_.end())
392 return string16();
393 return it->second->message();
394 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698