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") {
deps = [
":background",
":chrome_util",
":gallerybutton",
":intent",
":main",
":metrics",
":nav",
":sound",
......@@ -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") {
deps = [
"externs:chrome_platform_analytics",
......@@ -52,6 +65,23 @@ js_library("sound") {
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") {
deps = [
"mojo:device_operator",
......
......@@ -85,3 +85,31 @@
}
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,36 +9,42 @@
*/
var cca = cca || {};
/**
* import {assertInstanceof} from './chrome_util.js';
*/
var assertInstanceof = assertInstanceof || {};
/**
* Creates a controller for the gallery-button.
* @param {cca.models.Gallery} model Model object.
* @implements {cca.models.Gallery.Observer}
* @constructor
*/
cca.GalleryButton = function(model) {
cca.GalleryButton = class {
/**
* @type {cca.models.Gallery}
* @param {!cca.models.Gallery} model Model object.
*/
constructor(model) {
/**
* @type {!cca.models.Gallery}
* @private
*/
this.model_ = model;
/**
* @type {cca.models.Gallery.Picture}
* @type {?cca.models.Gallery.Picture}
* @private
*/
this.lastPicture_ = null;
/**
* @type {HTMLButtonElement}
* @type {!HTMLButtonElement}
* @private
*/
this.button_ = document.querySelector('#gallery-enter');
// End of properties, seal the object.
Object.seal(this);
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.
// 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) {
......@@ -46,35 +52,38 @@ cca.GalleryButton = function(model) {
}
});
});
};
}
/**
/**
* Updates the button for the model changes.
* @private
*/
cca.GalleryButton.prototype.updateButton_ = function() {
this.model_.lastPicture().then((picture) => {
updateButton_() {
this.model_.lastPicture()
.then((picture) => {
if (picture !== this.lastPicture_) {
this.lastPicture_ = picture;
return true;
}
return false;
}).then((changed) => {
})
.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';
this.button_.style.backgroundImage =
url ? ('url("' + url + '")') : 'none';
});
};
}
/**
/**
* Opens the gallery to browse the picture.
* @param {cca.models.Gallery.Picture} picture Picture to be browsed.
* @private
*/
cca.GalleryButton.prototype.openGallery_ = function(picture) {
openGallery_(picture) {
const id = 'nlkncpkkdoccmpiclbokaimcnedabhhm|app|open';
const entry = picture.pictureEntry;
chrome.fileManagerPrivate.executeTask(id, [entry], (result) => {
......@@ -87,22 +96,24 @@ cca.GalleryButton.prototype.openGallery_ = function(picture) {
console.warn('Unable to open picture: ' + result);
}
});
};
}
/**
/**
* @override
*/
cca.GalleryButton.prototype.onPictureDeleted = function(picture) {
onPictureDeleted(picture) {
if (this.lastPicture_ === picture) {
this.updateButton_();
}
};
}
/**
/**
* @override
*/
cca.GalleryButton.prototype.onPictureAdded = function(picture) {
if (!this.lastPicture_ || this.lastPicture_.timestamp <= picture.timestamp) {
onPictureAdded(picture) {
if (!this.lastPicture_ ||
this.lastPicture_.timestamp <= picture.timestamp) {
this.updateButton_();
}
}
};
......@@ -9,53 +9,61 @@
*/
var cca = cca || {};
/**
* import {assert, assertInstanceof} from './chrome_util.js';
*/
var {assert, assertInstanceof} = {assert, assertInstanceof};
/**
* Creates the Camera App main object.
* @constructor
*/
cca.App = function() {
cca.App = class {
/**
* @public
*/
constructor() {
const shouldHandleIntentResult =
window.intent !== null && window.intent.shouldHandleResult;
cca.state.set('should-handle-intent-result', shouldHandleIntentResult);
/**
* @type {cca.models.Gallery}
* @type {!cca.models.Gallery}
* @private
*/
this.gallery_ = new cca.models.Gallery();
/**
* @type {cca.device.PhotoConstraintsPreferrer}
* @type {!cca.device.PhotoConstraintsPreferrer}
* @private
*/
this.photoPreferrer_ = new cca.device.PhotoConstraintsPreferrer(
() => this.cameraView_.restart());
/**
* @type {cca.device.VideoConstraintsPreferrer}
* @type {!cca.device.VideoConstraintsPreferrer}
* @private
*/
this.videoPreferrer_ = new cca.device.VideoConstraintsPreferrer(
() => this.cameraView_.restart());
/**
* @type {cca.device.DeviceInfoUpdater}
* @type {!cca.device.DeviceInfoUpdater}
* @private
*/
this.infoUpdater_ = new cca.device.DeviceInfoUpdater(
this.photoPreferrer_, this.videoPreferrer_);
/**
* @type {cca.GalleryButton}
* @type {!cca.GalleryButton}
* @private
*/
this.galleryButton_ = new cca.GalleryButton(this.gallery_);
/**
* @type {cca.views.Camera}
* @type {!cca.views.Camera}
* @private
*/
this.cameraView_ = shouldHandleIntentResult ?
this.cameraView_ = window.intent !== null && shouldHandleIntentResult ?
new cca.views.CameraIntent(
window.intent, this.infoUpdater_, this.photoPreferrer_,
this.videoPreferrer_) :
......@@ -63,13 +71,10 @@ cca.App = function() {
this.gallery_, this.infoUpdater_, this.photoPreferrer_,
this.videoPreferrer_);
// End of properties. Seal the object.
Object.seal(this);
document.body.addEventListener('keydown', this.onKeyPressed_.bind(this));
document.title = chrome.i18n.getMessage('name');
cca.util.setupI18nElements(document);
cca.util.setupI18nElements(document.body);
this.setupToggles_();
// Set up views navigation by their DOM z-order.
......@@ -86,13 +91,13 @@ cca.App = function() {
new cca.views.Warning(),
new cca.views.Dialog('#message-dialog'),
]);
};
}
/**
/**
* Sets up toggles (checkbox and radio) by data attributes.
* @private
*/
cca.App.prototype.setupToggles_ = function() {
setupToggles_() {
cca.proxy.browserProxy.localStorageGet(
{expert: false}, ({expert}) => cca.state.set('expert', expert));
document.querySelectorAll('input').forEach((element) => {
......@@ -127,16 +132,17 @@ cca.App.prototype.setupToggles_ = function() {
// Restore the previously saved state on startup.
cca.proxy.browserProxy.localStorageGet(
payload(element),
(values) =>
cca.util.toggleChecked(element, values[element.dataset.key]));
(values) => cca.util.toggleChecked(
assertInstanceof(element, HTMLInputElement),
values[element.dataset.key]));
}
});
};
}
/**
/**
* Starts the app by loading the model and opening the camera-view.
*/
cca.App.prototype.start = function() {
start() {
var ackMigrate = false;
cca.models.FileSystem
.initialize(() => {
......@@ -167,39 +173,40 @@ cca.App.prototype.start = function() {
.finally(() => {
cca.metrics.log(cca.metrics.Type.LAUNCH, ackMigrate);
});
};
}
/**
/**
* Handles pressed keys.
* @param {Event} event Key press event.
* @private
*/
cca.App.prototype.onKeyPressed_ = function(event) {
onKeyPressed_(event) {
cca.tooltip.hide(); // Hide shown tooltip on any keypress.
cca.nav.onKeyPressed(event);
};
}
/**
/**
* Suspends app and hides app window.
* @return {!Promise}
*/
cca.App.prototype.suspend = async function() {
async suspend() {
cca.state.set('suspend', true);
await this.cameraView_.restart();
chrome.app.window.current().hide();
};
}
/**
/**
* Resumes app from suspension and shows app window.
*/
cca.App.prototype.resume = function() {
resume() {
cca.state.set('suspend', false);
chrome.app.window.current().show();
}
};
/**
* Singleton of the App object.
* @type {cca.App}
* @type {?cca.App}
* @private
*/
cca.App.instance_ = null;
......
......@@ -21,7 +21,7 @@ cca.models = cca.models || {};
*/
cca.models.Gallery = function() {
/**
* @type {Array<cca.models.Gallery.Observer>}
* @type {!Array<!cca.models.Gallery.Observer>}
* @private
*/
this.observers_ = [];
......@@ -126,28 +126,25 @@ cca.models.Gallery.Picture.prototype.pictureURL = function() {
/**
* Observer interface for the pictures' model changes.
* @constructor
* @interface
*/
cca.models.Gallery.Observer = function() {
};
/**
cca.models.Gallery.Observer = class {
/**
* Notifies about a deleted picture.
* @param {cca.models.Gallery.Picture} picture Picture deleted.
*/
cca.models.Gallery.Observer.prototype.onPictureDeleted = function(picture) {
};
onPictureDeleted(picture) {}
/**
/**
* Notifies about an added picture.
* @param {cca.models.Gallery.Picture} picture Picture added.
*/
cca.models.Gallery.Observer.prototype.onPictureAdded = function(picture) {
onPictureAdded(picture) {}
};
/**
* 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) {
this.observers_.push(observer);
......@@ -160,7 +157,7 @@ cca.models.Gallery.prototype.addObserver = function(observer) {
* @private
*/
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") {
deps = [
":camera",
":camera_intent",
":dialog",
":settings",
":view",
":warning",
]
}
......@@ -34,6 +36,9 @@ js_library("camera") {
]
}
js_library("dialog") {
}
js_library("camera_intent") {
deps = [
":camera",
......@@ -60,3 +65,6 @@ js_library("view") {
externs_list = [ "../externs/chrome.js" ]
}
js_library("warning") {
}
......@@ -14,65 +14,75 @@ var cca = cca || {};
*/
cca.views = cca.views || {};
/**
* import {assertString} from '../chrome_util.js';
*/
var assertString = assertString || {};
/**
* import {assertInstanceof, assertString, assertBoolean}
* from '../chrome_util.js';
*/
var {assertInstanceof, assertString, assertBoolean} = {
assertInstanceof,
assertString,
assertBoolean,
};
/**
* Creates the Dialog view controller.
* @extends {cca.views.View}
* @constructor
*/
cca.views.Dialog = class extends cca.views.View {
/**
* @param {string} viewId Root element id of dialog view.
*/
cca.views.Dialog = function(viewId) {
cca.views.View.call(this, viewId, true);
constructor(viewId) {
super(viewId, true);
/**
* @type {HTMLButtonElement}
* @type {!HTMLButtonElement}
* @private
*/
this.positiveButton_ =
document.querySelector(`${viewId} .dialog-positive-button`);
this.positiveButton_ = assertInstanceof(
document.querySelector(`${viewId} .dialog-positive-button`),
HTMLButtonElement);
/**
* @type {!HTMLButtonElement}
* @private
*/
this.negativeButton_ =
document.querySelector(`${viewId} .dialog-negative-button`);
this.negativeButton_ = assertInstanceof(
document.querySelector(`${viewId} .dialog-negative-button`),
HTMLButtonElement);
/**
* @type {!HTMLElement}
* @private
*/
this.messageHolder_ = document.querySelector(`${viewId} .dialog-msg-holder`);
// End of properties, seal the object.
Object.seal(this);
this.messageHolder_ = assertInstanceof(
document.querySelector(`${viewId} .dialog-msg-holder`), HTMLElement);
this.positiveButton_.addEventListener('click', () => this.leave(true));
if (this.negativeButton_) {
this.negativeButton_.addEventListener('click', () => this.leave());
}
};
cca.views.Dialog.prototype = {
__proto__: cca.views.View.prototype,
};
}
/**
* @param {string} message Message of the dialog.
* @param {boolean} cancellable Whether the dialog is cancellable.
/**
* @override
*/
cca.views.Dialog.prototype.entering = function({message, cancellable} = {}) {
if (this.messageHolder_ && message) {
entering({message, cancellable = false} = {}) {
message = assertString(message);
this.messageHolder_.textContent = message;
}
if (this.negativeButton_) {
this.negativeButton_.hidden = !cancellable;
}
};
}
/**
/**
* @override
*/
cca.views.Dialog.prototype.focus = function() {
focus() {
this.positiveButton_.focus();
}
};
......@@ -14,6 +14,31 @@ var cca = cca || {};
*/
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).
* @param {string} selector Selector text of the view's root element.
......@@ -87,28 +112,27 @@ cca.views.View.prototype.onKeyPressed = function(key) {
/**
* Focuses the default element on the view if applicable.
*/
cca.views.View.prototype.focus = function() {
};
cca.views.View.prototype.focus = function() {};
/**
* Layouts the view.
*/
cca.views.View.prototype.layout = function() {
};
cca.views.View.prototype.layout = function() {};
/**
* 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.
* @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.
*/
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.
if (!this.session_) {
var end;
......@@ -119,7 +143,7 @@ cca.views.View.prototype.enter = function(...args) {
end(result);
};
}
this.entering(...args);
this.entering(options);
return this.session_;
};
......
......@@ -14,34 +14,34 @@ var cca = cca || {};
*/
cca.views = cca.views || {};
/**
* import {assertString} from '../chrome_util.js';
*/
var assertString = assertString || {};
/**
* Creates the warning-view controller.
* @extends {cca.views.View}
* @constructor
*/
cca.views.Warning = function() {
cca.views.View.call(this, '#warning');
cca.views.Warning = class extends cca.views.View {
/**
* @public
*/
constructor() {
super('#warning');
/**
* @type {Array<string>}
* @type {!Array<string>}
* @private
*/
this.errorNames_ = [];
}
// End of properties, seal the object.
Object.seal(this);
};
cca.views.Warning.prototype = {
__proto__: cca.views.View.prototype,
};
/**
/**
* Updates the error message for the latest error-name in the stack.
* @private
*/
cca.views.Warning.prototype.updateMessage_ = function() {
var message = '';
updateMessage_() {
let message = '';
switch (this.errorNames_[this.errorNames_.length - 1]) {
case 'no-camera':
message = 'error_msg_no_camera';
......@@ -52,32 +52,38 @@ cca.views.Warning.prototype.updateMessage_ = function() {
}
document.querySelector('#error-msg').textContent =
chrome.i18n.getMessage(message);
};
}
/**
* @param {string} name Name of the error.
/**
* @override
*/
cca.views.Warning.prototype.entering = function(name) {
entering(name) {
name = assertString(name);
// Remove the error-name from the stack to avoid duplication. Then make the
// error-name the latest one to show its message.
var index = this.errorNames_.indexOf(name);
if (index != -1) {
const index = this.errorNames_.indexOf(name);
if (index !== -1) {
this.errorNames_.splice(index, 1);
}
this.errorNames_.push(name);
this.updateMessage_();
};
}
/**
* @param {string} name Recovered error-name for leaving the view.
/**
* @override
*/
cca.views.Warning.prototype.leaving = function(name) {
leaving(...args) {
/**
* Recovered error-name for leaving the view.
* @type {string}
*/
const name = assertString(args[0]);
// Remove the recovered error from the stack but don't leave the view until
// there is no error left in the stack.
var index = this.errorNames_.indexOf(name);
if (index != -1) {
const index = this.errorNames_.indexOf(name);
if (index !== -1) {
this.errorNames_.splice(index, 1);
}
if (this.errorNames_.length) {
......@@ -86,4 +92,5 @@ cca.views.Warning.prototype.leaving = function(name) {
}
document.querySelector('#error-msg').textContent = '';
return true;
}
};
......@@ -20,13 +20,13 @@
<script src="../js/tooltip.js"></script>
<script src="../js/state.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/camera3_device_info.js"></script>
<script src="../js/device/constraints_preferrer.js"></script>
<script src="../js/device/device_info_updater.js"></script>
<script src="../js/models/filenamer.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/result_saver.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