| Index: ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js
|
| diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c6240659b20e6784b2e89cc31c677c1d86cfe5ed
|
| --- /dev/null
|
| +++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider.js
|
| @@ -0,0 +1,205 @@
|
| +// Copyright 2015 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.
|
| +
|
| +/**
|
| + * @typedef {{
|
| + * thumbnailURL:(string|undefined),
|
| + * thumbnailTransform: (string|undefined)
|
| + * }}
|
| + */
|
| +var ContentMetadata;
|
| +
|
| +/**
|
| + * @param {!MetadataProviderCache} cache
|
| + * @param {!MessagePort=} opt_messagePort Message port overriding the default
|
| + * worker port.
|
| + * @extends {NewMetadataProvider<!ContentMetadata>}
|
| + * @constructor
|
| + * @struct
|
| + */
|
| +function ContentMetadataProvider(cache, opt_messagePort) {
|
| + NewMetadataProvider.call(this, cache, ['thumbnailURL', 'thumbnailTransform']);
|
| +
|
| + /**
|
| + * Pass all URLs to the metadata reader until we have a correct filter.
|
| + * @private {RegExp}
|
| + */
|
| + this.urlFilter_ = /.*/;
|
| +
|
| + /**
|
| + * @private {!MessagePort}
|
| + * @const
|
| + */
|
| + this.dispatcher_ = opt_messagePort ?
|
| + opt_messagePort :
|
| + new SharedWorker(ContentMetadataProvider.WORKER_SCRIPT).port;
|
| + this.dispatcher_.onmessage = this.onMessage_.bind(this);
|
| + this.dispatcher_.postMessage({verb: 'init'});
|
| + this.dispatcher_.start();
|
| +
|
| + /**
|
| + * Initialization is not complete until the Worker sends back the
|
| + * 'initialized' message. See below.
|
| + * @private {boolean}
|
| + */
|
| + this.initialized_ = false;
|
| +
|
| + /**
|
| + * Map from Entry.toURL() to callback.
|
| + * Note that simultaneous requests for same url are handled in MetadataCache.
|
| + * @private {!Object<!string, !Array<function(Object)>>}
|
| + * @const
|
| + */
|
| + this.callbacks_ = {};
|
| +}
|
| +
|
| +/**
|
| + * Path of a worker script.
|
| + * @const {string}
|
| + */
|
| +ContentMetadataProvider.WORKER_SCRIPT =
|
| + 'chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/' +
|
| + 'foreground/js/metadata/metadata_dispatcher.js';
|
| +
|
| +/**
|
| + * Converts content metadata from parsers to the internal format.
|
| + * @param {Object} metadata The content metadata.
|
| + * @return {!ContentMetadata} Converted metadata.
|
| + */
|
| +ContentMetadataProvider.convertContentMetadata = function(metadata) {
|
| + return {
|
| + thumbnailURL: metadata.thumbnailURL,
|
| + thumbnailTransform: metadata.thumbnailTransform
|
| + };
|
| +};
|
| +
|
| +ContentMetadataProvider.prototype.__proto__ = NewMetadataProvider.prototype;
|
| +
|
| +/**
|
| + * @override
|
| + */
|
| +ContentMetadataProvider.prototype.getImpl = function(requests) {
|
| + var promises = [];
|
| + for (var i = 0; i < requests.length; i++) {
|
| + promises.push(new Promise(function(request, fulfill, reject) {
|
| + this.fetch(request.entry, request.names, function(metadata) {
|
| + if (metadata)
|
| + fulfill(metadata);
|
| + else
|
| + reject();
|
| + });
|
| + }.bind(this, requests[i])));
|
| + }
|
| + return Promise.all(promises);
|
| +};
|
| +
|
| +/**
|
| + * Fetches the metadata.
|
| + * @param {Entry} entry File entry.
|
| + * @param {!Array<string>} names Requested metadata type.
|
| + * @param {function(Object)} callback Callback expects a map from metadata type
|
| + * to metadata value. This callback is called asynchronously.
|
| + */
|
| +ContentMetadataProvider.prototype.fetch = function(entry, names, callback) {
|
| + if (entry.isDirectory) {
|
| + setTimeout(callback.bind(null, {}), 0);
|
| + return;
|
| + }
|
| + var url = entry.toURL();
|
| + if (this.callbacks_[url]) {
|
| + this.callbacks_[url].push(callback);
|
| + } else {
|
| + this.callbacks_[url] = [callback];
|
| + this.dispatcher_.postMessage({verb: 'request', arguments: [url]});
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * Dispatch a message from a metadata reader to the appropriate on* method.
|
| + * @param {Object} event The event.
|
| + * @private
|
| + */
|
| +ContentMetadataProvider.prototype.onMessage_ = function(event) {
|
| + var data = event.data;
|
| + switch (data.verb) {
|
| + case 'initialized':
|
| + this.onInitialized_(data.arguments[0]);
|
| + break;
|
| + case 'result':
|
| + this.onResult_(data.arguments[0], data.arguments[1]);
|
| + break;
|
| + case 'error':
|
| + this.onError_(
|
| + data.arguments[0],
|
| + data.arguments[1],
|
| + data.arguments[2],
|
| + data.arguments[3]);
|
| + break;
|
| + case 'log':
|
| + this.onLog_(data.arguments[0]);
|
| + break;
|
| + default:
|
| + assertNotReached();
|
| + break;
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * Handles the 'initialized' message from the metadata reader Worker.
|
| + * @param {Object} regexp Regexp of supported urls.
|
| + * @private
|
| + */
|
| +ContentMetadataProvider.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.
|
| + util.testSendMessage('worker-initialized');
|
| + this.initialized_ = true;
|
| +};
|
| +
|
| +/**
|
| + * Handles the 'result' message from the worker.
|
| + * @param {string} url File url.
|
| + * @param {Object} metadata The metadata.
|
| + * @private
|
| + */
|
| +ContentMetadataProvider.prototype.onResult_ = function(url, metadata) {
|
| + var callbacks = this.callbacks_[url];
|
| + delete this.callbacks_[url];
|
| + for (var i = 0; i < callbacks.length; i++) {
|
| + callbacks[i](
|
| + metadata ?
|
| + ContentMetadataProvider.convertContentMetadata(metadata) : null);
|
| + }
|
| +};
|
| +
|
| +/**
|
| + * 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
|
| + */
|
| +ContentMetadataProvider.prototype.onError_ =
|
| + function(url, step, error, metadata) {
|
| + if (MetadataCache.log) // Avoid log spam by default.
|
| + console.warn('metadata: ' + url + ': ' + step + ': ' + error);
|
| + this.onResult_(url, null);
|
| +};
|
| +
|
| +/**
|
| + * Handles the 'log' message from the worker.
|
| + * @param {Array.<*>} arglist Log arguments.
|
| + * @private
|
| + */
|
| +ContentMetadataProvider.prototype.onLog_ = function(arglist) {
|
| + if (MetadataCache.log) // Avoid log spam by default.
|
| + console.log.apply(console, ['metadata:'].concat(arglist));
|
| +};
|
|
|