| Index: ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata.js
|
| diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata.js b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata.js
|
| index 8841cf184ea0748490c15bb86682c260f74618cc..0e7583f69258149e2f5413a54f04fbf3069f3238 100644
|
| --- a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata.js
|
| +++ b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata.js
|
| @@ -3,25 +3,42 @@
|
| // found in the LICENSE file.
|
|
|
| /**
|
| - * @param {!MetadataProviderCache} cache
|
| + * @param {!VolumeManagerCommon.VolumeInfoProvider} volumeManager
|
| + * @constructor
|
| + * @struct
|
| + * @extends {CachedMetadataProvider}
|
| + */
|
| +function FileSystemMetadata(volumeManager) {
|
| + CachedMetadataProvider.call(
|
| + this,
|
| + new MultiMetadataProvider(
|
| + new FileSystemMetadataProvider(),
|
| + new ExternalMetadataProvider(),
|
| + new ContentMetadataProvider(),
|
| + volumeManager));
|
| +};
|
| +
|
| +FileSystemMetadata.prototype.__proto__ = CachedMetadataProvider.prototype;
|
| +
|
| +/**
|
| * @param {!FileSystemMetadataProvider} fileSystemMetadataProvider
|
| * @param {!ExternalMetadataProvider} externalMetadataProvider
|
| * @param {!ContentMetadataProvider} contentMetadataProvider
|
| * @param {!VolumeManagerCommon.VolumeInfoProvider} volumeManager
|
| * @constructor
|
| + * @extends {NewMetadataProvider}
|
| * @struct
|
| */
|
| -function FileSystemMetadata(
|
| - cache,
|
| +function MultiMetadataProvider(
|
| fileSystemMetadataProvider,
|
| externalMetadataProvider,
|
| contentMetadataProvider,
|
| volumeManager) {
|
| - /**
|
| - * @private {!MetadataProviderCache}
|
| - * @const
|
| - */
|
| - this.cache_ = cache;
|
| + NewMetadataProvider.call(
|
| + this,
|
| + FileSystemMetadataProvider.PROPERTY_NAMES.concat(
|
| + ExternalMetadataProvider.PROPERTY_NAMES).concat(
|
| + ContentMetadataProvider.PROPERTY_NAMES));
|
|
|
| /**
|
| * @private {!FileSystemMetadataProvider}
|
| @@ -48,152 +65,124 @@ function FileSystemMetadata(
|
| this.volumeManager_ = volumeManager;
|
| }
|
|
|
| -/**
|
| - * @param {!MetadataProviderCache} cache
|
| - * @param {!VolumeManagerCommon.VolumeInfoProvider} volumeManager
|
| - * @return {!FileSystemMetadata}
|
| - */
|
| -FileSystemMetadata.create = function(cache, volumeManager) {
|
| - return new FileSystemMetadata(
|
| - cache,
|
| - new FileSystemMetadataProvider(cache),
|
| - new ExternalMetadataProvider(cache),
|
| - new ContentMetadataProvider(cache),
|
| - volumeManager);
|
| -};
|
| +MultiMetadataProvider.prototype.__proto__ = NewMetadataProvider.prototype;
|
|
|
| /**
|
| * Obtains metadata for entries.
|
| - * @param {!Array<!Entry>} entries Entries.
|
| - * @param {!Array<string>} names Metadata property names to be obtained.
|
| + * @param {!Array<!MetadataRequest>} requests
|
| * @return {!Promise<!Array<!MetadataItem>>}
|
| */
|
| -FileSystemMetadata.prototype.get = function(entries, names) {
|
| - var localEntries = [];
|
| - var externalEntries = [];
|
| - for (var i = 0; i < entries.length; i++) {
|
| - var volumeInfo = this.volumeManager_.getVolumeInfo(entries[i]);
|
| +MultiMetadataProvider.prototype.get = function(requests) {
|
| + var fileSystemRequests = [];
|
| + var externalRequests = [];
|
| + var contentRequests = [];
|
| + var fallbackContentRequests = [];
|
| + requests.forEach(function(request) {
|
| + // Group property names.
|
| + var fileSystemPropertyNames = [];
|
| + var externalPropertyNames = [];
|
| + var contentPropertyNames = [];
|
| + var fallbackContentPropertyNames = [];
|
| + for (var i = 0; i < request.names.length; i++) {
|
| + var name = request.names[i];
|
| + var isFileSystemProperty =
|
| + FileSystemMetadataProvider.PROPERTY_NAMES.indexOf(name) !== -1;
|
| + var isExternalProperty =
|
| + ExternalMetadataProvider.PROPERTY_NAMES.indexOf(name) !== -1;
|
| + var isContentProperty =
|
| + ContentMetadataProvider.PROPERTY_NAMES.indexOf(name) !== -1;
|
| + assert(isFileSystemProperty || isExternalProperty || isContentProperty);
|
| + assert(!(isFileSystemProperty && isContentProperty));
|
| + // If the property can be obtained both from ExternalProvider and from
|
| + // ContentProvider, we can obtain the property from ExternalProvider
|
| + // without fetching file content. On the other hand, the values from
|
| + // ExternalProvider may be out of sync if the file is 'dirty'. Thus we
|
| + // fallback to ContentProvider if the file is dirty. See below.
|
| + if (isExternalProperty && isContentProperty) {
|
| + externalPropertyNames.push(name);
|
| + fallbackContentPropertyNames.push(name);
|
| + continue;
|
| + }
|
| + if (isFileSystemProperty)
|
| + fileSystemPropertyNames.push(name);
|
| + if (isExternalProperty)
|
| + externalPropertyNames.push(name);
|
| + if (isContentProperty)
|
| + contentPropertyNames.push(name);
|
| + }
|
| + var volumeInfo = this.volumeManager_.getVolumeInfo(request.entry);
|
| + var addRequests = function(list, names) {
|
| + if (names.length)
|
| + list.push(new MetadataRequest(request.entry, names));
|
| + };
|
| if (volumeInfo &&
|
| (volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE ||
|
| volumeInfo.volumeType === VolumeManagerCommon.VolumeType.PROVIDED)) {
|
| - externalEntries.push(entries[i]);
|
| + if (fallbackContentPropertyNames.length &&
|
| + externalPropertyNames.indexOf('dirty') === -1) {
|
| + externalPropertyNames.push('dirty');
|
| + }
|
| + addRequests(externalRequests, externalPropertyNames);
|
| + addRequests(contentRequests, contentPropertyNames);
|
| + addRequests(fallbackContentRequests, fallbackContentPropertyNames);
|
| } else {
|
| - localEntries.push(entries[i]);
|
| + addRequests(fileSystemRequests, fileSystemPropertyNames);
|
| + addRequests(
|
| + contentRequests,
|
| + contentPropertyNames.concat(fallbackContentPropertyNames));
|
| }
|
| - }
|
| + }.bind(this));
|
|
|
| - // Group property names.
|
| - var fileSystemPropertyNames = [];
|
| - var externalPropertyNames = [];
|
| - var contentPropertyNames = [];
|
| - var fallbackContentPropertyNames = [];
|
| - for (var i = 0; i < names.length; i++) {
|
| - var name = names[i];
|
| - var isFileSystemProperty =
|
| - FileSystemMetadataProvider.PROPERTY_NAMES.indexOf(name) !== -1;
|
| - var isExternalProperty =
|
| - ExternalMetadataProvider.PROPERTY_NAMES.indexOf(name) !== -1;
|
| - var isContentProperty =
|
| - ContentMetadataProvider.PROPERTY_NAMES.indexOf(name) !== -1;
|
| - assert(isFileSystemProperty || isExternalProperty || isContentProperty);
|
| - assert(!(isFileSystemProperty && isContentProperty));
|
| - // If the property can be obtained both from ExternalProvider and from
|
| - // ContentProvider, we can obtain the property from ExternalProvider without
|
| - // fetching file content. On the other hand, the values from
|
| - // ExternalProvider may be out of sync if the file is 'dirty'. Thus we
|
| - // fallback to ContentProvider if the file is dirty. See below.
|
| - if (isExternalProperty && isContentProperty) {
|
| - externalPropertyNames.push(name);
|
| - fallbackContentPropertyNames.push(name);
|
| - continue;
|
| - }
|
| - if (isFileSystemProperty)
|
| - fileSystemPropertyNames.push(name);
|
| - if (isExternalProperty)
|
| - externalPropertyNames.push(name);
|
| - if (isContentProperty)
|
| - contentPropertyNames.push(name);
|
| - }
|
| -
|
| - // Obtain each group of property names.
|
| - var resultPromises = [];
|
| - var get = function(provider, entries, names) {
|
| - return provider.get(entries, names).then(function(results) {
|
| - return {entries: entries, results: results};
|
| + var get = function(provider, inRequests) {
|
| + return provider.get(inRequests).then(function(results) {
|
| + return {
|
| + requests: inRequests,
|
| + results: results
|
| + };
|
| });
|
| };
|
| - resultPromises.push(get(
|
| - this.fileSystemMetadataProvider_, localEntries, fileSystemPropertyNames));
|
| - resultPromises.push(get(
|
| - this.externalMetadataProvider_, externalEntries, externalPropertyNames));
|
| - resultPromises.push(get(
|
| - this.contentMetadataProvider_, entries, contentPropertyNames));
|
| - if (fallbackContentPropertyNames.length) {
|
| - var dirtyEntriesPromise = this.externalMetadataProvider_.get(
|
| - externalEntries, ['dirty']).then(function(results) {
|
| - return externalEntries.filter(function(entry, index) {
|
| - return results[index].dirty;
|
| - });
|
| - });
|
| - resultPromises.push(dirtyEntriesPromise.then(function(dirtyEntries) {
|
| - return get(
|
| - this.contentMetadataProvider_,
|
| - localEntries.concat(dirtyEntries),
|
| - fallbackContentPropertyNames);
|
| - }.bind(this)));
|
| - }
|
| + var fileSystemPromise = get(
|
| + this.fileSystemMetadataProvider_, fileSystemRequests);
|
| + var externalPromise = get(this.externalMetadataProvider_, externalRequests);
|
| + var contentPromise = get(this.contentMetadataProvider_, contentRequests);
|
| + var fallbackContentPromise = externalPromise.then(
|
| + function(requestsAndResults) {
|
| + var requests = requestsAndResults.requests;
|
| + var results = requestsAndResults.results;
|
| + var dirtyMap = [];
|
| + for (var i = 0; i < results.length; i++) {
|
| + dirtyMap[requests[i].entry.toURL()] = results[i].dirty;
|
| + }
|
| + return get(
|
| + this.contentMetadataProvider_,
|
| + fallbackContentRequests.filter(
|
| + function(request) {
|
| + return dirtyMap[request.entry.toURL()];
|
| + }));
|
| + }.bind(this));
|
|
|
| // Merge results.
|
| - return Promise.all(resultPromises).then(function(resultsList) {
|
| + return Promise.all([
|
| + fileSystemPromise,
|
| + externalPromise,
|
| + contentPromise,
|
| + fallbackContentPromise
|
| + ]).then(function(resultsList) {
|
| var integratedResults = {};
|
| for (var i = 0; i < resultsList.length; i++) {
|
| - var inEntries = resultsList[i].entries;
|
| + var inRequests = resultsList[i].requests;
|
| var results = resultsList[i].results;
|
| - for (var j = 0; j < inEntries.length; j++) {
|
| - var url = inEntries[j].toURL();
|
| + assert(inRequests.length === results.length);
|
| + for (var j = 0; j < results.length; j++) {
|
| + var url = inRequests[j].entry.toURL();
|
| integratedResults[url] = integratedResults[url] || new MetadataItem();
|
| for (var name in results[j]) {
|
| integratedResults[url][name] = results[j][name];
|
| }
|
| }
|
| }
|
| - return entries.map(function(entry) {
|
| - return integratedResults[entry.toURL()];
|
| + return requests.map(function(request) {
|
| + return integratedResults[request.entry.toURL()] || new MetadataItem();
|
| });
|
| });
|
| };
|
| -
|
| -/**
|
| - * Obtains metadata cache for entries.
|
| - * @param {!Array<!Entry>} entries Entries.
|
| - * @param {!Array<string>} names Metadata property names to be obtained.
|
| - * @return {!Array<!MetadataItem>}
|
| - */
|
| -FileSystemMetadata.prototype.getCache = function(entries, names) {
|
| - return this.cache_.get(entries, names);
|
| -};
|
| -
|
| -/**
|
| - * Clears old metadata for newly created entries.
|
| - * @param {!Array<!Entry>} entries
|
| - */
|
| -FileSystemMetadata.prototype.notifyEntriesCreated = function(entries) {
|
| - this.cache_.clear(util.entriesToURLs(entries));
|
| -};
|
| -
|
| -/**
|
| - * Clears metadata for deleted entries.
|
| - * @param {!Array<string>} urls Note it is not an entry list because we cannot
|
| - * obtain entries after removing them from the file system.
|
| - */
|
| -FileSystemMetadata.prototype.notifyEntriesRemoved = function(urls) {
|
| - this.cache_.clear(urls);
|
| -};
|
| -
|
| -/**
|
| - * Invalidates metadata for updated entries.
|
| - * @param {!Array<!Entry>} entries
|
| - */
|
| -FileSystemMetadata.prototype.notifyEntriesChanged = function(entries) {
|
| - this.cache_.invalidate(this.cache_.generateRequestId(), entries);
|
| -};
|
|
|