diff options
author | serya@chromium.org <serya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-10 17:34:39 +0000 |
---|---|---|
committer | serya@chromium.org <serya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-10 17:34:39 +0000 |
commit | cb6dbc5953beafe4801716bf8e87e3db771cc134 (patch) | |
tree | b9d6ea40d8fc3026090a67366d653fa5dca383fb | |
parent | 751d410765c3b6e34c84f6f29ad4e2e10186baa8 (diff) | |
download | chromium_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.cc | 108 | ||||
-rw-r--r-- | chrome/browser/extensions/file_manager_util.h | 12 | ||||
-rw-r--r-- | chrome/browser/resources/file_manager/js/file_manager.js | 119 | ||||
-rw-r--r-- | chrome/browser/resources/file_manager/js/main.js | 14 | ||||
-rw-r--r-- | chrome/browser/ui/browser.cc | 5 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 30 |
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/': [ |