diff options
Diffstat (limited to 'chromium/chrome/browser/resources/file_manager/foreground/js/metadata/metadata_cache.js')
-rw-r--r-- | chromium/chrome/browser/resources/file_manager/foreground/js/metadata/metadata_cache.js | 1042 |
1 files changed, 0 insertions, 1042 deletions
diff --git a/chromium/chrome/browser/resources/file_manager/foreground/js/metadata/metadata_cache.js b/chromium/chrome/browser/resources/file_manager/foreground/js/metadata/metadata_cache.js deleted file mode 100644 index 4bbbe182958..00000000000 --- a/chromium/chrome/browser/resources/file_manager/foreground/js/metadata/metadata_cache.js +++ /dev/null @@ -1,1042 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -'use strict'; - -/** - * MetadataCache is a map from Entry to an object containing properties. - * Properties are divided by types, and all properties of one type are accessed - * at once. - * Some of the properties: - * { - * filesystem: size, modificationTime - * internal: presence - * drive: pinned, present, hosted, availableOffline - * streaming: (no property) - * - * Following are not fetched for non-present drive files. - * media: artist, album, title, width, height, imageTransform, etc. - * thumbnail: url, transform - * - * Following are always fetched from content, and so force the downloading - * of remote drive files. One should use this for required content metadata, - * i.e. image orientation. - * fetchedMedia: width, height, etc. - * } - * - * Typical usages: - * { - * cache.get([entry1, entry2], 'drive|filesystem', function(metadata) { - * if (metadata[0].drive.pinned && metadata[1].filesystem.size == 0) - * alert("Pinned and empty!"); - * }); - * - * cache.set(entry, 'internal', {presence: 'deleted'}); - * - * cache.clear([fileEntry1, fileEntry2], 'filesystem'); - * - * // Getting fresh value. - * cache.clear(entry, 'thumbnail'); - * cache.get(entry, 'thumbnail', function(thumbnail) { - * img.src = thumbnail.url; - * }); - * - * var cached = cache.getCached(entry, 'filesystem'); - * var size = (cached && cached.size) || UNKNOWN_SIZE; - * } - * - * @constructor - */ -function MetadataCache() { - /** - * Map from Entry (using Entry.toURL) to metadata. Metadata contains - * |properties| - an hierarchical object of values, and an object for each - * metadata provider: <prodiver-id>: {time, callbacks} - * @private - */ - this.cache_ = {}; - - /** - * List of metadata providers. - * @private - */ - this.providers_ = []; - - /** - * List of observers added. Each one is an object with fields: - * re - regexp of urls; - * type - metadata type; - * callback - the callback. - * @private - */ - this.observers_ = []; - this.observerId_ = 0; - - this.batchCount_ = 0; - this.totalCount_ = 0; - - this.currentCacheSize_ = 0; - - /** - * Time of first get query of the current batch. Items updated later than this - * will not be evicted. - * @private - */ - this.lastBatchStart_ = new Date(); -} - -/** - * Observer type: it will be notified if the changed Entry is exactly the same - * as the observed Entry. - */ -MetadataCache.EXACT = 0; - -/** - * Observer type: it will be notified if the changed Entry is an immediate child - * of the observed Entry. - */ -MetadataCache.CHILDREN = 1; - -/** - * Observer type: it will be notified if the changed Entry is a descendant of - * of the observer Entry. - */ -MetadataCache.DESCENDANTS = 2; - -/** - * Margin of the cache size. This amount of caches may be kept in addition. - */ -MetadataCache.EVICTION_THRESHOLD_MARGIN = 500; - -/** - * @return {MetadataCache!} The cache with all providers. - */ -MetadataCache.createFull = function() { - var cache = new MetadataCache(); - cache.providers_.push(new FilesystemProvider()); - cache.providers_.push(new DriveProvider()); - cache.providers_.push(new ContentProvider()); - return cache; -}; - -/** - * Clones metadata entry. Metadata entries may contain scalars, arrays, - * hash arrays and Date object. Other objects are not supported. - * @param {Object} metadata Metadata object. - * @return {Object} Cloned entry. - */ -MetadataCache.cloneMetadata = function(metadata) { - if (metadata instanceof Array) { - var result = []; - for (var index = 0; index < metadata.length; index++) { - result[index] = MetadataCache.cloneMetadata(metadata[index]); - } - return result; - } else if (metadata instanceof Date) { - var result = new Date(); - result.setTime(metadata.getTime()); - return result; - } else if (metadata instanceof Object) { // Hash array only. - var result = {}; - for (var property in metadata) { - if (metadata.hasOwnProperty(property)) - result[property] = MetadataCache.cloneMetadata(metadata[property]); - } - return result; - } else { - return metadata; - } -}; - -/** - * @return {boolean} Whether all providers are ready. - */ -MetadataCache.prototype.isInitialized = function() { - for (var index = 0; index < this.providers_.length; index++) { - if (!this.providers_[index].isInitialized()) return false; - } - return true; -}; - -/** - * Sets the size of cache. The actual cache size may be larger than the given - * value. - * @param {number} size The cache size to be set. - */ -MetadataCache.prototype.setCacheSize = function(size) { - this.currentCacheSize_ = size; - - if (this.totalCount_ > this.currentEvictionThreshold_()) - this.evict_(); -}; - -/** - * Returns the current threshold to evict caches. When the number of caches - * exceeds this, the cache should be evicted. - * @return {number} Threshold to evict caches. - * @private - */ -MetadataCache.prototype.currentEvictionThreshold_ = function() { - return this.currentCacheSize_ * 2 + MetadataCache.EVICTION_THRESHOLD_MARGIN; -}; - -/** - * Fetches the metadata, puts it in the cache, and passes to callback. - * If required metadata is already in the cache, does not fetch it again. - * @param {Entry|Array.<Entry>} entries The list of entries. May be just a - * single item. - * @param {string} type The metadata type. - * @param {function(Object)} callback The metadata is passed to callback. - */ -MetadataCache.prototype.get = function(entries, type, callback) { - if (!(entries instanceof Array)) { - this.getOne(entries, type, callback); - return; - } - - if (entries.length == 0) { - if (callback) callback([]); - return; - } - - var result = []; - var remaining = entries.length; - this.startBatchUpdates(); - - var onOneItem = function(index, value) { - result[index] = value; - remaining--; - if (remaining == 0) { - this.endBatchUpdates(); - if (callback) setTimeout(callback, 0, result); - } - }; - - for (var index = 0; index < entries.length; index++) { - result.push(null); - this.getOne(entries[index], type, onOneItem.bind(this, index)); - } -}; - -/** - * Fetches the metadata for one Entry. See comments to |get|. - * @param {Entry} entry The entry. - * @param {string} type Metadata type. - * @param {function(Object)} callback The callback. - */ -MetadataCache.prototype.getOne = function(entry, type, callback) { - if (type.indexOf('|') != -1) { - var types = type.split('|'); - var result = {}; - var typesLeft = types.length; - - var onOneType = function(requestedType, metadata) { - result[requestedType] = metadata; - typesLeft--; - if (typesLeft == 0) callback(result); - }; - - for (var index = 0; index < types.length; index++) { - this.getOne(entry, types[index], onOneType.bind(null, types[index])); - } - return; - } - - callback = callback || function() {}; - - var entryURL = entry.toURL(); - if (!(entryURL in this.cache_)) { - this.cache_[entryURL] = this.createEmptyItem_(); - this.totalCount_++; - } - - var item = this.cache_[entryURL]; - - if (type in item.properties) { - callback(item.properties[type]); - return; - } - - this.startBatchUpdates(); - var providers = this.providers_.slice(); - var currentProvider; - var self = this; - - var onFetched = function() { - if (type in item.properties) { - self.endBatchUpdates(); - // Got properties from provider. - callback(item.properties[type]); - } else { - tryNextProvider(); - } - }; - - var onProviderProperties = function(properties) { - var id = currentProvider.getId(); - var fetchedCallbacks = item[id].callbacks; - delete item[id].callbacks; - item.time = new Date(); - self.mergeProperties_(entry, properties); - - for (var index = 0; index < fetchedCallbacks.length; index++) { - fetchedCallbacks[index](); - } - }; - - var queryProvider = function() { - var id = currentProvider.getId(); - if ('callbacks' in item[id]) { - // We are querying this provider now. - item[id].callbacks.push(onFetched); - } else { - item[id].callbacks = [onFetched]; - currentProvider.fetch(entry, type, onProviderProperties); - } - }; - - var tryNextProvider = function() { - if (providers.length == 0) { - self.endBatchUpdates(); - callback(item.properties[type] || null); - return; - } - - currentProvider = providers.shift(); - if (currentProvider.supportsEntry(entry) && - currentProvider.providesType(type)) { - queryProvider(); - } else { - tryNextProvider(); - } - }; - - tryNextProvider(); -}; - -/** - * Returns the cached metadata value, or |null| if not present. - * @param {Entry|Array.<Entry>} entries The list of entries. May be just a - * single entry. - * @param {string} type The metadata type. - * @return {Object} The metadata or null. - */ -MetadataCache.prototype.getCached = function(entries, type) { - var single = false; - if (!(entries instanceof Array)) { - single = true; - entries = [entries]; - } - - var result = []; - for (var index = 0; index < entries.length; index++) { - var entryURL = entries[index].toURL(); - result.push(entryURL in this.cache_ ? - (this.cache_[entryURL].properties[type] || null) : null); - } - - return single ? result[0] : result; -}; - -/** - * Puts the metadata into cache - * @param {Entry|Array.<Entry>} entries The list of entries. May be just a - * single entry. - * @param {string} type The metadata type. - * @param {Array.<Object>} values List of corresponding metadata values. - */ -MetadataCache.prototype.set = function(entries, type, values) { - if (!(entries instanceof Array)) { - entries = [entries]; - values = [values]; - } - - this.startBatchUpdates(); - for (var index = 0; index < entries.length; index++) { - var entryURL = entries[index].toURL(); - if (!(entryURL in this.cache_)) { - this.cache_[entryURL] = this.createEmptyItem_(); - this.totalCount_++; - } - this.cache_[entryURL].properties[type] = values[index]; - this.notifyObservers_(entries[index], type); - } - this.endBatchUpdates(); -}; - -/** - * Clears the cached metadata values. - * @param {Entry|Array.<Entry>} entries The list of entries. May be just a - * single entry. - * @param {string} type The metadata types or * for any type. - */ -MetadataCache.prototype.clear = function(entries, type) { - if (!(entries instanceof Array)) - entries = [entries]; - - var types = type.split('|'); - - for (var index = 0; index < entries.length; index++) { - var entry = entries[index]; - var entryURL = entry.toURL(); - if (entryURL in this.cache_) { - if (type === '*') { - this.cache_[entryURL].properties = {}; - } else { - for (var j = 0; j < types.length; j++) { - var type = types[j]; - delete this.cache_[entryURL].properties[type]; - } - } - } - } -}; - -/** - * Clears the cached metadata values recursively. - * @param {Entry} entry An entry to be cleared recursively from cache. - * @param {string} type The metadata types or * for any type. - */ -MetadataCache.prototype.clearRecursively = function(entry, type) { - var types = type.split('|'); - var keys = Object.keys(this.cache_); - var entryURL = entry.toURL(); - - for (var index = 0; index < keys.length; index++) { - var cachedEntryURL = keys[index]; - if (cachedEntryURL.substring(0, entryURL.length) === entryURL) { - if (type === '*') { - this.cache_[cachedEntryURL].properties = {}; - } else { - for (var j = 0; j < types.length; j++) { - var type = types[j]; - delete this.cache_[cachedEntryURL].properties[type]; - } - } - } - } -}; - -/** - * Adds an observer, which will be notified when metadata changes. - * @param {Entry} entry The root entry to look at. - * @param {number} relation This defines, which items will trigger the observer. - * See comments to |MetadataCache.EXACT| and others. - * @param {string} type The metadata type. - * @param {function(Array.<Entry>, Array.<Object>)} observer List of entries - * and corresponding metadata values are passed to this callback. - * @return {number} The observer id, which can be used to remove it. - */ -MetadataCache.prototype.addObserver = function( - entry, relation, type, observer) { - var entryURL = entry.toURL(); - var re; - if (relation == MetadataCache.CHILDREN) - re = entryURL + '(/[^/]*)?'; - else if (relation == MetadataCache.DESCENDANTS) - re = entryURL + '(/.*)?'; - else - re = entryURL; - - var id = ++this.observerId_; - this.observers_.push({ - re: new RegExp('^' + re + '$'), - type: type, - callback: observer, - id: id, - pending: {} - }); - - return id; -}; - -/** - * Removes the observer. - * @param {number} id Observer id. - * @return {boolean} Whether observer was removed or not. - */ -MetadataCache.prototype.removeObserver = function(id) { - for (var index = 0; index < this.observers_.length; index++) { - if (this.observers_[index].id == id) { - this.observers_.splice(index, 1); - return true; - } - } - return false; -}; - -/** - * Start batch updates. - */ -MetadataCache.prototype.startBatchUpdates = function() { - this.batchCount_++; - if (this.batchCount_ == 1) - this.lastBatchStart_ = new Date(); -}; - -/** - * End batch updates. Notifies observers if all nested updates are finished. - */ -MetadataCache.prototype.endBatchUpdates = function() { - this.batchCount_--; - if (this.batchCount_ != 0) return; - if (this.totalCount_ > this.currentEvictionThreshold_()) - this.evict_(); - for (var index = 0; index < this.observers_.length; index++) { - var observer = this.observers_[index]; - var entries = []; - var properties = []; - for (var entryURL in observer.pending) { - if (observer.pending.hasOwnProperty(entryURL) && - entryURL in this.cache_) { - var entry = observer.pending[entryURL]; - entries.push(entry); - properties.push( - this.cache_[entryURL].properties[observer.type] || null); - } - } - observer.pending = {}; - if (entries.length > 0) { - observer.callback(entries, properties); - } - } -}; - -/** - * Notifies observers or puts the data to pending list. - * @param {Entry} entry Changed entry. - * @param {string} type Metadata type. - * @private - */ -MetadataCache.prototype.notifyObservers_ = function(entry, type) { - var entryURL = entry.toURL(); - for (var index = 0; index < this.observers_.length; index++) { - var observer = this.observers_[index]; - if (observer.type == type && observer.re.test(entryURL)) { - if (this.batchCount_ == 0) { - // Observer expects array of urls and array of properties. - observer.callback( - [entry], [this.cache_[entryURL].properties[type] || null]); - } else { - observer.pending[entryURL] = entry; - } - } - } -}; - -/** - * Removes the oldest items from the cache. - * This method never removes the items from last batch. - * @private - */ -MetadataCache.prototype.evict_ = function() { - var toRemove = []; - - // We leave only a half of items, so we will not call evict_ soon again. - var desiredCount = this.currentEvictionThreshold_(); - var removeCount = this.totalCount_ - desiredCount; - for (var url in this.cache_) { - if (this.cache_.hasOwnProperty(url) && - this.cache_[url].time < this.lastBatchStart_) { - toRemove.push(url); - } - } - - toRemove.sort(function(a, b) { - var aTime = this.cache_[a].time; - var bTime = this.cache_[b].time; - return aTime < bTime ? -1 : aTime > bTime ? 1 : 0; - }.bind(this)); - - removeCount = Math.min(removeCount, toRemove.length); - this.totalCount_ -= removeCount; - for (var index = 0; index < removeCount; index++) { - delete this.cache_[toRemove[index]]; - } -}; - -/** - * @return {Object} Empty cache item. - * @private - */ -MetadataCache.prototype.createEmptyItem_ = function() { - var item = {properties: {}}; - for (var index = 0; index < this.providers_.length; index++) { - item[this.providers_[index].getId()] = {}; - } - return item; -}; - -/** - * Caches all the properties from data to cache entry for the entry. - * @param {Entry} entry The file entry. - * @param {Object} data The properties. - * @private - */ -MetadataCache.prototype.mergeProperties_ = function(entry, data) { - if (data == null) return; - var properties = this.cache_[entry.toURL()].properties; - for (var type in data) { - if (data.hasOwnProperty(type) && !properties.hasOwnProperty(type)) { - properties[type] = data[type]; - this.notifyObservers_(entry, type); - } - } -}; - -/** - * Base class for metadata providers. - * @constructor - */ -function MetadataProvider() { -} - -/** - * @param {Entry} entry The entry. - * @return {boolean} Whether this provider supports the entry. - */ -MetadataProvider.prototype.supportsEntry = function(entry) { return false; }; - -/** - * @param {string} type The metadata type. - * @return {boolean} Whether this provider provides this metadata. - */ -MetadataProvider.prototype.providesType = function(type) { return false; }; - -/** - * @return {string} Unique provider id. - */ -MetadataProvider.prototype.getId = function() { return ''; }; - -/** - * @return {boolean} Whether provider is ready. - */ -MetadataProvider.prototype.isInitialized = function() { return true; }; - -/** - * Fetches the metadata. It's suggested to return all the metadata this provider - * can fetch at once. - * @param {Entry} entry File entry. - * @param {string} type Requested metadata type. - * @param {function(Object)} callback Callback expects a map from metadata type - * to metadata value. - */ -MetadataProvider.prototype.fetch = function(entry, type, callback) { - throw new Error('Default metadata provider cannot fetch.'); -}; - - -/** - * Provider of filesystem metadata. - * This provider returns the following objects: - * filesystem: { size, modificationTime } - * @constructor - */ -function FilesystemProvider() { - MetadataProvider.call(this); -} - -FilesystemProvider.prototype = { - __proto__: MetadataProvider.prototype -}; - -/** - * @param {Entry} entry The entry. - * @return {boolean} Whether this provider supports the entry. - */ -FilesystemProvider.prototype.supportsEntry = function(entry) { - return true; -}; - -/** - * @param {string} type The metadata type. - * @return {boolean} Whether this provider provides this metadata. - */ -FilesystemProvider.prototype.providesType = function(type) { - return type == 'filesystem'; -}; - -/** - * @return {string} Unique provider id. - */ -FilesystemProvider.prototype.getId = function() { return 'filesystem'; }; - -/** - * Fetches the metadata. - * @param {Entry} entry File entry. - * @param {string} type Requested metadata type. - * @param {function(Object)} callback Callback expects a map from metadata type - * to metadata value. - */ -FilesystemProvider.prototype.fetch = function( - entry, type, callback) { - function onError(error) { - callback(null); - } - - function onMetadata(entry, metadata) { - callback({ - filesystem: { - size: entry.isFile ? (metadata.size || 0) : -1, - modificationTime: metadata.modificationTime - } - }); - } - - entry.getMetadata(onMetadata.bind(null, entry), onError); -}; - -/** - * Provider of drive metadata. - * This provider returns the following objects: - * drive: { pinned, hosted, present, customIconUrl, etc. } - * thumbnail: { url, transform } - * streaming: { } - * @constructor - */ -function DriveProvider() { - MetadataProvider.call(this); - - // We batch metadata fetches into single API call. - this.entries_ = []; - this.callbacks_ = []; - this.scheduled_ = false; - - this.callApiBound_ = this.callApi_.bind(this); -} - -DriveProvider.prototype = { - __proto__: MetadataProvider.prototype -}; - -/** - * @param {Entry} entry The entry. - * @return {boolean} Whether this provider supports the entry. - */ -DriveProvider.prototype.supportsEntry = function(entry) { - return FileType.isOnDrive(entry); -}; - -/** - * @param {string} type The metadata type. - * @return {boolean} Whether this provider provides this metadata. - */ -DriveProvider.prototype.providesType = function(type) { - return type == 'drive' || type == 'thumbnail' || - type == 'streaming' || type == 'media'; -}; - -/** - * @return {string} Unique provider id. - */ -DriveProvider.prototype.getId = function() { return 'drive'; }; - -/** - * Fetches the metadata. - * @param {Entry} entry File entry. - * @param {string} type Requested metadata type. - * @param {function(Object)} callback Callback expects a map from metadata type - * to metadata value. - */ -DriveProvider.prototype.fetch = function(entry, type, callback) { - this.entries_.push(entry); - this.callbacks_.push(callback); - if (!this.scheduled_) { - this.scheduled_ = true; - setTimeout(this.callApiBound_, 0); - } -}; - -/** - * Schedules the API call. - * @private - */ -DriveProvider.prototype.callApi_ = function() { - this.scheduled_ = false; - - var entries = this.entries_; - var callbacks = this.callbacks_; - this.entries_ = []; - this.callbacks_ = []; - var self = this; - - var task = function(entry, callback) { - // TODO(mtomasz): Make getDriveEntryProperties accept Entry instead of URL. - var entryURL = entry.toURL(); - chrome.fileBrowserPrivate.getDriveEntryProperties(entryURL, - function(properties) { - callback(self.convert_(properties, entry)); - }); - }; - - for (var i = 0; i < entries.length; i++) - task(entries[i], callbacks[i]); -}; - -/** - * @param {DriveEntryProperties} data Drive entry properties. - * @param {Entry} entry File entry. - * @return {boolean} True if the file is available offline. - */ -DriveProvider.isAvailableOffline = function(data, entry) { - if (data.isPresent) - return true; - - if (!data.isHosted) - return false; - - // What's available offline? See the 'Web' column at: - // http://support.google.com/drive/bin/answer.py?hl=en&answer=1628467 - var subtype = FileType.getType(entry).subtype; - return (subtype == 'doc' || - subtype == 'draw' || - subtype == 'sheet' || - subtype == 'slides'); -}; - -/** - * @param {DriveEntryProperties} data Drive entry properties. - * @return {boolean} True if opening the file does not require downloading it - * via a metered connection. - */ -DriveProvider.isAvailableWhenMetered = function(data) { - return data.isPresent || data.isHosted; -}; - -/** - * Converts API metadata to internal format. - * @param {Object} data Metadata from API call. - * @param {Entry} entry File entry. - * @return {Object} Metadata in internal format. - * @private - */ -DriveProvider.prototype.convert_ = function(data, entry) { - var result = {}; - result.drive = { - present: data.isPresent, - pinned: data.isPinned, - hosted: data.isHosted, - imageWidth: data.imageWidth, - imageHeight: data.imageHeight, - imageRotation: data.imageRotation, - availableOffline: DriveProvider.isAvailableOffline(data, entry), - availableWhenMetered: DriveProvider.isAvailableWhenMetered(data), - customIconUrl: data.customIconUrl || '', - contentMimeType: data.contentMimeType || '', - sharedWithMe: data.sharedWithMe, - shared: data.shared - }; - - if (!data.isPresent) { - // Block the local fetch for drive files, which require downloading. - result.thumbnail = {url: '', transform: null}; - result.media = {}; - } - - if ('thumbnailUrl' in data) { - result.thumbnail = { - url: data.thumbnailUrl, - transform: null - }; - } - if (!data.isPresent) { - // Indicate that the data is not available in local cache. - // It used to have a field 'url' for streaming play, but it is - // derprecated. See crbug.com/174560. - result.streaming = {}; - } - return result; -}; - - -/** - * Provider of content metadata. - * This provider returns the following objects: - * thumbnail: { url, transform } - * media: { artist, album, title, width, height, imageTransform, etc. } - * fetchedMedia: { same fields here } - * @constructor - */ -function ContentProvider() { - MetadataProvider.call(this); - - // Pass all URLs to the metadata reader until we have a correct filter. - this.urlFilter_ = /.*/; - - var path = document.location.pathname; - var workerPath = document.location.origin + - path.substring(0, path.lastIndexOf('/') + 1) + - 'foreground/js/metadata/metadata_dispatcher.js'; - - this.dispatcher_ = new SharedWorker(workerPath).port; - this.dispatcher_.start(); - - this.dispatcher_.onmessage = this.onMessage_.bind(this); - this.dispatcher_.postMessage({verb: 'init'}); - - // Initialization is not complete until the Worker sends back the - // 'initialized' message. See below. - this.initialized_ = false; - - // Map from Entry.toURL() to callback. - // Note that simultaneous requests for same url are handled in MetadataCache. - this.callbacks_ = {}; -} - -ContentProvider.prototype = { - __proto__: MetadataProvider.prototype -}; - -/** - * @param {Entry} entry The entry. - * @return {boolean} Whether this provider supports the entry. - */ -ContentProvider.prototype.supportsEntry = function(entry) { - return entry.toURL().match(this.urlFilter_); -}; - -/** - * @param {string} type The metadata type. - * @return {boolean} Whether this provider provides this metadata. - */ -ContentProvider.prototype.providesType = function(type) { - return type == 'thumbnail' || type == 'fetchedMedia' || type == 'media'; -}; - -/** - * @return {string} Unique provider id. - */ -ContentProvider.prototype.getId = function() { return 'content'; }; - -/** - * Fetches the metadata. - * @param {Entry} entry File entry. - * @param {string} type Requested metadata type. - * @param {function(Object)} callback Callback expects a map from metadata type - * to metadata value. - */ -ContentProvider.prototype.fetch = function(entry, type, callback) { - if (entry.isDirectory) { - callback({}); - return; - } - var entryURL = entry.toURL(); - this.callbacks_[entryURL] = callback; - this.dispatcher_.postMessage({verb: 'request', arguments: [entryURL]}); -}; - -/** - * Dispatch a message from a metadata reader to the appropriate on* method. - * @param {Object} event The event. - * @private - */ -ContentProvider.prototype.onMessage_ = function(event) { - var data = event.data; - - var methodName = - 'on' + data.verb.substr(0, 1).toUpperCase() + data.verb.substr(1) + '_'; - - if (!(methodName in this)) { - console.error('Unknown message from metadata reader: ' + data.verb, data); - return; - } - - this[methodName].apply(this, data.arguments); -}; - -/** - * @return {boolean} Whether provider is ready. - */ -ContentProvider.prototype.isInitialized = function() { - return this.initialized_; -}; - -/** - * Handles the 'initialized' message from the metadata reader Worker. - * @param {Object} regexp Regexp of supported urls. - * @private - */ -ContentProvider.prototype.onInitialized_ = function(regexp) { - this.urlFilter_ = regexp; - - // Tests can monitor for this state with - // ExtensionTestMessageListener listener("worker-initialized"); - // ASSERT_TRUE(listener.WaitUntilSatisfied()); - // Automated tests need to wait for this, otherwise we crash in - // browser_test cleanup because the worker process still has - // URL requests in-flight. - var test = chrome.test || window.top.chrome.test; - test.sendMessage('worker-initialized'); - this.initialized_ = true; -}; - -/** - * Converts content metadata from parsers to the internal format. - * @param {Object} metadata The content metadata. - * @param {Object=} opt_result The internal metadata object ot put result in. - * @return {Object!} Converted metadata. - */ -ContentProvider.ConvertContentMetadata = function(metadata, opt_result) { - var result = opt_result || {}; - - if ('thumbnailURL' in metadata) { - metadata.thumbnailTransform = metadata.thumbnailTransform || null; - result.thumbnail = { - url: metadata.thumbnailURL, - transform: metadata.thumbnailTransform - }; - } - - for (var key in metadata) { - if (metadata.hasOwnProperty(key)) { - if (!('media' in result)) result.media = {}; - result.media[key] = metadata[key]; - } - } - - if ('media' in result) { - result.fetchedMedia = result.media; - } - - return result; -}; - -/** - * Handles the 'result' message from the worker. - * @param {string} url File url. - * @param {Object} metadata The metadata. - * @private - */ -ContentProvider.prototype.onResult_ = function(url, metadata) { - var callback = this.callbacks_[url]; - delete this.callbacks_[url]; - callback(ContentProvider.ConvertContentMetadata(metadata)); -}; - -/** - * Handles the 'error' message from the worker. - * @param {string} url File entry. - * @param {string} step Step failed. - * @param {string} error Error description. - * @param {Object?} metadata The metadata, if available. - * @private - */ -ContentProvider.prototype.onError_ = function(url, step, error, metadata) { - if (MetadataCache.log) // Avoid log spam by default. - console.warn('metadata: ' + url + ': ' + step + ': ' + error); - metadata = metadata || {}; - // Prevent asking for thumbnail again. - metadata.thumbnailURL = ''; - this.onResult_(url, metadata); -}; - -/** - * Handles the 'log' message from the worker. - * @param {Array.<*>} arglist Log arguments. - * @private - */ -ContentProvider.prototype.onLog_ = function(arglist) { - if (MetadataCache.log) // Avoid log spam by default. - console.log.apply(console, ['metadata:'].concat(arglist)); -}; |