blob: 8a6ba3e7c30b1debe238779bc877fc336e5f4dd9 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import './test_api/test_api.js';
import './components/common_styles/oobe_flex_layout_styles.css.js';
import './components/api_keys_notice.js';
// clang-format on
import {assert} from '//resources/ash/common/assert.js';
import {$} from '//resources/ash/common/util.js';
import {startColorChangeUpdater} from '//resources/cr_components/color_change_listener/colors_css_updater.js';
import {Oobe} from './cr_ui.js';
import * as OobeDebugger from './debug/debug.js';
import {invokePolymerMethod} from './display_manager.js';
import {loadTimeData} from './i18n_setup.js';
import {MultiTapDetector} from './multi_tap_detector.js';
import {TraceEvent, traceExecution} from './oobe_trace.js';
import {commonScreensList, loginScreensList, oobeScreensList} from './screens.js';
// Everything has been imported at this point.
traceExecution(TraceEvent.FIRST_LINE_AFTER_IMPORTS);
/**
* Add screens from the given list into the main screen container.
* Screens are added with the following properties:
* - Classes: "step hidden" + any extra classes the screen may have
* - Attribute: "hidden"
*
* If a screen should be added only under some certain conditions, it must have
* the `condition` property associated with a boolean flag. If the condition
* yields true it will be added, otherwise it is skipped.
* @param {Array<{tag: string, id: string}>}
*/
function addScreensToMainContainer(screenList) {
const screenContainer = $('inner-container');
for (const screen of screenList) {
if (screen.condition) {
if (!loadTimeData.getBoolean(screen.condition)) {
continue;
}
}
const screenElement = document.createElement(screen.tag);
screenElement.id = screen.id;
screenElement.classList.add('step', 'hidden');
screenElement.setAttribute('hidden', '');
if (screen.extra_classes) {
screenElement.classList.add(...screen.extra_classes);
}
screenContainer.appendChild(screenElement);
assert(
!!$(screen.id).shadowRoot, `Error! No shadow root in <${screen.tag}>`);
}
}
// Create the global values attached to `window` that are used
// for accessing OOBE controls from the browser side.
function prepareGlobalValues(globalValue) {
// '$(id)' is an alias for 'document.getElementById(id)'. It is defined
// in //resources/ash/common/util.js. If this function is not exposed
// via the global object, it would not be available to tests that inject
// JavaScript directly into the renderer.
window.$ = $;
// Expose MultiTapDetector class on window for tests to set static methods.
window.MultiTapDetector = MultiTapDetector;
// TODO(crbug.com/1229130) - Remove the necessity for these global objects.
if (globalValue.cr == undefined) {
globalValue.cr = {};
}
if (globalValue.cr.ui == undefined) {
globalValue.cr.ui = {};
}
if (globalValue.cr.ui.login == undefined) {
globalValue.cr.ui.login = {};
}
// Expose some values in the global object that are needed by OOBE.
globalValue.cr.ui.Oobe = Oobe;
globalValue.Oobe = Oobe;
}
function initializeOobe() {
if (document.readyState === 'loading') {
return;
}
document.removeEventListener('DOMContentLoaded', initializeOobe);
traceExecution(TraceEvent.DOM_CONTENT_LOADED);
const isOobeJellyEnabled = loadTimeData.getBoolean('isOobeJellyEnabled');
if (isOobeJellyEnabled) {
const link = document.createElement('link');
link.rel = 'stylesheet';
// URL protocol prefix necessary, otherwise "new URL(href)"
// in colors_css_updater.ts will crash
link.href = 'chrome://theme/colors.css?sets=legacy,sys';
document.head.appendChild(link);
document.body.classList.add('jelly-enabled');
startColorChangeUpdater();
}
// Initialize the on-screen debugger if present.
if (OobeDebugger.DebuggerUI) {
OobeDebugger.DebuggerUI.getInstance().register(document.body);
}
try {
Oobe.initialize();
} finally {
// TODO(crbug.com/712078): Do not set readyForTesting in case of that
// initialize() is failed. Currently, in some situation, initialize()
// raises an exception unexpectedly. It means testing APIs should not
// be called then. However, checking it here now causes bots failures
// unfortunately. So, as a short term workaround, here set
// readyForTesting even on failures, just to make test bots happy.
Oobe.readyForTesting = true;
}
traceExecution(TraceEvent.OOBE_INITIALIZED);
// Mark initialization complete and wake any callers that might be waiting
// for OOBE to load.
cr.ui.Oobe.initializationComplete = true;
cr.ui.Oobe.initCallbacks.forEach(resolvePromise => resolvePromise());
}
/**
* ----------- OOBE Execution Begins -----------
*/
(function() {
// Ensure that there is a global error listener when OOBE starts.
// This error listener is added in the main HTML document.
assert(window.OobeErrorStore, 'OobeErrorStore not present on global object!');
// Update localized strings at the document level.
Oobe.updateDocumentLocalizedStrings();
prepareGlobalValues(window);
// Add common screens to the document.
addScreensToMainContainer(commonScreensList);
traceExecution(TraceEvent.COMMON_SCREENS_ADDED);
// Add OOBE or LOGIN screens to the document.
const isOobeFlow = loadTimeData.getBoolean('isOobeFlow');
if (isOobeFlow) {
addScreensToMainContainer(oobeScreensList);
traceExecution(TraceEvent.OOBE_SCREENS_ADDED);
} else {
addScreensToMainContainer(loginScreensList);
traceExecution(TraceEvent.LOGIN_SCREENS_ADDED);
}
// The default is to have the class 'oobe-display' in <body> for the OOBE
// flow. For the 'Add Person' flow, we remove it.
if (!isOobeFlow) {
document.body.classList.remove('oobe-display');
} else {
assert(
document.body.classList.contains('oobe-display'),
'The body of the document must contain oobe-display as a class for the OOBE flow!');
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeOobe);
} else {
initializeOobe();
}
})();