| 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 |