Commit 38a5e578 authored by mtomasz@chromium.org's avatar mtomasz@chromium.org

Get rid of the fake Drive/root entry.

This patch removes the fake Drive/root entry, which was a hack. Along the way, the labels got moved away from the fake entries.

TEST=Tested manually. Partly browser tests.
BUG=334512

Review URL: https://codereview.chromium.org/135753003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245441 0039d316-1c4b-4281-b951-d872f2087c98
parent 547d5010
......@@ -30,40 +30,32 @@ function VolumeInfo(
deviceType,
isReadOnly,
profile) {
this.volumeType = volumeType;
this.volumeType_ = volumeType;
// TODO(hidehiko): This should include FileSystem instance.
this.mountPath = mountPath;
this.volumeId = volumeId;
this.root = root;
this.fakeEntries = {};
this.mountPath_ = mountPath;
this.volumeId_ = volumeId;
this.root_ = root;
this.displayRoot_ = null;
this.fakeEntries_ = {};
this.resolveQueue_ = new AsyncUtil.Queue();
if (volumeType === util.VolumeType.DRIVE) {
this.fakeEntries[RootType.DRIVE] = {
fullPath: RootDirectory.DRIVE + '/' + DriveSubRootDirectory.ROOT,
isDirectory: true,
rootType: RootType.DRIVE,
label: PathUtil.getRootLabel(RootType.DRIVE),
toURL: function() { return 'fake-entry://' + this.fullPath; }
};
this.fakeEntries[RootType.DRIVE_OFFLINE] = {
fullPath: RootDirectory.DRIVE_OFFLINE,
isDirectory: true,
rootType: RootType.DRIVE_OFFLINE,
label: PathUtil.getRootLabel(RootType.DRIVE_OFFLINE),
toURL: function() { return 'fake-entry://' + this.fullPath; }
};
this.fakeEntries[RootType.DRIVE_SHARED_WITH_ME] = {
fullPath: RootDirectory.DRIVE_SHARED_WITH_ME,
isDirectory: true,
rootType: RootType.DRIVE_SHARED_WITH_ME,
label: PathUtil.getRootLabel(RootType.DRIVE_SHARED_WITH_ME),
toURL: function() { return 'fake-entry://' + this.fullPath; }
};
this.fakeEntries[RootType.DRIVE_RECENT] = {
fullPath: RootDirectory.DRIVE_RECENT,
isDirectory: true,
rootType: RootType.DRIVE_RECENT,
label: PathUtil.getRootLabel(RootType.DRIVE_RECENT),
toURL: function() { return 'fake-entry://' + this.fullPath; }
};
}
......@@ -76,17 +68,86 @@ function VolumeInfo(
this.isReadOnly = isReadOnly;
this.profile = Object.freeze(profile);
// VolumeInfo is immutable.
Object.freeze(this);
Object.seal(this);
}
VolumeInfo.prototype = {
/**
* @return {util.VolumeType} Volume type.
*/
get volumeType() {
return this.volumeType_;
},
/**
* @return {string} Mount path.
*/
get mountPath() {
return this.mountPath_;
},
/**
* @return {string} Volume id.
*/
get volumeId() {
return this.volumeId_;
},
/**
* @return {DirectoryEntry} Root path.
*/
get root() {
return this.root_;
},
/**
* @return {DirectoryEntry} Display root path. It is null before
* resolveDisplayRoot() is called.
*/
get displayRoot() {
return this.displayRoot_;
},
/**
* @return {Object.<string, Object>} Fake entries.
*/
get fakeEntries() {
return this.fakeEntries_;
}
};
/**
* Obtains a URL of the display root directory that users can see as a root.
* @return {string} URL of root entry.
*/
VolumeInfo.prototype.getDisplayRootDirectoryURL = function() {
return this.root.toURL() +
(this.volumeType === util.VolumeType.DRIVE ? '/root' : '');
* Obtains the display root of the entry. It may take long time for Drive. Once
* resolved, it is cached.
*
* @param {function(DirectoryEntry)} onSuccess Success callback with the display
* root directory as an argument.
* @param {function(FileError)} onFailure Failure callback.
*/
VolumeInfo.prototype.resolveDisplayRoot = function(onSuccess, onFailure) {
// TODO(mtomasz): Do not add VolumeInfo which failed to resolve root, and
// remove this if logic. Call onSuccess() always, instead.
if (this.volumeType !== util.VolumeType.DRIVE) {
if (this.root)
onSuccess(this.root);
else
onFailure(this.error);
return;
}
// For Drive, we need to resolve.
this.resolveQueue_.run(function(callback) {
if (this.displayRoot) {
onSuccess(this.displayRoot);
callback();
return;
}
var displayRootURL = this.root.toURL() + '/root';
webkitResolveLocalFileSystemURL(
displayRootURL, function(directoryEntry) {
this.displayRoot_ = directoryEntry;
onSuccess(directoryEntry);
callback();
}.bind(this), function(fileError) {
onFailure(fileError);
callback();
}.bind(this));
}.bind(this));
};
/**
......
......@@ -1036,10 +1036,8 @@ DirectoryModel.prototype.specialSearch = function(path, opt_query) {
this.dispatchEvent(e);
}.bind(this, this.changeDirectorySequence_);
// TODO(hirono): We don't need to obtain the drive root to search.
this.resolveDirectory(volumeInfo.fakeEntries[RootType.DRIVE].fullPath,
onDriveDirectoryResolved /* success */,
function() {} /* failed */);
volumeInfo.resolveDisplayRoot(
onDriveDirectoryResolved /* success */, function() {} /* failed */);
};
/**
......
......@@ -50,9 +50,11 @@ DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) {
while (this.entries_[index]) {
var currentEntry = this.entries_[index];
var currentElement = this.items[index];
// TODO(mtomasz): Stop using full paths, and use getLocationInfo() instead.
var label = PathUtil.getFolderLabel(currentEntry.fullPath);
if (index >= this.items.length) {
var item = new DirectoryItem(currentEntry, this, tree);
var item = new DirectoryItem(label, currentEntry, this, tree);
this.add(item);
index++;
} else if (currentEntry.fullPath == currentElement.fullPath) {
......@@ -61,7 +63,7 @@ DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) {
index++;
} else if (currentEntry.fullPath < currentElement.fullPath) {
var item = new DirectoryItem(currentEntry, this, tree);
var item = new DirectoryItem(label, currentEntry, this, tree);
this.addAt(item, index);
index++;
} else if (currentEntry.fullPath > currentElement.fullPath) {
......@@ -109,29 +111,31 @@ Object.freeze(DirectoryItemTreeBaseMethods);
/**
* A directory in the tree. Each element represents one directory.
*
* @param {string} label Label for this item.
* @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
* @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
* @param {DirectoryTree} tree Current tree, which contains this item.
* @extends {cr.ui.TreeItem}
* @constructor
*/
function DirectoryItem(dirEntry, parentDirItem, tree) {
function DirectoryItem(label, dirEntry, parentDirItem, tree) {
var item = cr.doc.createElement('div');
DirectoryItem.decorate(item, dirEntry, parentDirItem, tree);
DirectoryItem.decorate(item, label, dirEntry, parentDirItem, tree);
return item;
}
/**
* @param {HTMLElement} el Element to be DirectoryItem.
* @param {string} label Label for this item.
* @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
* @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
* @param {DirectoryTree} tree Current tree, which contains this item.
*/
DirectoryItem.decorate =
function(el, dirEntry, parentDirItem, tree) {
function(el, label, dirEntry, parentDirItem, tree) {
el.__proto__ = DirectoryItem.prototype;
(/** @type {DirectoryItem} */ el).decorate(
dirEntry, parentDirItem, tree);
label, dirEntry, parentDirItem, tree);
};
DirectoryItem.prototype = {
......@@ -178,12 +182,13 @@ DirectoryItem.prototype.searchAndSelectByEntry = function(entry) {
};
/**
* @param {string} label Localized label for this item.
* @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
* @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
* @param {DirectoryTree} tree Current tree, which contains this item.
*/
DirectoryItem.prototype.decorate = function(
dirEntry, parentDirItem, tree) {
label, dirEntry, parentDirItem, tree) {
this.className = 'tree-item';
this.innerHTML =
'<div class="tree-row">' +
......@@ -197,7 +202,7 @@ DirectoryItem.prototype.decorate = function(
this.parentTree_ = tree;
this.directoryModel_ = tree.directoryModel;
this.parent_ = parentDirItem;
this.label = dirEntry.label || dirEntry.name;
this.label = label;
this.fullPath = dirEntry.fullPath;
this.dirEntry_ = dirEntry;
this.fileFilter_ = this.directoryModel_.getFileFilter();
......@@ -511,14 +516,6 @@ DirectoryTree.prototype.decorate = function(directoryModel, volumeManager) {
this.scrollBar_ = MainPanelScrollBar();
this.scrollBar_.initialize(this.parentNode, this);
// Once, draws the list with the fake '/drive/' entry.
this.redraw(false /* recursive */);
// Resolves 'My Drive' entry and replaces the fake with the true one.
this.maybeResolveMyDriveRoot_(function() {
// After the true entry is resolved, draws the list again.
this.redraw(true /* recursive */);
}.bind(this));
};
/**
......@@ -531,74 +528,56 @@ DirectoryTree.prototype.selectByEntry = function(entry) {
if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(entry.fullPath))
return;
this.maybeResolveMyDriveRoot_(function() {
if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry))
return;
if (this.searchAndSelectByEntry(entry))
return;
this.selectedItem = null;
this.updateSubDirectories(
false /* recursive */,
// Success callback, failure is not handled.
function() {
if (!this.searchAndSelectByEntry(entry))
this.selectedItem = null;
}.bind(this));
}.bind(this));
};
/**
* Resolves the My Drive root's entry, if it is a fake. If the entry is already
* resolved to a DirectoryEntry, completionCallback() will be called
* immediately.
* @param {function()} completionCallback Called when the resolving is
* done (or the entry is already resolved), regardless if it is
* successfully done or not.
* @private
*/
DirectoryTree.prototype.maybeResolveMyDriveRoot_ = function(
completionCallback) {
var myDriveItem = this.items[0];
if (!myDriveItem || !util.isFakeEntry(myDriveItem.entry)) {
// The entry is already resolved. Don't need to try again.
completionCallback();
var volumeInfo = this.volumeManager_.getVolumeInfo(entry);
if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry))
return;
}
// The entry is a fake.
this.directoryModel_.resolveDirectory(
myDriveItem.fullPath,
function(entry) {
if (!util.isFakeEntry(entry))
myDriveItem.dirEntry_ = entry;
if (this.searchAndSelectByEntry(entry))
return;
completionCallback();
},
completionCallback);
this.updateSubDirectories(false /* recursive */);
// TODO(yoshiki, mtomasz): There may be a race in here.
volumeInfo.resolveDisplayRoot(function() {
if (!this.searchAndSelectByEntry(entry))
this.selectedItem = null;
}.bind(this));
};
/**
* Retrieves the latest subdirectories and update them on the tree.
*
* @param {boolean} recursive True if the update is recursively.
* @param {function()=} opt_successCallback Callback called on success.
* @param {function()=} opt_errorCallback Callback called on error.
* @param {function()=} opt_callback Called when subdirectories are fully
* updated.
*/
DirectoryTree.prototype.updateSubDirectories = function(
recursive, opt_successCallback, opt_errorCallback) {
var hasFakeEntries = this.currentVolumeInfo_ &&
this.currentVolumeInfo_.volumeType === util.VolumeType.DRIVE;
this.entries_ = hasFakeEntries ? [
this.currentVolumeInfo_.fakeEntries[RootType.DRIVE],
this.currentVolumeInfo_.fakeEntries[RootType.DRIVE_OFFLINE],
this.currentVolumeInfo_.fakeEntries[RootType.DRIVE_SHARED_WITH_ME],
this.currentVolumeInfo_.fakeEntries[RootType.DRIVE_RECENT]
] : [];
this.redraw(recursive);
if (opt_successCallback)
opt_successCallback();
recursive, opt_callback) {
var callback = opt_callback || function() {};
this.entries_ = [];
var compareEntries = function(a, b) {
return a.toURL() < b.toURL();
};
// Add fakes (if any).
for (var key in this.currentVolumeInfo_.fakeEntries) {
this.entries_.push(this.currentVolumeInfo_.fakeEntries[key]);
}
// If the display root is not available yet, then redraw anyway with what
// we have. However, concurrently try to resolve the display root and then
// redraw.
if (!this.currentVolumeInfo_.displayRoot) {
this.entries_.sort(compareEntries);
this.redraw(recursive);
}
this.currentVolumeInfo_.resolveDisplayRoot(function(displayRoot) {
this.entries_.push(this.currentVolumeInfo_.displayRoot);
this.entries_.sort(compareEntries);
this.redraw(recursive); // Redraw.
callback();
}.bind(this), callback /* Ignore errors. */);
};
/**
......
......@@ -514,8 +514,12 @@ FileListBannerController.prototype.maybeShowLowSpaceWarning_ = function(
return;
}
// If not mounted correctly, then do not continue.
if (!volume.root)
return;
chrome.fileBrowserPrivate.getSizeStats(
volume.getDisplayRootDirectoryURL(),
volume.root.toURL(),
function(sizeStats) {
var currentVolume = this.volumeManager_.getVolumeInfo(
this.directoryModel_.getCurrentDirEntry());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment