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..76734af698f064211614b0d500d3909f8aa6cead |
--- /dev/null |
+++ b/chrome/browser/resources/file_manager/js/volume_manager.js |
@@ -0,0 +1,291 @@ |
+// 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. |
+ * |
+ * 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.getInstance = function() { |
+ return VolumeManager.instance_ = VolumeManager.instance_ || new VolumeManager(); |
+}; |
+ |
+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; |
+ var gDataMounted = false; |
+ function step(mountPoints) { |
+ if (index < mountPoints.length) { |
+ var info = mountPoints[index]; |
+ if (info.mountType == 'gdata') |
+ gDataMounted = true; |
+ self.makeVolumeInfo_('/' + info.mountPath, info.mountCondition, |
+ function(volume) { |
+ mountedVolumes[volume.mountPath] = volume; |
+ index++; |
+ step(mountPoints); |
+ }); |
+ } else { |
+ self.mountedVolumes_ = mountedVolumes; |
+ // Do not change ERROR status if gData is not mounted. |
+ if (self.getGDataStatus() != VolumeManager.GDataStatus.ERROR && |
+ !gDataMounted) { |
+ self.setGDataStatus_(gDataMounted ? |
+ VolumeManager.GDataStatus.MOUNTED : |
+ VolumeManager.GDataStatus.UNMOUNTED); |
+ } |
+ } |
+ } |
+ |
+ 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) { |
+ var requestKey = this.makeRequestKey_('mount', event.mountType, event.sourcePath); |
+ 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); |
+ |
+ 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') |
+ 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) { |
+ 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; |
+ }, 500); |
+ 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) { |
+ 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. |
+ * @param {Entry} entry The entry to unmount. |
+ */ |
+VolumeManager.prototype.unmount = function(mountPath, successCallback, errorCallback) { |
+ 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) { |
+ return 'filesystem:' + chrome.extension.getURL('external' + path); |
+}; |
+ |
+VolumeManager.prototype.mount_ = function(url, mountType, |
+ successCallback, errorCallback) { |
+ console.log('mount ', url, mountType); |
+ 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) { |
+ console.log('Start request: ', key); |
+ 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), 10000) |
+ }; |
+ } |
+}; |
+ |
+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].call(self, args); |
+ } |
+ } |
+ if (status == 'success') |
+ callEach(request.successCallbacks, this, [opt_mountPath]); |
+ else |
+ callEach(request.errorCallbacks, this, [status]); |
+}; |
+ |
+VolumeManager.prototype.notifyChange_ = function() { |
+ cr.dispatchSimpleEvent(this, 'change'); |
+}; |
+ |