Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(378)

Unified Diff: chrome/browser/resources/file_manager/js/directory_model.js

Issue 10342010: Add gdata content search to file_manager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix indent Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/browser/resources/file_manager/js/file_copy_manager.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 155b94e378eef5a2cf8cb94a9192a057e53add22..650f296b43191eb23dc5b1085b403c693f1a57a6 100644
--- a/chrome/browser/resources/file_manager/js/directory_model.js
+++ b/chrome/browser/resources/file_manager/js/directory_model.js
@@ -55,6 +55,21 @@ function DirectoryModel(root, singleSelection, metadataCache) {
* @type {Object.<string, boolean>}
*/
this.volumeReadOnlyStatus_ = {};
+
+ /**
+ * Directory in which search results are displayed. Not null iff search
+ * results are being displayed.
+ * @private
+ * @type {Entry}
+ */
+ this.searchDirEntry_ = null;
+
+ /**
+ * Is search in progress.
+ * @private
+ * @type {boolean}
+ */
+ this.isSearching_ = false;
}
/**
@@ -106,6 +121,21 @@ DirectoryModel.GDATA_ACCESS_LAZY = 1;
DirectoryModel.GDATA_ACCESS_FULL = 2;
/**
+ * Root path used for displaying gdata content search results.
+ * Search results will be shown in directory 'GDATA_SEARCH_ROOT_PATH/query'.
+ *
+ * @const
+ * @type {string}
+ */
+DirectoryModel.GDATA_SEARCH_ROOT_PATH = '/drive/.search';
+
+/**
+ * @const
+ * @type {Array.<string>}
+ */
+DirectoryModel.GDATA_SEARCH_ROOT_COMPONENTS = ['', 'drive', '.search'];
+
+/**
* DirectoryModel extends cr.EventTarget.
*/
DirectoryModel.prototype.__proto__ = cr.EventTarget.prototype;
@@ -177,7 +207,21 @@ DirectoryModel.prototype.isReadOnly = function() {
};
/**
- * @param {string} path Path to check.
+ * @return {boolean} True if search is in progress.
+ */
+DirectoryModel.prototype.isSearching = function() {
+ return this.isSearching_;
+};
+
+/**
+ * @return {boolean} True if we are currently showing search results.
+ */
+DirectoryModel.prototype.isOnGDataSearchDir = function() {
+ return this.getSearchOrCurrentDirEntry() != this.getCurrentDirEntry();
+};
+
+/**
+ * @param {strin} path Path to check.
* @return {boolean} True if the |path| is read only.
*/
DirectoryModel.prototype.isPathReadOnly = function(path) {
@@ -222,6 +266,16 @@ DirectoryModel.prototype.getCurrentDirEntry = function() {
};
/**
+ * If search results are being displayed, returns search directory, else returns
+ * current directory.
+ *
+ * @return {DirectoryEntry} search or directory entry.
+ */
+DirectoryModel.prototype.getSearchOrCurrentDirEntry = function() {
+ return this.searchDirEntry_ || this.currentDirEntry_;
+};
+
+/**
* @return {string} Path for the current directory.
*/
DirectoryModel.prototype.getCurrentDirPath = function() {
@@ -336,7 +390,8 @@ DirectoryModel.prototype.addFilter = function(name, filter) {
* @param {string} name Identifier of a filter.
*/
DirectoryModel.prototype.removeFilter = function(name) {
- delete this.filters_[name];
+ if (this.filters_[name])
+ delete this.filters_[name];
this.rescanSoon();
};
@@ -426,7 +481,7 @@ DirectoryModel.prototype.createScanner_ = function(list, successCallback) {
}
return new DirectoryModel.Scanner(
- this.currentDirEntry_,
+ this.getSearchOrCurrentDirEntry(),
list,
onSuccess,
onFailure,
@@ -513,6 +568,38 @@ DirectoryModel.prototype.prefetchCacheForSorting_ = function(entries,
};
/**
+ * Gets name that should be displayed in the UI for the entry.
+ * @param {string} path Full path of the entry whose display name we are
+ * getting.
+ * @param {string} defaultName Default name to use if no name is calculated.
+ * @return {string} Name to be used for display.
+ */
+DirectoryModel.prototype.getDisplayName = function(path, defaultName) {
+ var searchResultName = util.getFileAndDisplayNameForGDataSearchResult(path);
+ return searchResultName ? searchResultName.displayName : defaultName;
+};
+
+/**
+ * Creates file name that should be used as a new file name in filesystem
+ * operations while renaming. If the given entry is not a gdata search result
+ * entry, |displayName| will be used.
+ *
+ * @private
+ * @param {Entry} entry Entry which is being renamed.
+ * @param {string} displayName The new file name provided by user.
+ * @return {string} File name that should be used in renaming filesystem
+ * operations.
+ */
+DirectoryModel.prototype.getEntryNameForRename_ = function(entry, displayName) {
+ // If we are renaming gdata search result, we'll have to format newName to
+ // use in file system operation like: <resource_id>.<file_name>.
+ var searchResultName =
+ util.getFileAndDisplayNameForGDataSearchResult(entry.fullPath);
+ return searchResultName ? searchResultName.resourceId + '.' + displayName :
+ displayName;
+};
+
+/**
* Delete the list of files and directories from filesystem and
* update the file list.
* @param {Array.<Entry>} entries Entries to delete.
@@ -549,14 +636,19 @@ DirectoryModel.prototype.deleteEntries = function(entries, opt_callback) {
* @param {string} name Filename.
*/
DirectoryModel.prototype.onEntryChanged = function(name) {
- var currentEntry = this.currentDirEntry_;
+ var currentEntry = this.getSearchOrCurrentDirEntry();
+ if (currentEntry != this.currentDirEntry_)
+ return;
var dm = this.fileList_;
var self = this;
function onEntryFound(entry) {
+ // Do nothing if current directory changed during async operations.
+ if (self.getSearchOrCurrentDirEntry() != currentEntry)
+ return;
self.prefetchCacheForSorting_([entry], function() {
// Do nothing if current directory changed during async operations.
- if (self.currentDirEntry_ != currentEntry)
+ if (self.getSearchOrCurrentDirEntry() != currentEntry)
return;
var index = self.findIndexByName_(name);
@@ -581,7 +673,7 @@ DirectoryModel.prototype.onEntryChanged = function(name) {
dm.splice(index, 1);
};
- util.resolvePath(this.currentDirEntry_, name, onEntryFound, onError);
+ util.resolvePath(currentEntry, name, onEntryFound, onError);
};
/**
@@ -600,11 +692,12 @@ DirectoryModel.prototype.findIndexByName_ = function(name) {
/**
* Rename the entry in the filesystem and update the file list.
* @param {Entry} entry Entry to rename.
- * @param {string} newName New name.
+ * @param {string} newDisplayName New name.
* @param {function} errorCallback Called on error.
* @param {function} opt_successCallback Called on success.
*/
-DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback,
+DirectoryModel.prototype.renameEntry = function(entry, newDisplayName,
+ errorCallback,
opt_successCallback) {
var self = this;
function onSuccess(newEntry) {
@@ -613,25 +706,31 @@ DirectoryModel.prototype.renameEntry = function(entry, newName, errorCallback,
var index = fileList.indexOf(entry);
if (index >= 0)
fileList.splice(index, 1, newEntry);
- self.selectEntry(newName);
+ self.selectEntry(newEntry.name);
// If the entry doesn't exist in the list it mean that it updated from
// outside (probably by directory rescan).
if (opt_successCallback)
opt_successCallback();
});
}
- entry.moveTo(this.currentDirEntry_, newName, onSuccess, errorCallback);
+
+ var newEntryName = this.getEntryNameForRename_(entry, newDisplayName);
+ entry.moveTo(this.getSearchOrCurrentDirEntry(), newEntryName, onSuccess,
+ errorCallback);
};
/**
* Checks if current directory contains a file or directory with this name.
- * @param {string} newName Name to check.
+ * @param {string} entry Entry to which newName will be given.
+ * @param {string} displayName Name to check.
* @param {function(boolean, boolean?)} callback Called when the result's
* available. First parameter is true if the entry exists and second
* is true if it's a file.
*/
-DirectoryModel.prototype.doesExist = function(newName, callback) {
- util.resolvePath(this.currentDirEntry_, newName,
+DirectoryModel.prototype.doesExist = function(entry, displayName, callback) {
+ var entryName = this.getEntryNameForRename_(entry, displayName);
+
+ util.resolvePath(this.getSearchOrCurrentDirEntry(), entryName,
function(entry) {
callback(true, entry.isFile);
},
@@ -677,7 +776,15 @@ DirectoryModel.prototype.createDirectory = function(name, successCallback,
* @param {string} path New current directory path.
*/
DirectoryModel.prototype.changeDirectory = function(path) {
- this.resolveDirectory(path, function(directoryEntry) {
+ var targetPath = path;
+ // We should not be changing directory to gdata search path. If we do, default
+ // to gdata root.
+ if (DirectoryModel.isGDataSearchPath(path)) {
+ console.error('Attempt to change directory to search path.');
+ targetPath = '/' + DirectoryModel.GDATA_DIRECTORY;
+ }
+
+ this.resolveDirectory(targetPath, function(directoryEntry) {
this.changeDirectoryEntry_(false, directoryEntry);
}.bind(this), function(error) {
console.error('Error changing directory to ' + path + ': ', error);
@@ -759,6 +866,7 @@ DirectoryModel.prototype.changeRoot = function(path) {
*/
DirectoryModel.prototype.changeDirectoryEntry_ = function(initial, dirEntry,
opt_callback) {
+ this.clearSearch_();
var previous = this.currentDirEntry_;
this.currentDirEntry_ = dirEntry;
function onRescanComplete() {
@@ -1135,6 +1243,87 @@ DirectoryModel.isSystemDirectory = function(path) {
};
/**
+ * Performs search and displays results. The search type is dependent on the
+ * current directory. If we are currently on gdata, server side content search
+ * over gdata mount point. If the current directory is not on the gdata, file
+ * name search over current directory wil be performed.
+ *
+ * @param {string} query Query that will be searched for.
+ * @param {function} onSearchRescan Function that will be called when the search
+ * directory is rescanned (i.e. search results are displayed)
+ * @param {function} onClearSearch Function to be called when search state gets
+ * cleared.
+ */
+DirectoryModel.prototype.search = function(query,
+ onSearchRescan,
+ onClearSearch) {
+ if (!query) {
+ if (this.isSearching_)
+ this.clearSearch_();
+ return;
+ }
+
+ this.isSearching_ = true;
+
+ // If we alreaqdy have event listener for an old search, we have to remove it.
+ if (this.onSearchRescan_)
+ this.removeEventListener('rescan-completed', this.onSearchRescan_);
+
+ this.onSearchRescan_ = onSearchRescan;
+ this.onClearSearch_ = onClearSearch;
+
+ this.addEventListener('rescan-completed', this.onSearchRescan_);
+
+ // If we are offline, let's fallback to file name search inside dir.
+ if (this.getRootType() == DirectoryModel.RootType.GDATA &&
+ !this.isOffline()) {
+ var self = this;
+ // Create shadow directory which will contain search results.
+ this.root_.getDirectory(DirectoryModel.createGDataSearchPath(query),
+ {create: false},
+ function(dir) {
+ self.searchDirEntry_ = dir;
+ self.rescanSoon();
+ },
+ function() {
+ self.isSearching_ = false;
+ });
+ } else {
+ var queryLC = query.toLowerCase();
+ this.searchDirEntry_ = this.currentDirEntry_;
+ this.addFilter(
+ 'searchbox',
+ function(e) {
+ return e.name.toLowerCase().indexOf(queryLC) > -1;
+ });
+ }
+};
+
+
+/**
+ * Clears any state set by previous searches.
+ * @private
+ */
+DirectoryModel.prototype.clearSearch_ = function() {
+ if (!this.isSearching_)
+ return;
+ this.searchDirEntry_ = null;
+ this.isSearching_ = false;
+ // This will trigger rescan.
+ this.removeFilter('searchbox');
+
+ if (this.onSearchRescan_) {
+ this.removeEventListener('rescan-completed', this.onSearchRescan_);
+ this.onSearchRescan_ = null;
+ }
+
+ if (this.onClearSearch_) {
+ this.onClearSearch_();
+ this.onClearSearch_ = null;
+ }
+};
+
+/**
* @param {string} path Any path.
* @return {string} The root path.
*/
@@ -1199,6 +1388,28 @@ DirectoryModel.isRootPath = function(path) {
};
/**
+ * Checks if the provided path is under gdata search.
+ *
+ * @param {string} path Path to be tested.
+ * @return {boolean} Is the path gdata search path.
+ */
+DirectoryModel.isGDataSearchPath = function(path) {
+ return path == DirectoryModel.GDATA_SEARCH_ROOT_PATH ||
+ path.indexOf(DirectoryModel.GDATA_SEARCH_ROOT_PATH + '/') == 0;
+};
+
+/**
+ * Creates directory path in which gdata content search results for |query|
+ * should be displayed.
+ *
+ * @param {string} query Search query.
+ * @return {string} Virtual directory path for search results.
+ */
+DirectoryModel.createGDataSearchPath = function(query) {
+ return DirectoryModel.GDATA_SEARCH_ROOT_PATH + '/' + query;
+};
+
+/**
* @constructor
* @extends cr.EventTarget
* @param {DirectoryEntry} dir Directory to scan.
« no previous file with comments | « no previous file | chrome/browser/resources/file_manager/js/file_copy_manager.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698