Index: chrome/browser/resources/file_manager/js/directory_model.js |
diff --git a/chrome/browser/resources/file_manager/js/directory_model.js b/chrome/browser/resources/file_manager/js/directory_model.js |
index cd51a1dd04b8fdb6407570f3925bcfee6746af08..68031d68acf07bb7b25cc742ca5b5de4730c3b04 100644 |
--- a/chrome/browser/resources/file_manager/js/directory_model.js |
+++ b/chrome/browser/resources/file_manager/js/directory_model.js |
@@ -568,83 +568,99 @@ DirectoryModel.prototype = { |
* @param {Function=} opt_loadedCallback Invoked when the entire directory |
* has been loaded and any default file selected. If there are any |
* errors loading the directory this will not get called (even if the |
- * directory loads OK on retry later). |
+ * directory loads OK on retry later). Will NOT be called if another |
+ * directory change happened while setupPath was in progress. |
* @param {Function=} opt_pathResolveCallback Invoked as soon as the path has |
* been resolved, and called with the base and leaf portions of the path |
- * name, and a flag indicating if the entry exists. |
+ * name, and a flag indicating if the entry exists. Will be called even |
+ * if another directory change happened while setupPath was in progress, |
+ * but will pass |false| as |exist| parameter. |
*/ |
setupPath: function(path, opt_loadedCallback, opt_pathResolveCallback) { |
+ var overridden = false; |
+ function onExternalDirChange() { overridden = true } |
+ this.addEventListener('directory-changed', onExternalDirChange); |
+ |
+ var resolveCallback = function(exists) { |
+ this.removeEventListener('directory-changed', onExternalDirChange); |
+ if (opt_pathResolveCallback) |
+ opt_pathResolveCallback(baseName, leafName, exists && !overridden); |
+ }.bind(this); |
+ |
+ var changeDirectoryEntry = function(entry, callback, initial, exists) { |
+ resolveCallback(exists); |
+ if (!overridden) |
+ this.changeDirectoryEntry_(entry, callback, initial); |
+ }.bind(this); |
+ |
+ var INITIAL = true; |
+ var EXISTS = true; |
+ |
// Split the dirname from the basename. |
var ary = path.match(/^(?:(.*)\/)?([^\/]*)$/); |
var autoSelect = function() { |
- this.selectIndex(this.autoSelectIndex_); |
- if (opt_loadedCallback) |
- opt_loadedCallback(); |
+ this.selectIndex(this.autoSelectIndex_); |
+ if (opt_loadedCallback) |
+ opt_loadedCallback(); |
}.bind(this); |
if (!ary) { |
console.warn('Unable to split default path: ' + path); |
- this.changeDirectoryEntry_(this.root_, autoSelect, true); |
+ changeDirectoryEntry(this.root_, autoSelect, INITIAL, !EXISTS); |
return; |
} |
var baseName = ary[1]; |
var leafName = ary[2]; |
- function resolveCallback(exists) { |
- if (opt_pathResolveCallback) |
- opt_pathResolveCallback(baseName, leafName, exists); |
- } |
- |
function onLeafFound(baseDirEntry, leafEntry) { |
if (leafEntry.isDirectory) { |
baseName = path; |
leafName = ''; |
- resolveCallback(true); |
- this.changeDirectoryEntry_(leafEntry, autoSelect, true); |
+ changeDirectoryEntry(leafEntry, autoSelect, INITIAL, EXISTS); |
return; |
} |
- resolveCallback(true); |
// Leaf is an existing file, cd to its parent directory and select it. |
- this.changeDirectoryEntry_(baseDirEntry, |
- function() { |
- this.selectEntry(leafEntry.name); |
- if (opt_loadedCallback) |
- opt_loadedCallback(); |
- }.bind(this), |
- false /*HACK*/); |
+ changeDirectoryEntry(baseDirEntry, |
+ function() { |
+ this.selectEntry(leafEntry.name); |
+ if (opt_loadedCallback) |
+ opt_loadedCallback(); |
+ }.bind(this), |
+ !INITIAL /*HACK*/, |
+ EXISTS); |
// TODO(kaznacheev): Fix history.replaceState for the File Browser and |
- // change the last parameter back to |true|. Passing |false| makes things |
+ // change !INITIAL to INITIAL. Passing |false| makes things |
// less ugly for now. |
} |
function onLeafError(baseDirEntry, err) { |
- resolveCallback(false); |
// Usually, leaf does not exist, because it's just a suggested file name. |
if (err.code != FileError.NOT_FOUND_ERR) |
console.log('Unexpected error resolving default leaf: ' + err); |
- this.changeDirectoryEntry_(baseDirEntry, autoSelect, true); |
+ changeDirectoryEntry(baseDirEntry, autoSelect, INITIAL, !EXISTS); |
} |
var onBaseError = function(err) { |
- resolveCallback(false); |
console.log('Unexpected error resolving default base "' + |
baseName + '": ' + err); |
if (path != '/' + DirectoryModel.DOWNLOADS_DIRECTORY) { |
// Can't find the provided path, let's go to default one instead. |
- this.setupDefaultPath(opt_loadedCallback); |
+ resolveCallback(!EXISTS); |
+ if (!overridden) |
+ this.setupDefaultPath(opt_loadedCallback); |
} else { |
// Well, we can't find the downloads dir. Let's just show something, |
// or we will get an infinite recursion. |
- this.changeDirectoryEntry_(this.root_, opt_loadedCallback, true); |
+ changeDirectoryEntry(this.root_, opt_loadedCallback, INITIAL, !EXISTS); |
} |
}.bind(this); |
var onBaseFound = function(baseDirEntry) { |
if (!leafName) { |
// Default path is just a directory, cd to it and we're done. |
- this.changeDirectoryEntry_(baseDirEntry, autoSelect, true); |
+ changeDirectoryEntry(baseDirEntry, autoSelect, INITIAL, !EXISTS); |
return; |
} |
@@ -667,8 +683,14 @@ DirectoryModel.prototype = { |
}, |
setupDefaultPath: function(opt_callback) { |
+ var overridden = false; |
+ function onExternalDirChange() { overridden = true } |
+ this.addEventListener('directory-changed', onExternalDirChange); |
+ |
this.getDefaultDirectory_(function(path) { |
- this.setupPath(path, opt_callback); |
+ this.removeEventListener('directory-changed', onExternalDirChange); |
+ if (!overridden) |
+ this.setupPath(path, opt_callback); |
}.bind(this)); |
}, |
@@ -754,10 +776,11 @@ DirectoryModel.prototype = { |
}, |
/** |
- * Get root entries asynchronously. Invokes callback |
- * when have finished. |
+ * Get root entries asynchronously. |
+ * @param {function(Array.<Entry>} callback Called when roots are resolved. |
+ * @param {boolean} resolveGData See comment for updateRoots. |
*/ |
- resolveRoots_: function(callback) { |
+ resolveRoots_: function(callback, resolveGData) { |
var groups = { |
downloads: null, |
archives: null, |
@@ -796,17 +819,17 @@ DirectoryModel.prototype = { |
var self = this; |
function onGData(entry) { |
- console.log('onGData'); |
- console.log(entry); |
+ console.log('GData found:', entry); |
self.unmountedGDataEntry_ = null; |
groups.gdata = [entry]; |
done(); |
} |
function onGDataError(error) { |
- console.log('onGDataError'); |
- console.log(error); |
+ console.log('GData error: ', error); |
self.unmountedGDataEntry_ = { |
+ unmounted: true, // Clients use this field to distinguish a fake root. |
+ toURL: function() { return '' }, |
fullPath: '/' + DirectoryModel.GDATA_DIRECTORY |
}; |
groups.gdata = [self.unmountedGDataEntry_]; |
@@ -821,19 +844,27 @@ DirectoryModel.prototype = { |
util.readDirectory(root, DirectoryModel.REMOVABLE_DIRECTORY, |
append.bind(this, 'removables')); |
if (this.showGData_) { |
- root.getDirectory(DirectoryModel.GDATA_DIRECTORY, { create: false }, |
- onGData, onGDataError); |
+ if (resolveGData) { |
+ root.getDirectory(DirectoryModel.GDATA_DIRECTORY, { create: false }, |
+ onGData, onGDataError); |
+ } else { |
+ onGDataError('lazy mount'); |
+ } |
} else { |
groups.gdata = []; |
} |
}, |
- updateRoots: function(opt_callback) { |
- console.log('directoryModel_.updateRoots'); |
+ /** |
+ * @param {function} opt_callback Called when all roots are resolved. |
+ * @param {boolean} opt_resolveGData If true GData should be resolved for real, |
+ * If false a stub entry should be created. |
+ */ |
+ updateRoots: function(opt_callback, opt_resolveGData) { |
+ console.log('resolving roots'); |
var self = this; |
this.resolveRoots_(function(rootEntries) { |
- console.log('rootsList_ = '); |
- console.log(self.rootsList_); |
+ console.log('resolved roots:', rootEntries); |
var dm = self.rootsList_; |
var args = [0, dm.length].concat(rootEntries); |
dm.splice.apply(dm, args); |
@@ -842,12 +873,11 @@ DirectoryModel.prototype = { |
if (opt_callback) |
opt_callback(); |
- }); |
+ }, opt_resolveGData); |
}, |
onRootsSelectionChanged_: function(event) { |
var root = this.rootsList.item(this.rootsListSelection.selectedIndex); |
- var current = this.currentEntry.fullPath; |
if (root && this.rootPath != root.fullPath) |
this.changeDirectory(root.fullPath); |
}, |