Index: chrome/browser/resources/file_manager/js/file_manager.js |
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js |
index bc755bafa2ef3bb80fa6367d9bf6c1365b625851..2b6b76e1d98ca5a55ae9fead7de1daeb76367aeb 100644 |
--- a/chrome/browser/resources/file_manager/js/file_manager.js |
+++ b/chrome/browser/resources/file_manager/js/file_manager.js |
@@ -11,6 +11,10 @@ var g_slideshow_data = null; |
const IMAGE_EDITOR_ENABLED = false; |
+// If directory files changes too often, don't rescan directory more than once |
+// per specified interva; |
rginda
2011/08/31 00:32:58
typo: s/;/l./
Dmitry Zvorygin
2011/09/12 11:12:23
Done.
|
+const SIMULTANEOUS_RESCAN_INTERVAL = 1000; |
+ |
/** |
* FileManager constructor. |
* |
@@ -52,6 +56,9 @@ function FileManager(dialogDom, filesystem, rootEntries, params) { |
// True if we should filter out files that start with a dot. |
this.filterFiles_ = true; |
+ this.subscribedOnDirectoryChanges_ = false; |
+ this.rescanPending_ = []; |
rginda
2011/08/31 00:32:58
rescanPending_ and rescanRunning_ are *very* simil
Dmitry Zvorygin
2011/09/12 11:12:23
We need both array and flag because we empty array
|
+ this.rescanRunning_ = false; |
this.commands_ = {}; |
@@ -108,6 +115,8 @@ function FileManager(dialogDom, filesystem, rootEntries, params) { |
this.onCopyProgress_.bind(this)); |
window.addEventListener('popstate', this.onPopState_.bind(this)); |
+ window.addEventListener('unload', this.onUnload_.bind(this)); |
+ |
this.addEventListener('directory-changed', |
this.onDirectoryChanged_.bind(this)); |
this.addEventListener('selection-summarized', |
@@ -119,6 +128,9 @@ function FileManager(dialogDom, filesystem, rootEntries, params) { |
chrome.fileBrowserPrivate.onMountCompleted.addListener( |
this.onMountCompleted_.bind(this)); |
+ chrome.fileBrowserPrivate.onFileChanged.addListener( |
+ this.onFileChanged_.bind(this)); |
+ |
var self = this; |
// The list of active mount points to distinct them from other directories. |
@@ -2345,6 +2357,24 @@ FileManager.prototype = { |
this.document_.title = this.currentDirEntry_.fullPath; |
var self = this; |
+ |
+ if (this.subscribedOnDirectoryChanges_) { |
+ chrome.fileBrowserPrivate.removeFileWatch(event.previousDirEntry.toURL(), |
+ function(result) { |
+ if (!result) { |
+ console.log('Failed to remove file watch'); |
+ } |
+ }); |
+ } |
+ |
+ this.subscribedOnDirectoryChanges_ = true; |
+ chrome.fileBrowserPrivate.addFileWatch(event.newDirEntry.toURL(), |
+ function(result) { |
+ if (!result) { |
+ console.log('Failed to add file watch'); |
+ } |
+ }); |
+ |
this.rescanDirectory_(function() { |
if (event.selectedEntry) |
self.selectEntry(event.selectedEntry); |
@@ -2376,38 +2406,11 @@ FileManager.prototype = { |
* |
rginda
2011/08/31 00:32:58
Please add some description of the new queuing nat
Dmitry Zvorygin
2011/09/12 11:12:23
Done.
|
* @param {function()} opt_callback Optional function to invoke when the |
* rescan is complete. |
+ * |
+ * @param {function()} opt_onError Optional function to invoke when the |
+ * rescan fails. |
*/ |
- FileManager.prototype.rescanDirectory_ = function(opt_callback) { |
- var self = this; |
- var reader; |
- |
- function onReadSome(entries) { |
- if (entries.length == 0) { |
- if (opt_callback) |
- opt_callback(); |
- return; |
- } |
- |
- // Splice takes the to-be-spliced-in array as individual parameters, |
- // rather than as an array, so we need to perform some acrobatics... |
- var spliceArgs = [].slice.call(entries); |
- |
- // Hide files that start with a dot ('.'). |
- // TODO(rginda): User should be able to override this. Support for other |
- // commonly hidden patterns might be nice too. |
- if (self.filterFiles_) { |
- spliceArgs = spliceArgs.filter(function(e) { |
- return e.name.substr(0, 1) != '.'; |
- }); |
- } |
- |
- spliceArgs.unshift(0, 0); // index, deleteCount |
- self.dataModel_.splice.apply(self.dataModel_, spliceArgs); |
- |
- // Keep reading until entries.length is 0. |
- reader.readEntries(onReadSome); |
- }; |
- |
+ FileManager.prototype.rescanDirectory_ = function(opt_callback, opt_onError) { |
// Updated when a user clicks on the label of a file, used to detect |
// when a click is eligible to trigger a rename. Can be null, or |
// an object with 'path' and 'date' properties. |
@@ -2420,9 +2423,81 @@ FileManager.prototype = { |
this.updateBreadcrumbs_(); |
if (this.currentDirEntry_.fullPath != '/') { |
+ // Add current request to pending result list |
rginda
2011/08/31 00:32:58
rescanDirectory_ is getting pretty large, can this
Dmitry Zvorygin
2011/09/12 11:12:23
I think it's little useless because that function
|
+ this.rescanPending_.push({onSuccess:opt_callback, onError:opt_onError}); |
+ |
+ if (this.rescanRunning_) { |
rginda
2011/08/31 00:32:58
No braces necessary here.
Dmitry Zvorygin
2011/09/12 11:12:23
Done.
|
+ return; |
+ } |
+ |
+ this.rescanRunning_ = true; |
+ |
+ // Save list of items to notify locally in case we'll receive new requests |
rginda
2011/08/31 00:32:58
I don't think this comment is enough to describe w
Dmitry Zvorygin
2011/09/12 11:12:23
Done.
|
+ // to refresh while refreshing |
+ var callbacks = this.rescanPending_; |
+ |
+ this.rescanPending_ = []; |
+ |
+ var self = this; |
+ var reader; |
+ |
+ function onError() { |
+ |
+ for (var i= 0; i < callbacks.length; i++) { |
+ if (callbacks[i].onError) { |
rginda
2011/08/31 00:32:58
No braces.
Dmitry Zvorygin
2011/09/12 11:12:23
Done.
|
+ callbacks[i].onError(); |
rginda
2011/08/31 00:32:58
If any of these callbacks throw, rescanRunning wil
Dmitry Zvorygin
2011/09/12 11:12:23
Done.
|
+ } |
+ } |
+ |
+ if (self.rescanPending_.length > 0) { |
+ setTimeout(self.rescanDirectory_.bind(self), |
+ SIMULTANEOUS_RESCAN_INTERVAL); |
+ } |
+ |
+ self.rescanRunning_ = false; |
+ } |
+ |
+ function onReadSome(entries) { |
+ if (entries.length == 0) { |
+ |
+ for (var i= 0; i < callbacks.length; i++) { |
+ if (callbacks[i].onSuccess) { |
+ callbacks[i].onSuccess(); |
rginda
2011/08/31 00:32:58
Same issue with failed callbacks here. Also, unne
Dmitry Zvorygin
2011/09/12 11:12:23
Done.
|
+ } |
+ } |
+ |
+ if (self.rescanPending_.length > 0) { |
+ setTimeout(self.rescanDirectory_.bind(self), |
+ SIMULTANEOUS_RESCAN_INTERVAL); |
+ } |
+ |
+ self.rescanRunning_ = false; |
+ return; |
+ } |
+ |
+ // Splice takes the to-be-spliced-in array as individual parameters, |
+ // rather than as an array, so we need to perform some acrobatics... |
+ var spliceArgs = [].slice.call(entries); |
+ |
+ // Hide files that start with a dot ('.'). |
+ // TODO(rginda): User should be able to override this. Support for other |
+ // commonly hidden patterns might be nice too. |
+ if (self.filterFiles_) { |
+ spliceArgs = spliceArgs.filter(function(e) { |
+ return e.name.substr(0, 1) != '.'; |
+ }); |
+ } |
+ |
+ spliceArgs.unshift(0, 0); // index, deleteCount |
+ self.dataModel_.splice.apply(self.dataModel_, spliceArgs); |
+ |
+ // Keep reading until entries.length is 0. |
+ reader.readEntries(onReadSome, onError); |
+ }; |
+ |
// If not the root directory, just read the contents. |
reader = this.currentDirEntry_.createReader(); |
- reader.readEntries(onReadSome); |
+ reader.readEntries(onReadSome, onError); |
return; |
} |
@@ -2483,6 +2558,33 @@ FileManager.prototype = { |
} |
}; |
+ FileManager.prototype.onUnload_ = function(event) { |
+ if (this.subscribedOnDirectoryChanges_) { |
+ chrome.fileBrowserPrivate.removeFileWatch(event.previousDirEntry.toURL(), |
+ function(result) { |
+ if (!result) { |
+ console.log('Failed to remove file watch'); |
+ } |
+ }); |
+ } |
+ }; |
+ |
+ FileManager.prototype.onFileChanged_ = function(event) { |
+ // It might be massive change, so let's note somehow, that we need |
rginda
2011/08/31 00:32:58
How about just moving this code into a 'rescanDire
|
+ // rescanning and then wait some time |
+ |
+ if (this.rescanPending_.length == 0) { |
+ this.rescanPending_.push({onSuccess:undefined, onError:undefined}); |
+ |
+ // If rescan isn't going to run without |
+ // our interruption, then say that we need to run it |
+ if (!this.rescanRunning_) { |
+ setTimeout(this.rescanDirectory_.bind(this), |
+ SIMULTANEOUS_RESCAN_INTERVAL); |
+ } |
+ } |
+ }; |
+ |
/** |
* Determine whether or not a click should initiate a rename. |
* |