| OLD | NEW |
| 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 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Handler of device event. | 8 * Handler of device event. |
| 9 * @constructor | 9 * @constructor |
| 10 * @extends {cr.EventTarget} | 10 * @extends {cr.EventTarget} |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 */ | 90 */ |
| 91 this.buttonLabel = opt_buttonLabel || null; | 91 this.buttonLabel = opt_buttonLabel || null; |
| 92 | 92 |
| 93 /** | 93 /** |
| 94 * Queue of API call. | 94 * Queue of API call. |
| 95 * @type {AsyncUtil.Queue} | 95 * @type {AsyncUtil.Queue} |
| 96 * @private | 96 * @private |
| 97 */ | 97 */ |
| 98 this.queue_ = new AsyncUtil.Queue(); | 98 this.queue_ = new AsyncUtil.Queue(); |
| 99 | 99 |
| 100 /** | |
| 101 * Timeout ID. | |
| 102 * @type {number} | |
| 103 * @private | |
| 104 */ | |
| 105 this.pendingShowTimerId_ = 0; | |
| 106 | |
| 107 Object.seal(this); | 100 Object.seal(this); |
| 108 }; | 101 }; |
| 109 | 102 |
| 110 /** | 103 /** |
| 111 * @type {DeviceHandler.Notification} | 104 * @type {DeviceHandler.Notification} |
| 112 * @const | 105 * @const |
| 113 */ | 106 */ |
| 114 DeviceHandler.Notification.DEVICE = new DeviceHandler.Notification( | 107 DeviceHandler.Notification.DEVICE = new DeviceHandler.Notification( |
| 115 'device', | 108 'device', |
| 116 'REMOVABLE_DEVICE_DETECTION_TITLE', | 109 'REMOVABLE_DEVICE_DETECTION_TITLE', |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 'FORMATTING_OF_DEVICE_FAILED_TITLE', | 175 'FORMATTING_OF_DEVICE_FAILED_TITLE', |
| 183 'FORMATTING_FINISHED_FAILURE_MESSAGE'); | 176 'FORMATTING_FINISHED_FAILURE_MESSAGE'); |
| 184 | 177 |
| 185 /** | 178 /** |
| 186 * Shows the notification for the device path. | 179 * Shows the notification for the device path. |
| 187 * @param {string} devicePath Device path. | 180 * @param {string} devicePath Device path. |
| 188 * @param {string=} opt_message Message overrides the default message. | 181 * @param {string=} opt_message Message overrides the default message. |
| 189 * @return {string} Notification ID. | 182 * @return {string} Notification ID. |
| 190 */ | 183 */ |
| 191 DeviceHandler.Notification.prototype.show = function(devicePath, opt_message) { | 184 DeviceHandler.Notification.prototype.show = function(devicePath, opt_message) { |
| 192 this.clearTimeout_(); | |
| 193 var notificationId = this.makeId_(devicePath); | 185 var notificationId = this.makeId_(devicePath); |
| 194 this.queue_.run(function(callback) { | 186 this.queue_.run(function(callback) { |
| 195 var buttons = | 187 var buttons = |
| 196 this.buttonLabel ? [{title: str(this.buttonLabel)}] : undefined; | 188 this.buttonLabel ? [{title: str(this.buttonLabel)}] : undefined; |
| 197 chrome.notifications.create( | 189 chrome.notifications.create( |
| 198 notificationId, | 190 notificationId, |
| 199 { | 191 { |
| 200 type: 'basic', | 192 type: 'basic', |
| 201 title: str(this.title), | 193 title: str(this.title), |
| 202 message: opt_message || str(this.message), | 194 message: opt_message || str(this.message), |
| 203 iconUrl: chrome.runtime.getURL('/common/images/icon96.png'), | 195 iconUrl: chrome.runtime.getURL('/common/images/icon96.png'), |
| 204 buttons: buttons | 196 buttons: buttons |
| 205 }, | 197 }, |
| 206 callback); | 198 callback); |
| 207 }.bind(this)); | 199 }.bind(this)); |
| 208 return notificationId; | 200 return notificationId; |
| 209 }; | 201 }; |
| 210 | 202 |
| 211 /** | 203 /** |
| 212 * Shows the notification after 5 seconds. | |
| 213 * @param {string} devicePath Device path. | |
| 214 */ | |
| 215 DeviceHandler.Notification.prototype.showLater = function(devicePath) { | |
| 216 this.clearTimeout_(); | |
| 217 this.pendingShowTimerId_ = setTimeout(this.show.bind(this, devicePath), 5000); | |
| 218 }; | |
| 219 | |
| 220 /** | |
| 221 * Hides the notification for the device path. | 204 * Hides the notification for the device path. |
| 222 * @param {string} devicePath Device path. | 205 * @param {string} devicePath Device path. |
| 223 */ | 206 */ |
| 224 DeviceHandler.Notification.prototype.hide = function(devicePath) { | 207 DeviceHandler.Notification.prototype.hide = function(devicePath) { |
| 225 this.clearTimeout_(); | |
| 226 this.queue_.run(function(callback) { | 208 this.queue_.run(function(callback) { |
| 227 chrome.notifications.clear(this.makeId_(devicePath), callback); | 209 chrome.notifications.clear(this.makeId_(devicePath), callback); |
| 228 }.bind(this)); | 210 }.bind(this)); |
| 229 }; | 211 }; |
| 230 | 212 |
| 231 /** | 213 /** |
| 232 * Makes a notification ID for the device path. | 214 * Makes a notification ID for the device path. |
| 233 * @param {string} devicePath Device path. | 215 * @param {string} devicePath Device path. |
| 234 * @return {string} Notification ID. | 216 * @return {string} Notification ID. |
| 235 * @private | 217 * @private |
| 236 */ | 218 */ |
| 237 DeviceHandler.Notification.prototype.makeId_ = function(devicePath) { | 219 DeviceHandler.Notification.prototype.makeId_ = function(devicePath) { |
| 238 return this.prefix + ':' + devicePath; | 220 return this.prefix + ':' + devicePath; |
| 239 }; | 221 }; |
| 240 | 222 |
| 241 /** | 223 /** |
| 242 * Cancels the timeout request. | |
| 243 * @private | |
| 244 */ | |
| 245 DeviceHandler.Notification.prototype.clearTimeout_ = function() { | |
| 246 if (this.pendingShowTimerId_) { | |
| 247 clearTimeout(this.pendingShowTimerId_); | |
| 248 this.pendingShowTimerId_ = 0; | |
| 249 } | |
| 250 }; | |
| 251 | |
| 252 /** | |
| 253 * Handles notifications from C++ sides. | 224 * Handles notifications from C++ sides. |
| 254 * @param {DeviceEvent} event Device event. | 225 * @param {DeviceEvent} event Device event. |
| 255 * @private | 226 * @private |
| 256 */ | 227 */ |
| 257 DeviceHandler.prototype.onDeviceChanged_ = function(event) { | 228 DeviceHandler.prototype.onDeviceChanged_ = function(event) { |
| 258 switch (event.type) { | 229 switch (event.type) { |
| 259 case 'added': | 230 case 'scan_started': |
| 260 if (!this.isStartup_) | 231 DeviceHandler.Notification.DEVICE.show(event.devicePath); |
| 261 DeviceHandler.Notification.DEVICE.showLater(event.devicePath); | 232 break; |
| 262 this.mountStatus_[event.devicePath] = DeviceHandler.MountStatus.NO_RESULT; | 233 case 'scan_cancelled': |
| 234 DeviceHandler.Notification.DEVICE.hide(event.devicePath); |
| 263 break; | 235 break; |
| 264 case 'disabled': | 236 case 'disabled': |
| 265 DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.show( | 237 DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.show( |
| 266 event.devicePath); | 238 event.devicePath); |
| 267 break; | 239 break; |
| 268 case 'scan_canceled': | |
| 269 DeviceHandler.Notification.DEVICE.hide(event.devicePath); | |
| 270 break; | |
| 271 case 'removed': | 240 case 'removed': |
| 272 DeviceHandler.Notification.DEVICE.hide(event.devicePath); | 241 DeviceHandler.Notification.DEVICE.hide(event.devicePath); |
| 273 DeviceHandler.Notification.DEVICE_FAIL.hide(event.devicePath); | 242 DeviceHandler.Notification.DEVICE_FAIL.hide(event.devicePath); |
| 274 DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.hide( | 243 DeviceHandler.Notification.DEVICE_EXTERNAL_STORAGE_DISABLED.hide( |
| 275 event.devicePath); | 244 event.devicePath); |
| 276 delete this.mountStatus_[event.devicePath]; | 245 delete this.mountStatus_[event.devicePath]; |
| 277 break; | 246 break; |
| 278 case 'hard_unplugged': | 247 case 'hard_unplugged': |
| 279 if (!this.isStartup_) { | 248 if (!this.isStartup_) { |
| 280 DeviceHandler.Notification.DEVICE_HARD_UNPLUGGED.show( | 249 DeviceHandler.Notification.DEVICE_HARD_UNPLUGGED.show( |
| 281 event.devicePath); | 250 event.devicePath); |
| 282 } | 251 } |
| 283 break; | 252 break; |
| 284 case 'format_start': | 253 case 'format_start': |
| 285 DeviceHandler.Notification.FORMAT_START.show(event.devicePath); | 254 DeviceHandler.Notification.FORMAT_START.show(event.devicePath); |
| 286 break; | 255 break; |
| 287 case 'format_success': | 256 case 'format_success': |
| 288 DeviceHandler.Notification.FORMAT_START.hide(event.devicePath); | 257 DeviceHandler.Notification.FORMAT_START.hide(event.devicePath); |
| 289 DeviceHandler.Notification.FORMAT_SUCCESS.show(event.devicePath); | 258 DeviceHandler.Notification.FORMAT_SUCCESS.show(event.devicePath); |
| 290 break; | 259 break; |
| 291 case 'format_fail': | 260 case 'format_fail': |
| 292 DeviceHandler.Notification.FORMAT_START.hide(event.devicePath); | 261 DeviceHandler.Notification.FORMAT_START.hide(event.devicePath); |
| 293 DeviceHandler.Notification.FORMAT_FAIL.show(event.devicePath); | 262 DeviceHandler.Notification.FORMAT_FAIL.show(event.devicePath); |
| 294 break; | 263 break; |
| 264 default: |
| 265 console.error('Unknown event tyep: ' + event.type); |
| 266 break; |
| 295 } | 267 } |
| 296 }; | 268 }; |
| 297 | 269 |
| 298 /** | 270 /** |
| 299 * Mount status for the device. | 271 * Mount status for the device. |
| 300 * Each multi-partition devices can obtain multiple mount completed events. | 272 * Each multi-partition devices can obtain multiple mount completed events. |
| 301 * This status shows what results are already obtained for the device. | 273 * This status shows what results are already obtained for the device. |
| 302 * @enum {string} | 274 * @enum {string} |
| 303 * @const | 275 * @const |
| 304 */ | 276 */ |
| (...skipping 12 matching lines...) Expand all Loading... |
| 317 | 289 |
| 318 /** | 290 /** |
| 319 * Handles mount completed events to show notifications for removable devices. | 291 * Handles mount completed events to show notifications for removable devices. |
| 320 * @param {MountCompletedEvent} event Mount completed event. | 292 * @param {MountCompletedEvent} event Mount completed event. |
| 321 * @private | 293 * @private |
| 322 */ | 294 */ |
| 323 DeviceHandler.prototype.onMountCompleted_ = function(event) { | 295 DeviceHandler.prototype.onMountCompleted_ = function(event) { |
| 324 // If this is remounting, which happens when resuming ChromeOS, the device has | 296 // If this is remounting, which happens when resuming ChromeOS, the device has |
| 325 // already inserted to the computer. So we suppress the notification. | 297 // already inserted to the computer. So we suppress the notification. |
| 326 var volume = event.volumeMetadata; | 298 var volume = event.volumeMetadata; |
| 327 if (!volume.deviceType || event.isRemounting) | 299 if (!volume.deviceType || !event.shouldNotify) |
| 328 return; | 300 return; |
| 329 | 301 |
| 330 // If the current volume status is succeed and it should be handled in | 302 // If the current volume status is succeed and it should be handled in |
| 331 // Files.app, show the notification to navigate the volume. | 303 // Files.app, show the notification to navigate the volume. |
| 332 if (event.status === 'success' && event.shouldNotify) { | 304 if (event.eventType === 'mount' && |
| 305 event.status === 'success') { |
| 333 if (this.navigationVolumes_[event.volumeMetadata.devicePath]) { | 306 if (this.navigationVolumes_[event.volumeMetadata.devicePath]) { |
| 334 // The notification has already shown for the device. It seems the device | 307 // The notification has already shown for the device. It seems the device |
| 335 // has multiple volumes. The order of mount events of volumes are | 308 // has multiple volumes. The order of mount events of volumes are |
| 336 // undetermind, so it compares the volume Id and uses the earier order ID | 309 // undetermind, so it compares the volume Id and uses the earier order ID |
| 337 // to prevent Files.app from navigating to different volumes for each | 310 // to prevent Files.app from navigating to different volumes for each |
| 338 // time. | 311 // time. |
| 339 if (event.volumeMetadata.volumeId < | 312 if (event.volumeMetadata.volumeId < |
| 340 this.navigationVolumes_[event.volumeMetadata.devicePath]) { | 313 this.navigationVolumes_[event.volumeMetadata.devicePath]) { |
| 341 this.navigationVolumes_[event.volumeMetadata.devicePath] = | 314 this.navigationVolumes_[event.volumeMetadata.devicePath] = |
| 342 event.volumeMetadata.volumeId; | 315 event.volumeMetadata.volumeId; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 359 var getFirstStatus = function(event) { | 332 var getFirstStatus = function(event) { |
| 360 if (event.status === 'success') | 333 if (event.status === 'success') |
| 361 return DeviceHandler.MountStatus.SUCCESS; | 334 return DeviceHandler.MountStatus.SUCCESS; |
| 362 else if (event.volumeMetadata.isParentDevice) | 335 else if (event.volumeMetadata.isParentDevice) |
| 363 return DeviceHandler.MountStatus.ONLY_PARENT_ERROR; | 336 return DeviceHandler.MountStatus.ONLY_PARENT_ERROR; |
| 364 else | 337 else |
| 365 return DeviceHandler.MountStatus.CHILD_ERROR; | 338 return DeviceHandler.MountStatus.CHILD_ERROR; |
| 366 }; | 339 }; |
| 367 | 340 |
| 368 // Update the current status. | 341 // Update the current status. |
| 342 if (!this.mountStatus_[volume.devicePath]) |
| 343 this.mountStatus_[volume.devicePath] = DeviceHandler.MountStatus.NO_RESULT; |
| 369 switch (this.mountStatus_[volume.devicePath]) { | 344 switch (this.mountStatus_[volume.devicePath]) { |
| 370 // If there is no related device, do nothing. | |
| 371 case undefined: | |
| 372 return; | |
| 373 // If the multipart error message has already shown, do nothing because the | 345 // If the multipart error message has already shown, do nothing because the |
| 374 // message does not changed by the following mount results. | 346 // message does not changed by the following mount results. |
| 375 case DeviceHandler.MountStatus.MULTIPART_ERROR: | 347 case DeviceHandler.MountStatus.MULTIPART_ERROR: |
| 376 return; | 348 return; |
| 377 // If this is the first result, hide the scanning notification. | 349 // If this is the first result, hide the scanning notification. |
| 378 case DeviceHandler.MountStatus.NO_RESULT: | 350 case DeviceHandler.MountStatus.NO_RESULT: |
| 379 DeviceHandler.Notification.DEVICE.hide(volume.devicePath); | 351 DeviceHandler.Notification.DEVICE.hide(volume.devicePath); |
| 380 this.mountStatus_[volume.devicePath] = getFirstStatus(event); | 352 this.mountStatus_[volume.devicePath] = getFirstStatus(event); |
| 381 break; | 353 break; |
| 382 // If there are only parent errors, and the new result is child's one, hide | 354 // If there are only parent errors, and the new result is child's one, hide |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 this.dispatchEvent(event); | 420 this.dispatchEvent(event); |
| 449 } | 421 } |
| 450 }; | 422 }; |
| 451 | 423 |
| 452 DeviceHandler.prototype.onStartup_ = function() { | 424 DeviceHandler.prototype.onStartup_ = function() { |
| 453 this.isStartup_ = true; | 425 this.isStartup_ = true; |
| 454 setTimeout(function() { | 426 setTimeout(function() { |
| 455 this.isStartup_ = false; | 427 this.isStartup_ = false; |
| 456 }.bind(this), 5000); | 428 }.bind(this), 5000); |
| 457 }; | 429 }; |
| OLD | NEW |