Commit 16bcae66 authored by Kuo Jen Wei's avatar Kuo Jen Wei Committed by Commit Bot

[CCA] Convert background.js into ES6 module.

Bug: 141518780
Test: Pass closure compiler check, tast run <DUT> 'camera.CCAUI*' on
both HALv1 and v3 devices.

Change-Id: Ic6dbdf1b89cba83637a923ac2023b674021b9c00
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1991041
Auto-Submit: Kuo Jen Wei <inker@chromium.org>
Reviewed-by: default avatarShik Chen <shik@chromium.org>
Commit-Queue: Kuo Jen Wei <inker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#729692}
parent 04693202
...@@ -2,71 +2,62 @@ ...@@ -2,71 +2,62 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
'use strict'; import {
BackgroundOps, // eslint-disable-line no-unused-vars
/** ForegroundOps, // eslint-disable-line no-unused-vars
* Namespace for the Camera app. } from './background_ops.js';
*/ import {Intent} from './intent.js';
var cca = cca || {}; import {PerfEvent, PerfLogger} from './perf.js';
/**
* Namespace for the background page.
*/
cca.bg = {};
/** /**
* Fixed minimum width of the window inner-bounds in pixels. * Fixed minimum width of the window inner-bounds in pixels.
* @type {number} * @type {number}
* @const
*/ */
cca.bg.MIN_WIDTH = 768; const MIN_WIDTH = 768;
/** /**
* Initial apsect ratio of the window inner-bounds. * Initial apsect ratio of the window inner-bounds.
* @type {number} * @type {number}
* @const
*/ */
cca.bg.INITIAL_ASPECT_RATIO = 1.7777777777; const INITIAL_ASPECT_RATIO = 1.7777777777;
/** /**
* Top bar color of the window. * Top bar color of the window.
* @type {string} * @type {string}
* @const
*/ */
cca.bg.TOPBAR_COLOR = '#000000'; const TOPBAR_COLOR = '#000000';
/** /**
* The id of the test app used in Tast. * The id of the test app used in Tast.
* @type {string} * @type {string}
* @const
*/ */
cca.bg.TEST_API_ID = 'behllobkkfkfnphdnhnkndlbkcpglgmj'; const TEST_API_ID = 'behllobkkfkfnphdnhnkndlbkcpglgmj';
/** /**
* It's used in test to ensure that we won't connect to the main.html target * It's used in test to ensure that we won't connect to the main.html target
* before the window is created, otherwise the window might disappear. * before the window is created, otherwise the window might disappear.
* @type {?function(string): undefined} * @type {?function(string): undefined}
*/ */
cca.bg.onAppWindowCreatedForTesting = null; let onAppWindowCreatedForTesting = null;
/** /**
* It's used in test to catch the perf event before the creation of app window * It's used in test to catch the perf event before the creation of app window
* for time measurement before launch. * for time measurement before launch.
* @type {?cca.perf.PerfLogger} * @type {?PerfLogger}
*/ */
cca.bg.perfLoggerForTesting = null; let perfLoggerForTesting = null;
/** /**
* Background object for handling launch event. * Background object for handling launch event.
* @type {?cca.bg.Background} * @type {?Background}
*/ */
cca.bg.background = null; let background = null;
/** /**
* State of cca.bg.Window. * State of CCAWindow.
* @enum {string} * @enum {string}
*/ */
cca.bg.WindowState = { const WindowState = {
UNINIT: 'uninitialized', UNINIT: 'uninitialized',
LAUNCHING: 'launching', LAUNCHING: 'launching',
ACTIVE: 'active', ACTIVE: 'active',
...@@ -79,51 +70,51 @@ cca.bg.WindowState = { ...@@ -79,51 +70,51 @@ cca.bg.WindowState = {
/** /**
* Wrapper of AppWindow for tracking its state. * Wrapper of AppWindow for tracking its state.
* @implements {cca.bg.BackgroundOps} * @implements {BackgroundOps}
*/ */
cca.bg.Window = class { class CCAWindow {
/** /**
* @param {!function(cca.bg.Window)} onActive Called when window become active * @param {!function(CCAWindow)} onActive Called when window become active
* state. * state.
* @param {!function(cca.bg.Window)} onSuspended Called when window become * @param {!function(CCAWindow)} onSuspended Called when window become
* suspended state. * suspended state.
* @param {!function(cca.bg.Window)} onClosed Called when window become closed * @param {!function(CCAWindow)} onClosed Called when window become closed
* state. * state.
* @param {?cca.perf.PerfLogger} perfLogger The logger for perf events. If it * @param {?PerfLogger} perfLogger The logger for perf events. If it
* is null, we will create a new one for the window. * is null, we will create a new one for the window.
* @param {cca.intent.Intent=} intent Intent to be handled by the app window. * @param {Intent=} intent Intent to be handled by the app window.
* Set to null for app window not launching from intent. * Set to null for app window not launching from intent.
*/ */
constructor(onActive, onSuspended, onClosed, perfLogger, intent = null) { constructor(onActive, onSuspended, onClosed, perfLogger, intent = null) {
/** /**
* @type {!function(!cca.bg.Window)} * @type {!function(!CCAWindow)}
* @private * @private
*/ */
this.onActive_ = onActive; this.onActive_ = onActive;
/** /**
* @type {!function(!cca.bg.Window)} * @type {!function(!CCAWindow)}
* @private * @private
*/ */
this.onSuspended_ = onSuspended; this.onSuspended_ = onSuspended;
/** /**
* @type {!function(!cca.bg.Window)} * @type {!function(!CCAWindow)}
* @private * @private
*/ */
this.onClosed_ = onClosed; this.onClosed_ = onClosed;
/** /**
* @type {?cca.intent.Intent} * @type {?Intent}
* @private * @private
*/ */
this.intent_ = intent; this.intent_ = intent;
/** /**
* @type {!cca.perf.PerfLogger} * @type {!PerfLogger}
* @private * @private
*/ */
this.perfLogger_ = perfLogger || new cca.perf.PerfLogger(); this.perfLogger_ = perfLogger || new PerfLogger();
/** /**
* @type {?chrome.app.window.AppWindow} * @type {?chrome.app.window.AppWindow}
...@@ -132,21 +123,21 @@ cca.bg.Window = class { ...@@ -132,21 +123,21 @@ cca.bg.Window = class {
this.appWindow_ = null; this.appWindow_ = null;
/** /**
* @type {?cca.bg.ForegroundOps} * @type {?ForegroundOps}
* @private * @private
*/ */
this.foregroundOps_ = null; this.foregroundOps_ = null;
/** /**
* @type {!cca.bg.WindowState} * @type {!WindowState}
* @private * @private
*/ */
this.state_ = cca.bg.WindowState.UNINIT; this.state_ = WindowState.UNINIT;
} }
/** /**
* Gets state of the window. * Gets state of the window.
* @return {cca.bg.WindowState} * @return {WindowState}
*/ */
get state() { get state() {
return this.state_; return this.state_;
...@@ -156,12 +147,11 @@ cca.bg.Window = class { ...@@ -156,12 +147,11 @@ cca.bg.Window = class {
* Creates app window and launches app. * Creates app window and launches app.
*/ */
launch() { launch() {
this.state_ = cca.bg.WindowState.LAUNCHING; this.state_ = WindowState.LAUNCHING;
// The height will be later calculated to match video aspect ratio once the // The height will be later calculated to match video aspect ratio once the
// stream is available. // stream is available.
var initialHeight = const initialHeight = Math.round(MIN_WIDTH / INITIAL_ASPECT_RATIO);
Math.round(cca.bg.MIN_WIDTH / cca.bg.INITIAL_ASPECT_RATIO);
const windowId = const windowId =
this.intent_ !== null ? `main-${this.intent_.intentId}` : 'main'; this.intent_ !== null ? `main-${this.intent_.intentId}` : 'main';
...@@ -171,32 +161,31 @@ cca.bg.Window = class { ...@@ -171,32 +161,31 @@ cca.bg.Window = class {
chrome.app.window.create( chrome.app.window.create(
windowUrl, { windowUrl, {
id: windowId, id: windowId,
frame: {color: cca.bg.TOPBAR_COLOR}, frame: {color: TOPBAR_COLOR},
hidden: true, // Will be shown from main.js once loaded. hidden: true, // Will be shown from main.js once loaded.
innerBounds: { innerBounds: {
width: cca.bg.MIN_WIDTH, width: MIN_WIDTH,
height: initialHeight, height: initialHeight,
minWidth: cca.bg.MIN_WIDTH, minWidth: MIN_WIDTH,
left: Math.round((window.screen.availWidth - cca.bg.MIN_WIDTH) / 2), left: Math.round((window.screen.availWidth - MIN_WIDTH) / 2),
top: Math.round((window.screen.availHeight - initialHeight) / 2), top: Math.round((window.screen.availHeight - initialHeight) / 2),
}, },
}, },
(appWindow) => { (appWindow) => {
this.perfLogger_.start( this.perfLogger_.start(PerfEvent.LAUNCHING_FROM_WINDOW_CREATION);
cca.perf.PerfEvent.LAUNCHING_FROM_WINDOW_CREATION);
this.appWindow_ = appWindow; this.appWindow_ = appWindow;
this.appWindow_.onClosed.addListener(() => { this.appWindow_.onClosed.addListener(() => {
chrome.storage.local.set({maximized: appWindow.isMaximized()}); chrome.storage.local.set({maximized: appWindow.isMaximized()});
chrome.storage.local.set({fullscreen: appWindow.isFullscreen()}); chrome.storage.local.set({fullscreen: appWindow.isFullscreen()});
this.state_ = cca.bg.WindowState.CLOSED; this.state_ = WindowState.CLOSED;
if (this.intent_ !== null && !this.intent_.done) { if (this.intent_ !== null && !this.intent_.done) {
this.intent_.cancel(); this.intent_.cancel();
} }
this.onClosed_(this); this.onClosed_(this);
}); });
appWindow.contentWindow.backgroundOps = this; appWindow.contentWindow.backgroundOps = this;
if (cca.bg.onAppWindowCreatedForTesting !== null) { if (onAppWindowCreatedForTesting !== null) {
cca.bg.onAppWindowCreatedForTesting(windowUrl); onAppWindowCreatedForTesting(windowUrl);
} }
}); });
} }
...@@ -219,7 +208,7 @@ cca.bg.Window = class { ...@@ -219,7 +208,7 @@ cca.bg.Window = class {
* @override * @override
*/ */
notifyActivation() { notifyActivation() {
this.state_ = cca.bg.WindowState.ACTIVE; this.state_ = WindowState.ACTIVE;
// For intent only requiring open camera with specific mode without // For intent only requiring open camera with specific mode without
// returning the capture result, called onIntentHandled() right // returning the capture result, called onIntentHandled() right
// after app successfully launched. // after app successfully launched.
...@@ -233,7 +222,7 @@ cca.bg.Window = class { ...@@ -233,7 +222,7 @@ cca.bg.Window = class {
* @override * @override
*/ */
notifySuspension() { notifySuspension() {
this.state_ = cca.bg.WindowState.SUSPENDED; this.state_ = WindowState.SUSPENDED;
this.onSuspended_(this); this.onSuspended_(this);
} }
...@@ -248,11 +237,11 @@ cca.bg.Window = class { ...@@ -248,11 +237,11 @@ cca.bg.Window = class {
* Suspends the app window. * Suspends the app window.
*/ */
suspend() { suspend() {
if (this.state_ === cca.bg.WindowState.LAUNCHING) { if (this.state_ === WindowState.LAUNCHING) {
console.error('Call suspend() while window is still launching.'); console.error('Call suspend() while window is still launching.');
return; return;
} }
this.state_ = cca.bg.WindowState.SUSPENDING; this.state_ = WindowState.SUSPENDING;
this.foregroundOps_.suspend(); this.foregroundOps_.suspend();
} }
...@@ -260,7 +249,7 @@ cca.bg.Window = class { ...@@ -260,7 +249,7 @@ cca.bg.Window = class {
* Resumes the app window. * Resumes the app window.
*/ */
resume() { resume() {
this.state_ = cca.bg.WindowState.RESUMING; this.state_ = WindowState.RESUMING;
this.foregroundOps_.resume(); this.foregroundOps_.resume();
} }
...@@ -268,35 +257,35 @@ cca.bg.Window = class { ...@@ -268,35 +257,35 @@ cca.bg.Window = class {
* Closes the app window. * Closes the app window.
*/ */
close() { close() {
this.state_ = cca.bg.WindowState.CLOSING; this.state_ = WindowState.CLOSING;
this.appWindow_.close(); this.appWindow_.close();
} }
}; }
/** /**
* Launch event handler runs in background. * Launch event handler runs in background.
*/ */
cca.bg.Background = class { class Background {
/** /**
*/ */
constructor() { constructor() {
/** /**
* Launch window handles launch event triggered from app launcher. * Launch window handles launch event triggered from app launcher.
* @type {?cca.bg.Window} * @type {?CCAWindow}
* @private * @private
*/ */
this.launcherWindow_ = null; this.launcherWindow_ = null;
/** /**
* Intent window handles launch event triggered from ARC++ intent. * Intent window handles launch event triggered from ARC++ intent.
* @type {?cca.bg.Window} * @type {?CCAWindow}
* @private * @private
*/ */
this.intentWindow_ = null; this.intentWindow_ = null;
/** /**
* The pending intent arrived when foreground window is busy. * The pending intent arrived when foreground window is busy.
* @type {?cca.intent.Intent} * @type {?Intent}
*/ */
this.pendingIntent_ = null; this.pendingIntent_ = null;
} }
...@@ -330,7 +319,7 @@ cca.bg.Background = class { ...@@ -330,7 +319,7 @@ cca.bg.Background = class {
/** /**
* Returns a Window object handling launch event triggered from app launcher. * Returns a Window object handling launch event triggered from app launcher.
* @return {!cca.bg.Window} * @return {!CCAWindow}
* @private * @private
*/ */
createLauncherWindow_() { createLauncherWindow_() {
...@@ -364,16 +353,16 @@ cca.bg.Background = class { ...@@ -364,16 +353,16 @@ cca.bg.Background = class {
this.processPendingIntent_(); this.processPendingIntent_();
} }
}; };
const wnd = new cca.bg.Window( const wnd =
onActive, onSuspended, onClosed, cca.bg.perfLoggerForTesting); new CCAWindow(onActive, onSuspended, onClosed, perfLoggerForTesting);
cca.bg.perfLoggerForTesting = null; perfLoggerForTesting = null;
return wnd; return wnd;
} }
/** /**
* Returns a Window object handling launch event triggered from ARC++ intent. * Returns a Window object handling launch event triggered from ARC++ intent.
* @param {!cca.intent.Intent} intent Intent forwarding from ARC++. * @param {!Intent} intent Intent forwarding from ARC++.
* @return {!cca.bg.Window} * @return {!CCAWindow}
* @private * @private
*/ */
createIntentWindow_(intent) { createIntentWindow_(intent) {
...@@ -381,7 +370,7 @@ cca.bg.Background = class { ...@@ -381,7 +370,7 @@ cca.bg.Background = class {
this.assert_(wnd === this.intentWindow_, 'Wrong active intent window.'); this.assert_(wnd === this.intentWindow_, 'Wrong active intent window.');
this.assert_( this.assert_(
!this.launcherWindow_ || !this.launcherWindow_ ||
this.launcherWindow_.state === cca.bg.WindowState.SUSPENDED, this.launcherWindow_.state === WindowState.SUSPENDED,
() => `Launch window is ${ () => `Launch window is ${
this.launcherWindow_.state} when intent window is active.`); this.launcherWindow_.state} when intent window is active.`);
if (this.pendingIntent_) { if (this.pendingIntent_) {
...@@ -397,7 +386,7 @@ cca.bg.Background = class { ...@@ -397,7 +386,7 @@ cca.bg.Background = class {
this.assert_(wnd === this.intentWindow_, 'Wrong closed intent window.'); this.assert_(wnd === this.intentWindow_, 'Wrong closed intent window.');
this.assert_( this.assert_(
!this.launcherWindow_ || !this.launcherWindow_ ||
this.launcherWindow_.state === cca.bg.WindowState.SUSPENDED, this.launcherWindow_.state === WindowState.SUSPENDED,
() => `Launch window is ${ () => `Launch window is ${
this.launcherWindow_.state} when intent window is closed.`); this.launcherWindow_.state} when intent window is closed.`);
this.intentWindow_ = null; this.intentWindow_ = null;
...@@ -407,9 +396,9 @@ cca.bg.Background = class { ...@@ -407,9 +396,9 @@ cca.bg.Background = class {
this.launcherWindow_.resume(); this.launcherWindow_.resume();
} }
}; };
const wnd = new cca.bg.Window( const wnd = new CCAWindow(
onActive, onSuspended, onClosed, cca.bg.perfLoggerForTesting, intent); onActive, onSuspended, onClosed, perfLoggerForTesting, intent);
cca.bg.perfLoggerForTesting = null; perfLoggerForTesting = null;
return wnd; return wnd;
} }
...@@ -430,7 +419,7 @@ cca.bg.Background = class { ...@@ -430,7 +419,7 @@ cca.bg.Background = class {
/** /**
* Closes the existing pending intent and replaces it with a new incoming * Closes the existing pending intent and replaces it with a new incoming
* intent. * intent.
* @param {!cca.intent.Intent} intent New incoming intent. * @param {!Intent} intent New incoming intent.
* @private * @private
*/ */
replacePendingIntent_(intent) { replacePendingIntent_(intent) {
...@@ -442,16 +431,16 @@ cca.bg.Background = class { ...@@ -442,16 +431,16 @@ cca.bg.Background = class {
/** /**
* Handles launch event triggered from ARC++ intent. * Handles launch event triggered from ARC++ intent.
* @param {!cca.intent.Intent} intent Intent forwarding from ARC++. * @param {!Intent} intent Intent forwarding from ARC++.
*/ */
launchIntent(intent) { launchIntent(intent) {
if (this.intentWindow_) { if (this.intentWindow_) {
switch (this.intentWindow_.state) { switch (this.intentWindow_.state) {
case cca.bg.WindowState.LAUNCHING: case WindowState.LAUNCHING:
case cca.bg.WindowState.CLOSING: case WindowState.CLOSING:
this.replacePendingIntent_(intent); this.replacePendingIntent_(intent);
break; break;
case cca.bg.WindowState.ACTIVE: case WindowState.ACTIVE:
this.replacePendingIntent_(intent); this.replacePendingIntent_(intent);
this.intentWindow_.close(); this.intentWindow_.close();
break; break;
...@@ -463,13 +452,13 @@ cca.bg.Background = class { ...@@ -463,13 +452,13 @@ cca.bg.Background = class {
} }
} else if (this.launcherWindow_) { } else if (this.launcherWindow_) {
switch (this.launcherWindow_.state) { switch (this.launcherWindow_.state) {
case cca.bg.WindowState.LAUNCHING: case WindowState.LAUNCHING:
case cca.bg.WindowState.SUSPENDING: case WindowState.SUSPENDING:
case cca.bg.WindowState.RESUMING: case WindowState.RESUMING:
case cca.bg.WindowState.CLOSING: case WindowState.CLOSING:
this.replacePendingIntent_(intent); this.replacePendingIntent_(intent);
break; break;
case cca.bg.WindowState.ACTIVE: case WindowState.ACTIVE:
this.assert_( this.assert_(
!this.pendingIntent_, !this.pendingIntent_,
'Pending intent is not processed when launch window is active.'); 'Pending intent is not processed when launch window is active.');
...@@ -487,7 +476,7 @@ cca.bg.Background = class { ...@@ -487,7 +476,7 @@ cca.bg.Background = class {
this.intentWindow_.launch(); this.intentWindow_.launch();
} }
} }
}; }
/** /**
* Handles messages from the test extension used in Tast. * Handles messages from the test extension used in Tast.
...@@ -499,72 +488,70 @@ cca.bg.Background = class { ...@@ -499,72 +488,70 @@ cca.bg.Background = class {
* @return {boolean|undefined} True to indicate the response is sent * @return {boolean|undefined} True to indicate the response is sent
* asynchronously. * asynchronously.
*/ */
cca.bg.handleExternalMessageFromTest = function(message, sender, sendResponse) { function handleExternalMessageFromTest(message, sender, sendResponse) {
if (sender.id !== cca.bg.TEST_API_ID) { if (sender.id !== TEST_API_ID) {
console.warn(`Unknown sender id: ${sender.id}`); console.warn(`Unknown sender id: ${sender.id}`);
return; return;
} }
switch (message.action) { switch (message.action) {
case 'SET_WINDOW_CREATED_CALLBACK': case 'SET_WINDOW_CREATED_CALLBACK':
cca.bg.onAppWindowCreatedForTesting = sendResponse; onAppWindowCreatedForTesting = sendResponse;
return true; return true;
default: default:
console.warn(`Unknown action: ${message.action}`); console.warn(`Unknown action: ${message.action}`);
} }
}; }
/** /**
* Handles connection from the test extension used in Tast. * Handles connection from the test extension used in Tast.
* @param {Port} port The port that used to do two-way communication. * @param {Port} port The port that used to do two-way communication.
*/ */
cca.bg.handleExternalConnectionFromTest = function(port) { function handleExternalConnectionFromTest(port) {
if (port.sender.id !== cca.bg.TEST_API_ID) { if (port.sender.id !== TEST_API_ID) {
console.warn(`Unknown sender id: ${port.sender.id}`); console.warn(`Unknown sender id: ${port.sender.id}`);
return; return;
} }
switch (port.name) { switch (port.name) {
case 'SET_PERF_CONNECTION': case 'SET_PERF_CONNECTION':
port.onMessage.addListener((event) => { port.onMessage.addListener((event) => {
if (cca.bg.perfLoggerForTesting === null) { if (perfLoggerForTesting === null) {
cca.bg.perfLoggerForTesting = new cca.perf.PerfLogger(); perfLoggerForTesting = new PerfLogger();
cca.bg.perfLoggerForTesting.addListener((event, duration, extras) => { perfLoggerForTesting.addListener((event, duration, extras) => {
port.postMessage({event, duration, extras}); port.postMessage({event, duration, extras});
}); });
} }
const {name} = event; const {name} = event;
if (name !== cca.perf.PerfEvent.LAUNCHING_FROM_LAUNCH_APP_COLD && if (name !== PerfEvent.LAUNCHING_FROM_LAUNCH_APP_COLD &&
name !== cca.perf.PerfEvent.LAUNCHING_FROM_LAUNCH_APP_WARM) { name !== PerfEvent.LAUNCHING_FROM_LAUNCH_APP_WARM) {
console.warn(`Unknown event name from test: ${name}`); console.warn(`Unknown event name from test: ${name}`);
return; return;
} }
cca.bg.perfLoggerForTesting.start(name); perfLoggerForTesting.start(name);
}); });
return; return;
default: default:
console.warn(`Unknown port name: ${port.name}`); console.warn(`Unknown port name: ${port.name}`);
} }
}; }
chrome.app.runtime.onLaunched.addListener((launchData) => { chrome.app.runtime.onLaunched.addListener((launchData) => {
if (!cca.bg.background) { if (!background) {
cca.bg.background = new cca.bg.Background(); background = new Background();
} }
try { try {
if (launchData.url) { if (launchData.url) {
const intent = cca.intent.Intent.create(new URL(launchData.url)); const intent = Intent.create(new URL(launchData.url));
cca.bg.background.launchIntent(intent); background.launchIntent(intent);
} else { } else {
cca.bg.background.launchApp(); background.launchApp();
} }
} catch (e) { } catch (e) {
console.error(e.stack); console.error(e.stack);
} }
}); });
chrome.runtime.onMessageExternal.addListener( chrome.runtime.onMessageExternal.addListener(handleExternalMessageFromTest);
cca.bg.handleExternalMessageFromTest);
chrome.runtime.onConnectExternal.addListener( chrome.runtime.onConnectExternal.addListener(handleExternalConnectionFromTest);
cca.bg.handleExternalConnectionFromTest);
...@@ -4,14 +4,10 @@ ...@@ -4,14 +4,10 @@
found in the LICENSE file. --> found in the LICENSE file. -->
<html> <html>
<head> <head>
<script src="../js/namespace.js"></script>
<script src="../js/mojo/mojo_bindings_lite.js"></script> <script src="../js/mojo/mojo_bindings_lite.js"></script>
<script src="../js/mojo/camera_intent.mojom-lite.js"></script> <script src="../js/mojo/camera_intent.mojom-lite.js"></script>
<script src="../js/mojo/camera_app_helper.mojom-lite.js"></script> <script src="../js/mojo/camera_app_helper.mojom-lite.js"></script>
<script type="module" src="../js/mojo/chrome_helper.js"></script> <script src="../js/namespace.js"></script>
<script type="module" src="../js/type.js"></script> <script type="module" src="../js/background.js"></script>
<script type="module" src="../js/perf.js"></script>
<script type="module" src="../js/intent.js"></script>
<script defer src="../js/background.js"></script>
</head> </head>
</html> </html>
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