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

CCA: Preload css image assets before CCA start.

To preload image assets used by css, this CL add new BUILD.gn target
generating images into a js file under '/js/preload_images.js'. When
launching camera app, wait until images are loaded to show camera view.

Bug: b/172342439
Test: ./cca deploy <DUT>
Test: pass closure compiler
Test: Manually on DUT
Change-Id: I9ee8f73d0eed56c0002180259951235b6d0e642e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2531439
Commit-Queue: Shik Chen <shik@chromium.org>
Reviewed-by: default avatarShik Chen <shik@chromium.org>
Auto-Submit: Inker Kuo <inker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#828660}
parent 9d077c6f
......@@ -29,6 +29,7 @@ group("chrome_camera_app") {
":chrome_camera_app_js_views_camera_mode",
":chrome_camera_app_js_window_controller",
":chrome_camera_app_mojo_generated",
":chrome_camera_app_preload_images_js",
":chrome_camera_app_sounds",
":chrome_camera_app_views",
]
......@@ -46,55 +47,25 @@ copy("chrome_camera_app_css") {
outputs = [ "$out_camera_app_dir/css/{{source_file_part}}" ]
}
import("images/images.gni")
copy("chrome_camera_app_images") {
sources = [
"images/camera_app_icons_128.png",
"images/camera_app_icons_48.png",
"images/camera_button_fps_30.svg",
"images/camera_button_fps_60.svg",
"images/camera_button_grid_off.svg",
"images/camera_button_grid_on.svg",
"images/camera_button_mic_off.svg",
"images/camera_button_mic_on.svg",
"images/camera_button_mirror_off.svg",
"images/camera_button_mirror_on.svg",
"images/camera_button_settings.svg",
"images/camera_button_switch_device.svg",
"images/camera_button_switch_photo.svg",
"images/camera_button_switch_video.svg",
"images/camera_button_timer_off.svg",
"images/camera_button_timer_on_10s.svg",
"images/camera_button_timer_on_3s.svg",
"images/camera_focus_aim.svg",
"images/camera_intent_play_video.svg",
"images/camera_intent_result_cancel.svg",
"images/camera_intent_result_confirm.svg",
"images/camera_intro_banner_close.svg",
"images/camera_intro_banner_icon.svg",
"images/camera_mode_photo.svg",
"images/camera_mode_portrait.svg",
"images/camera_mode_square.svg",
"images/camera_mode_video.svg",
"images/camera_shutter_photo_start.svg",
"images/camera_shutter_photo_start_active.svg",
"images/camera_shutter_photo_start_hover.svg",
"images/camera_shutter_photo_stop.svg",
"images/camera_shutter_photo_stop_hover.svg",
"images/camera_shutter_video_pause.svg",
"images/settings_button_back.svg",
"images/settings_button_expand.svg",
"images/settings_expert.svg",
"images/settings_feedback.svg",
"images/settings_grid_type.svg",
"images/settings_help.svg",
"images/settings_resolution.svg",
"images/settings_timer_duration.svg",
"images/spinner.svg",
]
sources = []
foreach(asset, in_app_assets) {
sources += [ "images/$asset" ]
}
outputs = [ "$out_camera_app_dir/images/{{source_file_part}}" ]
}
copy("chrome_camera_app_preload_images_js") {
deps = [ "js:gen_preload_images_js" ]
js_gen_dir = get_label_info(deps[0], "target_gen_dir")
sources = [ "$js_gen_dir/preload_images.js" ]
outputs = [ "$out_camera_app_dir/js/{{source_file_part}}" ]
}
copy("chrome_camera_app_js") {
sources = [
"js/app_window.js",
......
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
in_app_assets = [
"camera_button_fps_30.svg",
"camera_button_fps_60.svg",
"camera_button_grid_off.svg",
"camera_button_grid_on.svg",
"camera_button_mic_off.svg",
"camera_button_mic_on.svg",
"camera_button_mirror_off.svg",
"camera_button_mirror_on.svg",
"camera_button_settings.svg",
"camera_button_switch_device.svg",
"camera_button_switch_photo.svg",
"camera_button_switch_video.svg",
"camera_button_timer_off.svg",
"camera_button_timer_on_10s.svg",
"camera_button_timer_on_3s.svg",
"camera_focus_aim.svg",
"camera_intent_play_video.svg",
"camera_intent_result_cancel.svg",
"camera_intent_result_confirm.svg",
"camera_intro_banner_close.svg",
"camera_intro_banner_icon.svg",
"camera_mode_photo.svg",
"camera_mode_portrait.svg",
"camera_mode_square.svg",
"camera_mode_video.svg",
"camera_shutter_photo_start.svg",
"camera_shutter_photo_start_active.svg",
"camera_shutter_photo_start_hover.svg",
"camera_shutter_photo_stop.svg",
"camera_shutter_photo_stop_hover.svg",
"camera_shutter_video_pause.svg",
"settings_button_back.svg",
"settings_button_expand.svg",
"settings_expert.svg",
"settings_feedback.svg",
"settings_grid_type.svg",
"settings_help.svg",
"settings_resolution.svg",
"settings_timer_duration.svg",
"spinner.svg",
]
......@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//chromeos/components/camera_app_ui/resources/images/images.gni")
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
......@@ -16,10 +17,38 @@ js_type_check("closure_compile") {
"hide_warnings_for=mojo/public/js/",
"hide_warnings_for=gen/",
"hide_warnings_for=js/lib/",
# For all js module in source tree.
"js_module_root=" + rebase_path(".", root_build_dir),
# For all dynamic generated js module.
"js_module_root=" + rebase_path(target_gen_dir, root_build_dir),
]
deps = [ ":compile_resources" ]
}
action("gen_preload_images_js") {
script = "../utils/gen_preload_images_js.py"
inputs = []
foreach(asset, in_app_assets) {
inputs += [ "../images/$asset" ]
}
outputs = [ "$target_gen_dir/preload_images.js" ]
response_file_contents = inputs
args = [
"--output_file",
rebase_path(outputs[0], root_build_dir),
"--images_list_file={{response_file_name}}",
]
}
js_library("preload_images") {
extra_deps = [ ":gen_preload_images_js" ]
sources = [ "$target_gen_dir/preload_images.js" ]
deps = []
}
js_library("compile_resources") {
sources = [
"app_window.js",
......@@ -94,6 +123,7 @@ js_library("compile_resources") {
"window_controller/window_controller_interface.js",
]
deps = [
":preload_images",
"//chromeos/components/camera_app_ui:mojo_bindings_js_library_for_compile",
"//components/arc/mojom:camera_intent_js_library_for_compile",
"//media/capture/mojom:image_capture_js_library_for_compile",
......
......@@ -23,9 +23,10 @@ import * as metrics from './metrics.js';
import * as filesystem from './models/file_system.js';
import {notifyCameraResourceReady} from './mojo/device_operator.js';
import * as nav from './nav.js';
import {preloadImagesList} from './preload_images.js';
import * as state from './state.js';
import * as tooltip from './tooltip.js';
import {Mode, PerfEvent, ViewName} from './type.js';
import {ErrorLevel, ErrorType, Mode, PerfEvent, ViewName} from './type.js';
import * as util from './util.js';
import {Camera} from './views/camera.js';
import {CameraIntent} from './views/camera_intent.js';
......@@ -263,8 +264,29 @@ export class App {
}
})();
const preloadImages = (async () => {
const loadImage = (url) => new Promise((resolve, reject) => {
const link =
/** @type {!HTMLLinkElement} */ (document.createElement('link'));
link.rel = 'preload';
link.as = 'image';
link.href = url;
link.onload = () => resolve();
link.onerror = (e) => reject(e.reason);
document.head.appendChild(link);
});
const results = await Promise.allSettled(
preloadImagesList.map((name) => loadImage(`/images/${name}`)));
const failure = results.find(({status}) => status === 'rejected');
if (failure !== undefined) {
error.reportError(
ErrorType.PRELOAD_IMAGE_FAILURE, ErrorLevel.ERROR,
assertInstanceof(failure.reason, Error));
}
})();
metrics.sendLaunchEvent({ackMigrate: false});
return Promise.all([showWindow, startCamera]);
return Promise.all([showWindow, startCamera, preloadImages]);
}
/**
......
......@@ -211,6 +211,7 @@ export let ErrorInfo;
*/
export const ErrorType = {
BROKEN_THUMBNAIL: 'broken-thumbnail',
PRELOAD_IMAGE_FAILURE: 'preload-image-failure',
UNCAUGHT_PROMISE: 'uncaught-promise',
};
......
......@@ -3,6 +3,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import ast
import argparse
from distutils import dir_util
import functools
......@@ -46,6 +47,24 @@ def build_locale_strings():
run(grit_cmd)
def build_preload_images_js():
with open('images/images.gni') as f:
in_app_assets = ast.literal_eval(
re.search(r'in_app_assets\s*=\s*(\[.*\])', f.read(),
re.DOTALL).group(1))
with tempfile.NamedTemporaryFile('w') as f:
f.writelines(asset + '\n' for asset in in_app_assets)
f.flush()
cmd = [
'utils/gen_preload_images_js.py',
'--images_list_file',
f.name,
'--output_file',
'build/camera/js/preload_images.js',
]
subprocess.check_call(cmd)
def build_mojom_bindings(mojom_bindings):
pylib = os.path.join(get_chromium_root(), 'mojo/public/tools/mojom')
sys.path.insert(0, pylib)
......@@ -156,6 +175,7 @@ def build_cca(overlay=None, key=None):
if d == 'build':
continue
dir_util.copy_tree(d, os.path.join('build/camera', d))
build_preload_images_js()
shutil.copy2('manifest.json', 'build/camera/manifest.json')
for f in mojo_files:
......
#!/usr/bin/env python3
# Copyright (c) 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Generates an array of images to be preloaded as a ES6 Module."""
import argparse
import json
import os
import shlex
import sys
def main():
argument_parser = argparse.ArgumentParser()
argument_parser.add_argument(
'--output_file',
help='The output js file exporting preload images array')
argument_parser.add_argument(
'--images_list_file',
help='File contains a list of images to be appended')
args = argument_parser.parse_args()
with open(args.images_list_file) as f:
filenames = [
os.path.basename(filename) for filename in shlex.split(f.read())
]
with open(args.output_file, 'w') as f:
f.write('export const preloadImagesList = %s;' %
json.dumps(filenames, indent=2))
return 0
if __name__ == '__main__':
sys.exit(main())
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