summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorserya@chromium.org <serya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-10 17:34:39 +0000
committerserya@chromium.org <serya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-10 17:34:39 +0000
commitcb6dbc5953beafe4801716bf8e87e3db771cc134 (patch)
treeb9d6ea40d8fc3026090a67366d653fa5dca383fb
parent751d410765c3b6e34c84f6f29ad4e2e10186baa8 (diff)
downloadchromium_src-cb6dbc5953beafe4801716bf8e87e3db771cc134.zip
chromium_src-cb6dbc5953beafe4801716bf8e87e3db771cc134.tar.gz
chromium_src-cb6dbc5953beafe4801716bf8e87e3db771cc134.tar.bz2
Keeping the current directory in URL.
It makes the refresh button on the file manager working in intuitive manner. Also now it's possible to set a bookmark to a specific directory or enter directory path in the omnibox. BUG=chromium-os:17787 TEST=None Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=95621 Review URL: http://codereview.chromium.org/7584004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96199 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/file_manager_util.cc108
-rw-r--r--chrome/browser/extensions/file_manager_util.h12
-rw-r--r--chrome/browser/resources/file_manager/js/file_manager.js119
-rw-r--r--chrome/browser/resources/file_manager/js/main.js14
-rw-r--r--chrome/browser/ui/browser.cc5
-rw-r--r--chrome/chrome_browser.gypi30
6 files changed, 162 insertions, 126 deletions
diff --git a/chrome/browser/extensions/file_manager_util.cc b/chrome/browser/extensions/file_manager_util.cc
index 779731e..f8310f9 100644
--- a/chrome/browser/extensions/file_manager_util.cc
+++ b/chrome/browser/extensions/file_manager_util.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/simple_message_box.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
+#include "chrome/common/url_constants.h"
#include "content/browser/browser_thread.h"
#include "content/browser/user_metrics.h"
#include "grit/generated_resources.h"
@@ -152,25 +153,65 @@ GURL FileManagerUtil::GetFileBrowserUrlWithParams(
const SelectFileDialog::FileTypeInfo* file_types,
int file_type_index,
const FilePath::StringType& default_extension) {
- std::string json = GetArgumentsJson(type, title, default_virtual_path,
- file_types, file_type_index,
- default_extension);
- return GURL(FileManagerUtil::GetFileBrowserUrl().spec() + "?" +
- EscapeUrlEncodedData(json, false));
+ 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("defaultExtension", default_extension);
+
+ if (file_types) {
+ ListValue* types_list = new ListValue();
+ for (size_t i = 0; i < file_types->extensions.size(); ++i) {
+ ListValue* extensions_list = new ListValue();
+ for (size_t j = 0; j < file_types->extensions[i].size(); ++j) {
+ extensions_list->Set(
+ i, Value::CreateStringValue(file_types->extensions[i][j]));
+ }
+
+ DictionaryValue* dict = new DictionaryValue();
+ dict->Set("extensions", extensions_list);
+
+ if (i < file_types->extension_description_overrides.size()) {
+ string16 desc = file_types->extension_description_overrides[i];
+ dict->SetString("description", desc);
+ }
+
+ dict->SetBoolean("selected",
+ (static_cast<size_t>(file_type_index) == i));
+
+ types_list->Set(i, dict);
+ }
+ arg_value.Set("typeList", types_list);
+ }
+
+ std::string json_args;
+ base::JSONWriter::Write(&arg_value, false, &json_args);
+
+ // kChromeUIFileManagerURL could not be used since query parameters are not
+ // supported for it.
+ std::string url = FileManagerUtil::GetFileBrowserUrl().spec() +
+ '?' + EscapeUrlEncodedData(json_args, false);
+ return GURL(url);
}
// static
void FileManagerUtil::ShowFullTabUrl(Profile*,
- const FilePath& default_path) {
- std::string json = GetArgumentsJson(SelectFileDialog::SELECT_NONE, string16(),
- default_path, NULL, 0, FilePath::StringType());
- GURL url(std::string(kBaseFileBrowserUrl) + "?" +
- EscapeUrlEncodedData(json, false));
+ const FilePath& dir) {
Browser* browser = BrowserList::GetLastActive();
if (!browser)
return;
+ FilePath virtual_path;
+ if (!FileManagerUtil::ConvertFileToRelativeFileSystemPath(browser->profile(),
+ dir,
+ &virtual_path)) {
+ return;
+ }
+
+ std::string url = chrome::kChromeUIFileManagerURL;
+ url += '#' + EscapeUrlEncodedData(virtual_path.value(), false);
+
UserMetrics::RecordAction(UserMetricsAction("ShowFileBrowserFullTab"));
browser->ShowSingletonTab(GURL(url));
}
@@ -227,53 +268,6 @@ void FileManagerUtil::ViewItem(const FilePath& full_path, bool enqueue) {
}
// static
-std::string FileManagerUtil::GetArgumentsJson(
- SelectFileDialog::Type type,
- const string16& title,
- const FilePath& default_virtual_path,
- const SelectFileDialog::FileTypeInfo* file_types,
- int file_type_index,
- const FilePath::StringType& default_extension) {
- DictionaryValue arg_value;
- arg_value.SetString("type", GetDialogTypeAsString(type));
- arg_value.SetString("title", title);
- // TODO(zelidrag): Convert local system path into virtual path for File API.
- arg_value.SetString("defaultPath", default_virtual_path.value());
- arg_value.SetString("defaultExtension", default_extension);
-
-
- if (file_types) {
- ListValue* types_list = new ListValue();
- for (size_t i = 0; i < file_types->extensions.size(); ++i) {
- ListValue* extensions_list = new ListValue();
- for (size_t j = 0; j < file_types->extensions[i].size(); ++j) {
- extensions_list->Set(
- i, Value::CreateStringValue(file_types->extensions[i][j]));
- }
-
- DictionaryValue* dict = new DictionaryValue();
- dict->Set("extensions", extensions_list);
-
- if (i < file_types->extension_description_overrides.size()) {
- string16 desc = file_types->extension_description_overrides[i];
- dict->SetString("description", desc);
- }
-
- dict->SetBoolean("selected",
- (static_cast<size_t>(file_type_index) == i));
-
- types_list->Set(i, dict);
- }
- arg_value.Set("typeList", types_list);
- }
-
- std::string rv;
- base::JSONWriter::Write(&arg_value, false, &rv);
-
- return rv;
-}
-
-// static
std::string FileManagerUtil::GetDialogTypeAsString(
SelectFileDialog::Type dialog_type) {
std::string type_str;
diff --git a/chrome/browser/extensions/file_manager_util.h b/chrome/browser/extensions/file_manager_util.h
index 76712ef..075b1e1f 100644
--- a/chrome/browser/extensions/file_manager_util.h
+++ b/chrome/browser/extensions/file_manager_util.h
@@ -42,9 +42,9 @@ class FileManagerUtil {
const FilePath::StringType& default_extension);
// Opens file browser UI in its own tab on file system location defined with
- // |default_path|.
+ // |dir|.
static void ShowFullTabUrl(Profile* profile,
- const FilePath& default_path);
+ const FilePath& dir);
static void ViewItem(const FilePath& full_path, bool enqueue);
@@ -52,14 +52,6 @@ class FileManagerUtil {
FileManagerUtil() {}
// Helper to convert numeric dialog type to a string.
static std::string GetDialogTypeAsString(SelectFileDialog::Type dialog_type);
- // Help to convert potential dialog arguments into json.
- static std::string GetArgumentsJson(
- SelectFileDialog::Type type,
- const string16& title,
- const FilePath& default_path,
- const SelectFileDialog::FileTypeInfo* file_types,
- int file_type_index,
- const FilePath::StringType& default_extension);
DISALLOW_COPY_AND_ASSIGN(FileManagerUtil);
};
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index e0bc1f2..cfff3c4 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -31,13 +31,15 @@ const IMAGE_EDITOR_ENABLED = false;
* - defaultPath: The default path for the dialog. The default path should
* end with a trailing slash if it represents a directory.
*/
-function FileManager(dialogDom, filesystem, rootEntries, params) {
+function FileManager(dialogDom, filesystem, rootEntries) {
console.log('Init FileManager: ' + dialogDom);
this.dialogDom_ = dialogDom;
this.rootEntries_ = rootEntries;
this.filesystem_ = filesystem;
- this.params_ = params || {};
+ this.params_ = location.search ?
+ JSON.parse(decodeURIComponent(location.search.substr(1))) :
+ {};
this.listType_ = null;
@@ -132,7 +134,7 @@ function FileManager(dialogDom, filesystem, rootEntries, params) {
this.initCommands_();
this.initDom_();
this.initDialogType_();
- this.initDefaultDirectory_(this.params_.defaultPath);
+ this.setupCurrentDirectory_();
this.summarizeSelection_();
this.updatePreview_();
@@ -818,6 +820,7 @@ FileManager.prototype = {
// Rename not in progress.
!this.renameInput_.currentEntry &&
// Only one file selected.
+ this.selection &&
this.selection.totalCount == 1 &&
!isSystemDirEntry(this.currentDirEntry_));
break;
@@ -1020,10 +1023,11 @@ FileManager.prototype = {
};
/**
- * Respond to the back button.
+ * Respond to the back and forward buttons.
*/
FileManager.prototype.onPopState_ = function(event) {
- this.changeDirectory(event.state, CD_NO_HISTORY);
+ // TODO(serya): We should restore selected items here.
+ this.setupCurrentDirectory_();
};
FileManager.prototype.requestResize_ = function(timeout) {
@@ -1061,31 +1065,50 @@ FileManager.prototype = {
errorCallback);
};
- FileManager.prototype.initDefaultDirectory_ = function(path) {
- if (!path) {
- // No preset given, find a good place to start.
- // Check for removable devices, if there are none, go to Downloads.
- for (var i = 0; i != this.rootEntries_.length; i++) {
- var rootEntry = this.rootEntries_[i];
- if (rootEntry.fullPath == REMOVABLE_DIRECTORY) {
- var foundRemovable = false;
- var self = this;
- util.forEachDirEntry(rootEntry, function(result) {
- if (result) {
- foundRemovable = true;
- } else { // Done enumerating, and we know the answer.
- self.initDefaultDirectory_(
- foundRemovable ? '/' : DOWNLOADS_DIRECTORY);
- }
- });
- return;
- }
- }
+ /**
+ * Restores current directory and may be a selected item after page load (or
+ * reload) or popping a state (after click on back/forward). If location.hash
+ * is present it means that the user has navigated somewhere and that place
+ * will be restored. defaultPath primarily is used with save/open dialogs.
+ * Default path may also contain a file name. Freshly opened file manager
+ * window has neither.
+ */
+ FileManager.prototype.setupCurrentDirectory_ = function() {
+ if (location.hash) {
+ // Location hash has the highest priority.
+ var path = decodeURI(location.hash.substr(1));
+ this.changeDirectory(path, CD_NO_HISTORY);
+ return;
+ } else if (this.params_.defaultPath) {
+ this.setupPath_(this.params_.defaultPath);
+ } else {
+ this.setupDefaultPath_();
+ }
+ };
- // Removable root directory is missing altogether.
- path = DOWNLOADS_DIRECTORY;
+ FileManager.prototype.setupDefaultPath_ = function() {
+ // No preset given, find a good place to start.
+ // Check for removable devices, if there are none, go to Downloads.
+ var removableDirectoryEntry = this.rootEntries_.filter(function(rootEntry) {
+ return rootEntry.fullPath == REMOVABLE_DIRECTORY;
+ })[0];
+ if (!removableDirectoryEntry) {
+ this.changeDirectory(DOWNLOADS_DIRECTORY, CD_NO_HISTORY);
+ return;
}
+ var foundRemovable = false;
+ util.forEachDirEntry(removableDirectoryEntry, function(result) {
+ if (result) {
+ foundRemovable = true;
+ } else { // Done enumerating, and we know the answer.
+ this.changeDirectory(foundRemovable ? '/' : DOWNLOADS_DIRECTORY,
+ CD_NO_HISTORY);
+ }
+ }.bind(this));
+ };
+
+ FileManager.prototype.setupPath_ = function(path) {
// Split the dirname from the basename.
var ary = path.match(/^(.*?)(?:\/([^\/]+))?$/);
if (!ary) {
@@ -2022,6 +2045,23 @@ FileManager.prototype = {
FileManager.prototype.changeDirectoryEntry = function(dirEntry,
opt_saveHistory,
opt_selectedEntry) {
+ if (typeof opt_saveHistory == 'undefined') {
+ opt_saveHistory = true;
+ } else {
+ opt_saveHistory = !!opt_saveHistory;
+ }
+
+ var location = '#' + encodeURI(dirEntry.fullPath);
+ if (opt_saveHistory) {
+ history.pushState(undefined, dirEntry.fullPath, location);
+ } else if (window.location.hash != location) {
+ // If the user typed URL manually that is not canonical it would be fixed
+ // here. However it seems history.replaceState doesn't work properly
+ // with rewritable URLs (while does with history.pushState). It changes
+ // window.location but doesn't change content of the ombibox.
+ history.replaceState(undefined, dirEntry.fullPath, location);
+ }
+
if (this.currentDirEntry_ &&
this.currentDirEntry_.fullPath == dirEntry.fullPath) {
// Directory didn't actually change.
@@ -2030,12 +2070,6 @@ FileManager.prototype = {
return;
}
- if (typeof opt_saveHistory == 'undefined') {
- opt_saveHistory = true;
- } else {
- opt_saveHistory = !!opt_saveHistory;
- }
-
var e = new cr.Event('directory-changed');
e.previousDirEntry = this.currentDirEntry_;
e.newDirEntry = dirEntry;
@@ -2062,7 +2096,9 @@ FileManager.prototype = {
opt_saveHistory,
opt_selectedEntry) {
if (path == '/')
- return this.changeDirectoryEntry(this.filesystem_.root);
+ return this.changeDirectoryEntry(this.filesystem_.root,
+ opt_saveHistory,
+ opt_selectedEntry);
var self = this;
@@ -2074,7 +2110,12 @@ FileManager.prototype = {
},
function(err) {
console.error('Error changing directory to: ' + path + ', ' + err);
- if (!self.currentDirEntry_) {
+ if (self.currentDirEntry_) {
+ var location = '#' + encodeURI(self.currentDirEntry_.fullPath);
+ history.replaceState(undefined,
+ self.currentDirEntry_.fullPath,
+ location);
+ } else {
// If we've never successfully changed to a directory, force them
// to the root.
self.changeDirectory('/', false);
@@ -2366,12 +2407,6 @@ FileManager.prototype = {
* @param {cr.Event} event The directory-changed event.
*/
FileManager.prototype.onDirectoryChanged_ = function(event) {
- if (event.saveHistory) {
- history.pushState(this.currentDirEntry_.fullPath,
- this.currentDirEntry_.fullPath,
- location.href);
- }
-
if (this.currentDirEntry_.fullPath.substr(0, DOWNLOADS_DIRECTORY.length) ==
DOWNLOADS_DIRECTORY) {
if (this.downloadsWarning_.style.height != DOWNLOADS_WARNING_HEIGHT) {
@@ -2854,7 +2889,7 @@ FileManager.prototype = {
case 46: // Delete.
if (this.dialogType_ == FileManager.DialogType.FULL_PAGE &&
- this.selection.totalCount > 0 &&
+ this.selection && this.selection.totalCount > 0 &&
!isSystemDirEntry(this.currentDirEntry_)) {
event.preventDefault();
this.deleteEntries(this.selection.entries);
diff --git a/chrome/browser/resources/file_manager/js/main.js b/chrome/browser/resources/file_manager/js/main.js
index a9bef8c..dffad2a 100644
--- a/chrome/browser/resources/file_manager/js/main.js
+++ b/chrome/browser/resources/file_manager/js/main.js
@@ -13,19 +13,15 @@ var fileManager;
* Called by main.html after the dom has been parsed.
*/
function init() {
- var params;
-
var rootPaths = ['Downloads', 'removable', 'archive', 'tmp'];
- if (document.location.search) {
- var json = decodeURIComponent(document.location.search.substr(1));
- var params = JSON.parse(json);
- console.log('params: ' + JSON.stringify(params));
- }
-
function onEntriesFound(filesystem, entries) {
FileManager.initStrings(function () {
- fileManager = new FileManager(document.body, filesystem, entries, params);
+ fileManager = new FileManager(document.body, filesystem, entries);
+ // We're ready to run. Tests can monitor for this state with
+ // ExtensionTestMessageListener listener("ready");
+ // ASSERT_TRUE(listener.WaitUntilSatisfied());
+ chrome.test.sendMessage('ready');
});
}
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 0c8c5e6..de8eaab 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -155,12 +155,15 @@
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/boot_times_loader.h"
-#include "chrome/browser/extensions/file_manager_util.h"
#include "chrome/browser/ui/webui/active_downloads_ui.h"
#else
#include "chrome/browser/download/download_shelf.h"
#endif
+#if defined(FILE_MANAGER_EXTENSION)
+#include "chrome/browser/extensions/file_manager_util.h"
+#endif
+
using base::TimeDelta;
///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 5526b1e..ad4caaa 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3802,15 +3802,9 @@
['exclude', '^browser/extensions/extension_input_ui_api.h'],
['exclude', '^browser/ui/webui/chromeos'],
['exclude', '^browser/ui/webui/options/chromeos'],
- ['exclude', 'browser/extensions/extension_file_browser_private_api.cc'],
- ['exclude', 'browser/extensions/extension_file_browser_private_api.h'],
['exclude', 'browser/extensions/extension_input_method_api.cc'],
['exclude', 'browser/extensions/extension_input_method_api.h'],
- ['exclude', 'browser/extensions/extension_mediaplayer_private_api.cc'],
- ['exclude', 'browser/extensions/extension_mediaplayer_private_api.h'],
['exclude', 'browser/extensions/extension_tts_api_chromeos.cc'],
- ['exclude', 'browser/extensions/file_manager_util.h'],
- ['exclude', 'browser/extensions/file_manager_util.cc'],
['exclude', 'browser/oom_priority_manager.cc'],
['exclude', 'browser/oom_priority_manager.h'],
['exclude', 'browser/policy/device_policy_cache.cc'],
@@ -3854,6 +3848,16 @@
'browser/upgrade_detector_impl.h',
],
}],
+ ['file_manager_extension==0', {
+ 'sources/': [
+ ['exclude', 'browser/extensions/extension_file_browser_private_api.cc'],
+ ['exclude', 'browser/extensions/extension_file_browser_private_api.h'],
+ ['exclude', 'browser/extensions/extension_mediaplayer_private_api.cc'],
+ ['exclude', 'browser/extensions/extension_mediaplayer_private_api.h'],
+ ['exclude', 'browser/extensions/file_manager_util.h'],
+ ['exclude', 'browser/extensions/file_manager_util.cc'],
+ ],
+ }],
['use_ibus==1', {
'dependencies': [
'../build/linux/system.gyp:ibus',
@@ -4614,13 +4618,25 @@
],
}],
# Exclude extension_input_ui_api again
- # (Required because of the '^browser/extensions/' include abrove)
+ # (Required because of the '^browser/extensions/' include above)
['toolkit_uses_gtk == 1 and ( touchui == 0 or chromeos == 0 )', {
'sources/': [
['exclude', '^browser/extensions/extension_input_ui_api.cc'],
['exclude', '^browser/extensions/extension_input_ui_api.h'],
],
}],
+ # Exclude file manager files again
+ # (Required because of the '^browser/extensions/' include above)
+ ['file_manager_extension==0', {
+ 'sources/': [
+ ['exclude', 'browser/extensions/extension_file_browser_private_api.cc'],
+ ['exclude', 'browser/extensions/extension_file_browser_private_api.h'],
+ ['exclude', 'browser/extensions/extension_mediaplayer_private_api.cc'],
+ ['exclude', 'browser/extensions/extension_mediaplayer_private_api.h'],
+ ['exclude', 'browser/extensions/file_manager_util.h'],
+ ['exclude', 'browser/extensions/file_manager_util.cc'],
+ ],
+ }],
# GTK build only
['toolkit_uses_gtk == 1 and toolkit_views == 0', {
'sources/': [