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 |