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 e.changedFiles = event.changedFiles;
54 this.dispatchEvent(e);
59 * Called when general metadata in the watched directory has been changed.
61 * @param {Array.<Entry>} entries Array of entries.
62 * @param {Object.<string, Object>} properties Map from entry URLs to metadata
66 FileWatcher.prototype.onFilesystemMetadataChanged_ = function(
67 entries, properties) {
68 this.dispatchMetadataEvent_('filesystem', entries, properties);
72 * Called when thumbnail metadata in the watched directory has been changed.
74 * @param {Array.<Entry>} entries Array of entries.
75 * @param {Object.<string, Object>} properties Map from entry URLs to metadata
79 FileWatcher.prototype.onThumbnailMetadataChanged_ = function(
80 entries, properties) {
81 this.dispatchMetadataEvent_('thumbnail', entries, properties);
85 * Called when drive metadata in the watched directory has been changed.
87 * @param {Array.<Entry>} entries Array of entries.
88 * @param {Object.<string, Object>} properties Map from entry URLs to metadata
92 FileWatcher.prototype.onDriveMetadataChanged_ = function(
93 entries, properties) {
94 this.dispatchMetadataEvent_('drive', entries, properties);
98 * Dispatches an event about detected change in metadata within the tracked
101 * @param {string} type Type of the metadata change.
102 * @param {Array.<Entry>} entries Array of entries.
103 * @param {Object.<string, Object>} properties Map from entry URLs to metadata
107 FileWatcher.prototype.dispatchMetadataEvent_ = function(
108 type, entries, properties) {
109 var e = new Event('watcher-metadata-changed');
110 e.metadataType = type;
112 e.properties = properties;
113 this.dispatchEvent(e);
117 * Changes the watched directory. In case of a fake entry, the watch is
118 * just released, since there is no reason to track a fake directory.
120 * @param {!DirectoryEntry|!Object} entry Directory entry to be tracked, or the
122 * @param {function()} callback Completion callback.
124 FileWatcher.prototype.changeWatchedDirectory = function(entry, callback) {
125 if (!util.isFakeEntry(entry)) {
126 this.changeWatchedEntry_(
131 'Unable to change the watched directory to: ' + entry.toURL());
135 this.resetWatchedEntry_(
138 console.error('Unable to reset the watched directory.');
145 * Resets the watched entry to the passed directory.
147 * @param {function()} onSuccess Success callback.
148 * @param {function()} onError Error callback.
151 FileWatcher.prototype.resetWatchedEntry_ = function(onSuccess, onError) {
152 // Run the tasks in the queue to avoid races.
153 this.queue_.run(function(callback) {
154 // Release the watched directory.
155 if (this.watchedDirectoryEntry_) {
156 chrome.fileBrowserPrivate.removeFileWatch(
157 this.watchedDirectoryEntry_.toURL(),
159 this.watchedDirectoryEntry_ = null;
166 this.metadataCache_.removeObserver(this.filesystemMetadataObserverId_);
167 this.metadataCache_.removeObserver(this.thumbnailMetadataObserverId_);
168 this.metadataCache_.removeObserver(this.driveMetadataObserverId_);
177 * Sets the watched entry to the passed directory.
179 * @param {!DirectoryEntry} entry Directory to be watched.
180 * @param {function()} onSuccess Success callback.
181 * @param {function()} onError Error callback.
184 FileWatcher.prototype.changeWatchedEntry_ = function(
185 entry, onSuccess, onError) {
186 var setEntryClosure = function() {
187 // Run the tasks in the queue to avoid races.
188 this.queue_.run(function(callback) {
189 chrome.fileBrowserPrivate.addFileWatch(
193 this.watchedDirectoryEntry_ = null;
196 this.watchedDirectoryEntry_ = entry;
201 this.filesystemMetadataObserverId_ = this.metadataCache_.addObserver(
203 MetadataCache.CHILDREN,
205 this.onFilesystemMetadataChanged_.bind(this));
206 this.thumbnailMetadataObserverId_ = this.metadataCache_.addObserver(
208 MetadataCache.CHILDREN,
210 this.onThumbnailMetadataChanged_.bind(this));
211 this.driveMetadataObserverId_ = this.metadataCache_.addObserver(
213 MetadataCache.CHILDREN,
215 this.onDriveMetadataChanged_.bind(this));
219 // Reset the watched directory first, then set the new watched directory.
220 this.resetWatchedEntry_(setEntryClosure, onError);
224 * @return {DirectoryEntry} Current watched directory entry.
226 FileWatcher.prototype.getWatchedDirectoryEntry = function() {
227 return this.watchedDirectoryEntry_;