* flush storage", or "mounted zip archive" etc.
*
* @param {util.VolumeType} volumeType The type of the volume.
- * @param {string} mountPath Where the volume is mounted.
* @param {string} volumeId ID of the volume.
* @param {DirectoryEntry} root The root directory entry of this volume.
* @param {string} error The error if an error is found.
*/
function VolumeInfo(
volumeType,
- mountPath,
volumeId,
root,
error,
profile) {
this.volumeType_ = volumeType;
// TODO(hidehiko): This should include FileSystem instance.
- this.mountPath_ = mountPath;
this.volumeId_ = volumeId;
this.root_ = root;
this.displayRoot_ = null;
this.displayRootPromise_ = null;
if (volumeType === util.VolumeType.DRIVE) {
- this.fakeEntries[RootType.DRIVE_OFFLINE] = {
- fullPath: RootDirectory.DRIVE_OFFLINE,
+ // TODO(mtomasz): Convert fake entries to DirectoryProvider.
+ this.fakeEntries_[RootType.DRIVE_OFFLINE] = {
isDirectory: true,
rootType: RootType.DRIVE_OFFLINE,
- toURL: function() { return 'fake-entry://' + this.fullPath; }
+ toURL: function() { return 'fake-entry://drive_offline' }
};
- this.fakeEntries[RootType.DRIVE_SHARED_WITH_ME] = {
- fullPath: RootDirectory.DRIVE_SHARED_WITH_ME,
+ this.fakeEntries_[RootType.DRIVE_SHARED_WITH_ME] = {
isDirectory: true,
rootType: RootType.DRIVE_SHARED_WITH_ME,
- toURL: function() { return 'fake-entry://' + this.fullPath; }
+ toURL: function() { return 'fake-entry://drive_shared_with_me'; }
};
- this.fakeEntries[RootType.DRIVE_RECENT] = {
- fullPath: RootDirectory.DRIVE_RECENT,
+ this.fakeEntries_[RootType.DRIVE_RECENT] = {
isDirectory: true,
rootType: RootType.DRIVE_RECENT,
- toURL: function() { return 'fake-entry://' + this.fullPath; }
+ toURL: function() { return 'fake-entry://drive_recent'; }
};
}
return this.volumeType_;
},
/**
- * @return {string} Mount path.
- */
- get mountPath() {
- return this.mountPath_;
- },
- /**
* @return {string} Volume id.
*/
get volumeId() {
/**
* Returns the root entry of a volume mounted at mountPath.
+ * TODO(mtomasz): Migrate to volumeId, once requestFileSystem can handle it.
*
* @param {string} mountPath The mounted path of the volume.
* @param {function(DirectoryEntry)} successCallback Called when the root entry
}
callback(new VolumeInfo(
volumeMetadata.volumeType,
- volumeMetadata.mountPath,
volumeMetadata.volumeId,
entry,
volumeMetadata.mountCondition,
volumeMetadata.mountPath + ', ' + fileError.name);
callback(new VolumeInfo(
volumeMetadata.volumeType,
- volumeMetadata.mountPath,
volumeMetadata.volumeId,
null, // Root entry is not found.
volumeMetadata.mountCondition,
];
/**
- * Orders two volumes by volumeType and mountPath.
+ * Orders two volumes by volumeType and volumeId.
*
* The volumes at first are compared by volume type in the order of
* volumeListOrder_. Then they are compared by volume ID.
};
/**
- * Searches the information of the volume that contains an item pointed by the
- * path.
- * @param {string} path Path pointing an entry on a volume.
+ * Searches the information of the volume that contains the passed entry.
+ * @param {Entry|Object} entry Entry on the volume to be foudn.
* @return {VolumeInfo} The volume's information, or null if not found.
*/
-VolumeInfoList.prototype.findByPath = function(path) {
+VolumeInfoList.prototype.findByEntry = function(entry) {
+ // TODO(mtomasz): Switch to comparing file systems once possible.
for (var i = 0; i < this.length; i++) {
- var mountPath = this.item(i).mountPath;
- if (path === mountPath || path.indexOf(mountPath + '/') === 0)
- return this.item(i);
+ var volumeInfo = this.item(i);
+ if (!volumeInfo.root)
+ continue;
+ if (util.isSameEntry(entry, volumeInfo.root) ||
+ entry.toURL().indexOf(volumeInfo.root.toURL() + '/') === 0) {
+ return volumeInfo;
+ }
+ // Additionally, check fake entries.
+ for (var key in volumeInfo.fakeEntries_) {
+ var fakeEntry = volumeInfo.fakeEntries_[key];
+ if (util.isSameEntry(fakeEntry, entry))
+ return volumeInfo;
+ }
}
return null;
};
*/
VolumeManager.prototype.onMountCompleted_ = function(event) {
if (event.eventType === 'mount') {
+ // TODO(mtomasz): Migrate to volumeId once possible.
if (event.volumeMetadata.mountPath) {
var requestKey = this.makeRequestKey_(
'mount',
event.volumeMetadata,
function(volumeInfo) {
this.volumeInfoList.add(volumeInfo);
- this.finishRequest_(requestKey, event.status, volumeInfo.mountPath);
+ this.finishRequest_(requestKey, event.status, volumeInfo);
if (volumeInfo.volumeType === util.VolumeType.DRIVE) {
// Update the network connection status, because until the
this.finishRequest_(requestKey, event.status);
}
} else if (event.eventType === 'unmount') {
- var mountPath = event.volumeMetadata.mountPath;
+ var volumeId = event.volumeMetadata.volumeId;
var status = event.status;
if (status === util.VolumeError.PATH_UNMOUNTED) {
- console.warn('Volume already unmounted: ', mountPath);
+ console.warn('Volume already unmounted: ', volumeId);
status = 'success';
}
- var requestKey = this.makeRequestKey_('unmount', mountPath);
+ var requestKey = this.makeRequestKey_('unmount', volumeId);
var requested = requestKey in this.requests_;
var volumeInfoIndex =
- this.volumeInfoList.findIndex(event.volumeMetadata.volumeId);
- var volumeInfo = volumeInfoIndex != -1 ?
+ this.volumeInfoList.findIndex(volumeId);
+ var volumeInfo = volumeInfoIndex !== -1 ?
this.volumeInfoList.item(volumeInfoIndex) : null;
if (event.status === 'success' && !requested && volumeInfo) {
- console.warn('Mounted volume without a request: ', mountPath);
+ console.warn('Mounted volume without a request: ', volumeId);
var e = new Event('externally-unmounted');
- // TODO(mtomasz): The mountPath field is deprecated. Remove it.
- e.mountPath = mountPath;
e.volumeInfo = volumeInfo;
this.dispatchEvent(e);
}
* Creates string to match mount events with requests.
* @param {string} requestType 'mount' | 'unmount'. TODO(hidehiko): Replace by
* enum.
- * @param {string} path Source path provided by API for mount request, or
- * mount path for unmount request.
+ * @param {string} argument Argument describing the request, eg. source file
+ * path of the archive to be mounted, or a volumeId for unmounting.
* @return {string} Key for |this.requests_|.
* @private
*/
-VolumeManager.prototype.makeRequestKey_ = function(requestType, path) {
- return requestType + ':' + path;
+VolumeManager.prototype.makeRequestKey_ = function(requestType, argument) {
+ return requestType + ':' + argument;
};
/**
* @param {string} fileUrl File url to the archive file.
- * @param {function(string)} successCallback Success callback.
+ * @param {function(VolumeInfo)} successCallback Success callback.
* @param {function(util.VolumeError)} errorCallback Error callback.
*/
VolumeManager.prototype.mountArchive = function(
fileUrl, successCallback, errorCallback) {
chrome.fileBrowserPrivate.addMount(fileUrl, function(sourcePath) {
console.info(
- 'Mount request: url=' + fileUrl + '; sourceUrl=' + sourcePath);
+ 'Mount request: url=' + fileUrl + '; sourcePath=' + sourcePath);
var requestKey = this.makeRequestKey_('mount', sourcePath);
this.startRequest_(requestKey, successCallback, errorCallback);
}.bind(this));
/**
* Unmounts volume.
* @param {!VolumeInfo} volumeInfo Volume to be unmounted.
- * @param {function(string)} successCallback Success callback.
+ * @param {function()} successCallback Success callback.
* @param {function(util.VolumeError)} errorCallback Error callback.
*/
VolumeManager.prototype.unmount = function(volumeInfo,
successCallback,
errorCallback) {
- chrome.fileBrowserPrivate.removeMount(
- util.makeFilesystemUrl(volumeInfo.mountPath));
- var requestKey = this.makeRequestKey_('unmount', volumeInfo.mountPath);
+ chrome.fileBrowserPrivate.removeMount(volumeInfo.volumeId);
+ var requestKey = this.makeRequestKey_('unmount', volumeInfo.volumeId);
this.startRequest_(requestKey, successCallback, errorCallback);
};
/**
- * Resolves the absolute path to its entry. Shouldn't be used outside of the
- * Files app's initialization.
- * @param {string} path The path to be resolved.
- * @param {function(Entry)} successCallback Called with the resolved entry on
- * success.
- * @param {function(FileError)} errorCallback Called on error.
+ * Obtains a volume info containing the passed entry.
+ * @param {Entry|Object} entry Entry on the volume to be returned. Can be fake.
+ * @return {VolumeInfo} The VolumeInfo instance or null if not found.
*/
-VolumeManager.prototype.resolveAbsolutePath = function(
- path, successCallback, errorCallback) {
- // Make sure the path is in the mounted volume.
- var volumeInfo = this.getVolumeInfo(path);
- if (!volumeInfo || !volumeInfo.root) {
- errorCallback(util.createDOMError(util.FileError.NOT_FOUND_ERR));
- return;
- }
-
- webkitResolveLocalFileSystemURL(
- util.makeFilesystemUrl(path), successCallback, errorCallback);
-};
-
-/**
- * Obtains the information of the volume that containing an entry pointed by the
- * specified path.
- * TODO(hirono): Stop to use path to get a volume info.
- *
- * @param {string|Entry} target Path or Entry pointing anywhere on a volume.
- * @return {VolumeInfo} The data about the volume.
- */
-VolumeManager.prototype.getVolumeInfo = function(target) {
- if (typeof target === 'string')
- return this.volumeInfoList.findByPath(target);
- else if (util.isFakeEntry(target))
- return this.getCurrentProfileVolumeInfo(util.VolumeType.DRIVE);
- else
- return this.volumeInfoList.findByPath(target.fullPath);
+VolumeManager.prototype.getVolumeInfo = function(entry) {
+ return this.volumeInfoList.findByEntry(entry);
};
/**
true /* fake entries are read only. */);
}
- // TODO(mtomasz): Find by Entry instead.
- var volumeInfo = this.volumeInfoList.findByPath(entry.fullPath);
+ var volumeInfo = this.volumeInfoList.findByEntry(entry);
if (!volumeInfo)
return null;
- var rootPath;
var rootType;
var isReadOnly;
+ var isRootEntry;
if (volumeInfo.volumeType === util.VolumeType.DRIVE) {
- // If the volume is drive, root path can be either mountPath + '/root' or
- // mountPath + '/other'.
- if ((entry.fullPath + '/').indexOf(volumeInfo.mountPath + '/root/') === 0) {
- rootPath = volumeInfo.mountPath + '/root';
+ // For Drive, the roots are /root and /other, instead of /.
+ // TODO(mtomasz): Simplify once switching to filesystem per volume.
+ if (entry.toURL() === volumeInfo.root.toURL() + '/root' ||
+ entry.toURL().indexOf(volumeInfo.root.toURL() + '/root/') === 0) {
rootType = RootType.DRIVE;
- isReadOnly = volumeInfo.isReadOnly ||
- this.getDriveConnectionState().type ===
- util.DriveConnectionType.OFFLINE;
- } else if ((entry.fullPath + '/').indexOf(
- volumeInfo.mountPath + '/other/') === 0) {
- rootPath = volumeInfo.mountPath + '/other';
+ isReadOnly = volumeInfo.isReadOnly;
+ isRootEntry = entry.toURL() === volumeInfo.root.toURL() + '/root';
+ } else if (entry.toURL() === volumeInfo.root.toURL() + '/other' ||
+ entry.toURL().indexOf(volumeInfo.root.toURL() + '/other/') === 0) {
rootType = RootType.DRIVE_OTHER;
isReadOnly = true;
+ isRootEntry = entry.toURL() === volumeInfo.root.toURL() + '/other';
} else {
- throw new Error(entry.fullPath + ' is an invalid drive path.');
+ // Accessing Drive files outside of /drive/root and /drive/other is not
+ // allowed, but can happen. Therefore returning null.
+ return null;
}
} else {
// Otherwise, root path is same with a mount path of the volume.
- rootPath = volumeInfo.mountPath;
switch (volumeInfo.volumeType) {
case util.VolumeType.DOWNLOADS:
rootType = RootType.DOWNLOADS;
rootType = RootType.CLOUD_DEVICE;
break;
default:
+ // Programming error, throw an exception.
throw new Error('Invalid volume type: ' + volumeInfo.volumeType);
}
isReadOnly = volumeInfo.isReadOnly;
+ isRootEntry = util.isSameEntry(entry, volumeInfo.root);
}
- var isRootEntry = (entry.fullPath.substr(0, rootPath.length) || '/') ===
- entry.fullPath;
return new EntryLocation(volumeInfo, rootType, isRootEntry, isReadOnly);
};
/**
* @param {string} key Key produced by |makeRequestKey_|.
- * @param {function(string)} successCallback To be called when request finishes
- * successfully.
+ * @param {function(VolumeInfo)} successCallback To be called when request
+ * finishes successfully.
* @param {function(util.VolumeError)} errorCallback To be called when
* request fails.
* @private
/**
* @param {string} key Key produced by |makeRequestKey_|.
* @param {util.VolumeError|'success'} status Status received from the API.
- * @param {string=} opt_mountPath Mount path.
+ * @param {VolumeInfo=} opt_volumeInfo Volume info of the mounted volume.
* @private
*/
-VolumeManager.prototype.finishRequest_ = function(key, status, opt_mountPath) {
+VolumeManager.prototype.finishRequest_ = function(key, status, opt_volumeInfo) {
var request = this.requests_[key];
if (!request)
return;
clearTimeout(request.timeout);
- this.invokeRequestCallbacks_(request, status, opt_mountPath);
+ this.invokeRequestCallbacks_(request, status, opt_volumeInfo);
delete this.requests_[key];
};
* @param {Object} request Structure created in |startRequest_|.
* @param {util.VolumeError|string} status If status === 'success'
* success callbacks are called.
- * @param {string=} opt_mountPath Mount path. Required if success.
+ * @param {VolumeInfo=} opt_volumeInfo Volume info of the mounted volume.
* @private
*/
-VolumeManager.prototype.invokeRequestCallbacks_ = function(request, status,
- opt_mountPath) {
+VolumeManager.prototype.invokeRequestCallbacks_ = function(
+ request, status, opt_volumeInfo) {
var callEach = function(callbacks, self, args) {
for (var i = 0; i < callbacks.length; i++) {
callbacks[i].apply(self, args);
}
};
if (status === 'success') {
- callEach(request.successCallbacks, this, [opt_mountPath]);
+ callEach(request.successCallbacks, this, [opt_volumeInfo]);
} else {
volumeManagerUtil.validateError(status);
callEach(request.errorCallbacks, this, [status]);