diff options
author | hirono <hirono@chromium.org> | 2015-01-06 17:16:50 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-07 01:17:37 +0000 |
commit | 699c53ebb13827f09e6cb5d4564f69da03d58692 (patch) | |
tree | 54aebd5ff92e4f6aad353817d4e9a5dcaa3bd223 /ui | |
parent | 75ef78d7e4d3afa6702344a69f6e64ab9defb518 (diff) | |
download | chromium_src-699c53ebb13827f09e6cb5d4564f69da03d58692.zip chromium_src-699c53ebb13827f09e6cb5d4564f69da03d58692.tar.gz chromium_src-699c53ebb13827f09e6cb5d4564f69da03d58692.tar.bz2 |
Gallery: Obtain metadata from MetadataCache when saving items.
Previously, when saving items, the new metadata was generated by
GalleryDataModel. But the generated metadata was broken and it contained old
thumbnail data that causes memory shortage.
The metadata for new items can be otained by using normal code path
(MetadataCache), so the CL removes special geneartion of metadata for new items
and let Gallery obtain the metadata by using MeatadataCache.
BUG=439898
TEST=GalleryJsTest.GalleryItemTest
Review URL: https://codereview.chromium.org/802283005
Cr-Commit-Position: refs/heads/master@{#310205}
Diffstat (limited to 'ui')
-rw-r--r-- | ui/file_manager/gallery/js/gallery.js | 24 | ||||
-rw-r--r-- | ui/file_manager/gallery/js/gallery_item.js | 59 | ||||
-rw-r--r-- | ui/file_manager/gallery/js/gallery_item_unittest.html | 23 | ||||
-rw-r--r-- | ui/file_manager/gallery/js/gallery_item_unittest.js | 79 |
4 files changed, 136 insertions, 49 deletions
diff --git a/ui/file_manager/gallery/js/gallery.js b/ui/file_manager/gallery/js/gallery.js index a575e86..b0a12ceb 100644 --- a/ui/file_manager/gallery/js/gallery.js +++ b/ui/file_manager/gallery/js/gallery.js @@ -71,47 +71,27 @@ GalleryDataModel.prototype.saveItem = function( var oldEntry = item.getEntry(); var oldMetadata = item.getMetadata(); var oldLocationInfo = item.getLocationInfo(); - var metadataEncoder = ImageEncoder.encodeMetadata( - item.getMetadata(), canvas, 1 /* quality */); - var newMetadata = ContentProvider.ConvertContentMetadata( - metadataEncoder.getMetadata(), - MetadataCache.cloneMetadata(item.getMetadata())); - if (newMetadata.filesystem) - newMetadata.filesystem.modificationTime = new Date(); - if (newMetadata.external) - newMetadata.external.present = true; - return new Promise(function(fulfill, reject) { item.saveToFile( volumeManager, this.fallbackSaveDirectory, overwrite, canvas, - metadataEncoder, function(success) { if (!success) { reject('Failed to save the image.'); return; } - // The item's entry is updated to the latest entry. Update metadata. - item.setMetadata(newMetadata); - // Current entry is updated. // Dispatch an event. var event = new Event('content'); event.item = item; event.oldEntry = oldEntry; - event.metadata = newMetadata; + event.metadata = item.getMetadata(); this.dispatchEvent(event); - if (util.isSameEntry(oldEntry, item.getEntry())) { - // Need an update of metdataCache. - this.metadataCache_.set( - item.getEntry(), - Gallery.METADATA_TYPE, - newMetadata); - } else { + if (!util.isSameEntry(oldEntry, item.getEntry())) { // New entry is added and the item now tracks it. // Add another item for the old entry. var anotherItem = new Gallery.Item( diff --git a/ui/file_manager/gallery/js/gallery_item.js b/ui/file_manager/gallery/js/gallery_item.js index 7244bf5..227940a 100644 --- a/ui/file_manager/gallery/js/gallery_item.js +++ b/ui/file_manager/gallery/js/gallery_item.js @@ -112,14 +112,6 @@ Gallery.Item.prototype.getFetchedMedia = function() { }; /** - * Sets the metadata. - * @param {!Object} metadata New metadata. - */ -Gallery.Item.prototype.setMetadata = function(metadata) { - this.metadata_ = Object.preventExtensions(metadata); -}; - -/** * @return {string} File name. */ Gallery.Item.prototype.getFileName = function() { @@ -231,30 +223,45 @@ Gallery.Item.prototype.createCopyName_ = function(dirEntry, callback) { * Writes the new item content to either the existing or a new file. * * @param {!VolumeManager} volumeManager Volume manager instance. - * @param {string} fallbackDir Fallback directory in case the current directory - * is read only. + * @param {DirectoryEntry} fallbackDir Fallback directory in case the current + * directory is read only. * @param {boolean} overwrite Whether to overwrite the image to the item or not. * @param {!HTMLCanvasElement} canvas Source canvas. - * @param {!ImageEncoder.MetadataEncoder} metadataEncoder MetadataEncoder. * @param {function(boolean)=} opt_callback Callback accepting true for success. */ Gallery.Item.prototype.saveToFile = function( - volumeManager, fallbackDir, overwrite, canvas, metadataEncoder, - opt_callback) { + volumeManager, fallbackDir, overwrite, canvas, opt_callback) { ImageUtil.metrics.startInterval(ImageUtil.getMetricName('SaveTime')); var name = this.getFileName(); - var onSuccess = function(entry, locationInfo) { + var onSuccess = function(entry) { + var locationInfo = volumeManager.getLocationInfo(entry); + if (!locationInfo) { + // Reuse old location info if it fails to obtain location info. + locationInfo = this.locationInfo_; + } ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 1, 2); ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('SaveTime')); this.entry_ = entry; this.locationInfo_ = locationInfo; - this.metadataCache_.clear([this.entry_], 'fetchedMedia'); - if (opt_callback) - opt_callback(true); + // Updates the metadata. + this.metadataCache_.clear([this.entry_], '*'); + this.metadataCache_.getLatest( + [this.entry_], + Gallery.METADATA_TYPE, + function(metadataList) { + if (metadataList.length === 1) { + this.metadata_ = metadataList[0]; + if (opt_callback) + opt_callback(true); + } else { + if (opt_callback) + opt_callback(false); + } + }.bind(this)); }.bind(this); var onError = function(error) { @@ -266,15 +273,19 @@ Gallery.Item.prototype.saveToFile = function( var doSave = function(newFile, fileEntry) { fileEntry.createWriter(function(fileWriter) { - function writeContent() { + var writeContent = function() { fileWriter.onwriteend = onSuccess.bind(null, fileEntry); + // TODO(hirono): Remove the quality 1 for thumbanils. The code path is + // no longer used. + var metadataEncoder = ImageEncoder.encodeMetadata( + this.metadata_, canvas, 1 /* quality */); // Contrary to what one might think 1.0 is not a good default. Opening // and saving an typical photo taken with consumer camera increases its // file size by 50-100%. Experiments show that 0.9 is much better. It // shrinks some photos a bit, keeps others about the same size, but does // not visibly lower the quality. fileWriter.write(ImageEncoder.getBlob(canvas, metadataEncoder, 0.9)); - } + }.bind(this); fileWriter.onerror = function(error) { onError(error); // Disable all callbacks on the first error. @@ -287,18 +298,12 @@ Gallery.Item.prototype.saveToFile = function( fileWriter.onwriteend = writeContent; fileWriter.truncate(0); } - }, onError); - }; + }.bind(this), onError); + }.bind(this); var getFile = function(dir, newFile) { dir.getFile(name, {create: newFile, exclusive: newFile}, function(fileEntry) { - var locationInfo = volumeManager.getLocationInfo(fileEntry); - // If the volume is gone, then abort the saving operation. - if (!locationInfo) { - onError('NotFound'); - return; - } doSave(newFile, fileEntry); }.bind(this), onError); }.bind(this); diff --git a/ui/file_manager/gallery/js/gallery_item_unittest.html b/ui/file_manager/gallery/js/gallery_item_unittest.html new file mode 100644 index 0000000..70ef7d0 --- /dev/null +++ b/ui/file_manager/gallery/js/gallery_item_unittest.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<!-- 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. + --> +<script> +// Define mock Gallery class to define Gallery.Item class. +var Gallery = function() {}; +</script> +<!-- Should be loaded before volume_manager.js --> +<script src="../../file_manager/common/js/volume_manager_common.js"></script> +<!-- Others --> +<script src="../../../webui/resources/js/assert.js"></script> +<script src="../../../webui/resources/js/cr.js"></script> +<script src="../../../webui/resources/js/cr/event_target.js"></script> +<script src="../../../webui/resources/js/cr/ui/array_data_model.js"></script> +<script src="../../../webui/resources/js/load_time_data.js"></script> +<script src="../../file_manager/common/js/mock_entry.js"></script> +<script src="../../file_manager/common/js/unittest_util.js"></script> +<script src="../../file_manager/common/js/util.js"></script> +<script src="gallery_item.js"></script> + +<script src="gallery_item_unittest.js"></script> diff --git a/ui/file_manager/gallery/js/gallery_item_unittest.js b/ui/file_manager/gallery/js/gallery_item_unittest.js new file mode 100644 index 0000000..e3c545b --- /dev/null +++ b/ui/file_manager/gallery/js/gallery_item_unittest.js @@ -0,0 +1,79 @@ +// 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. + +/** + * Mock of ImageUtil. + */ +var ImageUtil = { + getMetricName: function() {}, + metrics: { + recordEnum: function() {}, + recordInterval: function() {}, + startInterval: function() {} + } +}; + +/** + * Mock of ImageEncoder + */ +var ImageEncoder = { + encodeMetadata: function() {}, + getBlob: function() {} +}; + +/** + * Load time data. + */ +loadTimeData.data = { + DRIVE_DIRECTORY_LABEL: '', + DOWNLOADS_DIRECTORY_LABEL: '' +}; + +/** + * Tests for GalleryItem#saveToFile. + */ +function testSaveToFile(callback) { + var fileSystem = new MockFileSystem('volumeId'); + fileSystem.populate(['/test.jpg']); + var entry = fileSystem.entries['/test.jpg']; + entry.createWriter = function(callback) { + callback({ + write: function() { + Promise.resolve().then(function() { + this.onwriteend(); + }.bind(this)); + }, + truncate: function() { + this.write(); + } + }); + }; + var fetchedMediaCleared = false; + var metadataCache = { + getLatest: function(entries, type, callback) { + callback([{name: 'newMetadata'}]); + }, + clear: function(entries, type) { + fetchedMediaCleared = true; + } + }; + var item = new Gallery.Item( + entry, + {isReadOnly: false}, + {name: 'oldMetadata'}, + metadataCache, + /* original */ true); + assertEquals('oldMetadata', item.getMetadata().name); + assertFalse(fetchedMediaCleared); + reportPromise( + new Promise(item.saveToFile.bind( + item, + {getLocationInfo: function() { return {}; }}, + null, + true, + document.createElement('canvas'))).then(function() { + assertEquals('newMetadata', item.getMetadata().name); + assertTrue(fetchedMediaCleared); + }), callback); +} |