Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(506)

Side by Side Diff: chrome/browser/resources/file_manager/js/image_editor/gallery.js

Issue 8819013: Add UMA metrics to Photo Editor (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Better trace Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 * Base class that Ribbon uses to display photos. 6 * Base class that Ribbon uses to display photos.
7 */ 7 */
8 8
9 function RibbonClient() {} 9 function RibbonClient() {}
10 10
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 function initRibbon() { 218 function initRibbon() {
219 self.ribbon_.load(urls, selectedIndex); 219 self.ribbon_.load(urls, selectedIndex);
220 // Flash the ribbon briefly to let the user know it is there. 220 // Flash the ribbon briefly to let the user know it is there.
221 self.cancelFading_(); 221 self.cancelFading_();
222 self.initiateFading_(Gallery.FIRST_FADE_TIMEOUT); 222 self.initiateFading_(Gallery.FIRST_FADE_TIMEOUT);
223 } 223 }
224 224
225 var selectedURL = urls[selectedIndex]; 225 var selectedURL = urls[selectedIndex];
226 // Initialize the ribbon only after the selected image is fully loaded. 226 // Initialize the ribbon only after the selected image is fully loaded.
227 this.metadataProvider_.fetch(selectedURL, function (metadata) { 227 this.metadataProvider_.fetch(selectedURL, function (metadata) {
228 // The first change is load, we should not count it. 228 self.openImage(selectedIndex, selectedURL, metadata, 0, initRibbon);
229 self.imageChanges_ = -1;
230 self.filenameEdit_.value = ImageUtil.getFileNameFromUrl(selectedURL);
231 self.editor_.openSession(
232 selectedIndex, selectedURL, metadata, 0, initRibbon);
233 }); 229 });
234 }; 230 };
235 231
236 Gallery.prototype.onImageContentChanged_ = function() { 232 Gallery.prototype.onImageContentChanged_ = function() {
237 this.imageChanges_++; 233 this.imageChanges_++;
238 if (this.imageChanges_ == 1) 234 if (this.imageChanges_ == 1) { // First edit
239 this.ribbon_.getSelectedItem().setCopyName(); 235 this.ribbon_.getSelectedItem().setCopyName();
236 ImageUtil.metrics.recordUserAction(ImageUtil.getMetricName('Edit'));
237 }
240 this.updateFilename_(); 238 this.updateFilename_();
241 }; 239 };
242 240
243 Gallery.prototype.saveItem_ = function(item, callback, canvas, modified) { 241 Gallery.prototype.saveItem_ = function(item, callback, canvas, modified) {
244 if (modified) { 242 if (modified) {
245 item.save( 243 item.save(
246 this.parentDirEntry_, this.metadataProvider_, canvas, callback); 244 this.parentDirEntry_, this.metadataProvider_, canvas, callback);
247 } else { 245 } else {
248 if (callback) callback(); 246 if (callback) callback();
249 } 247 }
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 335
338 Gallery.prototype.onClose_ = function() { 336 Gallery.prototype.onClose_ = function() {
339 // TODO: handle write errors gracefully (suggest retry or saving elsewhere). 337 // TODO: handle write errors gracefully (suggest retry or saving elsewhere).
340 this.saveChanges_(this.closeCallback_); 338 this.saveChanges_(this.closeCallback_);
341 }; 339 };
342 340
343 Gallery.prototype.prefetchImage = function(id, content, metadata) { 341 Gallery.prototype.prefetchImage = function(id, content, metadata) {
344 this.editor_.prefetchImage(id, content, metadata); 342 this.editor_.prefetchImage(id, content, metadata);
345 }; 343 };
346 344
345 // Used for metrics reporting, keep in sync with the histogram description.
346 Gallery.FILE_TYPES = ['jpg', 'png', 'gif', 'bmp', 'webp'];
dgozman 2011/12/06 15:45:56 Move to ImageUtil near metric names?
Vladislav Kaznacheev 2011/12/06 16:07:44 Done.
347
347 Gallery.prototype.openImage = function(id, content, metadata, slide, callback) { 348 Gallery.prototype.openImage = function(id, content, metadata, slide, callback) {
348 // The first change is load, we should not count it. 349 // The first change is load, we should not count it.
349 this.imageChanges_ = -1; 350 this.imageChanges_ = -1;
350 this.updateFilename_(); 351
351 this.editor_.openSession(id, content, metadata, slide, callback); 352 var item = this.ribbon_.getSelectedItem();
353 if (item) {
354 this.updateFilename_();
355 } else {
356 this.filenameEdit_.value = ImageUtil.getFileNameFromUrl(content);
357 }
358
359 var self = this;
360 function loadDone() {
361 ImageUtil.metrics.recordUserAction(ImageUtil.getMetricName('View'));
362
363 function toMillions(number) { return Math.round(number / (1000 * 1000)) }
364
365 ImageUtil.metrics.recordSmallCount(ImageUtil.getMetricName('Size.MB'),
366 toMillions(metadata.fileSize));
367
368 var canvas = self.imageView_.getCanvas();
369 ImageUtil.metrics.recordSmallCount(ImageUtil.getMetricName('Size.MPix'),
370 toMillions(canvas.width * canvas.height));
371
372 var url = item ? item.getUrl() : content;
373 var extIndex = url.lastIndexOf('.');
374 var ext = extIndex < 0 ? '' : url.substr(extIndex + 1).toLowerCase();
375 if (ext == 'jpeg') ext = 'jpg';
376 ImageUtil.metrics.recordEnum(
377 ImageUtil.getMetricName('FileType'), ext, Gallery.FILE_TYPES);
378
379 callback(arguments);
380 }
381
382 this.editor_.openSession(id, content, metadata, slide, loadDone);
352 }; 383 };
353 384
354 Gallery.prototype.closeImage = function(item) { 385 Gallery.prototype.closeImage = function(item) {
355 this.editor_.closeSession(this.saveItem_.bind(this, item, null)); 386 this.editor_.closeSession(this.saveItem_.bind(this, item, null));
356 }; 387 };
357 388
358 Gallery.prototype.isEditing_ = function() { 389 Gallery.prototype.isEditing_ = function() {
359 return this.container_.hasAttribute('editing'); 390 return this.container_.hasAttribute('editing');
360 }; 391 };
361 392
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 616
586 var selectedItem = this.getSelectedItem(); 617 var selectedItem = this.getSelectedItem();
587 selectedItem.select(true); 618 selectedItem.select(true);
588 this.redraw(); 619 this.redraw();
589 620
590 var self = this; 621 var self = this;
591 selectedItem.fetchMetadata(this.metadataProvider_, function(metadata){ 622 selectedItem.fetchMetadata(this.metadataProvider_, function(metadata){
592 if (!selectedItem.isSelected()) return; 623 if (!selectedItem.isSelected()) return;
593 self.client_.openImage( 624 self.client_.openImage(
594 selectedItem.getIndex(), selectedItem.getContent(), metadata, step, 625 selectedItem.getIndex(), selectedItem.getContent(), metadata, step,
595 function(loadedInstantly) { 626 function(loadType) {
596 if (!selectedItem.isSelected()) return; 627 if (!selectedItem.isSelected()) return;
597 if (Math.abs(step) != 1) return; 628 if (Math.abs(step) != 1) return;
598 if (loadedInstantly || (self.sequenceLength_ >= 3)) { 629 if ((loadType == ImageView.LOAD_TYPE_CACHED_FULL) ||
630 (self.sequenceLength_ >= 3)) {
599 // We can always afford to prefetch if the previous load was 631 // We can always afford to prefetch if the previous load was
600 // instant. Even if it was not we should start prefetching 632 // instant. Even if it was not we should start prefetching
601 // if we have been going in the same direction for long enough. 633 // if we have been going in the same direction for long enough.
602 self.requestPrefetch(step); 634 self.requestPrefetch(step);
603 } 635 }
604 if (opt_callback) opt_callback(); 636 if (opt_callback) opt_callback();
605 }); 637 });
606 }); 638 });
607 }; 639 };
608 640
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 if (this.canvas_) 823 if (this.canvas_)
792 return; // The image is being saved, the thumbnail is already up-to-date. 824 return; // The image is being saved, the thumbnail is already up-to-date.
793 825
794 var metadataEncoder = 826 var metadataEncoder =
795 ImageEncoder.encodeMetadata(this.getMetadata(), canvas, 1); 827 ImageEncoder.encodeMetadata(this.getMetadata(), canvas, 1);
796 this.setMetadata(metadataEncoder.getMetadata()); 828 this.setMetadata(metadataEncoder.getMetadata());
797 }; 829 };
798 830
799 Ribbon.Item.prototype.save = function( 831 Ribbon.Item.prototype.save = function(
800 dirEntry, metadataProvider, canvas, opt_callback) { 832 dirEntry, metadataProvider, canvas, opt_callback) {
833
834 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('SaveTime'));
dgozman 2011/12/06 15:45:56 Is it ok to not call recordInterval in the case of
Vladislav Kaznacheev 2011/12/06 16:07:44 Absolutely. The interval start time will stay in t
835
801 var metadataEncoder = 836 var metadataEncoder =
802 ImageEncoder.encodeMetadata(this.getMetadata(), canvas, 1); 837 ImageEncoder.encodeMetadata(this.getMetadata(), canvas, 1);
803 838
804 this.overrideContent(canvas, metadataEncoder.getMetadata()); 839 this.overrideContent(canvas, metadataEncoder.getMetadata());
805 840
806 var self = this; 841 var self = this;
807 842
808 if (!dirEntry) { // Happens only in gallery_demo.js 843 if (!dirEntry) { // Happens only in gallery_demo.js
809 self.onSaveSuccess( 844 self.onSaveSuccess(
810 window.webkitURL.createObjectURL( 845 window.webkitURL.createObjectURL(
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 Ribbon.Item.prototype.getContent = function () { 952 Ribbon.Item.prototype.getContent = function () {
918 return this.canvas_ || this.url_; 953 return this.canvas_ || this.url_;
919 }; 954 };
920 955
921 Ribbon.Item.prototype.getMetadata = function () { 956 Ribbon.Item.prototype.getMetadata = function () {
922 return this.metadata_; 957 return this.metadata_;
923 }; 958 };
924 959
925 Ribbon.Item.prototype.fetchMetadata = function (metadataProvider, callback) { 960 Ribbon.Item.prototype.fetchMetadata = function (metadataProvider, callback) {
926 if (this.metadata_) { 961 if (this.metadata_) {
927 setTimeout(callback.bind(null, this.metadata_), 0); 962 callback(this.metadata_); // Every millisecond counts, call directly
928 } else { 963 } else {
929 metadataProvider.fetch(this.getUrl(), callback); 964 metadataProvider.fetch(this.getUrl(), callback);
930 } 965 }
931 }; 966 };
932 967
933 Ribbon.Item.prototype.onSaveSuccess = function(url) { 968 Ribbon.Item.prototype.onSaveSuccess = function(url) {
934 this.url_ = url; 969 this.url_ = url;
935 delete this.backupMetadata_; 970 delete this.backupMetadata_;
936 delete this.canvas_; 971 delete this.canvas_;
972 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('Save'), 1, 2);
973 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('SaveTime'));
937 }; 974 };
938 975
939 Ribbon.Item.prototype.onSaveError = function(error) { 976 Ribbon.Item.prototype.onSaveError = function(error) {
940 // TODO(kaznacheev): notify the user that the file write failed and 977 // TODO(kaznacheev): notify the user that the file write failed and
941 // suggest ways to rescue the modified image (retry/save elsewhere). 978 // suggest ways to rescue the modified image (retry/save elsewhere).
942 // For now - just drop the modified content and revert the thumbnail. 979 // For now - just drop the modified content and revert the thumbnail.
943 this.setMetadata(this.backupMetadata_); 980 this.setMetadata(this.backupMetadata_);
944 delete this.backupMetadata_; 981 delete this.backupMetadata_;
945 delete this.canvas_; 982 delete this.canvas_;
983 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('Save'), 0, 2);
946 }; 984 };
947 985
948 Ribbon.MAX_THUMBNAIL_PIXEL_COUNT = 1 << 21; // 2 MPix 986 Ribbon.MAX_THUMBNAIL_PIXEL_COUNT = 1 << 21; // 2 MPix
949 Ribbon.MAX_THUMBNAIL_FILE_SIZE = 1 << 20; // 1 Mb 987 Ribbon.MAX_THUMBNAIL_FILE_SIZE = 1 << 20; // 1 Mb
950 988
951 Ribbon.Item.canUseImageForThumbnail = function(metadata) { 989 Ribbon.Item.canUseImageForThumbnail = function(metadata) {
952 return (metadata.fileSize && 990 return (metadata.fileSize &&
953 metadata.fileSize <= Ribbon.MAX_THUMBNAIL_FILE_SIZE) || 991 metadata.fileSize <= Ribbon.MAX_THUMBNAIL_FILE_SIZE) ||
954 (metadata.width && metadata.height && 992 (metadata.width && metadata.height &&
955 (metadata.width * metadata.height <= Ribbon.MAX_THUMBNAIL_PIXEL_COUNT)); 993 (metadata.width * metadata.height <= Ribbon.MAX_THUMBNAIL_PIXEL_COUNT));
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 ShareMode.prototype.setUp = function() { 1099 ShareMode.prototype.setUp = function() {
1062 ImageEditor.Mode.prototype.setUp.apply(this, arguments); 1100 ImageEditor.Mode.prototype.setUp.apply(this, arguments);
1063 ImageUtil.setAttribute(this.menu_, 'hidden', false); 1101 ImageUtil.setAttribute(this.menu_, 'hidden', false);
1064 ImageUtil.setAttribute(this.button_, 'pressed', false); 1102 ImageUtil.setAttribute(this.button_, 'pressed', false);
1065 }; 1103 };
1066 1104
1067 ShareMode.prototype.cleanUpUI = function() { 1105 ShareMode.prototype.cleanUpUI = function() {
1068 ImageEditor.Mode.prototype.cleanUpUI.apply(this, arguments); 1106 ImageEditor.Mode.prototype.cleanUpUI.apply(this, arguments);
1069 ImageUtil.setAttribute(this.menu_, 'hidden', true); 1107 ImageUtil.setAttribute(this.menu_, 'hidden', true);
1070 }; 1108 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698