Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Object representing an image item (a photo). | 6 * Object representing an image item (a photo). |
| 7 * | 7 * |
| 8 * @param {!FileEntry} entry Image entry. | 8 * @param {!FileEntry} entry Image entry. |
| 9 * @param {!EntryLocation} locationInfo Entry location information. | 9 * @param {!EntryLocation} locationInfo Entry location information. |
| 10 * @param {!Object} metadata Metadata for the entry. | 10 * @param {!Object} metadata Metadata for the entry. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 function(metadata) { | 105 function(metadata) { |
| 106 if (metadata[0]) | 106 if (metadata[0]) |
| 107 fulfill(metadata[0]); | 107 fulfill(metadata[0]); |
| 108 else | 108 else |
| 109 reject('Failed to load metadata.'); | 109 reject('Failed to load metadata.'); |
| 110 }); | 110 }); |
| 111 }.bind(this)); | 111 }.bind(this)); |
| 112 }; | 112 }; |
| 113 | 113 |
| 114 /** | 114 /** |
| 115 * Sets the metadata. | |
| 116 * @param {!Object} metadata New metadata. | |
| 117 */ | |
| 118 Gallery.Item.prototype.setMetadata = function(metadata) { | |
| 119 this.metadata_ = Object.preventExtensions(metadata); | |
| 120 }; | |
| 121 | |
| 122 /** | |
| 123 * @return {string} File name. | 115 * @return {string} File name. |
| 124 */ | 116 */ |
| 125 Gallery.Item.prototype.getFileName = function() { | 117 Gallery.Item.prototype.getFileName = function() { |
| 126 return this.entry_.name; | 118 return this.entry_.name; |
| 127 }; | 119 }; |
| 128 | 120 |
| 129 /** | 121 /** |
| 130 * @return {boolean} True if this image has not been created in this session. | 122 * @return {boolean} True if this image has not been created in this session. |
| 131 */ | 123 */ |
| 132 Gallery.Item.prototype.isOriginal = function() { return this.original_; }; | 124 Gallery.Item.prototype.isOriginal = function() { return this.original_; }; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 callback.bind(null, name + ext)); | 216 callback.bind(null, name + ext)); |
| 225 } | 217 } |
| 226 | 218 |
| 227 tryNext(10); | 219 tryNext(10); |
| 228 }; | 220 }; |
| 229 | 221 |
| 230 /** | 222 /** |
| 231 * Writes the new item content to either the existing or a new file. | 223 * Writes the new item content to either the existing or a new file. |
| 232 * | 224 * |
| 233 * @param {!VolumeManager} volumeManager Volume manager instance. | 225 * @param {!VolumeManager} volumeManager Volume manager instance. |
| 234 * @param {string} fallbackDir Fallback directory in case the current directory | 226 * @param {DirectoryEntry} fallbackDir Fallback directory in case the current |
| 235 * is read only. | 227 * directory is read only. |
| 236 * @param {boolean} overwrite Whether to overwrite the image to the item or not. | 228 * @param {boolean} overwrite Whether to overwrite the image to the item or not. |
| 237 * @param {!HTMLCanvasElement} canvas Source canvas. | 229 * @param {!HTMLCanvasElement} canvas Source canvas. |
| 238 * @param {!ImageEncoder.MetadataEncoder} metadataEncoder MetadataEncoder. | |
| 239 * @param {function(boolean)=} opt_callback Callback accepting true for success. | 230 * @param {function(boolean)=} opt_callback Callback accepting true for success. |
| 240 */ | 231 */ |
| 241 Gallery.Item.prototype.saveToFile = function( | 232 Gallery.Item.prototype.saveToFile = function( |
| 242 volumeManager, fallbackDir, overwrite, canvas, metadataEncoder, | 233 volumeManager, fallbackDir, overwrite, canvas, opt_callback) { |
| 243 opt_callback) { | |
| 244 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('SaveTime')); | 234 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('SaveTime')); |
| 245 | 235 |
| 246 var name = this.getFileName(); | 236 var name = this.getFileName(); |
| 247 | 237 |
| 248 var onSuccess = function(entry, locationInfo) { | 238 var onSuccess = function(entry) { |
| 239 var locationInfo = volumeManager.getLocationInfo(entry); | |
| 240 if (!locationInfo) { | |
| 241 // Reuse old location info if it fails to obtain location info. | |
| 242 locationInfo = this.locationInfo_; | |
| 243 } | |
| 249 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 1, 2); | 244 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 1, 2); |
| 250 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('SaveTime')); | 245 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('SaveTime')); |
| 251 | 246 |
| 252 this.entry_ = entry; | 247 this.entry_ = entry; |
| 253 this.locationInfo_ = locationInfo; | 248 this.locationInfo_ = locationInfo; |
| 254 | 249 |
| 250 // Updates the metadata. | |
| 255 this.metadataCache_.clear([this.entry_], 'fetchedMedia'); | 251 this.metadataCache_.clear([this.entry_], 'fetchedMedia'); |
|
yawano
2015/01/06 08:40:02
Since the file is changed by this operation, other
hirono
2015/01/06 10:33:57
Done.
| |
| 256 if (opt_callback) | 252 this.metadataCache_.getLatest( |
| 257 opt_callback(true); | 253 [this.entry_], |
| 254 Gallery.METADATA_TYPE, | |
| 255 function(metadataList) { | |
| 256 if (metadataList.length === 1) { | |
| 257 this.metadata_ = metadataList[0]; | |
| 258 if (this.metadata_.filesystem) | |
|
yawano
2015/01/06 08:40:02
Just for confirmation, event after the file write
hirono
2015/01/06 10:33:57
It looks the values are property updated. Removed
| |
| 259 this.metadata_.filesystem.modificationTime = new Date(); | |
| 260 if (this.metadata_.external) | |
| 261 this.metadata_.external.present = true; | |
| 262 if (opt_callback) | |
| 263 opt_callback(true); | |
| 264 } else { | |
| 265 if (opt_callback) | |
| 266 opt_callback(false); | |
| 267 } | |
| 268 }.bind(this)); | |
| 258 }.bind(this); | 269 }.bind(this); |
| 259 | 270 |
| 260 var onError = function(error) { | 271 var onError = function(error) { |
| 261 console.error('Error saving from gallery', name, error); | 272 console.error('Error saving from gallery', name, error); |
| 262 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 0, 2); | 273 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 0, 2); |
| 263 if (opt_callback) | 274 if (opt_callback) |
| 264 opt_callback(false); | 275 opt_callback(false); |
| 265 }; | 276 }; |
| 266 | 277 |
| 267 var doSave = function(newFile, fileEntry) { | 278 var doSave = function(newFile, fileEntry) { |
| 268 fileEntry.createWriter(function(fileWriter) { | 279 fileEntry.createWriter(function(fileWriter) { |
| 269 function writeContent() { | 280 var writeContent = function() { |
| 270 fileWriter.onwriteend = onSuccess.bind(null, fileEntry); | 281 fileWriter.onwriteend = onSuccess.bind(null, fileEntry); |
| 282 // TODO(hirono): Remove the quality 1 for thumbanils. The code path is | |
| 283 // no longer used. | |
| 284 var metadataEncoder = ImageEncoder.encodeMetadata( | |
| 285 this.metadata_, canvas, 1 /* quality */); | |
| 271 // Contrary to what one might think 1.0 is not a good default. Opening | 286 // Contrary to what one might think 1.0 is not a good default. Opening |
| 272 // and saving an typical photo taken with consumer camera increases its | 287 // and saving an typical photo taken with consumer camera increases its |
| 273 // file size by 50-100%. Experiments show that 0.9 is much better. It | 288 // file size by 50-100%. Experiments show that 0.9 is much better. It |
| 274 // shrinks some photos a bit, keeps others about the same size, but does | 289 // shrinks some photos a bit, keeps others about the same size, but does |
| 275 // not visibly lower the quality. | 290 // not visibly lower the quality. |
| 276 fileWriter.write(ImageEncoder.getBlob(canvas, metadataEncoder, 0.9)); | 291 fileWriter.write(ImageEncoder.getBlob(canvas, metadataEncoder, 0.9)); |
| 277 } | 292 }.bind(this); |
| 278 fileWriter.onerror = function(error) { | 293 fileWriter.onerror = function(error) { |
| 279 onError(error); | 294 onError(error); |
| 280 // Disable all callbacks on the first error. | 295 // Disable all callbacks on the first error. |
| 281 fileWriter.onerror = null; | 296 fileWriter.onerror = null; |
| 282 fileWriter.onwriteend = null; | 297 fileWriter.onwriteend = null; |
| 283 }; | 298 }; |
| 284 if (newFile) { | 299 if (newFile) { |
| 285 writeContent(); | 300 writeContent(); |
| 286 } else { | 301 } else { |
| 287 fileWriter.onwriteend = writeContent; | 302 fileWriter.onwriteend = writeContent; |
| 288 fileWriter.truncate(0); | 303 fileWriter.truncate(0); |
| 289 } | 304 } |
| 290 }, onError); | 305 }.bind(this), onError); |
| 291 }; | 306 }.bind(this); |
| 292 | 307 |
| 293 var getFile = function(dir, newFile) { | 308 var getFile = function(dir, newFile) { |
| 294 dir.getFile(name, {create: newFile, exclusive: newFile}, | 309 dir.getFile(name, {create: newFile, exclusive: newFile}, |
| 295 function(fileEntry) { | 310 function(fileEntry) { |
| 296 var locationInfo = volumeManager.getLocationInfo(fileEntry); | |
| 297 // If the volume is gone, then abort the saving operation. | |
| 298 if (!locationInfo) { | |
| 299 onError('NotFound'); | |
| 300 return; | |
| 301 } | |
| 302 doSave(newFile, fileEntry); | 311 doSave(newFile, fileEntry); |
| 303 }.bind(this), onError); | 312 }.bind(this), onError); |
| 304 }.bind(this); | 313 }.bind(this); |
| 305 | 314 |
| 306 var checkExistence = function(dir) { | 315 var checkExistence = function(dir) { |
| 307 dir.getFile(name, {create: false, exclusive: false}, | 316 dir.getFile(name, {create: false, exclusive: false}, |
| 308 getFile.bind(null, dir, false /* existing file */), | 317 getFile.bind(null, dir, false /* existing file */), |
| 309 getFile.bind(null, dir, true /* create new file */)); | 318 getFile.bind(null, dir, true /* create new file */)); |
| 310 }; | 319 }; |
| 311 | 320 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 return Promise.reject(str('GALLERY_FILE_EXISTS')); | 366 return Promise.reject(str('GALLERY_FILE_EXISTS')); |
| 358 }, function() { | 367 }, function() { |
| 359 return new Promise( | 368 return new Promise( |
| 360 this.entry_.moveTo.bind(this.entry_, parentDirectory, newFileName)); | 369 this.entry_.moveTo.bind(this.entry_, parentDirectory, newFileName)); |
| 361 }.bind(this)); | 370 }.bind(this)); |
| 362 }.bind(this)); | 371 }.bind(this)); |
| 363 }.bind(this)).then(function(entry) { | 372 }.bind(this)).then(function(entry) { |
| 364 this.entry_ = entry; | 373 this.entry_ = entry; |
| 365 }.bind(this)); | 374 }.bind(this)); |
| 366 }; | 375 }; |
| OLD | NEW |