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

Side by Side Diff: chrome/browser/resources/file_manager/background/js/device_handler.js

Issue 247123002: Move Files.app files to ui/file_manager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix the test failure on non-chromeos Created 6 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 2014 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 'use strict';
6
7 /**
8 * Handler of device event.
9 * @constructor
10 */
11 function DeviceHandler() {
12 /**
13 * Map of device path and mount status of devices.
14 * @type {Object.<string, DeviceHandler.MountStatus>}
15 * @private
16 */
17 this.mountStatus_ = {};
18
19 /**
20 * List of ID of notificaitons that have a button.
21 * @type {Array.<string>}
22 * @private
23 */
24 this.buttonNotifications_ = [];
25
26 chrome.fileBrowserPrivate.onDeviceChanged.addListener(
27 this.onDeviceChanged_.bind(this));
28 chrome.fileBrowserPrivate.onMountCompleted.addListener(
29 this.onMountCompleted_.bind(this));
30 chrome.notifications.onButtonClicked.addListener(
31 this.onNotificationButtonClicked_.bind(this));
32
33 Object.seal(this);
34 }
35
36 /**
37 * Notification type.
38 * @param {string} prefix Prefix of notification ID.
39 * @param {string} title String ID of title.
40 * @param {string} message String ID of message.
41 * @param {string=} opt_buttonLabel String ID of the button label.
42 * @constructor
43 */
44 DeviceHandler.Notification = function(prefix, title, message, opt_buttonLabel) {
45 /**
46 * Prefix of notification ID.
47 * @type {string}
48 */
49 this.prefix = prefix;
50
51 /**
52 * String ID of title.
53 * @type {string}
54 */
55 this.title = title;
56
57 /**
58 * String ID of message.
59 * @type {string}
60 */
61 this.message = message;
62
63 /**
64 * String ID of button label.
65 * @type {?string}
66 */
67 this.buttonLabel = opt_buttonLabel || null;
68
69 Object.freeze(this);
70 };
71
72 /**
73 * @type {DeviceHandler.Notification}
74 * @const
75 */
76 DeviceHandler.Notification.DEVICE = new DeviceHandler.Notification(
77 'device',
78 'REMOVABLE_DEVICE_DETECTION_TITLE',
79 'REMOVABLE_DEVICE_SCANNING_MESSAGE');
80
81 /**
82 * @type {DeviceHandler.Notification}
83 * @const
84 */
85 DeviceHandler.Notification.DEVICE_FAIL = new DeviceHandler.Notification(
86 'deviceFail',
87 'REMOVABLE_DEVICE_DETECTION_TITLE',
88 'DEVICE_UNSUPPORTED_DEFAULT_MESSAGE');
89
90 /**
91 * @type {DeviceHandler.Notification}
92 * @const
93 */
94 DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED =
95 new DeviceHandler.Notification(
96 'deviceFail',
97 'REMOVABLE_DEVICE_DETECTION_TITLE',
98 'EXTERNAL_STORAGE_DISABLED_MESSAGE');
99
100 /**
101 * @type {DeviceHandler.Notification}
102 * @const
103 */
104 DeviceHandler.Notification.DEVICE_HARD_UNPLUGGED =
105 new DeviceHandler.Notification(
106 'deviceFail',
107 'DEVICE_HARD_UNPLUGGED_TITLE',
108 'DEVICE_HARD_UNPLUGGED_MESSAGE',
109 'DEVICE_HARD_UNPLUGGED_BUTTON_LABEL');
110
111 /**
112 * @type {DeviceHandler.Notification}
113 * @const
114 */
115 DeviceHandler.Notification.FORMAT_START = new DeviceHandler.Notification(
116 'formatStart',
117 'FORMATTING_OF_DEVICE_PENDING_TITLE',
118 'FORMATTING_OF_DEVICE_PENDING_MESSAGE');
119
120 /**
121 * @type {DeviceHandler.Notification}
122 * @const
123 */
124 DeviceHandler.Notification.FORMAT_SUCCESS = new DeviceHandler.Notification(
125 'formatSuccess',
126 'FORMATTING_OF_DEVICE_FINISHED_TITLE',
127 'FORMATTING_FINISHED_SUCCESS_MESSAGE');
128
129 /**
130 * @type {DeviceHandler.Notification}
131 * @const
132 */
133 DeviceHandler.Notification.FORMAT_FAIL = new DeviceHandler.Notification(
134 'formatFail',
135 'FORMATTING_OF_DEVICE_FAILED_TITLE',
136 'FORMATTING_FINISHED_FAILURE_MESSAGE');
137
138 /**
139 * Shows the notification for the device path.
140 * @param {string} devicePath Device path.
141 * @param {string=} opt_message Message overrides the default message.
142 * @return {string} Notification ID.
143 */
144 DeviceHandler.Notification.prototype.show = function(devicePath, opt_message) {
145 var buttons = this.buttonLabel ? [{title: str(this.buttonLabel)}] : undefined;
146 var notificationId = this.makeId_(devicePath);
147 chrome.notifications.create(
148 notificationId,
149 {
150 type: 'basic',
151 title: str(this.title),
152 message: opt_message || str(this.message),
153 iconUrl: chrome.runtime.getURL('/common/images/icon96.png'),
154 buttons: buttons
155 },
156 function() {});
157 return notificationId;
158 };
159
160 /**
161 * Hides the notification for the device path.
162 * @param {string} devicePath Device path.
163 */
164 DeviceHandler.Notification.prototype.hide = function(devicePath) {
165 chrome.notifications.clear(this.makeId_(devicePath), function() {});
166 };
167
168 /**
169 * Makes a notification ID for the device path.
170 * @param {string} devicePath Device path.
171 * @return {string} Notification ID.
172 * @private
173 */
174 DeviceHandler.Notification.prototype.makeId_ = function(devicePath) {
175 return this.prefix + ':' + devicePath;
176 };
177
178 /**
179 * Handles notifications from C++ sides.
180 * @param {DeviceEvent} event Device event.
181 * @private
182 */
183 DeviceHandler.prototype.onDeviceChanged_ = function(event) {
184 switch (event.type) {
185 case 'added':
186 DeviceHandler.Notification.DEVICE.show(event.devicePath);
187 this.mountStatus_[event.devicePath] = DeviceHandler.MountStatus.NO_RESULT;
188 break;
189 case 'disabled':
190 DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.show(
191 event.devicePath);
192 break;
193 case 'scan_canceled':
194 DeviceHandler.Notification.DEVICE.hide(event.devicePath);
195 break;
196 case 'removed':
197 DeviceHandler.Notification.DEVICE.hide(event.devicePath);
198 DeviceHandler.Notification.DEVICE_FAIL.hide(event.devicePath);
199 DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.hide(
200 event.devicePath);
201 delete this.mountStatus_[event.devicePath];
202 break;
203 case 'hard_unplugged':
204 var id = DeviceHandler.Notification.DEVICE_HARD_UNPLUGGED.show(
205 event.devicePath);
206 this.buttonNotifications_.push(id);
207 break;
208 case 'format_start':
209 DeviceHandler.Notification.FORMAT_START.show(event.devicePath);
210 break;
211 case 'format_success':
212 DeviceHandler.Notification.FORMAT_START.hide(event.devicePath);
213 DeviceHandler.Notification.FORMAT_SUCCESS.show(event.devicePath);
214 break;
215 case 'format_fail':
216 DeviceHandler.Notification.FORMAT_START.hide(event.devicePath);
217 DeviceHandler.Notification.FORMAT_FAIL.show(event.devicePath);
218 break;
219 }
220 };
221
222 /**
223 * Mount status for the device.
224 * Each multi-partition devices can obtain multiple mount completed events.
225 * This status shows what results are already obtained for the device.
226 * @enum {string}
227 * @const
228 */
229 DeviceHandler.MountStatus = Object.freeze({
230 // There is no mount results on the device.
231 NO_RESULT: 'noResult',
232 // There is no error on the device.
233 SUCCESS: 'success',
234 // There is only parent errors, that can be overridden by child results.
235 ONLY_PARENT_ERROR: 'onlyParentError',
236 // There is one child error.
237 CHILD_ERROR: 'childError',
238 // There is multiple child results and at least one is failure.
239 MULTIPART_ERROR: 'multipartError'
240 });
241
242 /**
243 * Handles mount completed events to show notifications for removable devices.
244 * @param {MountCompletedEvent} event Mount completed event.
245 * @private
246 */
247 DeviceHandler.prototype.onMountCompleted_ = function(event) {
248 // If this is remounting, which happens when resuming ChromeOS, the device has
249 // already inserted to the computer. So we suppress the notification.
250 var volume = event.volumeMetadata;
251 if (!volume.deviceType || event.isRemounting)
252 return;
253
254 var getFirstStatus = function(event) {
255 if (event.status === 'success')
256 return DeviceHandler.MountStatus.SUCCESS;
257 else if (event.volumeMetadata.isParentDevice)
258 return DeviceHandler.MountStatus.ONLY_PARENT_ERROR;
259 else
260 return DeviceHandler.MountStatus.CHILD_ERROR;
261 };
262
263 // Update the current status.
264 switch (this.mountStatus_[volume.devicePath]) {
265 // If there is no related device, do nothing.
266 case undefined:
267 return;
268 // If the multipart error message has already shown, do nothing because the
269 // message does not changed by the following mount results.
270 case DeviceHandler.MULTIPART_ERROR:
271 return;
272 // If this is the first result, hide the scanning notification.
273 case DeviceHandler.MountStatus.NO_RESULT:
274 DeviceHandler.Notification.DEVICE.hide(volume.devicePath);
275 this.mountStatus_[volume.devicePath] = getFirstStatus(event);
276 break;
277 // If there are only parent errors, and the new result is child's one, hide
278 // the parent error. (parent device contains partition table, which is
279 // unmountable)
280 case DeviceHandler.MountStatus.ONLY_PARENT_ERROR:
281 if (!volume.isParentDevice)
282 DeviceHandler.Notification.DEVICE_FAIL.hide(volume.devicePath);
283 this.mountStatus_[volume.devicePath] = getFirstStatus(event);
284 break;
285 // We have a multi-partition device for which at least one mount
286 // failed.
287 case DeviceHandler.MountStatus.SUCCESS:
288 case DeviceHandler.MountStatus.CHILD_ERROR:
289 if (this.mountStatus_[volume.devicePath] ===
290 DeviceHandler.MountStatus.SUCCESS &&
291 event.status === 'success') {
292 this.mountStatus_[volume.devicePath] =
293 DeviceHandler.MountStatus.SUCCESS;
294 } else {
295 this.mountStatus_[volume.devicePath] =
296 DeviceHandler.MountStatus.MULTIPART_ERROR;
297 }
298 break;
299 }
300
301 // Show the notification for the current errors.
302 // If there is no error, do not show/update the notification.
303 var message;
304 switch (this.mountStatus_[volume.devicePath]) {
305 case DeviceHandler.MountStatus.MULTIPART_ERROR:
306 message = volume.deviceLabel ?
307 strf('MULTIPART_DEVICE_UNSUPPORTED_MESSAGE', volume.deviceLabel) :
308 str('MULTIPART_DEVICE_UNSUPPORTED_DEFAULT_MESSAGE');
309 break;
310 case DeviceHandler.MountStatus.CHILD_ERROR:
311 case DeviceHandler.MountStatus.ONLY_PARENT_ERROR:
312 if (event.status === 'error_unsuported_filesystem') {
313 message = volume.deviceLabel ?
314 strf('DEVICE_UNSUPPORTED_MESSAGE', volume.deviceLabel) :
315 str('DEVICE_UNSUPPORTED_DEFAULT_MESSAGE');
316 } else {
317 message = volume.deviceLabel ?
318 strf('DEVICE_UNKNOWN_MESSAGE', volume.deviceLabel) :
319 str('DEVICE_UNKNOWN_DEFAULT_MESSAGE');
320 }
321 break;
322 }
323 if (message) {
324 DeviceHandler.Notification.DEVICE_FAIL.hide(volume.devicePath);
325 DeviceHandler.Notification.DEVICE_FAIL.show(volume.devicePath, message);
326 }
327 };
328
329 /**
330 * Handles notification button click.
331 * @param {string} id ID of the notification.
332 * @private
333 */
334 DeviceHandler.prototype.onNotificationButtonClicked_ = function(id) {
335 var index = this.buttonNotifications_.indexOf(id);
336 if (index !== -1) {
337 chrome.notifications.clear(id, function() {});
338 this.buttonNotifications_.splice(index, 1);
339 }
340 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698