Chromium Code Reviews| Index: chrome/browser/resources/file_manager/js/volume_manager.js |
| diff --git a/chrome/browser/resources/file_manager/js/volume_manager.js b/chrome/browser/resources/file_manager/js/volume_manager.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..746a3fecdc7b9da72ba1d4b6f70c372fec5eead7 |
| --- /dev/null |
| +++ b/chrome/browser/resources/file_manager/js/volume_manager.js |
| @@ -0,0 +1,290 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +/** |
| + * FileManager constructor. |
|
rginda
2012/05/15 19:51:15
Copypasta documentation here. And the rest of the
SeRya
2012/05/16 13:45:44
Robert, I uploaded this CL for preliminary code re
|
| + * |
| + * FileManager objects encapsulate the functionality of the file selector |
| + * dialogs, as well as the full screen file manager application (though the |
| + * latter is not yet implemented). |
| + * |
| + * @constructor |
| + * @param {HTMLElement} dialogDom The DOM node containing the prototypical |
| + * dialog UI. |
| + */ |
| +function VolumeManager() { |
| + // The list of archives requested to mount. We will show contents once |
| + // archive is mounted, but only for mounts from within this filebrowser tab. |
| + this.requests_ = {}; |
| + this.mountedVolumes_ = {}; |
| + |
| + this.initMountPoints_(); |
| + chrome.fileBrowserPrivate.onMountCompleted.addListener( |
| + this.onMountCompleted_.bind(this)); |
| + this.gDataStatus_ = VolumeManager.GDataStatus.UNMOUNTED; |
| +} |
| + |
| +VolumeManager.prototype.__proto__ = cr.EventTarget.prototype; |
| + |
| +VolumeManager.Error = { |
| + /* Internal errors */ |
| + NOT_MOUNTED: 'not_mounted', |
| + TIMEOUT: 'timeout', |
| + |
| + /* System events */ |
| + UNKNOWN: 'error_unknown', |
| + INTERNAL: 'error_internal', |
| + UNKNOWN_FILESYSTEM: 'error_unknown_filesystem', |
| + UNSUPPORTED_FILESYSTEM: 'error_unsuported_filesystem', |
| + INVALID_ARCHIVE: 'error_invalid_archive', |
| + LIBCROS_MISSING: 'error_libcros_missing', |
| + AUTHENTICATION: 'error_authentication', |
| + PATH_UNMOUNTED: 'error_path_unmounted' |
| +}; |
| + |
| +VolumeManager.GDataStatus = { |
| + UNMOUNTED: 'unmounted', |
| + MOUNTING: 'mounting', |
| + ERROR: 'error', |
| + MOUNTED: 'mounted' |
| +}; |
| + |
| +VolumeManager.TIMEOUT = 15 * 60 * 1000; |
| +VolumeManager.MOUNTING_DELAY = 500; |
| + |
| +VolumeManager.getInstance = function() { |
| + return VolumeManager.instance_ = VolumeManager.instance_ || new VolumeManager(); |
|
dgozman
2012/05/16 14:31:46
long line
|
| +}; |
| + |
| +VolumeManager.prototype.setGDataStatus_ = function(newStatus) { |
| + if (this.gDataStatus_ != newStatus) { |
| + this.gDataStatus_ = newStatus; |
| + cr.dispatchSimpleEvent(this, 'gdata-status-changed'); |
| + } |
| +}; |
| + |
| +VolumeManager.prototype.getGDataStatus = function() { |
| + return this.gDataStatus_; |
| +}; |
| + |
| +VolumeManager.prototype.isMounted = function(mountPath) { |
| + return mountPath in this.mountedVolumes_; |
| +}; |
| + |
| +VolumeManager.prototype.initMountPoints_ = function() { |
| + var mountedVolumes = []; |
| + var self = this; |
| + var index = 0; |
| + function step(mountPoints) { |
| + if (index < mountPoints.length) { |
| + var info = mountPoints[index]; |
| + if (info.mountType == 'gdata') |
| + console.error('GData is not extpected initially mounted'); |
| + self.makeVolumeInfo_('/' + info.mountPath, info.mountCondition, |
| + function(volume) { |
| + mountedVolumes.push(volume); |
| + index++; |
| + step(mountPoints); |
| + }); |
| + } else { |
| + for (var i = 0; i < mountedVolumes.length; i++) { |
| + var volume = mountedVolumes[i]; |
| + self.mountedVolumes_[volume.mountPath] = volume; |
| + } |
| + if (mountedVolumes.length > 0) |
| + self.notifyChange_(); |
| + } |
| + } |
| + |
| + chrome.fileBrowserPrivate.getMountPoints(step); |
| +}; |
| + |
| +/** |
| + * Event handler called when some volume was mounted or unmouted. |
| + */ |
| +VolumeManager.prototype.onMountCompleted_ = function(event) { |
| + if (event.eventType == 'mount') { |
| + if (event.mountPath) { |
|
dgozman
2012/05/16 14:31:46
check event.status == 'success' here?
|
| + var requestKey = this.makeRequestKey_('mount', event.mountType, event.sourcePath); |
|
dgozman
2012/05/16 14:31:46
long line
|
| + this.makeVolumeInfo_(event.mountPath, event.status, function(volume) { |
| + this.mountedVolumes_[volume.mountPath] = volume; |
| + this.finishRequest_(requestKey, event.status, event.mountPath); |
| + this.notifyChange_(); |
| + }.bind(this)); |
| + } else { |
| + console.log('No mount path'); |
| + this.finishRequest_(requestKey, event.status); |
| + } |
| + } else if (event.eventType == 'unmount') { |
| + var mountPath = '/' + event.mountPath; |
| + var status = event.status; |
| + if (status == VolumeManager.Error.PATH_UNMOUNTED) { |
| + console.log('Volume already unmounted: ', mountPath); |
| + status = 'success'; |
| + } |
| + this.finishRequest_(this.makeRequestKey_('mount', '', mountPath), status); |
|
dgozman
2012/05/16 14:31:46
'mount' -> 'unmount' ?
|
| + |
| + if (event.status == 'success') { |
| + delete this.mountedVolumes_[mountPath]; |
| + this.notifyChange_(); |
| + } |
| + } |
| + |
| + if (event.mountType == 'gdata') { |
| + if (event.status == 'success') { |
| + if (event.eventType == 'mount') |
| + this.setGDataStatus_(VolumeManager.GDataStatus.MOUNTED); |
| + else if (event.eventType == 'unmount' && event.status == 'success') |
|
dgozman
2012/05/16 14:31:46
event.status == 'success' two lines above
|
| + this.setGDataStatus_(VolumeManager.GDataStatus.UMOUNTED); |
| + } |
| + } |
| +}; |
| + |
| +VolumeManager.prototype.makeVolumeInfo_ = function( |
| + mountPath, status, callback) { |
| + chrome.fileBrowserPrivate.getVolumeMetadata(this.makeUrl_(mountPath), |
| + function(metadata) { |
| + callback({ |
| + mountPath: mountPath, |
| + status: status, |
| + readonly: !!metadata && metadata.isReadOnly |
| + }); |
| + }.bind(this)); |
| +}; |
| + |
| +/** |
| + * @param {string} requestType 'mount' | 'unmount' |
| + * @param {string} mountType 'device' | 'file' | 'network' | 'gdata'. |
| + * @param {string?} opt_sourcePath |
| + */ |
| +VolumeManager.prototype.makeRequestKey_ = function(requestType, mountType, opt_mountPath) { |
|
dgozman
2012/05/16 14:31:46
long line
|
| + return requestType + ':' + mountType + ':' + (opt_mountPath || ''); |
| +}; |
| + |
| +VolumeManager.prototype.mountGData = function(successCallback, errorCallback) { |
| + if (this.getGDataStatus() == VolumeManager.GDataStatus.ERROR) { |
| + this.setGDataStatus_(VolumeManager.GDataStatus.UNMOUNTED); |
| + } |
| + var self = this; |
| + var timeout = setTimeout(function() { |
| + if (self.getGDataStatus() == VolumeManager.GDataStatus.UNMOUNTED) |
| + self.setGDataStatus_(VolumeManager.GDataStatus.MOUNTING); |
| + timeout = null; |
| + }, VolumeManager.MOUNTING_DELAY); |
| + this.mount_('', 'gdata', function(mountPath) { |
| + if (timeout !== null) |
| + clearTimeout(timeout); |
| + successCallback(mountPath); |
| + }, function(error) { |
| + if (self.getGDataStatus() != VolumeManager.GDataStatus.MOUNTED) |
| + self.setGDataStatus_(VolumeManager.GDataStatus.ERROR); |
| + if (timeout != null) |
| + clearTimeout(timeout); |
| + errorCallback(error); |
| + }); |
| +}; |
| + |
| +VolumeManager.prototype.getMountCondition = function(mountPath) { |
|
dgozman
2012/05/16 14:31:46
I'd suggest to rename this to getMountStatus.
|
| + return this.getVolumeInfo_(mountPath).status; |
| +}; |
| + |
| +VolumeManager.prototype.isReadOnly = function(mountPath) { |
| + return this.getVolumeInfo_(mountPath).readonly; |
| +}; |
| + |
| +VolumeManager.prototype.getVolumeInfo_ = function(mountPath) { |
| + return this.mountedVolumes_[mountPath] || {}; |
| +}; |
| + |
| +/** |
| + * Unmounts device. |
|
dgozman
2012/05/16 14:31:46
indentation
|
| + * @param {Entry} entry The entry to unmount. |
| + */ |
| +VolumeManager.prototype.unmount = function(mountPath, successCallback, errorCallback) { |
|
dgozman
2012/05/16 14:31:46
long line
|
| + var volumeInfo = this.mountedVolumes_[mountPath]; |
| + if (!volumeInfo) { |
| + errorCallback(VolumeManager.Error.NOT_NOUNTED); |
| + return; |
| + } |
| + |
| + chrome.fileBrowserPrivate.removeMount(this.makeUrl_(mountPath)); |
| + this.startRequest_(this.makeRequestKey_('unmount', '', mountPath)); |
| +}; |
| + |
| +VolumeManager.prototype.mountArchive = function(fullPath, successCallback, |
| + errorCallback) { |
| + var requestKey = this.makeRequestKey_('mount', 'file'); |
| + if (requestKey in this.requests_) { |
| + // Parallel requests are not supported. API doesn't provide a way |
| + // to find request for specific response. |
| + errorCallback('inprogress'); |
| + return; |
| + } |
| + this.mount_(this.makeUrl_(fullPath), |
| + 'file', successCallback, errorCallback); |
| +}; |
| + |
| +VolumeManager.prototype.makeUrl_ = function(path) { |
|
dgozman
2012/05/16 14:31:46
Move this method to util.js.
|
| + return 'filesystem:' + chrome.extension.getURL('external' + path); |
| +}; |
| + |
| +VolumeManager.prototype.mount_ = function(url, mountType, |
| + successCallback, errorCallback) { |
| + chrome.fileBrowserPrivate.addMount(url, mountType, {}, |
| + function(sourcePath) { |
| + var requestKey = this.makeRequestKey_('mount', mountType, sourcePath); |
| + this.startRequest_(requestKey, successCallback, errorCallback); |
| + }.bind(this)); |
| +}; |
| + |
| +VolumeManager.prototype.startRequest_ = function(key, |
| + successCallback, errorCallback) { |
| + if (key in this.requests_) { |
| + var request = this.requests_[key]; |
| + request.successCallbacks.push(successCallback); |
| + request.errorCallbacks.push(errorCallback); |
| + } else { |
| + this.requests_[key] = { |
| + successCallbacks: [successCallback], |
| + errorCallbacks: [errorCallback], |
| + |
| + timeout: setTimeout(this.onTimeout_.bind(this, key), |
| + VolumeManager.TIMEOUT) |
| + }; |
| + } |
| +}; |
| + |
| +VolumeManager.prototype.onTimeout_ = function(key) { |
| + this.invokeRequestCallbacks_(this.requests_[key], |
| + VolumeManager.Error.TIMEOUT); |
| + delete this.requests_[key]; |
| +}; |
| + |
| +VolumeManager.prototype.finishRequest_ = function(key, status, opt_mountPath) { |
| + var request = this.requests_[key]; |
| + if (!request) |
| + return; |
| + |
| + clearTimeout(request.timeout); |
| + this.invokeRequestCallbacks_(request, status, opt_mountPath); |
| + delete this.requests_[key]; |
| +} |
| + |
| +VolumeManager.prototype.invokeRequestCallbacks_= function(request, status, |
| + opt_mountPath) { |
| + function callEach(callbacks, self, args) { |
| + for (var i = 0; i < callbacks.length; i++) { |
| + callbacks[i].apply(self, args); |
|
dgozman
2012/05/16 14:31:46
self -> null
|
| + } |
| + } |
| + if (status == 'success') |
| + callEach(request.successCallbacks, this, [opt_mountPath]); |
| + else |
| + callEach(request.errorCallbacks, this, [status]); |
| +}; |
| + |
| +VolumeManager.prototype.notifyChange_ = function() { |
| + cr.dispatchSimpleEvent(this, 'change'); |
| +}; |
| + |