Commit fe2d480f authored by Kuo Jen Wei's avatar Kuo Jen Wei Committed by Commit Bot

[CCA] Add intentResult dimension to GA capture event.

Bug: 1014829
Test: Verify capture event metrics is collected correctly under both
intent/non-intent mode.

Change-Id: I84833c4b6b58ddfe848434dcfdee0d26051b8e4b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1863060
Commit-Queue: Kuo Jen Wei <inker@chromium.org>
Auto-Submit: Kuo Jen Wei <inker@chromium.org>
Reviewed-by: default avatarShik Chen <shik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706894}
parent a744331c
...@@ -89,15 +89,27 @@ cca.metrics.launchType_ = function(ackMigrate) { ...@@ -89,15 +89,27 @@ cca.metrics.launchType_ = function(ackMigrate) {
.label(ackMigrate ? 'ack-migrate' : ''); .label(ackMigrate ? 'ack-migrate' : '');
}; };
/**
* Types of intent result dimension.
* @enum {string}
*/
cca.metrics.IntentResultType = {
NOT_INTENT: '',
CANCELED: 'canceled',
CONFIRMED: 'confirmed',
};
/** /**
* Returns event builder for the metrics type: capture. * Returns event builder for the metrics type: capture.
* @param {?string} facingMode Camera facing-mode of the capture. * @param {?string} facingMode Camera facing-mode of the capture.
* @param {number} length Length of 1 minute buckets for captured video. * @param {number} length Length of 1 minute buckets for captured video.
* @param {!{width: number, height: number}} resolution Capture resolution. * @param {!{width: number, height: number}} resolution Capture resolution.
* @param {!cca.metrics.IntentResultType} intentResult
* @return {!analytics.EventBuilder} * @return {!analytics.EventBuilder}
* @private * @private
*/ */
cca.metrics.captureType_ = function(facingMode, length, {width, height}) { cca.metrics.captureType_ = function(
facingMode, length, {width, height}, intentResult) {
var condState = (states, cond = undefined, strict = undefined) => { var condState = (states, cond = undefined, strict = undefined) => {
// Return the first existing state among the given states only if there is // Return the first existing state among the given states only if there is
// no gate condition or the condition is met. // no gate condition or the condition is met.
...@@ -122,6 +134,7 @@ cca.metrics.captureType_ = function(facingMode, length, {width, height}) { ...@@ -122,6 +134,7 @@ cca.metrics.captureType_ = function(facingMode, length, {width, height}) {
.dimen(9, condState(['tall'])) .dimen(9, condState(['tall']))
.dimen(10, `${width}x${height}`) .dimen(10, `${width}x${height}`)
.dimen(11, condState(['_30fps', '_60fps'], 'video-mode', true)) .dimen(11, condState(['_30fps', '_60fps'], 'video-mode', true))
.dimen(12, intentResult)
.value(length || 0); .value(length || 0);
}; };
......
...@@ -29,10 +29,10 @@ cca.views.CameraSuspendedError = class extends Error { ...@@ -29,10 +29,10 @@ cca.views.CameraSuspendedError = class extends Error {
/** /**
* Creates the camera-view controller. * Creates the camera-view controller.
* @param {cca.models.ResultSaver} resultSaver * @param {!cca.models.ResultSaver} resultSaver
* @param {cca.device.DeviceInfoUpdater} infoUpdater * @param {!cca.device.DeviceInfoUpdater} infoUpdater
* @param {cca.device.PhotoResolPreferrer} photoPreferrer * @param {!cca.device.PhotoResolPreferrer} photoPreferrer
* @param {cca.device.VideoConstraintsPreferrer} videoPreferrer * @param {!cca.device.VideoConstraintsPreferrer} videoPreferrer
* @constructor * @constructor
*/ */
cca.views.Camera = function( cca.views.Camera = function(
...@@ -67,28 +67,13 @@ cca.views.Camera = function( ...@@ -67,28 +67,13 @@ cca.views.Camera = function(
this.options_ = this.options_ =
new cca.views.camera.Options(infoUpdater, this.restart.bind(this)); new cca.views.camera.Options(infoUpdater, this.restart.bind(this));
const doSavePhoto = async (result, name) => { /**
cca.metrics.log( * @type {!cca.models.ResultSaver}
cca.metrics.Type.CAPTURE, this.facingMode_, 0, result.resolution); * @protected
try { */
await resultSaver.savePhoto(result.blob, name); this.resultSaver_ = resultSaver;
} catch (e) {
cca.toast.show('error_msg_save_file_failed');
throw e;
}
};
const createVideoSaver = async () => resultSaver.startSaveVideo(); const createVideoSaver = async () => resultSaver.startSaveVideo();
const doSaveVideo = async (result, name) => {
cca.metrics.log(
cca.metrics.Type.CAPTURE, this.facingMode_, result.duration,
result.resolution);
try {
await resultSaver.finishSaveVideo(result.videoSaver, name);
} catch (e) {
cca.toast.show('error_msg_save_file_failed');
throw e;
}
};
/** /**
* Modes for the camera. * Modes for the camera.
...@@ -97,7 +82,8 @@ cca.views.Camera = function( ...@@ -97,7 +82,8 @@ cca.views.Camera = function(
*/ */
this.modes_ = new cca.views.camera.Modes( this.modes_ = new cca.views.camera.Modes(
this.defaultMode, photoPreferrer, videoPreferrer, this.restart.bind(this), this.defaultMode, photoPreferrer, videoPreferrer, this.restart.bind(this),
doSavePhoto, createVideoSaver, doSaveVideo); this.doSavePhoto_.bind(this), createVideoSaver,
this.doSaveVideo_.bind(this));
/** /**
* @type {?string} * @type {?string}
...@@ -227,6 +213,44 @@ cca.views.Camera.prototype.endTake_ = function() { ...@@ -227,6 +213,44 @@ cca.views.Camera.prototype.endTake_ = function() {
return Promise.resolve(this.take_); return Promise.resolve(this.take_);
}; };
/**
* Handles captured photo result.
* @param {!cca.views.camera.PhotoResult} result Captured photo result.
* @param {string} name Name of the photo result to be saved as.
* @return {!Promise} Promise for the operation.
* @protected
*/
cca.views.Camera.prototype.doSavePhoto_ = async function(result, name) {
cca.metrics.log(
cca.metrics.Type.CAPTURE, this.facingMode_, /* length= */ 0,
result.resolution, cca.metrics.IntentResultType.NOT_INTENT);
try {
await this.resultSaver_.savePhoto(result.blob, name);
} catch (e) {
cca.toast.show('error_msg_save_file_failed');
throw e;
}
};
/**
* Handles captured video result.
* @param {!cca.views.camera.VideoResult} result Captured video result.
* @param {string} name Name of the video result to be saved as.
* @return {!Promise} Promise for the operation.
* @protected
*/
cca.views.Camera.prototype.doSaveVideo_ = async function(result, name) {
cca.metrics.log(
cca.metrics.Type.CAPTURE, this.facingMode_, result.duration,
result.resolution, cca.metrics.IntentResultType.NOT_INTENT);
try {
await this.resultSaver_.finishSaveVideo(result.videoSaver, name);
} catch (e) {
cca.toast.show('error_msg_save_file_failed');
throw e;
}
};
/** /**
* @override * @override
*/ */
......
...@@ -35,7 +35,6 @@ cca.views.CameraIntent = class extends cca.views.Camera { ...@@ -35,7 +35,6 @@ cca.views.CameraIntent = class extends cca.views.Camera {
constructor(intent, infoUpdater, photoPreferrer, videoPreferrer) { constructor(intent, infoUpdater, photoPreferrer, videoPreferrer) {
const resultSaver = { const resultSaver = {
savePhoto: async (blob) => { savePhoto: async (blob) => {
this.photoResult_ = blob;
if (intent.shouldDownScale) { if (intent.shouldDownScale) {
const image = await cca.util.blobToImage(blob); const image = await cca.util.blobToImage(blob);
const ratio = Math.sqrt( const ratio = Math.sqrt(
...@@ -52,7 +51,7 @@ cca.views.CameraIntent = class extends cca.views.Camera { ...@@ -52,7 +51,7 @@ cca.views.CameraIntent = class extends cca.views.Camera {
return await cca.models.IntentVideoSaver.create(intent); return await cca.models.IntentVideoSaver.create(intent);
}, },
finishSaveVideo: async (video, savedName) => { finishSaveVideo: async (video, savedName) => {
this.videoResult_ = await video.endWrite(); this.videoResultFile_ = await video.endWrite();
}, },
}; };
super(resultSaver, infoUpdater, photoPreferrer, videoPreferrer); super(resultSaver, infoUpdater, photoPreferrer, videoPreferrer);
...@@ -64,17 +63,23 @@ cca.views.CameraIntent = class extends cca.views.Camera { ...@@ -64,17 +63,23 @@ cca.views.CameraIntent = class extends cca.views.Camera {
this.intent_ = intent; this.intent_ = intent;
/** /**
* @type {?Blob} * @type {?cca.views.camera.PhotoResult}
* @private * @private
*/ */
this.photoResult_ = null; this.photoResult_ = null;
/** /**
* @type {?FileEntry} * @type {?cca.views.camera.VideoResult}
* @private * @private
*/ */
this.videoResult_ = null; this.videoResult_ = null;
/**
* @type {?FileEntry}
* @private
*/
this.videoResultFile_ = null;
/** /**
* @type {!cca.views.camera.ReviewResult} * @type {!cca.views.camera.ReviewResult}
* @private * @private
...@@ -82,12 +87,38 @@ cca.views.CameraIntent = class extends cca.views.Camera { ...@@ -82,12 +87,38 @@ cca.views.CameraIntent = class extends cca.views.Camera {
this.reviewResult_ = new cca.views.camera.ReviewResult(); this.reviewResult_ = new cca.views.camera.ReviewResult();
} }
/**
* @override
*/
async doSavePhoto_(result, name) {
this.photoResult_ = result;
try {
await this.resultSaver_.savePhoto(result.blob, name);
} catch (e) {
cca.toast.show('error_msg_save_file_failed');
throw e;
}
}
/**
* @override
*/
async doSaveVideo_(result, name) {
this.videoResult_ = result;
try {
await this.resultSaver_.finishSaveVideo(result.videoSaver, name);
} catch (e) {
cca.toast.show('error_msg_save_file_failed');
throw e;
}
}
/** /**
* @override * @override
*/ */
beginTake_() { beginTake_() {
if (this.photoResult_ !== null) { if (this.photoResult_ !== null) {
URL.revokeObjectURL(this.photoResult_); URL.revokeObjectURL(this.photoResult_.blob);
} }
this.photoResult_ = null; this.photoResult_ = null;
this.videoResult_ = null; this.videoResult_ = null;
...@@ -107,8 +138,14 @@ cca.views.CameraIntent = class extends cca.views.Camera { ...@@ -107,8 +138,14 @@ cca.views.CameraIntent = class extends cca.views.Camera {
await this.restart(); await this.restart();
const confirmed = await ( const confirmed = await (
this.photoResult_ !== null ? this.photoResult_ !== null ?
this.reviewResult_.openPhoto(this.photoResult_) : this.reviewResult_.openPhoto(this.photoResult_.blob) :
this.reviewResult_.openVideo(this.videoResult_)); this.reviewResult_.openVideo(this.videoResultFile_));
const result = this.photoResult_ || this.videoResult_;
cca.metrics.log(
cca.metrics.Type.CAPTURE, this.facingMode_, result.duration || 0,
result.resolution,
confirmed ? cca.metrics.IntentResultType.CONFIRMED :
cca.metrics.IntentResultType.CANCELED);
if (confirmed) { if (confirmed) {
await this.intent_.finish(); await this.intent_.finish();
window.close(); window.close();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment