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( ...@@ -30,40 +30,32 @@ function VolumeInfo(
deviceType, deviceType,
isReadOnly, isReadOnly,
profile) { profile) {
this.volumeType = volumeType; this.volumeType_ = volumeType;
// TODO(hidehiko): This should include FileSystem instance. // TODO(hidehiko): This should include FileSystem instance.
this.mountPath = mountPath; this.mountPath_ = mountPath;
this.volumeId = volumeId; this.volumeId_ = volumeId;
this.root = root; this.root_ = root;
this.fakeEntries = {}; this.displayRoot_ = null;
this.fakeEntries_ = {};
this.resolveQueue_ = new AsyncUtil.Queue();
if (volumeType === util.VolumeType.DRIVE) { 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] = { this.fakeEntries[RootType.DRIVE_OFFLINE] = {
fullPath: RootDirectory.DRIVE_OFFLINE, fullPath: RootDirectory.DRIVE_OFFLINE,
isDirectory: true, isDirectory: true,
rootType: RootType.DRIVE_OFFLINE, rootType: RootType.DRIVE_OFFLINE,
label: PathUtil.getRootLabel(RootType.DRIVE_OFFLINE),
toURL: function() { return 'fake-entry://' + this.fullPath; } toURL: function() { return 'fake-entry://' + this.fullPath; }
}; };
this.fakeEntries[RootType.DRIVE_SHARED_WITH_ME] = { this.fakeEntries[RootType.DRIVE_SHARED_WITH_ME] = {
fullPath: RootDirectory.DRIVE_SHARED_WITH_ME, fullPath: RootDirectory.DRIVE_SHARED_WITH_ME,
isDirectory: true, isDirectory: true,
rootType: RootType.DRIVE_SHARED_WITH_ME, rootType: RootType.DRIVE_SHARED_WITH_ME,
label: PathUtil.getRootLabel(RootType.DRIVE_SHARED_WITH_ME),
toURL: function() { return 'fake-entry://' + this.fullPath; } toURL: function() { return 'fake-entry://' + this.fullPath; }
}; };
this.fakeEntries[RootType.DRIVE_RECENT] = { this.fakeEntries[RootType.DRIVE_RECENT] = {
fullPath: RootDirectory.DRIVE_RECENT, fullPath: RootDirectory.DRIVE_RECENT,
isDirectory: true, isDirectory: true,
rootType: RootType.DRIVE_RECENT, rootType: RootType.DRIVE_RECENT,
label: PathUtil.getRootLabel(RootType.DRIVE_RECENT),
toURL: function() { return 'fake-entry://' + this.fullPath; } toURL: function() { return 'fake-entry://' + this.fullPath; }
}; };
} }
...@@ -76,17 +68,86 @@ function VolumeInfo( ...@@ -76,17 +68,86 @@ function VolumeInfo(
this.isReadOnly = isReadOnly; this.isReadOnly = isReadOnly;
this.profile = Object.freeze(profile); this.profile = Object.freeze(profile);
// VolumeInfo is immutable. Object.seal(this);
Object.freeze(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. * Obtains the display root of the entry. It may take long time for Drive. Once
* @return {string} URL of root entry. * resolved, it is cached.
*/ *
VolumeInfo.prototype.getDisplayRootDirectoryURL = function() { * @param {function(DirectoryEntry)} onSuccess Success callback with the display
return this.root.toURL() + * root directory as an argument.
(this.volumeType === util.VolumeType.DRIVE ? '/root' : ''); * @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) { ...@@ -1036,10 +1036,8 @@ DirectoryModel.prototype.specialSearch = function(path, opt_query) {
this.dispatchEvent(e); this.dispatchEvent(e);
}.bind(this, this.changeDirectorySequence_); }.bind(this, this.changeDirectorySequence_);
// TODO(hirono): We don't need to obtain the drive root to search. volumeInfo.resolveDisplayRoot(
this.resolveDirectory(volumeInfo.fakeEntries[RootType.DRIVE].fullPath, onDriveDirectoryResolved /* success */, function() {} /* failed */);
onDriveDirectoryResolved /* success */,
function() {} /* failed */);
}; };
/** /**
......
...@@ -50,9 +50,11 @@ DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) { ...@@ -50,9 +50,11 @@ DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) {
while (this.entries_[index]) { while (this.entries_[index]) {
var currentEntry = this.entries_[index]; var currentEntry = this.entries_[index];
var currentElement = this.items[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) { if (index >= this.items.length) {
var item = new DirectoryItem(currentEntry, this, tree); var item = new DirectoryItem(label, currentEntry, this, tree);
this.add(item); this.add(item);
index++; index++;
} else if (currentEntry.fullPath == currentElement.fullPath) { } else if (currentEntry.fullPath == currentElement.fullPath) {
...@@ -61,7 +63,7 @@ DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) { ...@@ -61,7 +63,7 @@ DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) {
index++; index++;
} else if (currentEntry.fullPath < currentElement.fullPath) { } 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); this.addAt(item, index);
index++; index++;
} else if (currentEntry.fullPath > currentElement.fullPath) { } else if (currentEntry.fullPath > currentElement.fullPath) {
...@@ -109,29 +111,31 @@ Object.freeze(DirectoryItemTreeBaseMethods); ...@@ -109,29 +111,31 @@ Object.freeze(DirectoryItemTreeBaseMethods);
/** /**
* A directory in the tree. Each element represents one directory. * 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 {DirectoryEntry} dirEntry DirectoryEntry of this item.
* @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
* @param {DirectoryTree} tree Current tree, which contains this item. * @param {DirectoryTree} tree Current tree, which contains this item.
* @extends {cr.ui.TreeItem} * @extends {cr.ui.TreeItem}
* @constructor * @constructor
*/ */
function DirectoryItem(dirEntry, parentDirItem, tree) { function DirectoryItem(label, dirEntry, parentDirItem, tree) {
var item = cr.doc.createElement('div'); var item = cr.doc.createElement('div');
DirectoryItem.decorate(item, dirEntry, parentDirItem, tree); DirectoryItem.decorate(item, label, dirEntry, parentDirItem, tree);
return item; return item;
} }
/** /**
* @param {HTMLElement} el Element to be DirectoryItem. * @param {HTMLElement} el Element to be DirectoryItem.
* @param {string} label Label for this item.
* @param {DirectoryEntry} dirEntry DirectoryEntry of this item. * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
* @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
* @param {DirectoryTree} tree Current tree, which contains this item. * @param {DirectoryTree} tree Current tree, which contains this item.
*/ */
DirectoryItem.decorate = DirectoryItem.decorate =
function(el, dirEntry, parentDirItem, tree) { function(el, label, dirEntry, parentDirItem, tree) {
el.__proto__ = DirectoryItem.prototype; el.__proto__ = DirectoryItem.prototype;
(/** @type {DirectoryItem} */ el).decorate( (/** @type {DirectoryItem} */ el).decorate(
dirEntry, parentDirItem, tree); label, dirEntry, parentDirItem, tree);
}; };
DirectoryItem.prototype = { DirectoryItem.prototype = {
...@@ -178,12 +182,13 @@ DirectoryItem.prototype.searchAndSelectByEntry = function(entry) { ...@@ -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 {DirectoryEntry} dirEntry DirectoryEntry of this item.
* @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
* @param {DirectoryTree} tree Current tree, which contains this item. * @param {DirectoryTree} tree Current tree, which contains this item.
*/ */
DirectoryItem.prototype.decorate = function( DirectoryItem.prototype.decorate = function(
dirEntry, parentDirItem, tree) { label, dirEntry, parentDirItem, tree) {
this.className = 'tree-item'; this.className = 'tree-item';
this.innerHTML = this.innerHTML =
'<div class="tree-row">' + '<div class="tree-row">' +
...@@ -197,7 +202,7 @@ DirectoryItem.prototype.decorate = function( ...@@ -197,7 +202,7 @@ DirectoryItem.prototype.decorate = function(
this.parentTree_ = tree; this.parentTree_ = tree;
this.directoryModel_ = tree.directoryModel; this.directoryModel_ = tree.directoryModel;
this.parent_ = parentDirItem; this.parent_ = parentDirItem;
this.label = dirEntry.label || dirEntry.name; this.label = label;
this.fullPath = dirEntry.fullPath; this.fullPath = dirEntry.fullPath;
this.dirEntry_ = dirEntry; this.dirEntry_ = dirEntry;
this.fileFilter_ = this.directoryModel_.getFileFilter(); this.fileFilter_ = this.directoryModel_.getFileFilter();
...@@ -511,14 +516,6 @@ DirectoryTree.prototype.decorate = function(directoryModel, volumeManager) { ...@@ -511,14 +516,6 @@ DirectoryTree.prototype.decorate = function(directoryModel, volumeManager) {
this.scrollBar_ = MainPanelScrollBar(); this.scrollBar_ = MainPanelScrollBar();
this.scrollBar_.initialize(this.parentNode, this); 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) { ...@@ -531,74 +528,56 @@ DirectoryTree.prototype.selectByEntry = function(entry) {
if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(entry.fullPath)) if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(entry.fullPath))
return; return;
this.maybeResolveMyDriveRoot_(function() { var volumeInfo = this.volumeManager_.getVolumeInfo(entry);
if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry)) 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();
return; return;
}
// The entry is a fake. if (this.searchAndSelectByEntry(entry))
this.directoryModel_.resolveDirectory( return;
myDriveItem.fullPath,
function(entry) {
if (!util.isFakeEntry(entry))
myDriveItem.dirEntry_ = entry;
completionCallback(); this.updateSubDirectories(false /* recursive */);
}, // TODO(yoshiki, mtomasz): There may be a race in here.
completionCallback); volumeInfo.resolveDisplayRoot(function() {
if (!this.searchAndSelectByEntry(entry))
this.selectedItem = null;
}.bind(this));
}; };
/** /**
* Retrieves the latest subdirectories and update them on the tree. * Retrieves the latest subdirectories and update them on the tree.
*
* @param {boolean} recursive True if the update is recursively. * @param {boolean} recursive True if the update is recursively.
* @param {function()=} opt_successCallback Callback called on success. * @param {function()=} opt_callback Called when subdirectories are fully
* @param {function()=} opt_errorCallback Callback called on error. * updated.
*/ */
DirectoryTree.prototype.updateSubDirectories = function( DirectoryTree.prototype.updateSubDirectories = function(
recursive, opt_successCallback, opt_errorCallback) { recursive, opt_callback) {
var hasFakeEntries = this.currentVolumeInfo_ && var callback = opt_callback || function() {};
this.currentVolumeInfo_.volumeType === util.VolumeType.DRIVE; this.entries_ = [];
this.entries_ = hasFakeEntries ? [
this.currentVolumeInfo_.fakeEntries[RootType.DRIVE], var compareEntries = function(a, b) {
this.currentVolumeInfo_.fakeEntries[RootType.DRIVE_OFFLINE], return a.toURL() < b.toURL();
this.currentVolumeInfo_.fakeEntries[RootType.DRIVE_SHARED_WITH_ME], };
this.currentVolumeInfo_.fakeEntries[RootType.DRIVE_RECENT]
] : []; // Add fakes (if any).
for (var key in this.currentVolumeInfo_.fakeEntries) {
this.redraw(recursive); this.entries_.push(this.currentVolumeInfo_.fakeEntries[key]);
if (opt_successCallback) }
opt_successCallback();
// 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( ...@@ -514,8 +514,12 @@ FileListBannerController.prototype.maybeShowLowSpaceWarning_ = function(
return; return;
} }
// If not mounted correctly, then do not continue.
if (!volume.root)
return;
chrome.fileBrowserPrivate.getSizeStats( chrome.fileBrowserPrivate.getSizeStats(
volume.getDisplayRootDirectoryURL(), volume.root.toURL(),
function(sizeStats) { function(sizeStats) {
var currentVolume = this.volumeManager_.getVolumeInfo( var currentVolume = this.volumeManager_.getVolumeInfo(
this.directoryModel_.getCurrentDirEntry()); 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