summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormtomasz@chromium.org <mtomasz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-29 01:07:37 +0000
committermtomasz@chromium.org <mtomasz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-29 01:07:37 +0000
commite614ad418e235707b20f71671b45617d28579109 (patch)
tree0f861c525080b60f1033e48095c2c09cb6764b64
parenta013dd5e8e9967562a2b12ba5e7adad2b63f0071 (diff)
downloadchromium_src-e614ad418e235707b20f71671b45617d28579109.zip
chromium_src-e614ad418e235707b20f71671b45617d28579109.tar.gz
chromium_src-e614ad418e235707b20f71671b45617d28579109.tar.bz2
Simplify directory initialization in Files app.
This patch cleans up the initialization code, by separating the current directory from selection. Before, there was only one variable holding either current directory or the selection, and heuristics were used to determine how to interpred the path there. The new code is also a preparation for migrating to URLs, since there are no more operations on the passed paths on the JS side. Note, that before we were fetching parent of a non existing path, which would be very tricky after migrating to URLs. And finally, this patch fixes wrong behaviour of the select directory dialog. Since now, the selected directory is really selected, and not opened. TEST=Tested manually several scenarios. All dialogs + recovering from crash. Drive and Downloads. BUG=328767, 321962 Review URL: https://codereview.chromium.org/144783002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247556 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/file_manager/url_util.cc8
-rw-r--r--chrome/browser/chromeos/file_manager/url_util.h3
-rw-r--r--chrome/browser/chromeos/file_manager/url_util_unittest.cc14
-rw-r--r--chrome/browser/resources/file_manager/background/js/background.js40
-rw-r--r--chrome/browser/resources/file_manager/common/js/util.js32
-rw-r--r--chrome/browser/resources/file_manager/foreground/js/file_manager.js240
-rw-r--r--chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js2
-rw-r--r--chrome/browser/resources/file_manager/foreground/js/file_tasks.js8
-rw-r--r--chrome/browser/resources/file_manager/foreground/js/photo/gallery.js4
-rw-r--r--chrome/browser/ui/views/select_file_dialog_extension.cc106
-rw-r--r--chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc4
-rw-r--r--chrome/test/data/extensions/api_test/file_manager_browsertest/test_cases.js50
12 files changed, 272 insertions, 239 deletions
diff --git a/chrome/browser/chromeos/file_manager/url_util.cc b/chrome/browser/chromeos/file_manager/url_util.cc
index 670a818..b670c96 100644
--- a/chrome/browser/chromeos/file_manager/url_util.cc
+++ b/chrome/browser/chromeos/file_manager/url_util.cc
@@ -67,14 +67,18 @@ GURL GetFileManagerMainPageUrl() {
GURL GetFileManagerMainPageUrlWithParams(
ui::SelectFileDialog::Type type,
const base::string16& title,
- const base::FilePath& default_virtual_path,
+ const base::FilePath& current_directory_virtual_path,
+ const base::FilePath& selection_virtual_path,
const ui::SelectFileDialog::FileTypeInfo* file_types,
int file_type_index,
const base::FilePath::StringType& default_extension) {
base::DictionaryValue arg_value;
arg_value.SetString("type", GetDialogTypeAsString(type));
arg_value.SetString("title", title);
- arg_value.SetString("defaultPath", default_virtual_path.value());
+ arg_value.SetString(
+ "currentDirectoryPath", current_directory_virtual_path.value());
+ arg_value.SetString("selectionPath", selection_virtual_path.value());
+ arg_value.SetString("targetName", selection_virtual_path.BaseName().value());
arg_value.SetString("defaultExtension", default_extension);
if (file_types) {
diff --git a/chrome/browser/chromeos/file_manager/url_util.h b/chrome/browser/chromeos/file_manager/url_util.h
index e68dadf..c1ab561 100644
--- a/chrome/browser/chromeos/file_manager/url_util.h
+++ b/chrome/browser/chromeos/file_manager/url_util.h
@@ -32,7 +32,8 @@ GURL GetFileManagerMainPageUrl();
GURL GetFileManagerMainPageUrlWithParams(
ui::SelectFileDialog::Type type,
const base::string16& title,
- const base::FilePath& default_virtual_path,
+ const base::FilePath& current_directory_virtual_path,
+ const base::FilePath& selection_virtual_path,
const ui::SelectFileDialog::FileTypeInfo* file_types,
int file_type_index,
const base::FilePath::StringType& default_extension);
diff --git a/chrome/browser/chromeos/file_manager/url_util_unittest.cc b/chrome/browser/chromeos/file_manager/url_util_unittest.cc
index 402d210..cd24c18 100644
--- a/chrome/browser/chromeos/file_manager/url_util_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/url_util_unittest.cc
@@ -43,7 +43,8 @@ TEST(FileManagerUrlUtilTest, GetFileManagerMainPageUrlWithParams_NoFileTypes) {
const GURL url = GetFileManagerMainPageUrlWithParams(
ui::SelectFileDialog::SELECT_OPEN_FILE,
base::UTF8ToUTF16("some title"),
- base::FilePath::FromUTF8Unsafe("foo.txt"),
+ base::FilePath::FromUTF8Unsafe("/Downloads"),
+ base::FilePath::FromUTF8Unsafe("/Downloads/foo.txt"),
NULL, // No file types
0, // Hence no file type index.
FILE_PATH_LITERAL("txt"));
@@ -55,9 +56,11 @@ TEST(FileManagerUrlUtilTest, GetFileManagerMainPageUrlWithParams_NoFileTypes) {
EXPECT_TRUE(url.query().find("%20") != std::string::npos);
// The escaped query is hard to read. Pretty print the escaped JSON.
EXPECT_EQ("{\n"
+ " \"currentDirectoryPath\": \"/Downloads\",\n"
" \"defaultExtension\": \"txt\",\n"
- " \"defaultPath\": \"foo.txt\",\n"
+ " \"selectionPath\": \"/Downloads/foo.txt\",\n"
" \"shouldReturnLocalPath\": true,\n"
+ " \"targetName\": \"foo.txt\",\n"
" \"title\": \"some title\",\n"
" \"type\": \"open-file\"\n"
"}\n",
@@ -85,7 +88,8 @@ TEST(FileManagerUrlUtilTest,
const GURL url = GetFileManagerMainPageUrlWithParams(
ui::SelectFileDialog::SELECT_OPEN_FILE,
base::UTF8ToUTF16("some title"),
- base::FilePath::FromUTF8Unsafe("foo.txt"),
+ base::FilePath::FromUTF8Unsafe("/Downloads"),
+ base::FilePath::FromUTF8Unsafe("/Downloads/foo.txt"),
&file_types,
1, // The file type index is 1-based.
FILE_PATH_LITERAL("txt"));
@@ -97,10 +101,12 @@ TEST(FileManagerUrlUtilTest,
EXPECT_TRUE(url.query().find("%20") != std::string::npos);
// The escaped query is hard to read. Pretty print the escaped JSON.
EXPECT_EQ("{\n"
+ " \"currentDirectoryPath\": \"/Downloads\",\n"
" \"defaultExtension\": \"txt\",\n"
- " \"defaultPath\": \"foo.txt\",\n"
" \"includeAllFiles\": false,\n"
+ " \"selectionPath\": \"/Downloads/foo.txt\",\n"
" \"shouldReturnLocalPath\": false,\n"
+ " \"targetName\": \"foo.txt\",\n"
" \"title\": \"some title\",\n"
" \"type\": \"open-file\",\n"
" \"typeList\": [ {\n"
diff --git a/chrome/browser/resources/file_manager/background/js/background.js b/chrome/browser/resources/file_manager/background/js/background.js
index 94e850e..edd3620 100644
--- a/chrome/browser/resources/file_manager/background/js/background.js
+++ b/chrome/browser/resources/file_manager/background/js/background.js
@@ -522,20 +522,33 @@ function launchFileManager(opt_appState, opt_id, opt_type, opt_callback) {
// reuse it instead of opening a new one.
if (type == LaunchType.FOCUS_SAME_OR_CREATE ||
type == LaunchType.FOCUS_ANY_OR_CREATE) {
- if (opt_appState && opt_appState.defaultPath) {
+ if (opt_appState) {
for (var key in background.appWindows) {
if (!key.match(FILES_ID_PATTERN))
continue;
var contentWindow = background.appWindows[key].contentWindow;
- if (contentWindow.appState &&
- opt_appState.defaultPath == contentWindow.appState.defaultPath) {
- background.appWindows[key].focus();
- if (opt_callback)
- opt_callback(key);
- onTaskCompleted();
- return;
+ if (!contentWindow.appState)
+ continue;
+
+ // Different current directories.
+ if (opt_appState.currentDirectoryPath !==
+ contentWindow.appState.currentDirectoryPath) {
+ continue;
+ }
+
+ // Selection path specified, and it is different.
+ if (opt_appState.selectionPath &&
+ opt_appState.selectionPath !==
+ contentWindow.appState.selectionPath) {
+ continue;
}
+
+ background.appWindows[key].focus();
+ if (opt_callback)
+ opt_callback(key);
+ onTaskCompleted();
+ return;
}
}
}
@@ -654,7 +667,11 @@ Background.prototype.onExecute_ = function(action, details) {
params: {
action: action
},
- defaultPath: details.entries[0].fullPath
+ // It is not allowed to call getParent() here, since there may be
+ // no permissions to access it at this stage. Therefore we are passing
+ // the selectionPath only, and the currentDirectory will be resolved
+ // later.
+ selectionPath: details.entries[0].fullPath
};
// For mounted devices just focus any Files.app window. The mounted
// volume will appear on the navigation list.
@@ -763,8 +780,9 @@ Background.prototype.onContextMenuClicked_ = function(info) {
try {
if (background.appWindows[key].contentWindow.isFocused()) {
var appState = {
- defaultPath: background.appWindows[key].contentWindow.
- appState.defaultPath
+ // Do not clone the selection path, only the current directory.
+ currentDirectoryPath: background.appWindows[key].contentWindow.
+ appState.currentDirectoryPath
};
launchFileManager(appState);
return;
diff --git a/chrome/browser/resources/file_manager/common/js/util.js b/chrome/browser/resources/file_manager/common/js/util.js
index ef44088..8494abc 100644
--- a/chrome/browser/resources/file_manager/common/js/util.js
+++ b/chrome/browser/resources/file_manager/common/js/util.js
@@ -683,27 +683,29 @@ util.createChild = function(parent, opt_className, opt_tag) {
};
/**
- * Update the app state.
+ * Updates the app state.
+ * TODO(mtomasz): Migrate to URLs.
*
- * @param {string} path Path to be put in the address bar after the hash.
- * If null the hash is left unchanged.
- * @param {string|Object=} opt_param Search parameter. Used directly if string,
- * stringified if object. If omitted the search query is left unchanged.
- */
-util.updateAppState = function(path, opt_param) {
+ * @param {string} currentDirectoryPath Currently opened path. If null the path
+ * is left unchanged.
+ * @param {string} selectionPath Currently selected path. If null the path is
+* left unchanged.
+ * @param {string|Object=} opt_param Additional parameters, to be stored. If
+ * null, then left unchanged.
+ */
+util.updateAppState = function(currentDirectoryPath, selectionPath, opt_param) {
window.appState = window.appState || {};
- if (typeof opt_param == 'string')
- window.appState.params = {};
- else if (typeof opt_param == 'object')
+ if (opt_param !== undefined && opt_param !== null)
window.appState.params = opt_param;
- if (path)
- window.appState.defaultPath = path;
+ if (currentDirectoryPath !== null)
+ window.appState.currentDirectoryPath = currentDirectoryPath;
+ if (selectionPath !== null)
+ window.appState.selectionPath = selectionPath;
util.saveAppState();
- return;
};
/**
- * Return a translated string.
+ * Returns a translated string.
*
* Wrapper function to make dealing with translated strings more concise.
* Equivalent to loadTimeData.getString(id).
@@ -716,7 +718,7 @@ function str(id) {
}
/**
- * Return a translated string with arguments replaced.
+ * Returns a translated string with arguments replaced.
*
* Wrapper function to make dealing with translated strings more concise.
* Equivalent to loadTimeData.getStringF(id, ...).
diff --git a/chrome/browser/resources/file_manager/foreground/js/file_manager.js b/chrome/browser/resources/file_manager/foreground/js/file_manager.js
index a1cfe96..c4523d2 100644
--- a/chrome/browser/resources/file_manager/foreground/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/foreground/js/file_manager.js
@@ -46,17 +46,6 @@ function FileManager() {
this.currentVolumeInfo_ = null;
}
-/**
- * Maximum delay in milliseconds for updating thumbnails in the bottom panel
- * to mitigate flickering. If images load faster then the delay they replace
- * old images smoothly. On the other hand we don't want to keep old images
- * too long.
- *
- * @type {number}
- * @const
- */
-FileManager.THUMBNAIL_SHOW_DELAY = 100;
-
FileManager.prototype = {
__proto__: cr.EventTarget.prototype,
get directoryModel() {
@@ -586,14 +575,20 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
*/
FileManager.prototype.initGeneral_ = function(callback) {
// Initialize the application state.
+ // TODO(mtomasz): Unify window.appState with location.search format.
if (window.appState) {
this.params_ = window.appState.params || {};
- this.defaultPath = window.appState.defaultPath;
+ this.initCurrentDirectoryPath_ = window.appState.currentDirectoryPath;
+ this.initSelectionPath_ = window.appState.selectionPath;
+ this.initTargetName_ = window.appState.targetName;
} else {
+ // Used by the select dialog only.
this.params_ = location.search ?
JSON.parse(decodeURIComponent(location.search.substr(1))) :
{};
- this.defaultPath = this.params_.defaultPath;
+ this.initCurrentDirectoryPath_ = this.params_.currentDirectoryPath;
+ this.initSelectionPath_ = this.params_.selectionPath;
+ this.initTargetName_ = this.params_.targetName;
}
// Initialize the member variables that depend this.params_.
@@ -1396,12 +1391,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
};
/**
- * Restores current directory and may be a selected item after page load (or
- * reload) or popping a state (after click on back/forward). defaultPath
- * primarily is used with save/open dialogs.
- * Default path may also contain a file name. Freshly opened file manager
- * window has neither.
- *
+ * Sets up the current directory during initialization.
* @private
*/
FileManager.prototype.setupCurrentDirectory_ = function() {
@@ -1414,138 +1404,108 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
this.volumeManager_.ensureInitialized(callback);
}.bind(this));
- // Obtains the fallback path.
- var defaultDisplayRoot;
+ var nextCurrentDirEntry;
+ var selectionEntry;
+
+ // Resolve the selectionPath to selectionEntry or to currentDirectoryEntry
+ // in case of being a display root.
queue.run(function(callback) {
- this.volumeManager_.getDefaultDisplayRoot(function(displayRoot) {
- defaultDisplayRoot = displayRoot;
+ // TODO(mtomasz): Migrate to URLs, and stop calling resolveAbsolutePath.
+ if (!this.initSelectionPath_) {
callback();
- }.bind(this));
+ return;
+ }
+ this.volumeManager_.resolveAbsolutePath(
+ this.initSelectionPath_,
+ function(inEntry) {
+ var locationInfo = this.volumeManager_.getLocationInfo(inEntry);
+ // If the selection is root, then use it as a current directory
+ // instead. This is because, selecting a root entry is done as
+ // opening it.
+ if (locationInfo && locationInfo.isRootEntry)
+ nextCurrentDirEntry = inEntry;
+ else
+ selectionEntry = inEntry;
+ callback();
+ }.bind(this), callback);
}.bind(this));
-
- // Resolve the default path.
- var defaultFullPath;
- var candidateFullPath;
- var candidateEntry;
+ // Resolve the currentDirectoryPath to currentDirectoryEntry (if not done
+ // by the previous step).
queue.run(function(callback) {
- // Cancel this sequence if the current directory has already changed.
- if (tracker.hasChanged) {
+ if (nextCurrentDirEntry || !this.initCurrentDirectoryPath_) {
callback();
return;
}
-
- // Resolve the absolute path in case only the file name or an empty string
- // is passed.
- if (!this.defaultPath) {
- // TODO(mtomasz): that in this case we can directly jump to #1540
- // and avoid fullPath conversion -> Entry.
- defaultFullPath = defaultDisplayRoot.fullPath;
- } else if (this.defaultPath.indexOf('/') === -1) {
- // Path is a file name.
- defaultFullPath = defaultDisplayRoot.fullPath + '/' + this.defaultPath;
- } else {
- defaultFullPath = this.defaultPath;
- }
-
- // If Drive is disabled but the path points to Drive's entry, fallback to
- // defaultDisplayRootPath.
- if (PathUtil.isDriveBasedPath(defaultFullPath) &&
- !this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE)) {
- candidateFullPath = defaultDisplayRoot.fullPath + '/' +
- PathUtil.basename(defaultFullPath);
- } else {
- candidateFullPath = defaultFullPath;
- }
-
- // If the path points a fake entry, use the entry directly.
- // TODO(hirono): Obtains proper volume.
- var volumeInfo = this.volumeManager_.getCurrentProfileVolumeInfo(
- util.VolumeType.DRIVE);
- if (volumeInfo) {
- for (var name in volumeInfo.fakeEntries) {
- var fakeEntry = volumeInfo.fakeEntries[name];
- // Skip the drive root fake entry, because we can need actual drive
- // root to list its files.
- if (fakeEntry.rootType === RootType.DRIVE)
- continue;
- if (candidateFullPath === fakeEntry.fullPath) {
- candidateEntry = fakeEntry;
+ // TODO(mtomasz): Migrate to URLs, and stop calling resolveAbsolutePath.
+ this.volumeManager_.resolveAbsolutePath(
+ this.initCurrentDirectoryPath_,
+ function(inEntry) {
+ nextCurrentDirEntry = inEntry;
callback();
- return;
- }
- }
- }
+ }, callback);
+ // TODO(mtomasz): Implement reopening on special search, when fake
+ // entries are converted to directory providers.
+ }.bind(this));
- // Convert the path to the directory entry and an optional selection
- // entry.
- // TODO(hirono): There may be a race here. The path on Drive, may not
- // be available yet.
- this.volumeManager_.resolveAbsolutePath(candidateFullPath,
- function(inEntry) {
- candidateEntry = inEntry;
+ // If the directory to be changed to is not available, then first fallback
+ // to the parent of the selection entry.
+ queue.run(function(callback) {
+ if (nextCurrentDirEntry || !selectionEntry) {
callback();
- }, function() {
+ return;
+ }
+ selectionEntry.getParent(function(inEntry) {
+ nextCurrentDirEntry = inEntry;
callback();
- });
+ }.bind(this));
}.bind(this));
- // Check the obtained entry.
- var nextCurrentDirEntry;
- var selectionEntry = null;
- var suggestedName = null;
- var error = null;
+ // If the directory to be changed to is still not resolved, then fallback
+ // to the default display root.
queue.run(function(callback) {
- // Cancel this sequence if the current directory has already changed.
- if (tracker.hasChanged) {
+ if (nextCurrentDirEntry) {
callback();
return;
}
+ this.volumeManager_.getDefaultDisplayRoot(function(displayRoot) {
+ nextCurrentDirEntry = displayRoot;
+ callback();
+ }.bind(this));
+ }.bind(this));
- if (candidateEntry) {
- // The entry is directory. Use it.
- if (candidateEntry.isDirectory) {
- nextCurrentDirEntry = candidateEntry;
- callback();
- return;
- }
- // The entry exists, but it is not a directory. Therefore use a
- // parent.
- candidateEntry.getParent(function(parentEntry) {
- nextCurrentDirEntry = parentEntry;
- selectionEntry = candidateEntry;
- callback();
- }, function() {
- error = new Error('Unable to resolve parent for: ' +
- candidateEntry.fullPath);
- callback();
- });
+ // If selection failed to be resolved (eg. didn't exist, in case of saving
+ // a file, or in case of a fallback of the current directory, then try to
+ // resolve again using the target name.
+ queue.run(function(callback) {
+ if (selectionEntry || !nextCurrentDirEntry || !this.initTargetName_) {
+ callback();
return;
}
-
- // If the entry doesn't exist, most probably because the path contains a
- // suggested name. Therefore try to open its parent. However, the parent
- // may also not exist. In such situation, fallback.
- var pathNodes = candidateFullPath.split('/');
- var baseName = pathNodes.pop();
- var parentPath = pathNodes.join('/');
- this.volumeManager_.resolveAbsolutePath(
- parentPath,
- function(parentEntry) {
- nextCurrentDirEntry = parentEntry;
- suggestedName = baseName;
+ // Try to resolve as a file first. If it fails, then as a directory.
+ nextCurrentDirEntry.getFile(
+ this.initTargetName_,
+ {},
+ function(targetEntry) {
+ selectionEntry = targetEntry;
callback();
- },
- callback); // In case of an error, continue.
+ }, function() {
+ // Failed to resolve as a file
+ nextCurrentDirEntry.getDirectory(
+ this.initTargetName_,
+ {},
+ function(targetEntry) {
+ selectionEntry = targetEntry;
+ callback();
+ }, function() {
+ // Failed to resolve as either file or directory.
+ callback();
+ });
+ }.bind(this));
}.bind(this));
- // If the directory is not set at this stage, fallback to the default
- // mount point.
+
+ // Finalize.
queue.run(function(callback) {
- // Check error.
- if (error) {
- callback();
- throw error;
- }
// Check directory change.
tracker.stop();
if (tracker.hasChanged) {
@@ -1554,9 +1514,9 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
}
// Finish setup current directory.
this.finishSetupCurrentDirectory_(
- nextCurrentDirEntry || defaultDisplayRoot,
+ nextCurrentDirEntry,
selectionEntry,
- suggestedName);
+ this.initTargetName_);
callback();
}.bind(this));
};
@@ -1588,6 +1548,8 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
var task = null;
// Handle restoring after crash, or the gallery action.
+ // TODO(mtomasz): Use the gallery action instead of just the gallery
+ // field.
if (this.params_.gallery || this.params_.action === 'gallery') {
if (!opt_selectionEntry) {
// Non-existent file or a directory.
@@ -1599,7 +1561,6 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
} else {
// The file or the directory exists.
task = function() {
- // TODO(mtomasz): Replace the url with an entry.
new FileTasks(this, this.params_).openGallery([opt_selectionEntry]);
}.bind(this);
}
@@ -1611,6 +1572,12 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
// If there is a task to be run, run it after the scan is completed.
if (task) {
var listener = function() {
+ if (!util.isSameEntry(this.directoryModel_.getCurrentDirEntry(),
+ directoryEntry)) {
+ // Opened on a different path. Probably fallbacked. Therefore,
+ // do not invoke a task.
+ return;
+ }
this.directoryModel_.removeEventListener(
'scan-completed', listener);
task();
@@ -1619,7 +1586,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
}
} else if (this.dialogType === DialogType.SELECT_SAVEAS_FILE) {
this.filenameInput_.value = opt_suggestedName || '';
- this.selectDefaultPathInFilenameInput_();
+ this.selectTargetNameInFilenameInput_();
}
};
@@ -2046,7 +2013,7 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
/**
* @private
*/
- FileManager.prototype.selectDefaultPathInFilenameInput_ = function() {
+ FileManager.prototype.selectTargetNameInFilenameInput_ = function() {
var input = this.filenameInput_;
input.focus();
var selectionEnd = input.value.lastIndexOf('.');
@@ -2056,8 +2023,6 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
input.selectionStart = 0;
input.selectionEnd = selectionEnd;
}
- // Clear, so we never do this again.
- this.defaultPath = '';
};
/**
@@ -2321,9 +2286,12 @@ var BOTTOM_MARGIN_FOR_PREVIEW_PANEL_PX = 52;
this.selectionHandler_.onFileSelectionChanged();
this.ui_.searchBox.clear();
// TODO(mtomasz): Use Entry.toURL() instead of fullPath.
+ // TODO(mtomasz): Consider remembering the selection.
util.updateAppState(
- this.getCurrentDirectoryEntry() &&
- this.getCurrentDirectoryEntry().fullPath, '' /* opt_param */);
+ this.getCurrentDirectoryEntry() ?
+ this.getCurrentDirectoryEntry().fullPath : '',
+ '' /* selectionPath */,
+ '' /* opt_param */);
if (this.commandHandler)
this.commandHandler.updateAvailability();
diff --git a/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js b/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js
index 00ff483..f1b9a62 100644
--- a/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js
+++ b/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js
@@ -462,7 +462,7 @@ CommandHandler.COMMANDS_['new-window'] = {
execute: function(event, fileManager) {
// TODO(mtomasz): Use Entry.toURL() instead of fullPath.
fileManager.backgroundPage.launchFileManager({
- defaultPath: fileManager.getCurrentDirectoryEntry() &&
+ currentDirectoryPath: fileManager.getCurrentDirectoryEntry() &&
fileManager.getCurrentDirectoryEntry().fullPath
});
},
diff --git a/chrome/browser/resources/file_manager/foreground/js/file_tasks.js b/chrome/browser/resources/file_manager/foreground/js/file_tasks.js
index 8346d88..474e9d9 100644
--- a/chrome/browser/resources/file_manager/foreground/js/file_tasks.js
+++ b/chrome/browser/resources/file_manager/foreground/js/file_tasks.js
@@ -642,10 +642,14 @@ FileTasks.prototype.openGalleryInternal_ = function(entries) {
if (this.params_ && this.params_.gallery) {
// Remove the Gallery state from the location, we do not need it any more.
- util.updateAppState(null /* keep path */, '' /* remove search. */);
+ // TODO(mtomasz): Consider keeping the selection path.
+ util.updateAppState(
+ null, /* keep current directory */
+ '', /* remove current selection */
+ '' /* remove search. */);
}
- var savedAppState = window.appState;
+ var savedAppState = JSON.parse(JSON.stringify(window.appState));
var savedTitle = document.title;
// Push a temporary state which will be replaced every time the selection
diff --git a/chrome/browser/resources/file_manager/foreground/js/photo/gallery.js b/chrome/browser/resources/file_manager/foreground/js/photo/gallery.js
index 45e5968..8b3ae3f 100644
--- a/chrome/browser/resources/file_manager/foreground/js/photo/gallery.js
+++ b/chrome/browser/resources/file_manager/foreground/js/photo/gallery.js
@@ -659,7 +659,9 @@ Gallery.prototype.updateSelectionAndState_ = function() {
selectedItems.length);
}
- window.top.util.updateAppState(path,
+ window.top.util.updateAppState(
+ null, // Keep the current directory.
+ path, // Update the selection.
{gallery: (this.currentMode_ === this.mosaicMode_ ? 'mosaic' : 'slide')});
// We can't rename files in readonly directory.
diff --git a/chrome/browser/ui/views/select_file_dialog_extension.cc b/chrome/browser/ui/views/select_file_dialog_extension.cc
index 1a57202..ce3f5e8 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension.cc
@@ -295,10 +295,7 @@ void SelectFileDialogExtension::SelectFileImpl(
}
if (shell_window) {
- if (shell_window->window_type_is_panel()) {
- NOTREACHED() << "File dialog opened by panel.";
- return;
- }
+ DCHECK(!shell_window->window_type_is_panel());
base_window = shell_window->GetBaseWindow();
web_contents = shell_window->web_contents();
} else {
@@ -309,10 +306,6 @@ void SelectFileDialogExtension::SelectFileImpl(
chrome::FindLastActiveWithHostDesktopType(chrome::GetActiveDesktop());
}
DCHECK(owner_browser);
- if (!owner_browser) {
- LOG(ERROR) << "Could not find browser or shell window for popup.";
- return;
- }
base_window = owner_browser->window();
web_contents = owner_browser->tab_strip_model()->GetActiveWebContents();
}
@@ -323,50 +316,81 @@ void SelectFileDialogExtension::SelectFileImpl(
DCHECK(profile_);
// Check if we have another dialog opened for the contents. It's unlikely, but
- // possible.
+ // possible. In such situation, discard this request.
RoutingID routing_id = GetRoutingIDFromWebContents(web_contents);
- if (PendingExists(routing_id)) {
- DLOG(WARNING) << "Pending dialog exists with id " << routing_id;
+ if (PendingExists(routing_id))
return;
- }
-
- base::FilePath default_dialog_path;
const PrefService* pref_service = profile_->GetPrefs();
-
- if (default_path.empty() && pref_service) {
- default_dialog_path =
- pref_service->GetFilePath(prefs::kDownloadDefaultDirectory);
- } else {
- default_dialog_path = default_path;
+ DCHECK(pref_service);
+
+ base::FilePath download_default_path(
+ pref_service->GetFilePath(prefs::kDownloadDefaultDirectory));
+
+ base::FilePath selection_path = default_path.IsAbsolute() ?
+ default_path : download_default_path.Append(default_path.BaseName());
+
+ base::FilePath fallback_path = profile_->last_selected_directory().empty() ?
+ download_default_path : profile_->last_selected_directory();
+
+ // Convert the above absolute paths to virtual paths.
+ // TODO(mtomasz): Use URLs instead of paths.
+ base::FilePath selection_virtual_path;
+ if (!file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
+ profile_,
+ file_manager::kFileManagerAppId,
+ selection_path,
+ &selection_virtual_path)) {
+ // Due to the current design, an invalid temporal cache file path may passed
+ // as |default_path| (crbug.com/178013 #9-#11). In such a case, we use the
+ // last selected directory as a workaround. Real fix is tracked at
+ // crbug.com/110119.
+ if (!file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
+ profile_,
+ file_manager::kFileManagerAppId,
+ fallback_path.Append(default_path.BaseName()),
+ &selection_virtual_path)) {
+ LOG(ERROR) << "Unable to resolve the selection path.";
+ return;
+ }
}
-
- base::FilePath virtual_path;
- base::FilePath fallback_path = profile_->last_selected_directory().Append(
- default_dialog_path.BaseName());
- // If an absolute path is specified as the default path, convert it to the
- // virtual path in the file browser extension. Due to the current design,
- // an invalid temporal cache file path may passed as |default_dialog_path|
- // (crbug.com/178013 #9-#11). In such a case, we use the last selected
- // directory as a workaround. Real fix is tracked at crbug.com/110119.
- using file_manager::kFileManagerAppId;
- if (default_dialog_path.IsAbsolute() &&
- (file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
- profile_, kFileManagerAppId, default_dialog_path, &virtual_path) ||
- file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
- profile_, kFileManagerAppId, fallback_path, &virtual_path))) {
- virtual_path = base::FilePath("/").Append(virtual_path);
- } else {
- // If the path was relative, or failed to convert, just use the base name,
- virtual_path = default_dialog_path.BaseName();
+ // TODO(mtomasz): Adding a leading separator works, because this code is
+ // executed on Chrome OS only. This trick will be removed, once migration to
+ // URLs is finished.
+ selection_virtual_path = base::FilePath("/").Append(selection_virtual_path);
+
+ base::FilePath current_directory_virtual_path;
+ base::FilePath current_directory_path = selection_path.DirName();
+ if (!file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
+ profile_,
+ file_manager::kFileManagerAppId,
+ current_directory_path,
+ &current_directory_virtual_path)) {
+ // Fallback if necessary, see the comment above.
+ if (!file_manager::util::ConvertAbsoluteFilePathToRelativeFileSystemPath(
+ profile_,
+ file_manager::kFileManagerAppId,
+ fallback_path,
+ &current_directory_virtual_path)) {
+ LOG(ERROR) << "Unable to resolve the current directory path: "
+ << fallback_path.value();
+ return;
+ }
}
+ current_directory_virtual_path = base::FilePath("/").Append(
+ current_directory_virtual_path);
has_multiple_file_type_choices_ =
- file_types ? file_types->extensions.size() > 1 : true;
+ !file_types || (file_types->extensions.size() > 1);
GURL file_manager_url =
file_manager::util::GetFileManagerMainPageUrlWithParams(
- type, title, virtual_path, file_types, file_type_index,
+ type,
+ title,
+ current_directory_virtual_path,
+ selection_virtual_path,
+ file_types,
+ file_type_index,
default_extension);
ExtensionDialog* dialog = ExtensionDialog::Show(file_manager_url,
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
index f48d7cd..86899fb 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
@@ -21,6 +22,7 @@
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
@@ -115,6 +117,8 @@ class SelectFileDialogExtensionBrowserTest : public ExtensionBrowserTest {
void AddMountPoint(const base::FilePath& path) {
EXPECT_TRUE(file_manager::util::RegisterDownloadsMountPoint(
browser()->profile(), path));
+ browser()->profile()->GetPrefs()->SetFilePath(
+ prefs::kDownloadDefaultDirectory, downloads_dir_);
}
void CheckJavascriptErrors() {
diff --git a/chrome/test/data/extensions/api_test/file_manager_browsertest/test_cases.js b/chrome/test/data/extensions/api_test/file_manager_browsertest/test_cases.js
index 11fff7e..baaa622 100644
--- a/chrome/test/data/extensions/api_test/file_manager_browsertest/test_cases.js
+++ b/chrome/test/data/extensions/api_test/file_manager_browsertest/test_cases.js
@@ -328,7 +328,7 @@ testcase.intermediate.fileDisplay = function(path) {
StepsRunner.run([
function() {
- var appState = {defaultPath: path};
+ var appState = {currentDirectoryPath: path};
setupAndWaitUntilReady(appState, this.next);
},
// Notify that the list has been verified and a new file can be added
@@ -364,7 +364,7 @@ testcase.intermediate.galleryOpen = function(path) {
var appId;
StepsRunner.run([
function() {
- var appState = {defaultPath: path};
+ var appState = {currentDirectoryPath: path};
setupAndWaitUntilReady(appState, this.next);
},
// Resize the window to desired dimensions to avoid flakyness.
@@ -423,7 +423,7 @@ testcase.intermediate.audioOpen = function(path) {
var audioAppId;
StepsRunner.run([
function() {
- var appState = {defaultPath: path};
+ var appState = {currentDirectoryPath: path};
setupAndWaitUntilReady(appState, this.next);
},
// Select the song.
@@ -486,7 +486,7 @@ testcase.intermediate.videoOpen = function(path) {
var videoAppId;
StepsRunner.run([
function() {
- var appState = {defaultPath: path};
+ var appState = {currentDirectoryPath: path};
setupAndWaitUntilReady(appState, this.next);
},
function(inAppId) {
@@ -547,7 +547,7 @@ testcase.intermediate.keyboardCopy = function(path, callback) {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: path};
+ var appState = {currentDirectoryPath: path};
setupAndWaitUntilReady(appState, this.next);
},
// Copy the file.
@@ -593,7 +593,7 @@ testcase.intermediate.keyboardDelete = function(path) {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: path};
+ var appState = {currentDirectoryPath: path};
setupAndWaitUntilReady(appState, this.next);
},
// Delete the file.
@@ -700,7 +700,7 @@ testcase.openSidebarRecent = function() {
var appId;
StepsRunner.run([
function() {
- var appState = {defaultPath: RootPath.DRIVE};
+ var appState = {currentDirectoryPath: RootPath.DRIVE};
setupAndWaitUntilReady(appState, this.next);
},
// Click the icon of the Recent volume.
@@ -738,7 +738,7 @@ testcase.openSidebarOffline = function() {
var appId;
StepsRunner.run([
function() {
- var appState = {defaultPath: RootPath.DRIVE};
+ var appState = {currentDirectoryPath: RootPath.DRIVE};
setupAndWaitUntilReady(appState, this.next);
},
// Click the icon of the Offline volume.
@@ -775,7 +775,7 @@ testcase.openSidebarSharedWithMe = function() {
var appId;
StepsRunner.run([
function() {
- var appState = {defaultPath: RootPath.DRIVE};
+ var appState = {currentDirectoryPath: RootPath.DRIVE};
setupAndWaitUntilReady(appState, this.next);
},
// Click the icon of the Shared With Me volume.
@@ -817,7 +817,7 @@ testcase.autocomplete = function() {
StepsRunner.run([
function() {
- var appState = {defaultPath: RootPath.DRIVE};
+ var appState = {currentDirectoryPath: RootPath.DRIVE};
setupAndWaitUntilReady(appState, this.next);
},
// Perform an auto complete test and wait until the list changes.
@@ -859,7 +859,7 @@ testcase.intermediate.copyBetweenVolumes = function(targetFile,
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: RootPath.DOWNLOADS};
+ var appState = {currentDirectoryPath: RootPath.DOWNLOADS};
setupAndWaitUntilReady(appState, this.next);
},
// Select the source volume.
@@ -957,7 +957,7 @@ testcase.intermediate.share = function(path) {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: RootPath.DRIVE};
+ var appState = {currentDirectoryPath: RootPath.DRIVE};
setupAndWaitUntilReady(appState, this.next);
},
// Select the source file.
@@ -1035,7 +1035,7 @@ testcase.intermediate.traverseDirectories = function(root) {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: root};
+ var appState = {currentDirectoryPath: root};
callRemoteTestUtil('openMainWindow', null, [appState], this.next);
},
// Check the initial view.
@@ -1202,7 +1202,7 @@ testcase.intermediate.executeDefaultTask = function(drive) {
// Set up File Manager.
function() {
var appState = {
- defaultPath: root
+ currentDirectoryPath: root
};
setupAndWaitUntilReady(appState, this.next);
},
@@ -1272,7 +1272,7 @@ testcase.suggestAppDialog = function() {
var data = JSON.parse(json);
var appState = {
- defaultPath: RootPath.DRIVE,
+ currentDirectoryPath: RootPath.DRIVE,
suggestAppsDialogState: {
overrideCwsContainerUrlForTest: data.url,
overrideCwsContainerOriginForTest: data.origin
@@ -1386,7 +1386,7 @@ testcase.hideSearchBox = function() {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: RootPath.DOWNLOADS};
+ var appState = {currentDirectoryPath: RootPath.DOWNLOADS};
setupAndWaitUntilReady(appState, this.next);
},
// Resize the window.
@@ -1427,7 +1427,7 @@ testcase.restoreSortColumn = function() {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: RootPath.DOWNLOADS};
+ var appState = {currentDirectoryPath: RootPath.DOWNLOADS};
setupAndWaitUntilReady(appState, this.next);
},
// Sort by name.
@@ -1468,7 +1468,7 @@ testcase.restoreSortColumn = function() {
},
// Open another window, where the sorted column should be restored.
function() {
- var appState = {defaultPath: RootPath.DOWNLOADS};
+ var appState = {currentDirectoryPath: RootPath.DOWNLOADS};
setupAndWaitUntilReady(appState, this.next);
},
// Check the sorted style of the header.
@@ -1501,7 +1501,7 @@ testcase.restoreCurrentView = function() {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: RootPath.DOWNLOADS};
+ var appState = {currentDirectoryPath: RootPath.DOWNLOADS};
setupAndWaitUntilReady(appState, this.next);
},
// Check the initial view.
@@ -1536,7 +1536,7 @@ testcase.restoreCurrentView = function() {
},
// Open another window, where the current view is restored.
function() {
- var appState = {defaultPath: RootPath.DOWNLOADS};
+ var appState = {currentDirectoryPath: RootPath.DOWNLOADS};
callRemoteTestUtil('openMainWindow', null, [appState], this.next);
},
// Check the current view.
@@ -1562,7 +1562,7 @@ testcase.traverseNavigationList = function() {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: RootPath.DRIVE};
+ var appState = {currentDirectoryPath: RootPath.DRIVE};
setupAndWaitUntilReady(appState, this.next);
},
// Wait until Google Drive is selected.
@@ -1658,7 +1658,7 @@ testcase.restoreGeometry = function() {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: RootPath.DOWNLOADS};
+ var appState = {currentDirectoryPath: RootPath.DOWNLOADS};
setupAndWaitUntilReady(appState, this.next);
},
// Resize the window to minimal dimensions.
@@ -1688,7 +1688,7 @@ testcase.restoreGeometry = function() {
},
// Open another window, where the current view is restored.
function() {
- var appState = {defaultPath: RootPath.DOWNLOADS};
+ var appState = {currentDirectoryPath: RootPath.DOWNLOADS};
setupAndWaitUntilReady(appState, this.next);
},
// Check the next window's size.
@@ -1726,7 +1726,7 @@ testcase.searchBoxFocus = function() {
StepsRunner.run([
// Set up File Manager.
function() {
- var appState = {defaultPath: RootPath.DRIVE};
+ var appState = {currentDirectoryPath: RootPath.DRIVE};
setupAndWaitUntilReady(appState, this.next);
},
// Check that the file list has the focus on launch.
@@ -1776,7 +1776,7 @@ testcase.thumbnailsDownloads = function() {
var appId;
StepsRunner.run([
function() {
- var appState = {defaultPath: RootPath.DOWNLOADS};
+ var appState = {currentDirectoryPath: RootPath.DOWNLOADS};
setupAndWaitUntilReady(appState, this.next);
},
// Select the image.