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'); |
+}; |
+ |