OLD | NEW |
| (Empty) |
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. | |
4 | |
5 'use strict'; | |
6 | |
7 /** | |
8 * Watches for changes in the tracked directory, including local metadata | |
9 * changes. | |
10 * | |
11 * @param {MetadataCache} metadataCache Instance of MetadataCache. | |
12 * @extends {cr.EventTarget} | |
13 * @constructor | |
14 */ | |
15 function FileWatcher(metadataCache) { | |
16 this.queue_ = new AsyncUtil.Queue(); | |
17 this.metadataCache_ = metadataCache; | |
18 this.watchedDirectoryEntry_ = null; | |
19 | |
20 this.onDirectoryChangedBound_ = this.onDirectoryChanged_.bind(this); | |
21 chrome.fileBrowserPrivate.onDirectoryChanged.addListener( | |
22 this.onDirectoryChangedBound_); | |
23 | |
24 this.filesystemMetadataObserverId_ = null; | |
25 this.thumbnailMetadataObserverId_ = null; | |
26 this.driveMetadataObserverId_ = null; | |
27 } | |
28 | |
29 /** | |
30 * FileWatcher extends cr.EventTarget. | |
31 */ | |
32 FileWatcher.prototype.__proto__ = cr.EventTarget.prototype; | |
33 | |
34 /** | |
35 * Stops watching (must be called before page unload). | |
36 */ | |
37 FileWatcher.prototype.dispose = function() { | |
38 chrome.fileBrowserPrivate.onDirectoryChanged.removeListener( | |
39 this.onDirectoryChangedBound_); | |
40 if (this.watchedDirectoryEntry_) | |
41 this.resetWatchedEntry_(function() {}, function() {}); | |
42 }; | |
43 | |
44 /** | |
45 * Called when a file in the watched directory is changed. | |
46 * @param {Event} event Change event. | |
47 * @private | |
48 */ | |
49 FileWatcher.prototype.onDirectoryChanged_ = function(event) { | |
50 if (this.watchedDirectoryEntry_ && | |
51 event.directoryUrl == this.watchedDirectoryEntry_.toURL()) { | |
52 var e = new Event('watcher-directory-changed'); | |
53 this.dispatchEvent(e); | |
54 } | |
55 }; | |
56 | |
57 /** | |
58 * Called when general metadata in the watched directory has been changed. | |
59 * | |
60 * @param {Array.<string>} urls Array of urls. | |
61 * @param {Object.<string, Object>} properties Map from entry URLs to metadata | |
62 * properties. | |
63 * @private | |
64 */ | |
65 FileWatcher.prototype.onFilesystemMetadataChanged_ = function( | |
66 urls, properties) { | |
67 this.dispatchMetadataEvent_('filesystem', urls, properties); | |
68 }; | |
69 | |
70 /** | |
71 * Called when thumbnail metadata in the watched directory has been changed. | |
72 * | |
73 * @param {Array.<string>} urls Array of urls. | |
74 * @param {Object.<string, Object>} properties Map from entry URLs to metadata | |
75 * properties. | |
76 * @private | |
77 */ | |
78 FileWatcher.prototype.onThumbnailMetadataChanged_ = function( | |
79 urls, properties) { | |
80 this.dispatchMetadataEvent_('thumbnail', urls, properties); | |
81 }; | |
82 | |
83 /** | |
84 * Called when drive metadata in the watched directory has been changed. | |
85 * | |
86 * @param {Array.<string>} urls Array of urls. | |
87 * @param {Object.<string, Object>} properties Map from entry URLs to metadata | |
88 * properties. | |
89 * @private | |
90 */ | |
91 FileWatcher.prototype.onDriveMetadataChanged_ = function( | |
92 urls, properties) { | |
93 this.dispatchMetadataEvent_('drive', urls, properties); | |
94 }; | |
95 | |
96 /** | |
97 * Dispatches an event about detected change in metadata within the tracked | |
98 * directory. | |
99 * | |
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 | |
103 * properties. | |
104 * @private | |
105 */ | |
106 FileWatcher.prototype.dispatchMetadataEvent_ = function( | |
107 type, urls, properties) { | |
108 var e = new Event('watcher-metadata-changed'); | |
109 e.metadataType = type; | |
110 e.urls = urls; | |
111 e.properties = properties; | |
112 this.dispatchEvent(e); | |
113 }; | |
114 | |
115 /** | |
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. | |
118 * | |
119 * @param {!DirectoryEntry|!Object} entry Directory entry to be tracked, or the | |
120 * fake entry. | |
121 * @param {function()} callback Completion callback. | |
122 */ | |
123 FileWatcher.prototype.changeWatchedDirectory = function(entry, callback) { | |
124 if (entry && entry.toURL) { | |
125 this.changeWatchedEntry_( | |
126 entry, | |
127 callback, | |
128 function() { | |
129 console.error( | |
130 'Unable to change the watched directory to: ' + entry.toURL()); | |
131 callback(); | |
132 }); | |
133 } else { | |
134 this.resetWatchedEntry_( | |
135 callback, | |
136 function() { | |
137 console.error('Unable to reset the watched directory.'); | |
138 callback(); | |
139 }); | |
140 } | |
141 }; | |
142 | |
143 /** | |
144 * Resets the watched entry to the passed directory. | |
145 * | |
146 * @param {function()} onSuccess Success callback. | |
147 * @param {function()} onError Error callback. | |
148 * @private | |
149 */ | |
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(), | |
157 function(result) { | |
158 this.watchedDirectoryEntry_ = null; | |
159 if (result) | |
160 onSuccess(); | |
161 else | |
162 onError(); | |
163 callback(); | |
164 }.bind(this)); | |
165 this.metadataCache_.removeObserver(this.filesystemMetadataObserverId_); | |
166 this.metadataCache_.removeObserver(this.thumbnailMetadataObserverId_); | |
167 this.metadataCache_.removeObserver(this.driveMetadataObserverId_); | |
168 } else { | |
169 onSuccess(); | |
170 callback(); | |
171 } | |
172 }.bind(this)); | |
173 }; | |
174 | |
175 /** | |
176 * Sets the watched entry to the passed directory. | |
177 * | |
178 * @param {!DirectoryEntry} entry Directory to be watched. | |
179 * @param {function()} onSuccess Success callback. | |
180 * @param {function()} onError Error callback. | |
181 * @private | |
182 */ | |
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( | |
189 entry.toURL(), | |
190 function(result) { | |
191 if (!result) { | |
192 this.watchedDirectoryEntry_ = null; | |
193 onError(); | |
194 } else { | |
195 this.watchedDirectoryEntry_ = entry; | |
196 onSuccess(); | |
197 } | |
198 callback(); | |
199 }.bind(this)); | |
200 this.filesystemMetadataObserverId_ = this.metadataCache_.addObserver( | |
201 entry, | |
202 MetadataCache.CHILDREN, | |
203 'filesystem', | |
204 this.onFilesystemMetadataChanged_.bind(this)); | |
205 this.thumbnailMetadataObserverId_ = this.metadataCache_.addObserver( | |
206 entry, | |
207 MetadataCache.CHILDREN, | |
208 'thumbnail', | |
209 this.onThumbnailMetadataChanged_.bind(this)); | |
210 this.driveMetadataObserverId_ = this.metadataCache_.addObserver( | |
211 entry, | |
212 MetadataCache.CHILDREN, | |
213 'drive', | |
214 this.onDriveMetadataChanged_.bind(this)); | |
215 }.bind(this)); | |
216 }.bind(this); | |
217 | |
218 // Reset the watched directory first, then set the new watched directory. | |
219 this.resetWatchedEntry_(setEntryClosure, onError); | |
220 }; | |
221 | |
222 /** | |
223 * @return {DirectoryEntry} Current watched directory entry. | |
224 */ | |
225 FileWatcher.prototype.getWatchedDirectoryEntry = function() { | |
226 return this.watchedDirectoryEntry_; | |
227 }; | |
OLD | NEW |