| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 /** | 5 /** |
| 6 * Represents each volume, such as "drive", "download directory", each "USB | 6 * Represents each volume, such as "drive", "download directory", each "USB |
| 7 * flush storage", or "mounted zip archive" etc. | 7 * flush storage", or "mounted zip archive" etc. |
| 8 * | 8 * |
| 9 * @constructor | 9 * @constructor |
| 10 * @struct | 10 * @struct |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 if (error === VolumeManagerCommon.VolumeError[key]) | 218 if (error === VolumeManagerCommon.VolumeError[key]) |
| 219 return; | 219 return; |
| 220 } | 220 } |
| 221 | 221 |
| 222 throw new Error('Invalid mount error: ' + error); | 222 throw new Error('Invalid mount error: ' + error); |
| 223 }; | 223 }; |
| 224 | 224 |
| 225 /** | 225 /** |
| 226 * Builds the VolumeInfo data from VolumeMetadata. | 226 * Builds the VolumeInfo data from VolumeMetadata. |
| 227 * @param {VolumeMetadata} volumeMetadata Metadata instance for the volume. | 227 * @param {VolumeMetadata} volumeMetadata Metadata instance for the volume. |
| 228 * @param {function(VolumeInfo)} callback Called on completion. | 228 * @return {!Promise.<VolumeInfo>} Promise settled with the VolumeInfo instance. |
| 229 */ | 229 */ |
| 230 volumeManagerUtil.createVolumeInfo = function(volumeMetadata, callback) { | 230 volumeManagerUtil.createVolumeInfo = function(volumeMetadata) { |
| 231 var localizedLabel; | 231 var localizedLabel; |
| 232 switch (volumeMetadata.volumeType) { | 232 switch (volumeMetadata.volumeType) { |
| 233 case VolumeManagerCommon.VolumeType.DOWNLOADS: | 233 case VolumeManagerCommon.VolumeType.DOWNLOADS: |
| 234 localizedLabel = str('DOWNLOADS_DIRECTORY_LABEL'); | 234 localizedLabel = str('DOWNLOADS_DIRECTORY_LABEL'); |
| 235 break; | 235 break; |
| 236 case VolumeManagerCommon.VolumeType.DRIVE: | 236 case VolumeManagerCommon.VolumeType.DRIVE: |
| 237 localizedLabel = str('DRIVE_DIRECTORY_LABEL'); | 237 localizedLabel = str('DRIVE_DIRECTORY_LABEL'); |
| 238 break; | 238 break; |
| 239 default: | 239 default: |
| 240 // TODO(mtomasz): Calculate volumeLabel for all types of volumes in the | 240 // TODO(mtomasz): Calculate volumeLabel for all types of volumes in the |
| 241 // C++ layer. | 241 // C++ layer. |
| 242 localizedLabel = volumeMetadata.volumeLabel || | 242 localizedLabel = volumeMetadata.volumeLabel || |
| 243 volumeMetadata.volumeId.split(':', 2)[1]; | 243 volumeMetadata.volumeId.split(':', 2)[1]; |
| 244 break; | 244 break; |
| 245 } | 245 } |
| 246 | 246 |
| 247 console.debug('Requesting file system.'); | 247 console.debug('Requesting file system.'); |
| 248 chrome.fileManagerPrivate.requestFileSystem( | 248 return new Promise( |
| 249 volumeMetadata.volumeId, | 249 function(resolve, reject) { |
| 250 function(fileSystem) { | 250 chrome.fileSystem.requestFileSystem( |
| 251 // TODO(mtomasz): chrome.runtime.lastError should have error reason. | 251 { |
| 252 if (!fileSystem) { | 252 volumeId: volumeMetadata.volumeId, |
| 253 console.error('File system not found: ' + volumeMetadata.volumeId); | 253 writable: true |
| 254 callback(new VolumeInfo( | 254 }, |
| 255 /** @type {VolumeManagerCommon.VolumeType} */ | 255 function(isolatedFileSystem) { |
| 256 (volumeMetadata.volumeType), | 256 if (chrome.runtime.lastError) |
| 257 volumeMetadata.volumeId, | 257 reject(chrome.runtime.lastError.message); |
| 258 null, // File system is not found. | 258 else |
| 259 volumeMetadata.mountCondition, | 259 resolve(isolatedFileSystem); |
| 260 volumeMetadata.deviceType, | 260 }); |
| 261 volumeMetadata.devicePath, | 261 }) |
| 262 volumeMetadata.isReadOnly, | 262 .then( |
| 263 volumeMetadata.profile, | 263 /** |
| 264 localizedLabel, | 264 * @param {!FileSystem} isolatedFileSystem |
| 265 volumeMetadata.extensionId, | 265 */ |
| 266 volumeMetadata.hasMedia)); | 266 function(isolatedFileSystem) { |
| 267 return; | 267 // Since File System API works on isolated entries only, we need to |
| 268 } | 268 // convert it back to external one. |
| 269 | 269 // TODO(mtomasz): Make Files app work on isolated entries. |
| 270 console.debug('File system obtained: ' + volumeMetadata.volumeId); | 270 return new Promise(function(resolve, reject) { |
| 271 if (volumeMetadata.volumeType == | 271 chrome.fileManagerPrivate.resolveIsolatedEntries( |
| 272 VolumeManagerCommon.VolumeType.DRIVE) { | 272 [isolatedFileSystem.root], |
| 273 // After file system is mounted, we "read" drive grand root | 273 function(entries) { |
| 274 // entry at first. This triggers full feed fetch on background. | 274 if (chrome.runtime.lastError) |
| 275 // Note: we don't need to handle errors here, because even if | 275 reject(chrome.runtime.lastError.message); |
| 276 // it fails, accessing to some path later will just become | 276 else if (!entries[0]) |
| 277 // a fast-fetch and it re-triggers full-feed fetch. | 277 reject('Resolving for external context failed.'); |
| 278 fileSystem.root.createReader().readEntries( | 278 else |
| 279 function() { /* do nothing */ }, | 279 resolve(entries[0].filesystem); |
| 280 function(error) { | 280 }); |
| 281 console.error( | |
| 282 'Triggering full feed fetch is failed: ' + error.name); | |
| 283 }); | 281 }); |
| 284 } | 282 }) |
| 285 callback(new VolumeInfo( | 283 .then( |
| 286 /** @type {VolumeManagerCommon.VolumeType} */ | 284 /** |
| 287 (volumeMetadata.volumeType), | 285 * @param {!FileSystem} fileSystem |
| 288 volumeMetadata.volumeId, | 286 */ |
| 289 fileSystem, | 287 function(fileSystem) { |
| 290 volumeMetadata.mountCondition, | 288 console.debug('File system obtained: ' + volumeMetadata.volumeId); |
| 291 volumeMetadata.deviceType, | 289 if (volumeMetadata.volumeType === |
| 292 volumeMetadata.devicePath, | 290 VolumeManagerCommon.VolumeType.DRIVE) { |
| 293 volumeMetadata.isReadOnly, | 291 // After file system is mounted, we "read" drive grand root |
| 294 volumeMetadata.profile, | 292 // entry at first. This triggers full feed fetch on background. |
| 295 localizedLabel, | 293 // Note: we don't need to handle errors here, because even if |
| 296 volumeMetadata.extensionId, | 294 // it fails, accessing to some path later will just become |
| 297 volumeMetadata.hasMedia)); | 295 // a fast-fetch and it re-triggers full-feed fetch. |
| 298 }); | 296 fileSystem.root.createReader().readEntries( |
| 297 function() { /* do nothing */ }, |
| 298 function(error) { |
| 299 console.error( |
| 300 'Triggering full feed fetch is failed: ' + |
| 301 error.name); |
| 302 }); |
| 303 } |
| 304 return new VolumeInfo( |
| 305 /** @type {VolumeManagerCommon.VolumeType} */ |
| 306 (volumeMetadata.volumeType), |
| 307 volumeMetadata.volumeId, |
| 308 fileSystem, |
| 309 volumeMetadata.mountCondition, |
| 310 volumeMetadata.deviceType, |
| 311 volumeMetadata.devicePath, |
| 312 volumeMetadata.isReadOnly, |
| 313 volumeMetadata.profile, |
| 314 localizedLabel, |
| 315 volumeMetadata.extensionId, |
| 316 volumeMetadata.hasMedia); |
| 317 }) |
| 318 .catch( |
| 319 /** |
| 320 * @param {*} error |
| 321 */ |
| 322 function(error) { |
| 323 console.error('Failed to mount a file system: ' + |
| 324 volumeMetadata.volumeId + ' because of: ' + |
| 325 (error.stack || error)); |
| 326 return new VolumeInfo( |
| 327 /** @type {VolumeManagerCommon.VolumeType} */ |
| 328 (volumeMetadata.volumeType), |
| 329 volumeMetadata.volumeId, |
| 330 null, // File system is not found. |
| 331 volumeMetadata.mountCondition, |
| 332 volumeMetadata.deviceType, |
| 333 volumeMetadata.devicePath, |
| 334 volumeMetadata.isReadOnly, |
| 335 volumeMetadata.profile, |
| 336 localizedLabel, |
| 337 volumeMetadata.extensionId, |
| 338 volumeMetadata.hasMedia); |
| 339 }); |
| 299 }; | 340 }; |
| 300 | 341 |
| 301 /** | 342 /** |
| 302 * The order of the volume list based on root type. | 343 * The order of the volume list based on root type. |
| 303 * @type {Array.<VolumeManagerCommon.VolumeType>} | 344 * @type {Array.<VolumeManagerCommon.VolumeType>} |
| 304 * @const | 345 * @const |
| 305 * @private | 346 * @private |
| 306 */ | 347 */ |
| 307 volumeManagerUtil.volumeListOrder_ = [ | 348 volumeManagerUtil.volumeListOrder_ = [ |
| 308 VolumeManagerCommon.VolumeType.DRIVE, | 349 VolumeManagerCommon.VolumeType.DRIVE, |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 }; | 671 }; |
| 631 | 672 |
| 632 /** | 673 /** |
| 633 * Adds new volume info from the given volumeMetadata. If the corresponding | 674 * Adds new volume info from the given volumeMetadata. If the corresponding |
| 634 * volume info has already been added, the volumeMetadata is ignored. | 675 * volume info has already been added, the volumeMetadata is ignored. |
| 635 * @param {!VolumeMetadata} volumeMetadata | 676 * @param {!VolumeMetadata} volumeMetadata |
| 636 * @return {!Promise<!VolumeInfo>} | 677 * @return {!Promise<!VolumeInfo>} |
| 637 * @private | 678 * @private |
| 638 */ | 679 */ |
| 639 VolumeManager.prototype.addVolumeMetadata_ = function(volumeMetadata) { | 680 VolumeManager.prototype.addVolumeMetadata_ = function(volumeMetadata) { |
| 640 return new Promise(function(callback) { | 681 return volumeManagerUtil.createVolumeInfo(volumeMetadata).then( |
| 641 volumeManagerUtil.createVolumeInfo(volumeMetadata, callback); | 682 /** |
| 642 }).then(function(volumeInfo) { | 683 * @param {!VolumeInfo} volumeInfo |
| 643 if (this.volumeInfoList.findIndex(volumeInfo.volumeId) === -1) { | 684 * @return {!VolumeInfo} |
| 644 this.volumeInfoList.add(volumeInfo); | 685 */ |
| 686 function(volumeInfo) { |
| 687 if (this.volumeInfoList.findIndex(volumeInfo.volumeId) === -1) { |
| 688 this.volumeInfoList.add(volumeInfo); |
| 645 | 689 |
| 646 // Update the network connection status, because until the drive is | 690 // Update the network connection status, because until the drive is |
| 647 // initialized, the status is set to not ready. | 691 // initialized, the status is set to not ready. |
| 648 // TODO(mtomasz): The connection status should be migrated into | 692 // TODO(mtomasz): The connection status should be migrated into |
| 649 // VolumeMetadata. | 693 // VolumeMetadata. |
| 650 if (volumeMetadata.volumeType === | 694 if (volumeMetadata.volumeType === |
| 651 VolumeManagerCommon.VolumeType.DRIVE) { | 695 VolumeManagerCommon.VolumeType.DRIVE) { |
| 652 this.onDriveConnectionStatusChanged_(); | 696 this.onDriveConnectionStatusChanged_(); |
| 653 } | 697 } |
| 654 } | 698 } |
| 655 return volumeInfo; | 699 return volumeInfo; |
| 656 }.bind(this)); | 700 }.bind(this)); |
| 657 }; | 701 }; |
| 658 | 702 |
| 659 /** | 703 /** |
| 660 * Initializes mount points. | 704 * Initializes mount points. |
| 661 * @param {function()} callback Called upon the completion of the | 705 * @param {function()} callback Called upon the completion of the |
| 662 * initialization. | 706 * initialization. |
| 663 * @private | 707 * @private |
| 664 */ | 708 */ |
| 665 VolumeManager.prototype.initialize_ = function(callback) { | 709 VolumeManager.prototype.initialize_ = function(callback) { |
| 666 chrome.fileManagerPrivate.onMountCompleted.addListener( | 710 chrome.fileManagerPrivate.onMountCompleted.addListener( |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1037 this.isDriveBased; | 1081 this.isDriveBased; |
| 1038 | 1082 |
| 1039 /** | 1083 /** |
| 1040 * Whether the entry is read only or not. | 1084 * Whether the entry is read only or not. |
| 1041 * @type {boolean} | 1085 * @type {boolean} |
| 1042 */ | 1086 */ |
| 1043 this.isReadOnly = isReadOnly; | 1087 this.isReadOnly = isReadOnly; |
| 1044 | 1088 |
| 1045 Object.freeze(this); | 1089 Object.freeze(this); |
| 1046 } | 1090 } |
| OLD | NEW |