1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
8 * Watches for changes in the tracked directory, including local metadata
11 * @param {MetadataCache} metadataCache Instance of MetadataCache.
12 * @extends {cr.EventTarget}
15 function FileWatcher(metadataCache) {
16 this.queue_ = new AsyncUtil.Queue();
17 this.metadataCache_ = metadataCache;
18 this.watchedDirectoryEntry_ = null;
20 this.onDirectoryChangedBound_ = this.onDirectoryChanged_.bind(this);
21 chrome.fileBrowserPrivate.onDirectoryChanged.addListener(
22 this.onDirectoryChangedBound_);
24 this.filesystemMetadataObserverId_ = null;
25 this.thumbnailMetadataObserverId_ = null;
26 this.driveMetadataObserverId_ = null;
30 * FileWatcher extends cr.EventTarget.
32 FileWatcher.prototype.__proto__ = cr.EventTarget.prototype;
35 * Stops watching (must be called before page unload).
37 FileWatcher.prototype.dispose = function() {
38 chrome.fileBrowserPrivate.onDirectoryChanged.removeListener(
39 this.onDirectoryChangedBound_);
40 if (this.watchedDirectoryEntry_)
41 this.resetWatchedEntry_(function() {}, function() {});
45 * Called when a file in the watched directory is changed.
46 * @param {Event} event Change event.
49 FileWatcher.prototype.onDirectoryChanged_ = function(event) {
50 if (this.watchedDirectoryEntry_ &&
51 event.entry.toURL() === this.watchedDirectoryEntry_.toURL()) {
52 var e = new Event('watcher-directory-changed');
53 this.dispatchEvent(e);
58 * Called when general metadata in the watched directory has been changed.
60 * @param {Array.<string>} urls Array of urls.
61 * @param {Object.<string, Object>} properties Map from entry URLs to metadata
65 FileWatcher.prototype.onFilesystemMetadataChanged_ = function(
67 this.dispatchMetadataEvent_('filesystem', urls, properties);
71 * Called when thumbnail metadata in the watched directory has been changed.
73 * @param {Array.<string>} urls Array of urls.
74 * @param {Object.<string, Object>} properties Map from entry URLs to metadata
78 FileWatcher.prototype.onThumbnailMetadataChanged_ = function(
80 this.dispatchMetadataEvent_('thumbnail', urls, properties);
84 * Called when drive metadata in the watched directory has been changed.
86 * @param {Array.<string>} urls Array of urls.
87 * @param {Object.<string, Object>} properties Map from entry URLs to metadata
91 FileWatcher.prototype.onDriveMetadataChanged_ = function(
93 this.dispatchMetadataEvent_('drive', urls, properties);
97 * Dispatches an event about detected change in metadata within the tracked
100 * @param {string} type Type of the metadata change.
101 * @param {Array.<string>} urls Array of urls.
102 * @param {Object.<string, Object>} properties Map from entry URLs to metadata
106 FileWatcher.prototype.dispatchMetadataEvent_ = function(
107 type, urls, properties) {
108 var e = new Event('watcher-metadata-changed');
109 e.metadataType = type;
111 e.properties = properties;
112 this.dispatchEvent(e);
116 * Changes the watched directory. In case of a fake entry, the watch is
117 * just released, since there is no reason to track a fake directory.
119 * @param {!DirectoryEntry|!Object} entry Directory entry to be tracked, or the
121 * @param {function()} callback Completion callback.
123 FileWatcher.prototype.changeWatchedDirectory = function(entry, callback) {
124 if (entry && entry.toURL) {
125 this.changeWatchedEntry_(
130 'Unable to change the watched directory to: ' + entry.toURL());
134 this.resetWatchedEntry_(
137 console.error('Unable to reset the watched directory.');
144 * Resets the watched entry to the passed directory.
146 * @param {function()} onSuccess Success callback.
147 * @param {function()} onError Error callback.
150 FileWatcher.prototype.resetWatchedEntry_ = function(onSuccess, onError) {
151 // Run the tasks in the queue to avoid races.
152 this.queue_.run(function(callback) {
153 // Release the watched directory.
154 if (this.watchedDirectoryEntry_) {
155 chrome.fileBrowserPrivate.removeFileWatch(
156 this.watchedDirectoryEntry_.toURL(),
158 this.watchedDirectoryEntry_ = null;
165 this.metadataCache_.removeObserver(this.filesystemMetadataObserverId_);
166 this.metadataCache_.removeObserver(this.thumbnailMetadataObserverId_);
167 this.metadataCache_.removeObserver(this.driveMetadataObserverId_);
176 * Sets the watched entry to the passed directory.
178 * @param {!DirectoryEntry} entry Directory to be watched.
179 * @param {function()} onSuccess Success callback.
180 * @param {function()} onError Error callback.
183 FileWatcher.prototype.changeWatchedEntry_ = function(
184 entry, onSuccess, onError) {
185 var setEntryClosure = function() {
186 // Run the tasks in the queue to avoid races.
187 this.queue_.run(function(callback) {
188 chrome.fileBrowserPrivate.addFileWatch(
192 this.watchedDirectoryEntry_ = null;
195 this.watchedDirectoryEntry_ = entry;
200 this.filesystemMetadataObserverId_ = this.metadataCache_.addObserver(
202 MetadataCache.CHILDREN,
204 this.onFilesystemMetadataChanged_.bind(this));
205 this.thumbnailMetadataObserverId_ = this.metadataCache_.addObserver(
207 MetadataCache.CHILDREN,
209 this.onThumbnailMetadataChanged_.bind(this));
210 this.driveMetadataObserverId_ = this.metadataCache_.addObserver(
212 MetadataCache.CHILDREN,
214 this.onDriveMetadataChanged_.bind(this));
218 // Reset the watched directory first, then set the new watched directory.
219 this.resetWatchedEntry_(setEntryClosure, onError);
223 * @return {DirectoryEntry} Current watched directory entry.
225 FileWatcher.prototype.getWatchedDirectoryEntry = function() {
226 return this.watchedDirectoryEntry_;