Commit 97dfc720 authored by Kuo Jen Wei's avatar Kuo Jen Wei Committed by Commit Bot

[CCA] Add closure compiler check to main.

Bug: b/141518780
Test: Pass closure compiler check, tast run <DUT> 'camera.CCAUI*' and
validate all function of CCA on HALv1/v3 device works correctly.

Change-Id: Ib7c71fba143b809f612f5148070755cdf1eca131
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1933860Reviewed-by: default avatarShik Chen <shik@chromium.org>
Commit-Queue: Shik Chen <shik@chromium.org>
Auto-Submit: Kuo Jen Wei <inker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720151}
parent 0fc3b3ad
...@@ -19,7 +19,9 @@ js_type_check("compile_resources") { ...@@ -19,7 +19,9 @@ js_type_check("compile_resources") {
deps = [ deps = [
":background", ":background",
":chrome_util", ":chrome_util",
":gallerybutton",
":intent", ":intent",
":main",
":metrics", ":metrics",
":nav", ":nav",
":sound", ":sound",
...@@ -40,6 +42,17 @@ js_library("intent") { ...@@ -40,6 +42,17 @@ js_library("intent") {
] ]
} }
js_library("gallerybutton") {
deps = [
":chrome_util",
"models:gallery",
]
externs_list = [
"$externs_path/file_manager_private.js",
"$externs_path/file_system_provider.js",
]
}
js_library("metrics") { js_library("metrics") {
deps = [ deps = [
"externs:chrome_platform_analytics", "externs:chrome_platform_analytics",
...@@ -52,6 +65,23 @@ js_library("sound") { ...@@ -52,6 +65,23 @@ js_library("sound") {
js_library("type") { js_library("type") {
} }
js_library("main") {
deps = [
":chrome_util",
":gallerybutton",
":intent",
":state",
"device:constraints_preferrer",
"device:device_info_updater",
"models:gallery",
"views:camera",
"views:camera_intent",
"views:dialog",
"views:settings",
"views:warning",
]
}
js_library("nav") { js_library("nav") {
deps = [ deps = [
"mojo:device_operator", "mojo:device_operator",
......
...@@ -85,3 +85,31 @@ ...@@ -85,3 +85,31 @@
} }
return value; return value;
} }
/**
* @param {*} value The value to check.
* @param {string=} opt_message A message to show when this is hit.
* @return {string}
*/
/* #export */ function assertString(value, opt_message) {
// We don't use assert immediately here so that we avoid constructing an error
// message if we don't have to.
if (typeof value !== 'string') {
assertNotReached(opt_message || 'Value ' + value + ' is not a string');
}
return /** @type {string} */ (value);
}
/**
* @param {*} value The value to check.
* @param {string=} opt_message A message to show when this is hit.
* @return {boolean}
*/
/* #export */ function assertBoolean(value, opt_message) {
// We don't use assert immediately here so that we avoid constructing an error
// message if we don't have to.
if (typeof value !== 'boolean') {
assertNotReached(opt_message || 'Value ' + value + ' is not a boolean');
}
return /** @type {boolean} */ (value);
}
...@@ -9,100 +9,111 @@ ...@@ -9,100 +9,111 @@
*/ */
var cca = cca || {}; var cca = cca || {};
/**
* import {assertInstanceof} from './chrome_util.js';
*/
var assertInstanceof = assertInstanceof || {};
/** /**
* Creates a controller for the gallery-button. * Creates a controller for the gallery-button.
* @param {cca.models.Gallery} model Model object.
* @implements {cca.models.Gallery.Observer} * @implements {cca.models.Gallery.Observer}
* @constructor
*/ */
cca.GalleryButton = function(model) { cca.GalleryButton = class {
/** /**
* @type {cca.models.Gallery} * @param {!cca.models.Gallery} model Model object.
* @private
*/ */
this.model_ = model; constructor(model) {
/**
* @type {!cca.models.Gallery}
* @private
*/
this.model_ = model;
/**
* @type {?cca.models.Gallery.Picture}
* @private
*/
this.lastPicture_ = null;
/**
* @type {!HTMLButtonElement}
* @private
*/
this.button_ = assertInstanceof(
document.querySelector('#gallery-enter'), HTMLButtonElement);
this.button_.addEventListener('click', (event) => {
// Check if the last picture still exists before opening it in the
// gallery.
// TODO(yuli): Remove this workaround for unable watching changed-files.
this.model_.checkLastPicture().then((picture) => {
if (picture) {
this.openGallery_(picture);
}
});
});
}
/** /**
* @type {cca.models.Gallery.Picture} * Updates the button for the model changes.
* @private * @private
*/ */
this.lastPicture_ = null; updateButton_() {
this.model_.lastPicture()
.then((picture) => {
if (picture !== this.lastPicture_) {
this.lastPicture_ = picture;
return true;
}
return false;
})
.then((changed) => {
if (!changed) {
return;
}
this.button_.hidden = !this.lastPicture_;
var url = this.lastPicture_ && this.lastPicture_.thumbnailURL;
this.button_.style.backgroundImage =
url ? ('url("' + url + '")') : 'none';
});
}
/** /**
* @type {HTMLButtonElement} * Opens the gallery to browse the picture.
* @param {cca.models.Gallery.Picture} picture Picture to be browsed.
* @private * @private
*/ */
this.button_ = document.querySelector('#gallery-enter'); openGallery_(picture) {
const id = 'nlkncpkkdoccmpiclbokaimcnedabhhm|app|open';
// End of properties, seal the object. const entry = picture.pictureEntry;
Object.seal(this); chrome.fileManagerPrivate.executeTask(id, [entry], (result) => {
if (chrome.runtime.lastError) {
this.button_.addEventListener('click', (event) => { console.warn(
// Check if the last picture still exists before opening it in the gallery. 'Unable to open picture: ' + chrome.runtime.lastError.message);
// TODO(yuli): Remove this workaround for unable watching changed-files. return;
this.model_.checkLastPicture().then((picture) => { }
if (picture) { if (result !== 'opened' && result !== 'message_sent') {
this.openGallery_(picture); console.warn('Unable to open picture: ' + result);
} }
}); });
}); }
};
/**
* Updates the button for the model changes.
* @private
*/
cca.GalleryButton.prototype.updateButton_ = function() {
this.model_.lastPicture().then((picture) => {
if (picture !== this.lastPicture_) {
this.lastPicture_ = picture;
return true;
}
return false;
}).then((changed) => {
if (!changed) {
return;
}
this.button_.hidden = !this.lastPicture_;
var url = this.lastPicture_ && this.lastPicture_.thumbnailURL;
this.button_.style.backgroundImage = url ? ('url("' + url + '")') : 'none';
});
};
/** /**
* Opens the gallery to browse the picture. * @override
* @param {cca.models.Gallery.Picture} picture Picture to be browsed. */
* @private onPictureDeleted(picture) {
*/ if (this.lastPicture_ === picture) {
cca.GalleryButton.prototype.openGallery_ = function(picture) { this.updateButton_();
const id = 'nlkncpkkdoccmpiclbokaimcnedabhhm|app|open';
const entry = picture.pictureEntry;
chrome.fileManagerPrivate.executeTask(id, [entry], (result) => {
if (chrome.runtime.lastError) {
console.warn(
'Unable to open picture: ' + chrome.runtime.lastError.message);
return;
}
if (result !== 'opened' && result !== 'message_sent') {
console.warn('Unable to open picture: ' + result);
} }
});
};
/**
* @override
*/
cca.GalleryButton.prototype.onPictureDeleted = function(picture) {
if (this.lastPicture_ === picture) {
this.updateButton_();
} }
};
/** /**
* @override * @override
*/ */
cca.GalleryButton.prototype.onPictureAdded = function(picture) { onPictureAdded(picture) {
if (!this.lastPicture_ || this.lastPicture_.timestamp <= picture.timestamp) { if (!this.lastPicture_ ||
this.updateButton_(); this.lastPicture_.timestamp <= picture.timestamp) {
this.updateButton_();
}
} }
}; };
...@@ -21,7 +21,7 @@ cca.models = cca.models || {}; ...@@ -21,7 +21,7 @@ cca.models = cca.models || {};
*/ */
cca.models.Gallery = function() { cca.models.Gallery = function() {
/** /**
* @type {Array<cca.models.Gallery.Observer>} * @type {!Array<!cca.models.Gallery.Observer>}
* @private * @private
*/ */
this.observers_ = []; this.observers_ = [];
...@@ -126,28 +126,25 @@ cca.models.Gallery.Picture.prototype.pictureURL = function() { ...@@ -126,28 +126,25 @@ cca.models.Gallery.Picture.prototype.pictureURL = function() {
/** /**
* Observer interface for the pictures' model changes. * Observer interface for the pictures' model changes.
* @constructor * @interface
*/
cca.models.Gallery.Observer = function() {
};
/**
* Notifies about a deleted picture.
* @param {cca.models.Gallery.Picture} picture Picture deleted.
*/ */
cca.models.Gallery.Observer.prototype.onPictureDeleted = function(picture) { cca.models.Gallery.Observer = class {
}; /**
* Notifies about a deleted picture.
* @param {cca.models.Gallery.Picture} picture Picture deleted.
*/
onPictureDeleted(picture) {}
/** /**
* Notifies about an added picture. * Notifies about an added picture.
* @param {cca.models.Gallery.Picture} picture Picture added. * @param {cca.models.Gallery.Picture} picture Picture added.
*/ */
cca.models.Gallery.Observer.prototype.onPictureAdded = function(picture) { onPictureAdded(picture) {}
}; };
/** /**
* Adds an observer. * Adds an observer.
* @param {cca.models.Gallery.Observer} observer Observer to be added. * @param {!cca.models.Gallery.Observer} observer Observer to be added.
*/ */
cca.models.Gallery.prototype.addObserver = function(observer) { cca.models.Gallery.prototype.addObserver = function(observer) {
this.observers_.push(observer); this.observers_.push(observer);
...@@ -160,7 +157,7 @@ cca.models.Gallery.prototype.addObserver = function(observer) { ...@@ -160,7 +157,7 @@ cca.models.Gallery.prototype.addObserver = function(observer) {
* @private * @private
*/ */
cca.models.Gallery.prototype.notifyObservers_ = function(fn, picture) { cca.models.Gallery.prototype.notifyObservers_ = function(fn, picture) {
this.observers_.forEach((observer) => observer[fn](picture)); this.observers_.forEach((/** !Object */ observer) => observer[fn](picture));
}; };
/** /**
......
...@@ -15,8 +15,10 @@ js_type_check("compile_resources") { ...@@ -15,8 +15,10 @@ js_type_check("compile_resources") {
deps = [ deps = [
":camera", ":camera",
":camera_intent", ":camera_intent",
":dialog",
":settings", ":settings",
":view", ":view",
":warning",
] ]
} }
...@@ -34,6 +36,9 @@ js_library("camera") { ...@@ -34,6 +36,9 @@ js_library("camera") {
] ]
} }
js_library("dialog") {
}
js_library("camera_intent") { js_library("camera_intent") {
deps = [ deps = [
":camera", ":camera",
...@@ -60,3 +65,6 @@ js_library("view") { ...@@ -60,3 +65,6 @@ js_library("view") {
externs_list = [ "../externs/chrome.js" ] externs_list = [ "../externs/chrome.js" ]
} }
js_library("warning") {
}
...@@ -15,64 +15,74 @@ var cca = cca || {}; ...@@ -15,64 +15,74 @@ var cca = cca || {};
cca.views = cca.views || {}; cca.views = cca.views || {};
/** /**
* Creates the Dialog view controller. * import {assertString} from '../chrome_util.js';
* @extends {cca.views.View}
* @constructor
* @param {string} viewId Root element id of dialog view.
*/ */
cca.views.Dialog = function(viewId) { var assertString = assertString || {};
cca.views.View.call(this, viewId, true);
/** /**
* @type {HTMLButtonElement} * import {assertInstanceof, assertString, assertBoolean}
* @private * from '../chrome_util.js';
*/ */
this.positiveButton_ = var {assertInstanceof, assertString, assertBoolean} = {
document.querySelector(`${viewId} .dialog-positive-button`); assertInstanceof,
assertString,
assertBoolean,
};
/**
* Creates the Dialog view controller.
*/
cca.views.Dialog = class extends cca.views.View {
/** /**
* @type {!HTMLButtonElement} * @param {string} viewId Root element id of dialog view.
* @private
*/ */
this.negativeButton_ = constructor(viewId) {
document.querySelector(`${viewId} .dialog-negative-button`); super(viewId, true);
/** /**
* @type {!HTMLElement} * @type {!HTMLButtonElement}
* @private * @private
*/ */
this.messageHolder_ = document.querySelector(`${viewId} .dialog-msg-holder`); this.positiveButton_ = assertInstanceof(
document.querySelector(`${viewId} .dialog-positive-button`),
HTMLButtonElement);
// End of properties, seal the object. /**
Object.seal(this); * @type {!HTMLButtonElement}
* @private
*/
this.negativeButton_ = assertInstanceof(
document.querySelector(`${viewId} .dialog-negative-button`),
HTMLButtonElement);
this.positiveButton_.addEventListener('click', () => this.leave(true)); /**
if (this.negativeButton_) { * @type {!HTMLElement}
this.negativeButton_.addEventListener('click', () => this.leave()); * @private
} */
}; this.messageHolder_ = assertInstanceof(
document.querySelector(`${viewId} .dialog-msg-holder`), HTMLElement);
cca.views.Dialog.prototype = { this.positiveButton_.addEventListener('click', () => this.leave(true));
__proto__: cca.views.View.prototype, if (this.negativeButton_) {
}; this.negativeButton_.addEventListener('click', () => this.leave());
}
}
/** /**
* @param {string} message Message of the dialog. * @override
* @param {boolean} cancellable Whether the dialog is cancellable. */
* @override entering({message, cancellable = false} = {}) {
*/ message = assertString(message);
cca.views.Dialog.prototype.entering = function({message, cancellable} = {}) {
if (this.messageHolder_ && message) {
this.messageHolder_.textContent = message; this.messageHolder_.textContent = message;
if (this.negativeButton_) {
this.negativeButton_.hidden = !cancellable;
}
} }
if (this.negativeButton_) {
this.negativeButton_.hidden = !cancellable;
}
};
/** /**
* @override * @override
*/ */
cca.views.Dialog.prototype.focus = function() { focus() {
this.positiveButton_.focus(); this.positiveButton_.focus();
}
}; };
...@@ -14,6 +14,31 @@ var cca = cca || {}; ...@@ -14,6 +14,31 @@ var cca = cca || {};
*/ */
cca.views = cca.views || {}; cca.views = cca.views || {};
/* eslint-disable no-unused-vars */
/**
* message for message of the dialog view, cancellable for whether the dialog
* view is cancellable.
* @typedef {{
* message: string,
* cancellable: (boolean|undefined),
* }}
*/
cca.views.DialogEnterOptions;
/**
* Warning message name.
* @typedef {string}
*/
cca.views.WarningEnterOptions;
/**
* @typedef {!cca.views.DialogEnterOptions|!cca.views.WarningEnterOptions}
*/
cca.views.EnterOptions;
/* eslint-enable no-unused-vars */
/** /**
* Base controller of a view for views' navigation sessions (cca.nav). * Base controller of a view for views' navigation sessions (cca.nav).
* @param {string} selector Selector text of the view's root element. * @param {string} selector Selector text of the view's root element.
...@@ -87,28 +112,27 @@ cca.views.View.prototype.onKeyPressed = function(key) { ...@@ -87,28 +112,27 @@ cca.views.View.prototype.onKeyPressed = function(key) {
/** /**
* Focuses the default element on the view if applicable. * Focuses the default element on the view if applicable.
*/ */
cca.views.View.prototype.focus = function() { cca.views.View.prototype.focus = function() {};
};
/** /**
* Layouts the view. * Layouts the view.
*/ */
cca.views.View.prototype.layout = function() { cca.views.View.prototype.layout = function() {};
};
/** /**
* Hook of the subclass for entering the view. * Hook of the subclass for entering the view.
* @param {...*} args Optional rest parameters for entering the view. * @param {cca.views.EnterOptions=} options Optional rest parameters for
* entering the view.
*/ */
cca.views.View.prototype.entering = function(...args) { cca.views.View.prototype.entering = function(options) {};
};
/** /**
* Enters the view. * Enters the view.
* @param {...*} args Optional rest parameters for entering the view. * @param {cca.views.EnterOptions=} options Optional rest parameters for
* entering the view.
* @return {!Promise<*>} Promise for the navigation session. * @return {!Promise<*>} Promise for the navigation session.
*/ */
cca.views.View.prototype.enter = function(...args) { cca.views.View.prototype.enter = function(options) {
// The session is started by entering the view and ended by leaving the view. // The session is started by entering the view and ended by leaving the view.
if (!this.session_) { if (!this.session_) {
var end; var end;
...@@ -119,7 +143,7 @@ cca.views.View.prototype.enter = function(...args) { ...@@ -119,7 +143,7 @@ cca.views.View.prototype.enter = function(...args) {
end(result); end(result);
}; };
} }
this.entering(...args); this.entering(options);
return this.session_; return this.session_;
}; };
......
...@@ -14,76 +14,83 @@ var cca = cca || {}; ...@@ -14,76 +14,83 @@ var cca = cca || {};
*/ */
cca.views = cca.views || {}; cca.views = cca.views || {};
/**
* import {assertString} from '../chrome_util.js';
*/
var assertString = assertString || {};
/** /**
* Creates the warning-view controller. * Creates the warning-view controller.
* @extends {cca.views.View}
* @constructor
*/ */
cca.views.Warning = function() { cca.views.Warning = class extends cca.views.View {
cca.views.View.call(this, '#warning'); /**
* @public
*/
constructor() {
super('#warning');
/**
* @type {!Array<string>}
* @private
*/
this.errorNames_ = [];
}
/** /**
* @type {Array<string>} * Updates the error message for the latest error-name in the stack.
* @private * @private
*/ */
this.errorNames_ = []; updateMessage_() {
let message = '';
// End of properties, seal the object. switch (this.errorNames_[this.errorNames_.length - 1]) {
Object.seal(this); case 'no-camera':
}; message = 'error_msg_no_camera';
break;
case 'filesystem-failure':
message = 'error_msg_file_system_failed';
break;
}
document.querySelector('#error-msg').textContent =
chrome.i18n.getMessage(message);
}
cca.views.Warning.prototype = { /**
__proto__: cca.views.View.prototype, * @override
}; */
entering(name) {
name = assertString(name);
/** // Remove the error-name from the stack to avoid duplication. Then make the
* Updates the error message for the latest error-name in the stack. // error-name the latest one to show its message.
* @private const index = this.errorNames_.indexOf(name);
*/ if (index !== -1) {
cca.views.Warning.prototype.updateMessage_ = function() { this.errorNames_.splice(index, 1);
var message = ''; }
switch (this.errorNames_[this.errorNames_.length - 1]) { this.errorNames_.push(name);
case 'no-camera': this.updateMessage_();
message = 'error_msg_no_camera';
break;
case 'filesystem-failure':
message = 'error_msg_file_system_failed';
break;
} }
document.querySelector('#error-msg').textContent =
chrome.i18n.getMessage(message);
};
/** /**
* @param {string} name Name of the error. * @override
* @override */
*/ leaving(...args) {
cca.views.Warning.prototype.entering = function(name) { /**
// Remove the error-name from the stack to avoid duplication. Then make the * Recovered error-name for leaving the view.
// error-name the latest one to show its message. * @type {string}
var index = this.errorNames_.indexOf(name); */
if (index != -1) { const name = assertString(args[0]);
this.errorNames_.splice(index, 1);
}
this.errorNames_.push(name);
this.updateMessage_();
};
/** // Remove the recovered error from the stack but don't leave the view until
* @param {string} name Recovered error-name for leaving the view. // there is no error left in the stack.
* @override const index = this.errorNames_.indexOf(name);
*/ if (index !== -1) {
cca.views.Warning.prototype.leaving = function(name) { this.errorNames_.splice(index, 1);
// Remove the recovered error from the stack but don't leave the view until }
// there is no error left in the stack. if (this.errorNames_.length) {
var index = this.errorNames_.indexOf(name); this.updateMessage_();
if (index != -1) { return false;
this.errorNames_.splice(index, 1); }
} document.querySelector('#error-msg').textContent = '';
if (this.errorNames_.length) { return true;
this.updateMessage_();
return false;
} }
document.querySelector('#error-msg').textContent = '';
return true;
}; };
...@@ -20,13 +20,13 @@ ...@@ -20,13 +20,13 @@
<script src="../js/tooltip.js"></script> <script src="../js/tooltip.js"></script>
<script src="../js/state.js"></script> <script src="../js/state.js"></script>
<script src="../js/sound.js"></script> <script src="../js/sound.js"></script>
<script src="../js/gallerybutton.js"></script>
<script src="../js/device/error.js"></script> <script src="../js/device/error.js"></script>
<script src="../js/device/camera3_device_info.js"></script> <script src="../js/device/camera3_device_info.js"></script>
<script src="../js/device/constraints_preferrer.js"></script> <script src="../js/device/constraints_preferrer.js"></script>
<script src="../js/device/device_info_updater.js"></script> <script src="../js/device/device_info_updater.js"></script>
<script src="../js/models/filenamer.js"></script> <script src="../js/models/filenamer.js"></script>
<script src="../js/models/gallery.js"></script> <script src="../js/models/gallery.js"></script>
<script src="../js/gallerybutton.js"></script>
<script src="../js/models/filesystem.js"></script> <script src="../js/models/filesystem.js"></script>
<script src="../js/models/result_saver.js"></script> <script src="../js/models/result_saver.js"></script>
<script src="../js/models/video_saver_interface.js"></script> <script src="../js/models/video_saver_interface.js"></script>
......
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