diff options
Diffstat (limited to 'chromium/ui/webui')
114 files changed, 3132 insertions, 1068 deletions
diff --git a/chromium/ui/webui/PLATFORM_OWNERS b/chromium/ui/webui/PLATFORM_OWNERS index e875c99f4dd..9820db07c3d 100644 --- a/chromium/ui/webui/PLATFORM_OWNERS +++ b/chromium/ui/webui/PLATFORM_OWNERS @@ -4,7 +4,8 @@ antrim@chromium.org # CET calamity@chromium.org dpapad@chromium.org dschuyler@chromium.org +johntlee@chromium.org khorimoto@chromium.org # For Chrome OS changes. -michaelpg@chromium.org +michaelpg@chromium.org # For Chrome OS changes. rbpotter@chromium.org tommycli@chromium.org diff --git a/chromium/ui/webui/resources/PRESUBMIT.py b/chromium/ui/webui/resources/PRESUBMIT.py index 35b8ac52ab4..677dbd53fed 100644 --- a/chromium/ui/webui/resources/PRESUBMIT.py +++ b/chromium/ui/webui/resources/PRESUBMIT.py @@ -71,8 +71,8 @@ def _CheckWebDevStyle(input_api, output_api): cwd = input_api.PresubmitLocalPath() sys.path += [input_api.os_path.join(cwd, '..', '..', '..', 'tools')] from web_dev_style import presubmit_support - BLACKLIST = ['ui/webui/resources/js/jstemplate_compiled.js'] - file_filter = lambda f: f.LocalPath() not in BLACKLIST + IGNORELIST = ['ui/webui/resources/js/jstemplate_compiled.js'] + file_filter = lambda f: f.LocalPath() not in IGNORELIST results += presubmit_support.CheckStyle(input_api, output_api, file_filter) finally: sys.path = old_sys_path diff --git a/chromium/ui/webui/resources/cr_components/BUILD.gn b/chromium/ui/webui/resources/cr_components/BUILD.gn index a9eec51ac3c..f91009bc108 100644 --- a/chromium/ui/webui/resources/cr_components/BUILD.gn +++ b/chromium/ui/webui/resources/cr_components/BUILD.gn @@ -7,6 +7,7 @@ import("//third_party/closure_compiler/compile_js.gni") group("closure_compile") { deps = [ "certificate_manager:closure_compile_module", + "customize_themes:closure_compile", "managed_footnote:closure_compile", "managed_footnote:closure_compile_module", "omnibox:closure_compile", @@ -20,6 +21,7 @@ group("closure_compile") { group("polymer3_elements") { public_deps = [ "certificate_manager:web_components", + "customize_themes:web_components", "managed_footnote:managed_footnote_module", "omnibox:web_components", ] diff --git a/chromium/ui/webui/resources/cr_components/chromeos/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/BUILD.gn index be17a059d14..87fb0e397c1 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/BUILD.gn +++ b/chromium/ui/webui/resources/cr_components/chromeos/BUILD.gn @@ -19,7 +19,9 @@ group("closure_compile") { # Targets for auto-generated Polymer 3 JS Modules # TODO: Uncomment as Polymer3 migration makes progress. # "network:closure_compile_module", - # "quick_unlock:closure_compile_module", + + "quick_unlock:closure_compile_module", + "cellular_setup:closure_compile_module", "bluetooth:closure_compile_module", "network_health:closure_compile_module", "smb_shares:closure_compile_module", @@ -29,6 +31,7 @@ group("closure_compile") { group("polymer3_elements") { public_deps = [ "bluetooth:polymer3_elements", + "cellular_setup:polymer3_elements", "network:polymer3_elements", "network_health:polymer3_elements", "quick_unlock:polymer3_elements", diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn index d075a8d1d35..8deef8d61fe 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn +++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn @@ -3,6 +3,9 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/polymer.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") +import("../os_cr_components.gni") assert(is_chromeos, "CellularSetup UI is Chrome OS only.") @@ -14,6 +17,7 @@ js_type_check("closure_compile") { ":final_page", ":mojo_interface_provider", ":provisioning_page", + ":psim_flow_ui", ":sim_detect_page", ":webview_post_util", ] @@ -53,9 +57,8 @@ js_library("final_page") { deps = [ ":base_page" ] } -js_library("cellular_setup") { +js_library("psim_flow_ui") { deps = [ - ":button_bar", ":final_page", ":mojo_interface_provider", ":provisioning_page", @@ -65,9 +68,122 @@ js_library("cellular_setup") { ] } +js_library("cellular_setup") { + deps = [ + ":button_bar", + ":psim_flow_ui", + ] +} + js_library("mojo_interface_provider") { deps = [ "//chromeos/services/cellular_setup/public/mojom:mojom_js_library_for_compile", "//ui/webui/resources/js:cr", ] } + +# Polymer3 files + +js_type_check("closure_compile_module") { + is_polymer3 = true + deps = [ + # ":button_bar.m", + ":base_page.m", + + # ":button_bar.m", + # ":cellular_setup.m", + ":final_page.m", + ":mojo_interface_provider.m", + + # ":provisioning_page.m", + # ":psim_flow_ui.m", + ":sim_detect_page.m", + ":webview_post_util.m", + ] +} + +js_library("base_page.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/base_page.m.js" ] + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:i18n_behavior.m", + ] + extra_deps = [ ":base_page_module" ] +} + +js_library("final_page.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.m.js" ] + deps = [ + ":base_page.m", + "//ui/webui/resources/js:i18n_behavior.m", + ] + extra_deps = [ ":final_page_module" ] +} + +js_library("mojo_interface_provider.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.m.js" ] + deps = [ + "//chromeos/services/cellular_setup/public/mojom:mojom_js_library_for_compile", + "//ui/webui/resources/js:cr.m", + ] + extra_deps = [ ":modulize" ] +} + +js_library("webview_post_util.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/webview_post_util.m.js" ] + deps = [] + externs_list = [ + "$externs_path/chrome_extensions.js", + "$externs_path/webview_tag.js", + ] + extra_deps = [ ":modulize" ] +} + +js_library("sim_detect_page.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/cellular_setup/sim_detect_page.m.js" ] + deps = [ + ":base_page.m", + ] + extra_deps = [ ":sim_detect_page_module" ] +} + +group("polymer3_elements") { + public_deps = [ + ":base_page_module", + ":final_page_module", + ":sim_detect_page_module", + ":modulize", + ] +} + +polymer_modulizer("base_page") { + js_file = "base_page.js" + html_file = "base_page.html" + html_type = "dom-module" + namespace_rewrites = cr_components_chromeos_namespace_rewrites + auto_imports = cr_components_chromeos_auto_imports +} + +polymer_modulizer("final_page") { + js_file = "final_page.js" + html_file = "final_page.html" + html_type = "dom-module" + namespace_rewrites = cr_components_chromeos_namespace_rewrites + auto_imports = cr_components_chromeos_auto_imports +} + +polymer_modulizer("sim_detect_page") { + js_file = "sim_detect_page.js" + html_file = "sim_detect_page.html" + html_type = "dom-module" + namespace_rewrites = cr_components_chromeos_namespace_rewrites + auto_imports = cr_components_chromeos_auto_imports +} + +js_modulizer("modulize") { + input_files = [ + "mojo_interface_provider.js", + "webview_post_util.js", + ] + namespace_rewrites = cr_components_chromeos_namespace_rewrites +} diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html index 31727da02b2..d20e457a0cb 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.html @@ -1,39 +1,32 @@ <link rel="import" href="../../../html/polymer.html"> -<link rel="import" href="../../../html/i18n_behavior.html"> -<link rel="import" href="mojo_interface_provider.html"> <link rel="import" href="button_bar.html"> -<link rel="import" href="sim_detect_page.html"> -<link rel="import" href="provisioning_page.html"> -<link rel="import" href="final_page.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> +<link rel="import" href="psim_flow_ui.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> <dom-module id="cellular-setup"> <template> - <style include="iron-flex"> + <style> :host { - display: flex; flex: 1 1 auto; - flex-direction: column; padding: 10px; } + + iron-pages { + display: flex; + flex: 1 1 auto; + } </style> <iron-pages attr-for-selected="is" - selected="[[selectedPageName_]]" - selected-item="{{selectedPage_}}"> - <sim-detect-page show-error="[[showError_]]"></sim-detect-page> - <provisioning-page show-error="{{showError_}}" - cellular-metadata="[[cellularMetadata_]]" - on-carrier-portal-loaded="onCarrierPortalLoaded_" - on-carrier-portal-result="onCarrierPortalResult_"> - </provisioning-page> - <final-page show-error="[[showError_]]"></final-page> + selected="[[selectedPageName_]]"> + <!-- TODO(hsuregan): Implement <setup-flow-selection>. --> + <psim-flow-ui></psim-flow-ui> + <!-- TODO(hsuregan): Implement <esim-flow>. --> </iron-pages> <button-bar show-try-again-button="[[showTryAgainButton_]]" show-finish-button="[[showFinishButton_]]" - show-cancel-button="[[showCancelButton_]]"></button-bar> + show-cancel-button="[[showCancelButton_]]"> + </button-bar> </template> <script src="cellular_setup.js"> </script> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js index e1c84626120..e885a7f1ba2 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_setup.js @@ -1,369 +1,55 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. +// 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. cr.define('cellularSetup', function() { /** @enum{string} */ - const PageName = { - SIM_DETECT: 'sim-detect-page', - PROVISIONING: 'provisioning-page', - FINAL: 'final-page', + const CellularSetupPageName = { + PSIM_FLOW_UI: 'psim-flow-ui', }; - /** @enum{string} */ - const State = { - IDLE: 'idle', - STARTING_ACTIVATION: 'starting-activation', - WAITING_FOR_ACTIVATION_TO_START: 'waiting-for-activation-to-start', - TIMEOUT_START_ACTIVATION: 'timeout-start-activation', - WAITING_FOR_PORTAL_TO_LOAD: 'waiting-for-portal-to-load', - TIMEOUT_PORTAL_LOAD: 'timeout-portal-load', - WAITING_FOR_USER_PAYMENT: 'waiting-for-user-payment', - WAITING_FOR_ACTIVATION_TO_FINISH: 'waiting-for-activation-to-finish', - TIMEOUT_FINISH_ACTIVATION: 'timeout-finish-activation', - ACTIVATION_SUCCESS: 'activation-success', - ALREADY_ACTIVATED: 'already-activated', - ACTIVATION_FAILURE: 'activation-failure', - }; - - /** - * @param {!cellularSetup.State} state - * @return {?number} The time delta, in ms, for the timeout corresponding to - * |state|. If no timeout is applicable for this state, null is returned. - */ - function getTimeoutMsForState(state) { - // In some cases, starting activation may require power-cycling the device's - // modem, a process that can take several seconds. - if (state === State.STARTING_ACTIVATION) { - return 10000; // 10 seconds. - } - - // The portal is a website served by the mobile carrier. - if (state === State.WAITING_FOR_PORTAL_TO_LOAD) { - return 10000; // 10 seconds. - } - - // Finishing activation only requires sending a D-Bus message to Shill. - if (state === State.WAITING_FOR_ACTIVATION_TO_FINISH) { - return 1000; // 1 second. - } - - // No other states require timeouts. - return null; - } - return { - PageName: PageName, - State: State, - getTimeoutMsForState: getTimeoutMsForState + CellularSetupPageName: CellularSetupPageName, }; }); /** - * Root element for the cellular setup flow. This element interacts with the - * CellularSetup service to carry out the activation flow. It contains - * navigation buttons and sub-pages corresponding to each step of the flow. + * @fileoverview Root element for the cellular setup flow. This element wraps + * the psim setup flow, esim setup flow, and setup flow selection page. */ Polymer({ is: 'cellular-setup', - behaviors: [I18nBehavior], - properties: { - /** @private {!cellularSetup.State} */ - state_: { - type: String, - value: cellularSetup.State.IDLE, - }, - /** * Element name of the current selected sub-page. - * @private {!cellularSetup.PageName} + * @private {!cellularSetup.CellularSetupPageName} */ selectedPageName_: { type: String, - value: cellularSetup.PageName.SIM_DETECT, + value: cellularSetup.CellularSetupPageName.PSIM_FLOW_UI, notify: true, - }, - - /** - * DOM Element for the current selected sub-page. - * @private {!SimDetectPageElement|!ProvisioningPageElement| - * !FinalPageElement} - */ - selectedPage_: Object, - - /** - * Whether error state should be shown for the current page. - * @private {boolean} - */ - showError_: {type: Boolean, value: false}, - - /** - * Cellular metadata received via the onActivationStarted() callback. If - * that callback has not occurred, this field is null. - * @private {?chromeos.cellularSetup.mojom.CellularMetadata} - */ - cellularMetadata_: { - type: Object, - value: null, - }, - - /** - * Whether try again should be shown in the button bar. - * @private {boolean} - */ - showTryAgainButton_: {type: Boolean, value: false}, - - /** - * Whether finish button should be shown in the button bar. - * @private {boolean} - */ - showFinishButton_: {type: Boolean, value: false}, - - /** - * Whether cancel button should be shown in the button bar. - * @private {boolean} - */ - showCancelButton_: {type: Boolean, value: false} + } }, - observers: [ - 'updateShowError_(state_)', - 'updateSelectedPage_(state_)', - 'handleStateChange_(state_)', - ], - listeners: { 'backward-nav-requested': 'onBackwardNavRequested_', 'retry-requested': 'onRetryRequested_', 'complete-flow-requested': 'onCompleteFlowRequested_', }, - /** - * Provides an interface to the CellularSetup Mojo service. - * @private {?cellular_setup.MojoInterfaceProvider} - */ - mojoInterfaceProvider_: null, - - /** - * Delegate responsible for routing activation started/finished events. - * @private {?chromeos.cellularSetup.mojom.ActivationDelegateReceiver} - */ - activationDelegateReceiver_: null, - - /** - * The timeout ID corresponding to a timeout for the current state. If no - * timeout is active, this value is null. - * @private {?number} - */ - currentTimeoutId_: null, - - /** - * Handler used to communicate state updates back to the CellularSetup - * service. - * @private {?chromeos.cellularSetup.mojom.CarrierPortalHandlerRemote} - */ - carrierPortalHandler_: null, - - /** @override */ - created() { - this.mojoInterfaceProvider_ = - cellular_setup.MojoInterfaceProviderImpl.getInstance(); - }, - - /** @override */ - ready() { - this.state_ = cellularSetup.State.STARTING_ACTIVATION; - }, - - /** - * Overrides chromeos.cellularSetup.mojom.ActivationDelegateInterface. - * @param {!chromeos.cellularSetup.mojom.CellularMetadata} metadata - * @private - */ - onActivationStarted(metadata) { - this.clearTimer_(); - this.cellularMetadata_ = metadata; - this.state_ = cellularSetup.State.WAITING_FOR_PORTAL_TO_LOAD; - }, - - /** - * Overrides chromeos.cellularSetup.mojom.ActivationDelegateInterface. - * @param {!chromeos.cellularSetup.mojom.ActivationResult} result - * @private - */ - onActivationFinished(result) { - this.closeActivationConnection_(); - - const ActivationResult = chromeos.cellularSetup.mojom.ActivationResult; - switch (result) { - case ActivationResult.kSuccessfullyStartedActivation: - this.state_ = cellularSetup.State.ALREADY_ACTIVATED; - break; - case ActivationResult.kAlreadyActivated: - this.state_ = cellularSetup.State.ACTIVATION_SUCCESS; - break; - case ActivationResult.kFailedToActivate: - this.state_ = cellularSetup.State.ACTIVATION_FAILURE; - break; - default: - assertNotReached(); - } - }, - - /** @private */ - updateShowError_() { - switch (this.state_) { - case cellularSetup.State.TIMEOUT_START_ACTIVATION: - case cellularSetup.State.TIMEOUT_PORTAL_LOAD: - case cellularSetup.State.TIMEOUT_FINISH_ACTIVATION: - case cellularSetup.State.ACTIVATION_FAILURE: - this.showError_ = true; - return; - default: - this.showError_ = false; - return; - } - }, - - /** @private */ - updateSelectedPage_() { - switch (this.state_) { - case cellularSetup.State.IDLE: - case cellularSetup.State.STARTING_ACTIVATION: - case cellularSetup.State.WAITING_FOR_ACTIVATION_TO_START: - case cellularSetup.State.TIMEOUT_START_ACTIVATION: - this.selectedPageName_ = cellularSetup.PageName.SIM_DETECT; - return; - case cellularSetup.State.WAITING_FOR_PORTAL_TO_LOAD: - case cellularSetup.State.TIMEOUT_PORTAL_LOAD: - case cellularSetup.State.WAITING_FOR_USER_PAYMENT: - this.selectedPageName_ = cellularSetup.PageName.PROVISIONING; - return; - case cellularSetup.State.WAITING_FOR_ACTIVATION_TO_FINISH: - case cellularSetup.State.TIMEOUT_FINISH_ACTIVATION: - case cellularSetup.State.ACTIVATION_SUCCESS: - case cellularSetup.State.ALREADY_ACTIVATED: - case cellularSetup.State.ACTIVATION_FAILURE: - this.selectedPageName_ = cellularSetup.PageName.FINAL; - return; - default: - assertNotReached(); - } - }, - - /** @private */ - handleStateChange_() { - // Since the state has changed, the previous state did not time out, so - // clear any active timeout. - this.clearTimer_(); - - // If the new state has an associated timeout, set it. - const timeoutMs = cellularSetup.getTimeoutMsForState(this.state_); - if (timeoutMs !== null) { - this.currentTimeoutId_ = - setTimeout(this.onTimeout_.bind(this), timeoutMs); - } - - if (this.state_ === cellularSetup.State.STARTING_ACTIVATION) { - this.startActivation_(); - return; - } - }, - - /** @private */ - onTimeout_() { - // The activation attempt failed, so close the connection to the service. - this.closeActivationConnection_(); - - switch (this.state_) { - case cellularSetup.State.STARTING_ACTIVATION: - this.state_ = cellularSetup.State.TIMEOUT_START_ACTIVATION; - return; - case cellularSetup.State.WAITING_FOR_PORTAL_TO_LOAD: - this.state_ = cellularSetup.State.TIMEOUT_PORTAL_LOAD; - return; - case cellularSetup.State.WAITING_FOR_ACTIVATION_TO_FINISH: - this.state_ = cellularSetup.State.TIMEOUT_FINISH_ACTIVATION; - return; - default: - // Only the above states are expected to time out. - assertNotReached(); - } - }, - - /** @private */ - startActivation_() { - assert(!this.activationDelegateReceiver_); - this.activationDelegateReceiver_ = - new chromeos.cellularSetup.mojom.ActivationDelegateReceiver( - /** - * @type {!chromeos.cellularSetup.mojom.ActivationDelegateInterface} - */ - (this)); - - this.mojoInterfaceProvider_.getMojoServiceRemote() - .startActivation( - this.activationDelegateReceiver_.$.bindNewPipeAndPassRemote()) - .then( - /** - * @param {!chromeos.cellularSetup. - * mojom.CellularSetup_StartActivation_ResponseParams} - * params - */ - (params) => { - this.carrierPortalHandler_ = params.observer; - }); - }, - - /** @private */ - closeActivationConnection_() { - assert(!!this.activationDelegateReceiver_); - this.activationDelegateReceiver_.$.close(); - this.activationDelegateReceiver_ = null; - this.carrierPortalHandler_ = null; - this.cellularMetadata_ = null; - }, - - /** @private */ - clearTimer_() { - if (this.currentTimeoutId_) { - clearTimeout(this.currentTimeoutId_); - } - this.currentTimeoutId_ = null; - }, - - /** @private */ - onCarrierPortalLoaded_() { - this.state_ = cellularSetup.State.WAITING_FOR_USER_PAYMENT; - this.carrierPortalHandler_.onCarrierPortalStatusChange( - chromeos.cellularSetup.mojom.CarrierPortalStatus - .kPortalLoadedWithoutPaidUser); - }, - - /** - * @param {!CustomEvent<boolean>} event - * @private - */ - onCarrierPortalResult_(event) { - const success = event.detail; - this.state_ = success ? cellularSetup.State.ACTIVATION_SUCCESS : - cellularSetup.State.ACTIVATION_FAILURE; - }, - /** @private */ onBackwardNavRequested_() { - // TODO(azeemarshad): Add back navigation. + // TODO(crbug.com/1093185): Add back navigation. }, /** @private */ onRetryRequested_() { - // TODO(azeemarshad): Add try again logic. + // TODO(crbug.com/1093185): Add try again logic. }, /** @private */ - onCompleteFlowRequested__() { - // TODO(azeemarshad): Add completion logic. + onCompleteFlowRequested_() { + // TODO(crbug.com/1093185): Add completion logic. }, }); diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.js index 782b14cff1e..e5f87bd0164 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.js @@ -2,15 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// #import {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; + cr.define('cellular_setup', function() { /** @interface */ - class MojoInterfaceProvider { + /* #export */ class MojoInterfaceProvider { /** @return {!chromeos.cellularSetup.mojom.CellularSetupRemote} */ getMojoServiceRemote() {} } /** @implements {cellular_setup.MojoInterfaceProvider} */ - class MojoInterfaceProviderImpl { + /* #export */ class MojoInterfaceProviderImpl { constructor() { /** @private {?chromeos.cellularSetup.mojom.CellularSetupRemote} */ this.remote_ = null; @@ -28,6 +30,7 @@ cr.define('cellular_setup', function() { cr.addSingletonGetter(MojoInterfaceProviderImpl); + // #cr_define_end return { MojoInterfaceProvider: MojoInterfaceProvider, MojoInterfaceProviderImpl: MojoInterfaceProviderImpl, diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html new file mode 100644 index 00000000000..2782ca84a7e --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html @@ -0,0 +1,35 @@ +<link rel="import" href="../../../html/polymer.html"> + +<link rel="import" href="../../../html/i18n_behavior.html"> +<link rel="import" href="mojo_interface_provider.html"> +<link rel="import" href="sim_detect_page.html"> +<link rel="import" href="provisioning_page.html"> +<link rel="import" href="final_page.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> + +<dom-module id="psim-flow-ui"> + <template> + <style include="iron-flex"> + :host { + display: flex; + flex: 1 1 auto; + flex-direction: column; + } + </style> + <iron-pages attr-for-selected="is" + selected="[[selectedPSimPageName_]]" + selected-item="{{selectedPage_}}"> + <sim-detect-page show-error="[[showError_]]"></sim-detect-page> + <provisioning-page show-error="{{showError_}}" + cellular-metadata="[[cellularMetadata_]]" + on-carrier-portal-loaded="onCarrierPortalLoaded_" + on-carrier-portal-result="onCarrierPortalResult_"> + </provisioning-page> + <final-page show-error="[[showError_]]"></final-page> + </iron-pages> + </template> + <script src="psim_flow_ui.js"> + </script> +</dom-module> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.js new file mode 100644 index 00000000000..4f7dce5d81f --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.js @@ -0,0 +1,348 @@ +// 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. + +cr.define('cellularSetup', function() { + /** @enum{string} */ + const PSimPageName = { + SIM_DETECT: 'sim-detect-page', + PROVISIONING: 'provisioning-page', + FINAL: 'final-page', + }; + + /** @enum{string} */ + const PSimUIState = { + IDLE: 'idle', + STARTING_ACTIVATION: 'starting-activation', + WAITING_FOR_ACTIVATION_TO_START: 'waiting-for-activation-to-start', + TIMEOUT_START_ACTIVATION: 'timeout-start-activation', + WAITING_FOR_PORTAL_TO_LOAD: 'waiting-for-portal-to-load', + TIMEOUT_PORTAL_LOAD: 'timeout-portal-load', + WAITING_FOR_USER_PAYMENT: 'waiting-for-user-payment', + WAITING_FOR_ACTIVATION_TO_FINISH: 'waiting-for-activation-to-finish', + TIMEOUT_FINISH_ACTIVATION: 'timeout-finish-activation', + ACTIVATION_SUCCESS: 'activation-success', + ALREADY_ACTIVATED: 'already-activated', + ACTIVATION_FAILURE: 'activation-failure', + }; + + /** + * @param {!cellularSetup.PSimUIState} state + * @return {?number} The time delta, in ms, for the timeout corresponding to + * |state|. If no timeout is applicable for this state, null is returned. + */ + function getTimeoutMsForPSimUIState(state) { + // In some cases, starting activation may require power-cycling the device's + // modem, a process that can take several seconds. + if (state === PSimUIState.STARTING_ACTIVATION) { + return 10000; // 10 seconds. + } + + // The portal is a website served by the mobile carrier. + if (state === PSimUIState.WAITING_FOR_PORTAL_TO_LOAD) { + return 10000; // 10 seconds. + } + + // Finishing activation only requires sending a D-Bus message to Shill. + if (state === PSimUIState.WAITING_FOR_ACTIVATION_TO_FINISH) { + return 1000; // 1 second. + } + + // No other states require timeouts. + return null; + } + + return { + PSimPageName: PSimPageName, + PSimUIState: PSimUIState, + getTimeoutMsForPSimUIState: getTimeoutMsForPSimUIState + }; +}); + +/** + * Root element for the pSIM cellular setup flow. This element interacts with + * the CellularSetup service to carry out the psim activation flow. It contains + * navigation buttons and sub-pages corresponding to each step of the flow. + */ +Polymer({ + is: 'psim-flow-ui', + + behaviors: [I18nBehavior], + + properties: { + /** @private {!cellularSetup.PSimUIState} */ + state_: { + type: String, + value: cellularSetup.PSimUIState.IDLE, + }, + + /** + * Element name of the current selected sub-page. + * @private {!cellularSetup.PSimPageName} + */ + selectedPSimPageName_: { + type: String, + value: cellularSetup.PSimPageName.SIM_DETECT, + notify: true, + }, + + /** + * DOM Element for the current selected sub-page. + * @private {!SimDetectPageElement|!ProvisioningPageElement| + * !FinalPageElement} + */ + selectedPage_: Object, + + /** + * Whether error state should be shown for the current page. + * @private {boolean} + */ + showError_: {type: Boolean, value: false}, + + /** + * Cellular metadata received via the onActivationStarted() callback. If + * that callback has not occurred, this field is null. + * @private {?chromeos.cellularSetup.mojom.CellularMetadata} + */ + cellularMetadata_: { + type: Object, + value: null, + }, + + /** + * Whether try again should be shown in the button bar. + * @private {boolean} + */ + showTryAgainButton_: {type: Boolean, value: false}, + + /** + * Whether finish button should be shown in the button bar. + * @private {boolean} + */ + showFinishButton_: {type: Boolean, value: false}, + + /** + * Whether cancel button should be shown in the button bar. + * @private {boolean} + */ + showCancelButton_: {type: Boolean, value: false} + }, + + observers: [ + 'updateShowError_(state_)', + 'updateSelectedPage_(state_)', + 'handlePSimUIStateChange_(state_)', + ], + + /** + * Provides an interface to the CellularSetup Mojo service. + * @private {?cellular_setup.MojoInterfaceProvider} + */ + mojoInterfaceProvider_: null, + + /** + * Delegate responsible for routing activation started/finished events. + * @private {?chromeos.cellularSetup.mojom.ActivationDelegateReceiver} + */ + activationDelegateReceiver_: null, + + /** + * The timeout ID corresponding to a timeout for the current state. If no + * timeout is active, this value is null. + * @private {?number} + */ + currentTimeoutId_: null, + + /** + * Handler used to communicate state updates back to the CellularSetup + * service. + * @private {?chromeos.cellularSetup.mojom.CarrierPortalHandlerRemote} + */ + carrierPortalHandler_: null, + + /** @override */ + created() { + this.mojoInterfaceProvider_ = + cellular_setup.MojoInterfaceProviderImpl.getInstance(); + }, + + /** @override */ + ready() { + this.state_ = cellularSetup.PSimUIState.STARTING_ACTIVATION; + }, + + /** + * Overrides chromeos.cellularSetup.mojom.ActivationDelegateInterface. + * @param {!chromeos.cellularSetup.mojom.CellularMetadata} metadata + * @private + */ + onActivationStarted(metadata) { + this.clearTimer_(); + this.cellularMetadata_ = metadata; + this.state_ = cellularSetup.PSimUIState.WAITING_FOR_PORTAL_TO_LOAD; + }, + + /** + * Overrides chromeos.cellularSetup.mojom.ActivationDelegateInterface. + * @param {!chromeos.cellularSetup.mojom.ActivationResult} result + * @private + */ + onActivationFinished(result) { + this.closeActivationConnection_(); + + const ActivationResult = chromeos.cellularSetup.mojom.ActivationResult; + switch (result) { + case ActivationResult.kSuccessfullyStartedActivation: + this.state_ = cellularSetup.PSimUIState.ALREADY_ACTIVATED; + break; + case ActivationResult.kAlreadyActivated: + this.state_ = cellularSetup.PSimUIState.ACTIVATION_SUCCESS; + break; + case ActivationResult.kFailedToActivate: + this.state_ = cellularSetup.PSimUIState.ACTIVATION_FAILURE; + break; + default: + assertNotReached(); + } + }, + + /** @private */ + updateShowError_() { + switch (this.state_) { + case cellularSetup.PSimUIState.TIMEOUT_START_ACTIVATION: + case cellularSetup.PSimUIState.TIMEOUT_PORTAL_LOAD: + case cellularSetup.PSimUIState.TIMEOUT_FINISH_ACTIVATION: + case cellularSetup.PSimUIState.ACTIVATION_FAILURE: + this.showError_ = true; + return; + default: + this.showError_ = false; + return; + } + }, + + /** @private */ + updateSelectedPage_() { + switch (this.state_) { + case cellularSetup.PSimUIState.IDLE: + case cellularSetup.PSimUIState.STARTING_ACTIVATION: + case cellularSetup.PSimUIState.WAITING_FOR_ACTIVATION_TO_START: + case cellularSetup.PSimUIState.TIMEOUT_START_ACTIVATION: + this.selectedPSimPageName_ = cellularSetup.PSimPageName.SIM_DETECT; + return; + case cellularSetup.PSimUIState.WAITING_FOR_PORTAL_TO_LOAD: + case cellularSetup.PSimUIState.TIMEOUT_PORTAL_LOAD: + case cellularSetup.PSimUIState.WAITING_FOR_USER_PAYMENT: + this.selectedPSimPageName_ = cellularSetup.PSimPageName.PROVISIONING; + return; + case cellularSetup.PSimUIState.WAITING_FOR_ACTIVATION_TO_FINISH: + case cellularSetup.PSimUIState.TIMEOUT_FINISH_ACTIVATION: + case cellularSetup.PSimUIState.ACTIVATION_SUCCESS: + case cellularSetup.PSimUIState.ALREADY_ACTIVATED: + case cellularSetup.PSimUIState.ACTIVATION_FAILURE: + this.selectedPSimPageName_ = cellularSetup.PSimPageName.FINAL; + return; + default: + assertNotReached(); + } + }, + + /** @private */ + handlePSimUIStateChange_() { + // Since the state has changed, the previous state did not time out, so + // clear any active timeout. + this.clearTimer_(); + + // If the new state has an associated timeout, set it. + const timeoutMs = cellularSetup.getTimeoutMsForPSimUIState(this.state_); + if (timeoutMs !== null) { + this.currentTimeoutId_ = + setTimeout(this.onTimeout_.bind(this), timeoutMs); + } + + if (this.state_ === cellularSetup.PSimUIState.STARTING_ACTIVATION) { + this.startActivation_(); + return; + } + }, + + /** @private */ + onTimeout_() { + // The activation attempt failed, so close the connection to the service. + this.closeActivationConnection_(); + + switch (this.state_) { + case cellularSetup.PSimUIState.STARTING_ACTIVATION: + this.state_ = cellularSetup.PSimUIState.TIMEOUT_START_ACTIVATION; + return; + case cellularSetup.PSimUIState.WAITING_FOR_PORTAL_TO_LOAD: + this.state_ = cellularSetup.PSimUIState.TIMEOUT_PORTAL_LOAD; + return; + case cellularSetup.PSimUIState.WAITING_FOR_ACTIVATION_TO_FINISH: + this.state_ = cellularSetup.PSimUIState.TIMEOUT_FINISH_ACTIVATION; + return; + default: + // Only the above states are expected to time out. + assertNotReached(); + } + }, + + /** @private */ + startActivation_() { + assert(!this.activationDelegateReceiver_); + this.activationDelegateReceiver_ = + new chromeos.cellularSetup.mojom.ActivationDelegateReceiver( + /** + * @type {!chromeos.cellularSetup.mojom.ActivationDelegateInterface} + */ + (this)); + + this.mojoInterfaceProvider_.getMojoServiceRemote() + .startActivation( + this.activationDelegateReceiver_.$.bindNewPipeAndPassRemote()) + .then( + /** + * @param {!chromeos.cellularSetup. + * mojom.CellularSetup_StartActivation_ResponseParams} + * params + */ + (params) => { + this.carrierPortalHandler_ = params.observer; + }); + }, + + /** @private */ + closeActivationConnection_() { + assert(!!this.activationDelegateReceiver_); + this.activationDelegateReceiver_.$.close(); + this.activationDelegateReceiver_ = null; + this.carrierPortalHandler_ = null; + this.cellularMetadata_ = null; + }, + + /** @private */ + clearTimer_() { + if (this.currentTimeoutId_) { + clearTimeout(this.currentTimeoutId_); + } + this.currentTimeoutId_ = null; + }, + + /** @private */ + onCarrierPortalLoaded_() { + this.state_ = cellularSetup.PSimUIState.WAITING_FOR_USER_PAYMENT; + this.carrierPortalHandler_.onCarrierPortalStatusChange( + chromeos.cellularSetup.mojom.CarrierPortalStatus + .kPortalLoadedWithoutPaidUser); + }, + + /** + * @param {!CustomEvent<boolean>} event + * @private + */ + onCarrierPortalResult_(event) { + const success = event.detail; + this.state_ = success ? cellularSetup.PSimUIState.ACTIVATION_SUCCESS : + cellularSetup.PSimUIState.ACTIVATION_FAILURE; + }, +}); diff --git a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/webview_post_util.js b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/webview_post_util.js index 088b82645d2..5ee36ed4016 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/webview_post_util.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/cellular_setup/webview_post_util.js @@ -95,7 +95,8 @@ cr.define('webviewPost.util', function() { * @param {string} paymentUrl URL to load. * @param {string} postData Data to pass. */ - function postDeviceDataToWebview(webview, paymentUrl, postData) { + /* #export */ function postDeviceDataToWebview( + webview, paymentUrl, postData) { const webviewSrc = 'data:text/html;charset=utf-8,' + encodeURIComponent(WEBVIEW_REDIRECT_HTML); webview.addEventListener( @@ -105,5 +106,6 @@ cr.define('webviewPost.util', function() { webview.src = webviewSrc; } + // #cr_define_end return {postDeviceDataToWebview: postDeviceDataToWebview}; }); diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/icons.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/icons.html index 2eee1473ba5..797d976b284 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/icons.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/icons.html @@ -25,6 +25,9 @@ <g id="messages" fill="none" fill-rule="evenodd"> <path d="M16.3107503,3 L3.66666667,3 C2.75,3 2,3.75 2,4.66666667 L2,18.3161621 L5.33333333,15 L16.3107503,15 C17.227417,15 17.977417,14.2328288 17.977417,13.3161621 L17.977417,4.66666667 C17.977417,3.75 17.227417,3 16.3107503,3 Z M16,13 L4,13 L4,5 L16,5 L16,13 Z M6,8 L8,8 L8,10 L6,10 L6,8 Z M9,8 L11,8 L11,10 L9,10 L9,8 Z M12,8 L14,8 L14,10 L12,10 L12,8 Z" fill="#9AA0A6"></path> </g> + <g id="notifications" fill="none" fill-rule="evenodd"> + <path d="M11,3.10001812 C13.2822403,3.56328845 15,5.58104209 15,8 C15,10.7614237 15,13 15,13 L17,13 L17,15 L3,15 L3,13 L5,13 C5,13 5,9.9021552 5,8 C5,5.58104209 6.71775968,3.56328845 9,3.10001812 L9,2.5 C9,1.94771525 9.44771525,1.5 10,1.5 C10.5522847,1.5 11,1.94771525 11,2.5 L11,3.10001812 Z M7,8 L7,13 L13,13 L13,8 C13,6.34314575 11.6568542,5 10,5 C8.34314575,5 7,6.34314575 7,8 Z M10,18 C8.8954305,18 8,17.1045695 8,16 L12,16 C12,17.1045695 11.1045695,18 10,18 Z" fill="#9AA0A6"></path> + </g> <g id="downloads" fill="none" fill-rule="evenodd"> <path d="M2,13 L4,13 L4,16 L16,16 L16,13 L18,13 L18,16 C18,17.1 17.1,18 16,18 L4,18 C2.9,18 2,17.1 2,16 L2,13 Z M13.59,7.59 L11,10.17 L11,2 L9,2 L9,10.17 L6.41,7.59 L5,9 L10,14 L15,9 L13.59,7.59 Z" fill="#9AA0A6"></path> </g> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html index d5de70f7d2f..5da74e7edb3 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html @@ -153,6 +153,15 @@ locale, 'startSetupPageFeatureListAwm')]]"> </span> </div> + <template is="dom-if" if="[[phoneHubEnabled_]]"> + <div class="feature-detail"> + <iron-icon icon="multidevice-setup-icons-20:notifications"> + </iron-icon> + <span> + [[i18nDynamic(locale, 'startSetupPageFeatureMirrorPhoneNotifications')]] + </span> + </div> + </template> <div class="feature-detail"> <iron-icon icon="multidevice-setup-icons-20:downloads"> </iron-icon> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js index 8783fffae9d..fc28b6edfe9 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js @@ -51,6 +51,15 @@ Polymer({ * @type {!multidevice_setup.MultiDeviceSetupDelegate} */ delegate: Object, + + /** @private */ + phoneHubEnabled_: { + type: Boolean, + value() { + return loadTimeData.valueExists('phoneHubEnabled') && + loadTimeData.getBoolean('phoneHubEnabled'); + }, + }, }, behaviors: [ diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/network/BUILD.gn index ca7f9fc53fc..57abd5fe8a1 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/BUILD.gn +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/BUILD.gn @@ -3,11 +3,14 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("../os_cr_components.gni") assert(is_chromeos, "Only ChromeOS components belong here.") js_type_check("closure_compile") { deps = [ + ":cr_policy_network_behavior_mojo", + ":cr_policy_network_indicator_mojo", ":mojo_interface_provider", ":network_apnlist", ":network_choose_mobile", @@ -40,16 +43,33 @@ js_library("mojo_interface_provider") { ] } +js_library("cr_policy_network_behavior_mojo") { + deps = [ + ":mojo_interface_provider", + ":onc_mojo", + "../../../cr_elements/policy:cr_policy_indicator_behavior", + "//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile", + ] +} + +js_library("cr_policy_network_indicator_mojo") { + deps = [ + ":cr_policy_network_behavior_mojo", + "../../../cr_elements/policy:cr_policy_indicator_behavior", + "../../../cr_elements/policy:cr_tooltip_icon", + ] +} + js_library("network_apnlist") { deps = [ - "//ui/webui/resources/cr_components/chromeos/network:network_config", + ":network_config", "//ui/webui/resources/js:i18n_behavior", ] } js_library("network_choose_mobile") { deps = [ - "//ui/webui/resources/cr_components/chromeos/network:network_config", + ":network_config", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", ] @@ -57,9 +77,9 @@ js_library("network_choose_mobile") { js_library("network_config") { deps = [ + ":mojo_interface_provider", ":network_listener_behavior", "//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile", - "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", ] @@ -70,15 +90,15 @@ js_library("network_config") { js_library("network_config_element_behavior") { deps = [ + ":cr_policy_network_behavior_mojo", ":onc_mojo", - "//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo", ] } js_library("network_config_input") { deps = [ + ":cr_policy_network_behavior_mojo", ":network_config_element_behavior", - "//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo", ] externs_list = [ "$externs_path/networking_private.js" ] extra_sources = [ "$interfaces_path/networking_private_interface.js" ] @@ -86,8 +106,8 @@ js_library("network_config_input") { js_library("network_config_select") { deps = [ + ":cr_policy_network_behavior_mojo", ":network_config_element_behavior", - "//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", ] @@ -97,8 +117,8 @@ js_library("network_config_select") { js_library("network_config_toggle") { deps = [ + ":cr_policy_network_behavior_mojo", ":network_config_element_behavior", - "//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo", ] externs_list = [ "$externs_path/networking_private.js" ] extra_sources = [ "$interfaces_path/networking_private_interface.js" ] @@ -107,22 +127,24 @@ js_library("network_config_toggle") { js_library("network_ip_config") { deps = [ ":onc_mojo", + "../../../cr_elements/cr_toggle:cr_toggle", "//ui/webui/resources/js:i18n_behavior", ] } js_library("network_nameservers") { deps = [ + ":cr_policy_network_behavior_mojo", ":onc_mojo", - "//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo", + "../../../cr_elements/cr_radio_group:cr_radio_group", "//ui/webui/resources/js:i18n_behavior", ] } js_library("network_password_input") { deps = [ + ":cr_policy_network_behavior_mojo", ":network_config_element_behavior", - "//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo", "//ui/webui/resources/js:i18n_behavior", ] externs_list = [ "$externs_path/networking_private.js" ] @@ -131,8 +153,8 @@ js_library("network_password_input") { js_library("network_property_list_mojo") { deps = [ + ":cr_policy_network_behavior_mojo", ":onc_mojo", - "//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", ] @@ -140,8 +162,8 @@ js_library("network_property_list_mojo") { js_library("network_proxy") { deps = [ + ":cr_policy_network_behavior_mojo", ":onc_mojo", - "//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", ] @@ -185,8 +207,8 @@ js_library("network_list") { js_library("network_list_item") { deps = [ + ":cr_policy_network_behavior_mojo", ":network_list_types", - "//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", ] @@ -222,44 +244,69 @@ js_library("onc_mojo") { ] } -# TODO: Uncomment as the Polymer3 migration makes progress. -# js_type_check("closure_compile_module") { -# is_polymer3 = true -# deps = [ -# ":mojo_interface_provider.m", -# ":network_apnlist.m", -# ":network_choose_mobile.m", -# ":network_config.m", -# ":network_config_element_behavior.m", -# ":network_config_input.m", -# ":network_config_select.m", -# ":network_config_toggle.m", -# ":network_icon.m", -# ":network_icons.m", -# ":network_ip_config.m", -# ":network_list.m", -# ":network_list_item.m", -# ":network_list_types.m", -# ":network_listener_behavior.m", -# ":network_nameservers.m", -# ":network_password_input.m", -# ":network_property_list_mojo.m", -# ":network_proxy.m", -# ":network_proxy_exclusions.m", -# ":network_proxy_input.m", -# ":network_select.m", -# ":network_shared_css.m", -# ":network_siminfo.m", -# ":onc_mojo.m" -# ] -# } +js_type_check("closure_compile_module") { + is_polymer3 = true + deps = [ + ":cr_policy_network_behavior_mojo.m", + ":cr_policy_network_indicator_mojo.m", + ":mojo_interface_provider.m", + + # ":network_apnlist.m", + # ":network_choose_mobile.m", + # ":network_config.m", + ":network_config_element_behavior.m", + # ":network_config_input.m", + # ":network_config_select.m", + # ":network_config_toggle.m", + ":network_icon.m", + + # ":network_ip_config.m", + ":network_list.m", + ":network_list_item.m", + ":network_list_types.m", + ":network_listener_behavior.m", + + # ":network_nameservers.m", + ":network_password_input.m", + # ":network_property_list_mojo.m", + # ":network_proxy.m", + # ":network_proxy_exclusions.m", + # ":network_proxy_input.m", + # ":network_select.m", + ":network_shared_css.m", + # ":network_siminfo.m", + ":onc_mojo.m", + ] +} js_library("mojo_interface_provider.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.m.js" ] deps = [ - # TODO: Fill those in. + "//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile", + "//ui/webui/resources/js:cr.m", ] - extra_deps = [ ":mojo_interface_provider_module" ] + extra_deps = [ ":modulize" ] +} + +js_library("cr_policy_network_behavior_mojo.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.m.js" ] + deps = [ + "../../../cr_elements/policy:cr_policy_indicator_behavior.m", + "//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] + extra_deps = [ ":modulize" ] +} + +js_library("cr_policy_network_indicator_mojo.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_indicator_mojo.m.js" ] + deps = [ + ":cr_policy_network_behavior_mojo.m", + ":onc_mojo", + "../../../cr_elements/policy:cr_policy_indicator_behavior.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] + extra_deps = [ ":cr_policy_network_indicator_mojo_module" ] } js_library("network_apnlist.m") { @@ -288,9 +335,6 @@ js_library("network_config.m") { js_library("network_config_element_behavior.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_config_element_behavior.m.js" ] - deps = [ - # TODO: Fill those in. - ] extra_deps = [ ":modulize" ] } @@ -321,19 +365,14 @@ js_library("network_config_toggle.m") { js_library("network_icon.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_icon.m.js" ] deps = [ - # TODO: Fill those in. + ":onc_mojo.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:i18n_behavior.m", ] extra_deps = [ ":network_icon_module" ] } -js_library("network_icons.m") { - sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_icons.m.js" ] - deps = [ - # TODO: Fill those in. - ] - extra_deps = [ ":network_icons_module" ] -} - js_library("network_ip_config.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_ip_config.m.js" ] deps = [ @@ -345,7 +384,9 @@ js_library("network_ip_config.m") { js_library("network_list.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_list.m.js" ] deps = [ - # TODO: Fill those in. + "//third_party/polymer/v3_0/components-chromium/iron-list:iron-list", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements:cr_scrollable_behavior.m", ] extra_deps = [ ":network_list_module" ] } @@ -353,23 +394,21 @@ js_library("network_list.m") { js_library("network_list_item.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_list_item.m.js" ] deps = [ - # TODO: Fill those in. + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] extra_deps = [ ":network_list_item_module" ] } js_library("network_list_types.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_list_types.m.js" ] - deps = [ - # TODO: Fill those in. - ] - extra_deps = [ ":network_list_types_module" ] + extra_deps = [ ":modulize" ] } js_library("network_listener_behavior.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.m.js" ] deps = [ - # TODO: Fill those in. + ":mojo_interface_provider.m", + "//ui/webui/resources/js:assert.m", ] extra_deps = [ ":modulize" ] } @@ -385,7 +424,14 @@ js_library("network_nameservers.m") { js_library("network_password_input.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/network_password_input.m.js" ] deps = [ - # TODO: Fill those in. + ":cr_policy_network_behavior_mojo.m", + ":cr_policy_network_indicator_mojo.m", + ":network_config_element_behavior.m", + ":network_shared_css.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m", + "//ui/webui/resources/cr_elements/cr_input:cr_input.m", + "//ui/webui/resources/js:i18n_behavior.m", ] extra_deps = [ ":network_password_input_module" ] } @@ -449,17 +495,19 @@ js_library("network_siminfo.m") { js_library("onc_mojo.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network/onc_mojo.m.js" ] deps = [ - # TODO: Fill those in. + "//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:load_time_data.m", ] - extra_deps = [ ":onc_mojo_module" ] + extra_deps = [ ":modulize" ] } import("//tools/polymer/polymer.gni") group("polymer3_elements") { public_deps = [ + ":cr_policy_network_indicator_mojo_module", ":modulize", - ":mojo_interface_provider_module", ":network_apnlist_module", ":network_choose_mobile_module", ":network_config_input_module", @@ -471,7 +519,6 @@ group("polymer3_elements") { ":network_ip_config_module", ":network_list_item_module", ":network_list_module", - ":network_list_types_module", ":network_nameservers_module", ":network_password_input_module", ":network_property_list_mojo_module", @@ -480,14 +527,16 @@ group("polymer3_elements") { ":network_select_module", ":network_shared_css_module", ":network_siminfo_module", - ":onc_mojo_module", ] } -polymer_modulizer("mojo_interface_provider") { - js_file = "mojo_interface_provider.js" - html_file = "mojo_interface_provider.html" +polymer_modulizer("cr_policy_network_indicator_mojo") { + js_file = "cr_policy_network_indicator_mojo.js" + html_file = "cr_policy_network_indicator_mojo.html" html_type = "dom-module" + auto_imports = cr_components_chromeos_auto_imports + [ + "ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.html|CrPolicyIndicatorBehavior,CrPolicyIndicatorType", + ] } polymer_modulizer("network_apnlist") { @@ -530,6 +579,7 @@ polymer_modulizer("network_icon") { js_file = "network_icon.js" html_file = "network_icon.html" html_type = "dom-module" + auto_imports = cr_components_chromeos_auto_imports } polymer_modulizer("network_icons") { @@ -548,18 +598,14 @@ polymer_modulizer("network_list") { js_file = "network_list.js" html_file = "network_list.html" html_type = "dom-module" + auto_imports = cr_components_chromeos_auto_imports } polymer_modulizer("network_list_item") { js_file = "network_list_item.js" html_file = "network_list_item.html" html_type = "dom-module" -} - -polymer_modulizer("network_list_types") { - js_file = "network_list_types.js" - html_file = "network_list_types.html" - html_type = "dom-module" + auto_imports = cr_components_chromeos_auto_imports } polymer_modulizer("network_nameservers") { @@ -572,6 +618,9 @@ polymer_modulizer("network_password_input") { js_file = "network_password_input.js" html_file = "network_password_input.html" html_type = "dom-module" + auto_imports = cr_components_chromeos_auto_imports + [ + "ui/webui/resources/cr_components/chromeos/network/network_config_element_behavior.html|NetworkConfigElementBehavior", + ] } polymer_modulizer("network_property_list_mojo") { @@ -610,18 +659,17 @@ polymer_modulizer("network_siminfo") { html_type = "dom-module" } -polymer_modulizer("onc_mojo") { - js_file = "onc_mojo.js" - html_file = "onc_mojo.html" - html_type = "dom-module" -} - import("//ui/webui/resources/tools/js_modulizer.gni") js_modulizer("modulize") { input_files = [ + "cr_policy_network_behavior_mojo.js", + "mojo_interface_provider.js", "network_config_element_behavior.js", "network_listener_behavior.js", + "network_list_types.js", "network_proxy.js", + "onc_mojo.js", ] + namespace_rewrites = cr_components_chromeos_namespace_rewrites } diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.html b/chromium/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.html new file mode 100644 index 00000000000..56e995a45ea --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.html @@ -0,0 +1,5 @@ +<link rel="import" href="../../../html/polymer.html"> +<link rel="import" href="../../../cr_elements/policy/cr_policy_indicator_behavior.html"> +<link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html"> +<link rel="import" href="chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom.html"> +<script src="cr_policy_network_behavior_mojo.js"></script> diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior_mojo.js b/chromium/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.js index 10d48330d00..3845594d058 100644 --- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior_mojo.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.js @@ -8,8 +8,14 @@ * optional properties (which may be null|undefined). */ +// clang-format off +// #import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; +// #import 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-lite.js'; +// #import {CrPolicyIndicatorType} from 'chrome://resources/cr_elements/policy/cr_policy_indicator_behavior.m.js'; +// clang-format on + /** @polymerBehavior */ -const CrPolicyNetworkBehaviorMojo = { +/* #export */ const CrPolicyNetworkBehaviorMojo = { /** * @param {?OncMojo.ManagedProperty|undefined} property * @return {boolean} True if the property is controlled by network policy. diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator_mojo.html b/chromium/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_indicator_mojo.html index c0385286655..62cddfd80cd 100644 --- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator_mojo.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_indicator_mojo.html @@ -1,9 +1,9 @@ -<link rel="import" href="../../html/polymer.html"> +<link rel="import" href="../../../html/polymer.html"> -<link rel="import" href="../hidden_style_css.html"> -<link rel="import" href="cr_policy_indicator_behavior.html"> +<link rel="import" href="../../../cr_elements/hidden_style_css.html"> +<link rel="import" href="../../../cr_elements/policy/cr_policy_indicator_behavior.html"> +<link rel="import" href="../../../cr_elements/policy/cr_tooltip_icon.html"> <link rel="import" href="cr_policy_network_behavior_mojo.html"> -<link rel="import" href="cr_tooltip_icon.html"> <dom-module id="cr-policy-network-indicator-mojo"> <template> diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator_mojo.js b/chromium/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_indicator_mojo.js index 59af73c1a26..73ad2eaa2b3 100644 --- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator_mojo.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_indicator_mojo.js @@ -6,8 +6,6 @@ * @fileoverview Polymer element for indicating policies based on network * properties. */ -(function() { -'use strict'; Polymer({ is: 'cr-policy-network-indicator-mojo', @@ -80,4 +78,3 @@ Polymer({ return this.getIndicatorTooltip(this.indicatorType, '', matches); } }); -})(); diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.html b/chromium/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.html index 7eaa61575ef..3e7907f0ad6 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.html @@ -1,4 +1,7 @@ <link rel="import" href="../../../html/cr.html"> <link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html"> +<link rel="import" href="chrome://resources/mojo/services/network/public/mojom/ip_address.mojom.html"> +<link rel="import" href="chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom.html"> +<link rel="import" href="chrome://resources/mojo/mojo/public/mojom/base/time.mojom.html"> <link rel="import" href="chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom.html"> <script src="mojo_interface_provider.js"></script> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.js b/chromium/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.js index e83e3853d95..d90fc30a09f 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.js @@ -2,15 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; +// #import 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-lite.js'; +// #import 'chrome://resources/mojo/services/network/public/mojom/ip_address.mojom-lite.js'; +// #import 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js'; +// #import 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-lite.js'; +// clang-format on + +// #import {addSingletonGetter} from '../../../js/cr.m.js'; + cr.define('network_config', function() { /** @interface */ - class MojoInterfaceProvider { + /* #export */ class MojoInterfaceProvider { /** @return {!chromeos.networkConfig.mojom.CrosNetworkConfigRemote} */ getMojoServiceRemote() {} } /** @implements {network_config.MojoInterfaceProvider} */ - class MojoInterfaceProviderImpl { + /* #export */ class MojoInterfaceProviderImpl { constructor() { /** @private {?chromeos.networkConfig.mojom.CrosNetworkConfigRemote} */ this.remote_ = null; diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html index e12cc9d632c..250d68a8c23 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html @@ -16,24 +16,28 @@ <div class="property-box"> <div class="start">[[i18n('networkAccessPoint')]]</div> <select id="selectApn" class="md-select" on-change="onSelectApnChange_" + value="[[selectedApn_]]" + disabled="[[isDisabled_(selectedApn_)]]" aria-label="[[i18n('networkAccessPoint')]]"> <template is="dom-repeat" items="[[apnSelectList_]]"> - <option value="[[item.accessPointName]]" - selected$="[[isApnItemSelected_(item, selectedApn_)]]">[[apnDesc_(item)]]</option> + <option value="[[item.name]]"> + [[apnDesc_(item)]] + </option> </template> </select> </div> - <div class="property-box single-column indented" - hidden$="[[!isOtherSelected_(selectedApn_, managedProperties)]]"> - <network-property-list-mojo on-property-change="onOtherApnChange_" - fields="[[otherApnFields_]]" property-dict="[[otherApn_]]" - edit-field-types="[[otherApnEditTypes_]]" prefix="cellular.apn."> - </network-property-list-mojo> - <cr-button class="action-button" on-click="onSaveOtherTap_"> - [[i18n('save')]] - </cr-button> - </div> + <template is="dom-if" if="[[showOtherApn_(selectedApn_)]]"> + <div class="property-box single-column indented"> + <network-property-list-mojo on-property-change="onOtherApnChange_" + fields="[[otherApnFields_]]" property-dict="[[otherApn_]]" + edit-field-types="[[otherApnEditTypes_]]" prefix="cellular.apn."> + </network-property-list-mojo> + <cr-button class="action-button" on-click="onSaveOtherTap_"> + [[i18n('save')]] + </cr-button> + </div> + </template> </template> <script src="network_apnlist.js"></script> </dom-module> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js index afbc5ed687d..54f54419f47 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js @@ -25,7 +25,12 @@ Polymer({ }, /** - * accessPointName value of the selected APN. + * The name property of the selected APN. If a name property is empty, the + * accessPointName property will be used. We use 'name' so that multiple + * APNs with the same accessPointName can be supported, so long as they have + * a unique 'name' property. This is necessary to allow custom 'other' + * entries (which are always named 'Other') that match an existing + * accessPointName but provide a different username/password. * @private */ selectedApn_: { @@ -49,10 +54,16 @@ Polymer({ * The user settable properties for a new ('other') APN. The values for * accessPointName, username, and password will be set to the currently * active APN if it does not match an existing list entry. - * @private {chromeos.networkConfig.mojom.ApnProperties|undefined} + * @private {!chromeos.networkConfig.mojom.ApnProperties} */ otherApn_: { type: Object, + value() { + return { + accessPointName: kDefaultAccessPointName, + name: kOtherAccessPointName, + }; + } }, /** @@ -84,6 +95,14 @@ Polymer({ }, }, + /* + * Returns the select APN SelectElement. + * @return {?HTMLSelectElement} + */ + getApnSelect() { + return /** @type {?HTMLSelectElement} */ (this.$$('#selectApn')); + }, + /** * @param {!chromeos.networkConfig.mojom.ManagedApnProperties} apn * @return {!chromeos.networkConfig.mojom.ApnProperties} @@ -91,9 +110,8 @@ Polymer({ */ getApnFromManaged_(apn) { return { + // authentication and language are ignored in this UI. accessPointName: OncMojo.getActiveString(apn.accessPointName), - authentication: OncMojo.getActiveString(apn.authentication), - language: OncMojo.getActiveString(apn.language), localizedName: OncMojo.getActiveString(apn.localizedName), name: OncMojo.getActiveString(apn.name), password: OncMojo.getActiveString(apn.password), @@ -111,80 +129,84 @@ Polymer({ } else if (cellular.lastGoodApn && cellular.lastGoodApn.accessPointName) { activeApn = cellular.lastGoodApn; } + if (activeApn && !activeApn.accessPointName) { + activeApn = undefined; + } this.setApnSelectList_(activeApn); }, /** * Sets the list of selectable APNs for the UI. Appends an 'Other' entry * (see comments for |otherApn_| above). - * @param {chromeos.networkConfig.mojom.ApnProperties|undefined} activeApn The - * currently active APN properties. + * @param {chromeos.networkConfig.mojom.ApnProperties|undefined} activeApn * @private */ setApnSelectList_(activeApn) { - // Copy the list of APNs from this.managedProperties. - const apnList = this.getApnList_().slice(); - - // Test whether |activeApn| is in the current APN list in managedProperties. - const activeApnInList = activeApn && apnList.some(function(a) { - return a.accessPointName === activeApn.accessPointName; - }); - - // If |activeApn| is specified and not in the list, use the active - // properties for 'other'. Otherwise use any existing 'other' properties. - const otherApnProperties = - (activeApn && !activeApnInList) ? activeApn : this.otherApn_; - const otherApn = this.createApnObject_(otherApnProperties); - - // Always use 'Other' for the name of custom APN entries (the name does - // not get saved). - otherApn.name = kOtherAccessPointName; - - // If no 'active' or 'other' AccessPointName was provided, use the default. - otherApn.accessPointName = - otherApn.accessPointName || kDefaultAccessPointName; - - // Save the 'other' properties. - this.otherApn_ = otherApn; + assert(!activeApn || activeApn.accessPointName); + // The generated APN list ensures nonempty accessPointName and name + // properties. + const apnList = this.generateApnList_(); + if (apnList === undefined) { + // No APNList property indicates that the network is not in a + // connectable state. Disable the UI. + this.apnSelectList_ = []; + this.set('selectedApn_', ''); + return; + } + // Get the list entry for activeApn if it exists. It will have 'name' set. + let activeApnInList; + if (activeApn) { + activeApnInList = apnList.find(a => a.name === activeApn.name); + } - // Append 'other' to the end of the list of APNs. - apnList.push(otherApn); + // If the active APN is not in the list, copy it to otherApn_. + if (!activeApnInList && activeApn && activeApn.accessPointName) { + this.otherApn_ = { + accessPointName: activeApn.accessPointName, + name: kOtherAccessPointName, + username: activeApn.username, + password: activeApn.password, + }; + } + apnList.push(this.otherApn_); this.apnSelectList_ = apnList; - this.selectedApn_ = - (activeApn && activeApn.accessPointName) || otherApn.accessPointName; - }, + const selectedApn = + activeApnInList ? activeApnInList.name : kOtherAccessPointName; + assert(selectedApn); + this.set('selectedApn_', selectedApn); - /** - * @param {chromeos.networkConfig.mojom.ApnProperties=} - * apnProperties - * @return {!chromeos.networkConfig.mojom.ApnProperties} A new APN object with - * properties from |apnProperties| if provided. - * @private - */ - createApnObject_(apnProperties) { - const newApn = {accessPointName: ''}; - if (apnProperties) { - Object.assign(newApn, apnProperties); - } - return newApn; + // Wait for the dom-repeat to populate the <option> entries then explicitly + // set the selected value. + this.async(function() { + this.$.selectApn.value = this.selectedApn_; + }); }, /** - * @return {!Array<!chromeos.networkConfig.mojom.ApnProperties>} The list of - * APN properties in |managedProperties| or an empty list if the property - * is not set. + * Returns a modified copy of the APN properties or undefined if the + * property is not set. All entries in the returned copy will have nonempty + * name and accessPointName properties. + * @return {!Array<!chromeos.networkConfig.mojom.ApnProperties>|undefined} * @private */ - getApnList_() { + generateApnList_() { if (!this.managedProperties) { - return []; + return undefined; } const apnList = this.managedProperties.typeProperties.cellular.apnList; if (!apnList) { - return []; + return undefined; } - return apnList.activeValue; + return apnList.activeValue.filter(apn => !!apn.accessPointName).map(apn => { + return { + accessPointName: apn.accessPointName, + localizedName: apn.localizedName, + name: apn.name || apn.accessPointName, + username: apn.username, + password: apn.password, + }; + }); }, /** @@ -194,16 +216,18 @@ Polymer({ */ onSelectApnChange_(event) { const target = /** @type {!HTMLSelectElement} */ (event.target); - const accessPointName = target.value; - // When selecting 'Other', don't set a change event unless a valid + const name = target.value; + // When selecting 'Other', don't send a change event unless a valid // non-default value has been set for Other. - if (this.isOtherSelected_(accessPointName) && - (!this.otherApn_ || !this.otherApn_.accessPointName || + if (name === kOtherAccessPointName && + (!this.otherApn_.accessPointName || this.otherApn_.accessPointName === kDefaultAccessPointName)) { - this.selectedApn_ = accessPointName; + this.selectedApn_ = name; return; } - this.sendApnChange_(accessPointName); + // The change will generate an update which will update selectedApn_ and + // refresh the UI. + this.sendApnChange_(name); }, /** @@ -232,57 +256,57 @@ Polymer({ /** * Send the apn-change event. - * @param {string} accessPointName + * @param {string} name The APN name property. * @private */ - sendApnChange_(accessPointName) { - const apnList = this.getApnList_(); - let apn = this.findApnInList_(apnList, accessPointName); - if (apn === undefined) { - apn = this.createApnObject_(); - if (this.otherApn_) { - apn.accessPointName = this.otherApn_.accessPointName; - apn.username = this.otherApn_.username; - apn.password = this.otherApn_.password; + sendApnChange_(name) { + let apn; + if (name === kOtherAccessPointName) { + if (!this.otherApn_.accessPointName || + this.otherApn_.accessPointName === kDefaultAccessPointName) { + // No valid APN set, do nothing. + return; + } + apn = { + accessPointName: this.otherApn_.accessPointName, + username: this.otherApn_.username, + password: this.otherApn_.password, + }; + } else { + apn = this.apnSelectList_.find(a => a.name === name); + if (apn === undefined) { + // Potential edge case if an update is received before this is invoked. + console.error('Selected APN not in list'); + return; } } this.fire('apn-change', apn); }, /** - * @param {string} accessPointName - * @return {boolean} True if the 'other' APN is currently selected. + * @return {boolean} * @private */ - isOtherSelected_(accessPointName) { - if (!this.managedProperties) { - return false; - } - const apnList = this.getApnList_(); - const apn = this.findApnInList_(apnList, accessPointName); - return apn === undefined; + isDisabled_() { + return this.selectedApn_ === ''; }, /** - * @param {!chromeos.networkConfig.mojom.ApnProperties} apn - * @return {string} The most descriptive name for the access point. + * @return {boolean} * @private */ - apnDesc_(apn) { - return apn.localizedName || apn.name || apn.accessPointName; + showOtherApn_() { + return this.selectedApn_ === kOtherAccessPointName; }, /** - * @param {!Array<!chromeos.networkConfig.mojom.ApnProperties>} apnList - * @param {string} accessPointName - * @return {chromeos.networkConfig.mojom.ApnProperties|undefined} The entry in - * |apnList| matching |accessPointName| if it exists, or undefined. + * @param {!chromeos.networkConfig.mojom.ApnProperties} apn + * @return {string} The most descriptive name for the access point. * @private */ - findApnInList_(apnList, accessPointName) { - return apnList.find(function(a) { - return a.accessPointName === accessPointName; - }); + apnDesc_(apn) { + assert(apn.name); + return apn.localizedName || apn.name; }, /** diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.html index a01762f6acb..d0203e82933 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.html @@ -1,5 +1,7 @@ <link rel="import" href="../../../html/polymer.html"> +<link rel="import" href="chrome://resources/html/load_time_data.html"> +<link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html"> <link rel="import" href="mojo_interface_provider.html"> <link rel="import" href="network_listener_behavior.html"> <link rel="import" href="../../../cr_elements/action_link_css.html"> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_element_behavior.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_element_behavior.js index c341b01eba1..95d24a2dd8c 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_element_behavior.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_element_behavior.js @@ -7,7 +7,7 @@ */ /** @polymerBehavior */ -const NetworkConfigElementBehavior = { +/* #export */ const NetworkConfigElementBehavior = { properties: { disabled: { type: Boolean, diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_input.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_input.html index 9e57d8efd1b..3d36500a2a7 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_input.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_input.html @@ -1,9 +1,9 @@ <link rel="import" href="../../../html/polymer.html"> <link rel="import" href="../../../cr_elements/cr_input/cr_input.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_behavior_mojo.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_indicator_mojo.html"> <link rel="import" href="../../../cr_elements/shared_vars_css.html"> +<link rel="import" href="cr_policy_network_behavior_mojo.html"> +<link rel="import" href="cr_policy_network_indicator_mojo.html"> <link rel="import" href="network_config_element_behavior.html"> <link rel="import" href="network_shared_css.html"> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_select.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_select.html index 8220cc12d82..c22845fdfc4 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_select.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_select.html @@ -1,11 +1,11 @@ <link rel="import" href="../../../html/polymer.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_behavior_mojo.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_indicator_mojo.html"> <link rel="import" href="../../../cr_elements/policy/cr_tooltip_icon.html"> <link rel="import" href="../../../cr_elements/shared_vars_css.html"> <link rel="import" href="../../../cr_elements/shared_style_css.html"> <link rel="import" href="../../../cr_elements/md_select_css.html"> +<link rel="import" href="cr_policy_network_behavior_mojo.html"> +<link rel="import" href="cr_policy_network_indicator_mojo.html"> <link rel="import" href="network_config_element_behavior.html"> <link rel="import" href="network_shared_css.html"> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_toggle.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_toggle.html index 1036dedc58f..2fc37bed31b 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_toggle.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_toggle.html @@ -1,34 +1,53 @@ <link rel="import" href="../../../html/polymer.html"> <link rel="import" href="../../../cr_elements/cr_toggle/cr_toggle.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_behavior_mojo.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_indicator_mojo.html"> <link rel="import" href="../../../cr_elements/shared_vars_css.html"> +<link rel="import" href="cr_policy_network_behavior_mojo.html"> +<link rel="import" href="cr_policy_network_indicator_mojo.html"> <link rel="import" href="network_config_element_behavior.html"> <link rel="import" href="network_shared_css.html"> <dom-module id="network-config-toggle"> <template> <style include="network-shared"> + :host { + cursor: pointer; + } + :host([disabled]) { + cursor: initial; + } cr-policy-network-indicator-mojo { --cr-tooltip-icon-margin-start: var(--cr-controlled-by-spacing); } + cr-policy-network-indicator-mojo.left { + margin-inline-end: var(--cr-controlled-by-spacing); + } div.property-box { width: 100%; } </style> - <div class="property-box" actionable> + <div class="property-box"> <div class="start"> - [[label]] + <div aria-hidden="true">[[label]]</div> + <div id="sub-label" class="cr-secondary-text" aria-hidden="true"> + [[subLabel]] + </div> </div> + <template is="dom-if" if="[[policyOnLeft]]"> + <cr-policy-network-indicator-mojo class="left" + property="[[property]]" tooltip-position="left"> + </cr-policy-network-indicator-mojo> + </template> <cr-toggle checked="{{checked}}" disabled="[[getDisabled_(disabled, property)]]" - aria-label$="[[label]]"> + aria-label$="[[label]]" aria-describedby="sub-label"> </cr-toggle> - <cr-policy-network-indicator-mojo - property="[[property]]" tooltip-position="left"> - </cr-policy-network-indicator-mojo> + <template is="dom-if" if="[[!policyOnLeft]]"> + <cr-policy-network-indicator-mojo + property="[[property]]" tooltip-position="left"> + </cr-policy-network-indicator-mojo> + </template> </div> </template> <script src="network_config_toggle.js"></script> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_toggle.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_toggle.js index fe2e459cf37..87ebe656635 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_toggle.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config_toggle.js @@ -16,18 +16,34 @@ Polymer({ properties: { label: String, + subLabel: String, + checked: { type: Boolean, value: false, reflectToAttribute: true, notify: true, }, + + /** + * Uses Settings styling when true (policy icon is left of the toggle) + */ + policyOnLeft: { + type: Boolean, + value: false, + reflectToAttribute: true, + }, }, listeners: { 'click': 'onHostTap_', }, + /** @override */ + focus() { + this.$$('cr-toggle').focus(); + }, + /** * Handles non cr-toggle button clicks (cr-toggle handles its own click events * which don't bubble). diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.html index ca1475871b4..84065f5c3bf 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_icon.html @@ -1,10 +1,10 @@ <link rel="import" href="../../../html/polymer.html"> <link rel="import" href="../../chromeos/network/network_icons.html"> -<link rel="import" href="onc_mojo.html"> <link rel="import" href="../../../cr_elements/hidden_style_css.html"> <link rel="import" href="../../../html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> +<link rel="import" href="onc_mojo.html"> <dom-module id="network-icon"> <template> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html index a55a625f35a..7926dfafe55 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html @@ -2,8 +2,8 @@ <link rel="import" href="../../../cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="../../../cr_elements/policy/cr_policy_indicator.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_behavior_mojo.html"> <link rel="import" href="../../../html/i18n_behavior.html"> +<link rel="import" href="cr_policy_network_behavior_mojo.html"> <link rel="import" href="network_property_list_mojo.html"> <link rel="import" href="network_shared_css.html"> @@ -21,7 +21,7 @@ <cr-policy-indicator indicator-type="[[getPolicyIndicatorType( managedProperties.ipAddressConfigType)]]"> </cr-policy-indicator> - <cr-toggle checked="{{automatic_}}" + <cr-toggle id="autoConfigIpToggle" checked="{{automatic_}}" disabled="[[!canChangeIPConfigType_(managedProperties)]]" on-change="onAutomaticChange_" aria-labelledby="autoIPConfigLabel"> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js index 247901e5d17..aca1decb29c 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js @@ -49,11 +49,14 @@ const getRoutingPrefixAsNetmask = function(prefixLength) { */ const getRoutingPrefixAsLength = function(netmask) { 'use strict'; - let prefixLength = 0; + if (!netmask) { + return chromeos.networkConfig.mojom.NO_ROUTING_PREFIX; + } const tokens = netmask.split('.'); if (tokens.length !== 4) { - return -1; + return chromeos.networkConfig.mojom.NO_ROUTING_PREFIX; } + let prefixLength = 0; for (let i = 0; i < tokens.length; ++i) { const token = tokens[i]; // If we already found the last mask and the current one is not @@ -137,6 +140,14 @@ Polymer({ }, /** + * Returns the automatically configure IP CrToggleElement. + * @return {?CrToggleElement} + */ + getAutoConfigIpToggle() { + return /** @type {?CrToggleElement} */ (this.$$('#autoConfigIpToggle')); + }, + + /** * Saved static IP configuration properties when switching to 'automatic'. * @private {!OncMojo.IPConfigUIProperties|undefined} */ diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list.js index 2fed17a7beb..77c50ebf42e 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list.js @@ -90,7 +90,7 @@ Polymer({ /** @private */ updateListItems_() { - this.saveScroll(this.$.networkList); + this.saveScroll(/** @type {!IronListElement} */ (this.$.networkList)); const beforeNetworks = this.customItems.filter(function(item) { return item.showBeforeNetworksList === true; }); @@ -98,7 +98,7 @@ Polymer({ return item.showBeforeNetworksList !== true; }); this.listItems_ = beforeNetworks.concat(this.networks, afterNetworks); - this.restoreScroll(this.$.networkList); + this.restoreScroll(/** @type {!IronListElement} */ (this.$.networkList)); this.updateScrollableContents(); if (this.focusRequested_) { this.async(function() { diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.html index cab8b8eed10..e760d59f223 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.html @@ -1,15 +1,15 @@ <link rel="import" href="../../../html/polymer.html"> -<link rel="import" href="network_icon.html"> -<link rel="import" href="onc_mojo.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="../../../cr_elements/cr_icon_button/cr_icon_button.html"> <link rel="import" href="../../../cr_elements/icons.html"> <link rel="import" href="../../../cr_elements/policy/cr_policy_indicator.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_behavior_mojo.html"> <link rel="import" href="../../../cr_elements/shared_style_css.html"> <link rel="import" href="../../../cr_elements/shared_vars_css.html"> <link rel="import" href="../../../html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> +<link rel="import" href="cr_policy_network_behavior_mojo.html"> +<link rel="import" href="network_icon.html"> +<link rel="import" href="onc_mojo.html"> <dom-module id="network-list-item"> <template> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.js index dc84e735be9..c9a66919de1 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_item.js @@ -169,8 +169,21 @@ Polymer({ const status = this.getNetworkStateText_(); const isManaged = this.item.source === OncSource.kDevicePolicy || this.item.source === OncSource.kUserPolicy; - const index = this.parentElement.items.indexOf(this.item) + 1; - const total = this.parentElement.items.length; + + // TODO(jonmann): Reaching into the parent element breaks encapsulation so + // refactor this logic into the parent (NetworkList) and pass into + // NetworkListItem as a property. + let index; + let total; + if (this.parentElement.items) { + index = this.parentElement.items.indexOf(this.item) + 1; + total = this.parentElement.items.length; + } else { + // This should only happen in tests; see TODO above. + index = 0; + total = 1; + } + switch (this.item.type) { case NetworkType.kCellular: if (isManaged) { diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_types.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_types.js index 678692f020a..a98bcf66a95 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_types.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_list_types.js @@ -23,3 +23,5 @@ NetworkList.CustomItemState; /** @typedef {OncMojo.NetworkStateProperties|NetworkList.CustomItemState} */ NetworkList.NetworkListItemType; + +// #export {NetworkList} diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.js index d80f8ffdd20..c1e6de07362 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.js @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// #import {MojoInterfaceProviderImpl} from './mojo_interface_provider.m.js'; + /** * @fileoverview Polymer behavior for observing CrosNetworkConfigObserver * events. */ /** @polymerBehavior */ -const NetworkListenerBehavior = { +/* #export */ const NetworkListenerBehavior = { /** @private {?chromeos.networkConfig.mojom.CrosNetworkConfigObserver} */ observer_: null, diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html index 0c68cc71ce8..0c0c0f4ddfb 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html @@ -1,13 +1,13 @@ <link rel="import" href="../../../html/polymer.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="../../../cr_elements/cr_input/cr_input.html"> <link rel="import" href="../../../cr_elements/cr_radio_button/cr_radio_button.html"> <link rel="import" href="../../../cr_elements/cr_radio_group/cr_radio_group.html"> <link rel="import" href="../../../cr_elements/policy/cr_policy_indicator.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_behavior_mojo.html"> <link rel="import" href="../../../html/i18n_behavior.html"> <link rel="import" href="../../../cr_elements/md_select_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> +<link rel="import" href="cr_policy_network_behavior_mojo.html"> <link rel="import" href="network_shared_css.html"> <dom-module id="network-nameservers"> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js index ad2206877c3..a7025298708 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js @@ -71,6 +71,14 @@ Polymer({ */ savedNameservers_: [], + /* + * Returns the nameserver type CrRadioGroupElement. + * @return {?CrRadioGroupElement} + */ + getNameserverRadioButtons() { + return /** @type {?CrRadioGroupElement} */ (this.$$('#nameserverType')); + }, + /** * Returns true if |nameservers| contains any all google nameserver entries * and only google nameserver entries or empty entries. diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.html index 66e8763a97d..f327000afd8 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_password_input.html @@ -2,10 +2,10 @@ <link rel="import" href="../../../cr_elements/cr_icon_button/cr_icon_button.html"> <link rel="import" href="../../../cr_elements/cr_icons_css.html"> <link rel="import" href="../../../cr_elements/cr_input/cr_input.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_behavior_mojo.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_indicator_mojo.html"> <link rel="import" href="../../../cr_elements/shared_vars_css.html"> <link rel="import" href="../../../html/i18n_behavior.html"> +<link rel="import" href="cr_policy_network_behavior_mojo.html"> +<link rel="import" href="cr_policy_network_indicator_mojo.html"> <link rel="import" href="network_config_element_behavior.html"> <link rel="import" href="network_shared_css.html"> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.html index 24c4de57996..a982414f911 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.html @@ -1,11 +1,11 @@ <link rel="import" href="../../../html/polymer.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="../../../cr_elements/cr_input/cr_input.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_behavior_mojo.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_indicator_mojo.html"> <link rel="import" href="../../../cr_elements/shared_style_css.html"> <link rel="import" href="../../../html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> +<link rel="import" href="cr_policy_network_behavior_mojo.html"> +<link rel="import" href="cr_policy_network_indicator_mojo.html"> <link rel="import" href="network_shared_css.html"> <dom-module id="network-property-list-mojo"> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.js index 075080a3639..b9f058855de 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list_mojo.js @@ -117,6 +117,8 @@ Polymer({ result += 'OTP'; } else if (subKey === 'ssid') { result += 'SSID'; + } else if (subKey === 'bssid') { + result += 'BSSID'; } else if (subKey === 'serverCa') { result += 'ServerCA'; } else if (subKey === 'vpn') { diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.html index 7df225d8a45..41cf8344064 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.html @@ -1,14 +1,14 @@ <link rel="import" href="../../../html/polymer.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="../../../cr_elements/cr_button/cr_button.html"> <link rel="import" href="../../../cr_elements/cr_input/cr_input.html"> <link rel="import" href="../../../cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="../../../cr_elements/hidden_style_css.html"> -<link rel="import" href="../../../cr_elements/policy/cr_policy_network_behavior_mojo.html"> <link rel="import" href="../../../html/assert.html"> <link rel="import" href="../../../html/i18n_behavior.html"> <link rel="import" href="../../../cr_elements/md_select_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> +<link rel="import" href="cr_policy_network_behavior_mojo.html"> <link rel="import" href="network_proxy_exclusions.html"> <link rel="import" href="network_proxy_input.html"> <link rel="import" href="network_shared_css.html"> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.html b/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.html index fa7ff789d05..ad9823a513e 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.html @@ -1,2 +1,7 @@ <link rel="import" href="../../../html/assert.html"> +<link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html"> +<link rel="import" href="chrome://resources/mojo/services/network/public/mojom/ip_address.mojom.html"> +<link rel="import" href="chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom.html"> +<link rel="import" href="chrome://resources/mojo/mojo/public/mojom/base/time.mojom.html"> +<link rel="import" href="chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom.html"> <script src="onc_mojo.js"></script> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js b/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js index a193123d179..d9dd579801e 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/network/onc_mojo.js @@ -2,13 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// #import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; +// #import {loadTimeData} from '../../../js/load_time_data.m.js'; + /** * @fileoverview Utilities supporting network_config.mojom types. The strings * returned in the getFooTypeString methods are used for looking up localized * strings and for debugging. They are not intended to be drectly user facing. */ -class OncMojo { +/* #export */ class OncMojo { /** * @param {number|undefined} value * @return {string} @@ -1055,6 +1058,43 @@ class OncMojo { assertNotReached(); return 'OncNotConnected'; } + + /** + * Returns true the IPAddress bytes match. + * @param {?network.mojom.IPAddress|undefined} a + * @param {?network.mojom.IPAddress|undefined} b + * @return {boolean} + */ + static ipAddressMatch(a, b) { + if (!a || !b) { + return !!a === !!b; + } + const abytes = a.addressBytes; + const bbytes = b.addressBytes; + if (abytes.length !== bbytes.length) { + return false; + } + for (let i = 0; i < abytes.length; ++i) { + if (abytes[i] !== bbytes[i]) { + return false; + } + } + return true; + } + + /** + * Returns true the SIMLockStatus properties match. + * @param {?chromeos.networkConfig.mojom.SIMLockStatus|undefined} a + * @param {?chromeos.networkConfig.mojom.SIMLockStatus|undefined} b + * @return {boolean} + */ + static simLockStatusMatch(a, b) { + if (!a || !b) { + return !!a === !!b; + } + return a.lockType === b.lockType && a.lockEnabled === b.lockEnabled && + a.retriesLeft === b.retriesLeft; + } } /** @typedef {chromeos.networkConfig.mojom.DeviceStateProperties} */ diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network_health/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/network_health/BUILD.gn index 6c1f0d8f6ce..607bd812ae1 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/network_health/BUILD.gn +++ b/chromium/ui/webui/resources/cr_components/chromeos/network_health/BUILD.gn @@ -11,12 +11,18 @@ assert(is_chromeos, "Only ChromeOS components belong here.") # JS type check for Polymer 2 and 3 js_type_check("closure_compile") { - deps = [ ":network_health_summary" ] + deps = [ + ":network_diagnostics", + ":network_health_summary", + ] } js_type_check("closure_compile_module") { is_polymer3 = true - deps = [ ":network_health_summary.m" ] + deps = [ + ":network_diagnostics.m", + ":network_health_summary.m", + ] } # Sources with Polymer 3 generated modules @@ -29,6 +35,13 @@ js_library("network_health_summary") { ] } +js_library("network_diagnostics") { + deps = [ + "//chromeos/services/network_health/public/mojom:mojom_js_library_for_compile", + "//ui/webui/resources/js:i18n_behavior", + ] +} + js_library("network_health_summary.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network_health/network_health_summary.m.js" ] deps = [ @@ -40,6 +53,16 @@ js_library("network_health_summary.m") { extra_deps = [ ":network_health_summary_module" ] } +js_library("network_diagnostics.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.m.js" ] + deps = [ + "//chromeos/services/network_health/public/mojom:mojom_js_library_for_compile", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:i18n_behavior.m", + ] + extra_deps = [ ":network_diagnostics_module" ] +} + # polymer_modulizer for converting Polymer2 to Polymer3 polymer_modulizer("network_health_summary") { @@ -48,6 +71,15 @@ polymer_modulizer("network_health_summary") { html_type = "dom-module" } +polymer_modulizer("network_diagnostics") { + js_file = "network_diagnostics.js" + html_file = "network_diagnostics.html" + html_type = "dom-module" +} + group("polymer3_elements") { - public_deps = [ ":network_health_summary_module" ] + public_deps = [ + ":network_diagnostics_module", + ":network_health_summary_module", + ] } diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.html b/chromium/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.html new file mode 100644 index 00000000000..79255f781ac --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.html @@ -0,0 +1,86 @@ +<link rel="import" href="../../../html/polymer.html"> + +<link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html"> +<link rel="import" href="chrome://resources/mojo/chromeos/services/network_health/public/mojom/network_diagnostics.mojom.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> +<link rel="import" href="../../../cr_elements/cr_button/cr_button.html"> +<link rel="import" href="../../../html/i18n_behavior.html"> + +<dom-module id="network-diagnostics"> + <template> + <style> + .button-group > * { + margin-inline-start: 10px; + } + + .routine-group { + display: inline-flex; + flex-wrap: wrap; + } + + .routine-container { + border: 2px solid rgb(150, 150, 150); + height: 50px; + margin: 10px; + padding: 5px; + width: 400px; + } + + .run-btn { + background-color: white; + } + + .routine-name { + font-size: 1rem; + font-weight: bold; + } + + .routine-content { + display: flex; + } + + .routine-result { + flex: 1; + } + + .result-passed { + background-color: rgb(217, 234, 211); + } + + .result-error { + background-color: rgb(244, 204, 204); + } + + .result-not-run { + background-color: rgb(255, 242, 204); + } + </style> + <div class="button-group"> + <cr-button on-click="onRunAllRoutinesClick_"> + [[i18n('NetworkDiagnosticsRunAll')]] + </cr-button> + <cr-button on-click="onSendFeedbackReportClick_"> + [[i18n('NetworkDiagnosticsSendFeedback')]] + </cr-button> + </div> + <div class="routine-group"> + <template is="dom-repeat" items="[[routines_]]" as="routine"> + <div class="routine-container"> + <div class="routine-name">[[i18n(routine.name)]]</div> + <div class="routine-content"> + <span class="routine-result">[[routine.resultMsg]]</span> + + <template is="dom-if" if="[[routine.running]]"> + <paper-spinner-lite active></paper-spinner-lite> + </template> + + <cr-button class="run-btn" hidden="[[routine.running]]" on-click="onRunRoutineClick_"> + [[i18n('NetworkDiagnosticsRun')]] + </cr-button> + </div> + </div> + </template> + </div> + </template> + <script src="network_diagnostics.js"></script> +</dom-module> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.js b/chromium/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.js new file mode 100644 index 00000000000..ca948dc298d --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/chromeos/network_health/network_diagnostics.js @@ -0,0 +1,348 @@ + +// 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. + +/** + * @fileoverview Polymer element for interacting with Network Diagnostics. + */ + +// Namespace to make using the mojom objects more readable. +const diagnosticsMojom = chromeos.networkDiagnostics.mojom; + +/** + * A routine response from the Network Diagnostics mojo service. + * @typedef {{ + * verdict: chromeos.networkDiagnostics.mojom.RoutineVerdict, + * }} + * RoutineResponse can optionally have a `problems` field, which is an array of + * enums relevant to the routine run. Unfortunately the closure compiler cannot + * handle optional object fields. + */ +let RoutineResponse; + +/** + * A network diagnostics routine. Holds descriptive information about the + * routine, and it's transient state. + * @typedef {{ + * name: string, + * type: !RoutineType, + * running: boolean, + * resultMsg: string, + * result: ?RoutineResponse, + * }} + */ +let Routine; + +/** + * Definition for all Network diagnostic routine types. This enum is intended + * to be used as an index in an array of routines. + * @enum {number} + */ +const RoutineType = { + LAN_CONNECTIVITY: 0, + SIGNAL_STRENGTH: 1, + GATEWAY_PING: 2, + SECURE_WIFI: 3, + DNS_RESOLVER: 4, + DNS_LATENCY: 5, + DNS_RESOLUTION: 6, +}; + +/** + * Helper function to create a routine object. + * @param {string} name + * @param {!RoutineType} type + * @return {!Routine} Routine object + */ +function createRoutine(name, type) { + return {name: name, type: type, running: false, resultMsg: '', result: null}; +} + +Polymer({ + is: 'network-diagnostics', + + behaviors: [ + I18nBehavior, + ], + + properties: { + /** + * List of Diagnostics Routines + * @private {!Array<!Routine>} + */ + routines_: { + type: Array, + value: function() { + const routines = []; + routines[RoutineType.LAN_CONNECTIVITY] = createRoutine( + 'NetworkDiagnosticsLanConnectivity', RoutineType.LAN_CONNECTIVITY); + routines[RoutineType.SIGNAL_STRENGTH] = createRoutine( + 'NetworkDiagnosticsSignalStrength', RoutineType.SIGNAL_STRENGTH); + routines[RoutineType.GATEWAY_PING] = createRoutine( + 'NetworkDiagnosticsGatewayCanBePinged', RoutineType.GATEWAY_PING); + routines[RoutineType.SECURE_WIFI] = createRoutine( + 'NetworkDiagnosticsHasSecureWiFiConnection', + RoutineType.SECURE_WIFI); + routines[RoutineType.DNS_RESOLVER] = createRoutine( + 'NetworkDiagnosticsDnsResolverPresent', RoutineType.DNS_RESOLVER); + routines[RoutineType.DNS_LATENCY] = createRoutine( + 'NetworkDiagnosticsDnsLatency', RoutineType.DNS_LATENCY); + routines[RoutineType.DNS_RESOLUTION] = createRoutine( + 'NetworkDiagnosticsDnsResolution', RoutineType.DNS_RESOLUTION); + return routines; + } + } + }, + + /** + * Network Diagnostics mojo remote. + * @private { + * ?chromeos.networkDiagnostics.mojom.NetworkDiagnosticsRoutinesRemote} + */ + networkDiagnostics_: null, + + /** @override */ + created() { + this.networkDiagnostics_ = + diagnosticsMojom.NetworkDiagnosticsRoutines.getRemote(); + }, + + /** @private */ + onRunAllRoutinesClick_() { + for (const routine of this.routines_) { + this.runRoutine_(routine.type); + } + }, + + /** + * @param {!Event} event + * @private + */ + onRunRoutineClick_(event) { + this.runRoutine_(event.model.index); + }, + + /** @private */ + onSendFeedbackReportClick_() { + const results = {}; + for (const routine of this.routines_) { + if (routine.result) { + const name = routine.name.replace('NetworkDiagnostics', ''); + const result = {}; + result['verdict'] = + this.getRoutineVerdictFeedbackString_(routine.result.verdict); + if (routine.result.problems && routine.result.problems.length > 0) { + result['problems'] = this.getRoutineProblemsFeedbackString_( + routine.type, routine.result.problems); + } + + results[name] = result; + } + } + this.fire('open-feedback-dialog', JSON.stringify(results, undefined, 2)); + }, + + /** + * @param {!RoutineType} type + * @private + */ + runRoutine_(type) { + this.set(`routines_.${type}.running`, true); + this.set(`routines_.${type}.resultMsg`, ''); + this.set(`routines_.${type}.result`, null); + const element = + this.shadowRoot.querySelectorAll('.routine-container')[type]; + element.classList.remove('result-passed', 'result-error', 'result-not-run'); + switch (type) { + case RoutineType.LAN_CONNECTIVITY: + this.networkDiagnostics_.lanConnectivity().then( + result => this.evaluateRoutine_(type, result)); + break; + case RoutineType.SIGNAL_STRENGTH: + this.networkDiagnostics_.signalStrength().then( + result => this.evaluateRoutine_(type, result)); + break; + case RoutineType.GATEWAY_PING: + this.networkDiagnostics_.gatewayCanBePinged().then( + result => this.evaluateRoutine_(type, result)); + break; + case RoutineType.SECURE_WIFI: + this.networkDiagnostics_.hasSecureWiFiConnection().then( + result => this.evaluateRoutine_(type, result)); + break; + case RoutineType.DNS_RESOLVER: + this.networkDiagnostics_.dnsResolverPresent().then( + result => this.evaluateRoutine_(type, result)); + break; + case RoutineType.DNS_LATENCY: + this.networkDiagnostics_.dnsLatency().then( + result => this.evaluateRoutine_(type, result)); + break; + case RoutineType.DNS_RESOLUTION: + this.networkDiagnostics_.dnsResolution().then( + result => this.evaluateRoutine_(type, result)); + break; + } + }, + + /** + * @param {!RoutineType} type + * @param {!RoutineResponse} result + * @private + */ + evaluateRoutine_(type, result) { + const routine = `routines_.${type}`; + this.set(`${routine}.running`, false); + + const element = + this.shadowRoot.querySelectorAll('.routine-container')[type]; + let resultMsg = ''; + + switch (result.verdict) { + case diagnosticsMojom.RoutineVerdict.kNoProblem: + resultMsg = this.i18n('NetworkDiagnosticsPassed'); + element.classList.add('result-passed'); + break; + case diagnosticsMojom.RoutineVerdict.kProblem: + resultMsg = this.i18n('NetworkDiagnosticsFailed'); + element.classList.add('result-error'); + break; + case diagnosticsMojom.RoutineVerdict.kNotRun: + resultMsg = this.i18n('NetworkDiagnosticsNotRun'); + element.classList.add('result-not-run'); + break; + } + + this.set(routine + '.result', result); + this.set(routine + '.resultMsg', resultMsg); + }, + + /** + * + * @param {!RoutineType} type The type of routine + * @param {!Array<number>} problems The list of problems for the routine + * @return {Array<string>} String for a networking problem used for feedback + * @private + */ + getRoutineProblemsFeedbackString_(type, problems) { + const problemStrings = []; + for (const problem of problems) { + switch (type) { + case RoutineType.SIGNAL_STRENGTH: + switch (problem) { + case diagnosticsMojom.SignalStrengthProblem.kSignalNotFound: + problemStrings.push('Signal Not Found'); + break; + case diagnosticsMojom.SignalStrengthProblem.kWeakSignal: + problemStrings.push('Weak Signal'); + break; + } + break; + + case RoutineType.GATEWAY_PING: + switch (problem) { + case diagnosticsMojom.GatewayCanBePingedProblem.kUnreachableGateway: + problemStrings.push('Gateway is Unreachable'); + break; + case diagnosticsMojom.GatewayCanBePingedProblem + .kFailedToPingDefaultNetwork: + problemStrings.push('Failed to ping default network'); + break; + case diagnosticsMojom.GatewayCanBePingedProblem + .kDefaultNetworkAboveLatencyThreshold: + problemStrings.push('Default network above latency threshold'); + break; + case diagnosticsMojom.GatewayCanBePingedProblem + .kUnsuccessfulNonDefaultNetworksPings: + problemStrings.push('Non-default network has failed pings'); + break; + case diagnosticsMojom.GatewayCanBePingedProblem + .kNonDefaultNetworksAboveLatencyThreshold: + problemStrings.push( + 'Non-default network is above latency threshold'); + break; + } + break; + + case RoutineType.SECURE_WIFI: + switch (problem) { + case diagnosticsMojom.HasSecureWiFiConnectionProblem + .kSecurityTypeNone: + problemStrings.push('WiFi Network is not secure'); + break; + case diagnosticsMojom.HasSecureWiFiConnectionProblem + .kSecurityTypeWep8021x: + problemStrings.push('WiFi Network secured with WEP 802.1x'); + break; + case diagnosticsMojom.HasSecureWiFiConnectionProblem + .kSecurityTypeWepPsk: + problemStrings.push('WiFi Network secured with WEP PSK'); + break; + case diagnosticsMojom.HasSecureWiFiConnectionProblem + .kUnknownSecurityType: + problemStrings.push('WiFi Network secured with WEP PSK'); + break; + } + break; + + case RoutineType.DNS_RESOLVER: + switch (problem) { + case diagnosticsMojom.DnsResolverPresentProblem.kNoNameServersFound: + problemStrings.push('No name servers found'); + break; + case diagnosticsMojom.DnsResolverPresentProblem + .kMalformedNameServers: + problemStrings.push('Malformed name servers'); + break; + case diagnosticsMojom.DnsResolverPresentProblem.kEmptyNameServers: + problemStrings.push('Empty name servers'); + break; + } + break; + + case RoutineType.DNS_LATENCY: + switch (problem) { + case diagnosticsMojom.DnsLatencyProblem.kFailedToResolveAllHosts: + problemStrings.push('Failed to resolve all hosts'); + break; + case diagnosticsMojom.DnsLatencyProblem.kSlightlyAboveThreshold: + problemStrings.push('DNS latency slightly above threshold'); + break; + case diagnosticsMojom.DnsLatencyProblem + .kSignificantlyAboveThreshold: + problemStrings.push('DNS latency significantly above threshold'); + break; + } + break; + + case RoutineType.DNS_RESOLUTION: + switch (problem) { + case diagnosticsMojom.DnsResolutionProblem.kFailedToResolveHost: + problemStrings.push('Failed to resolve host'); + break; + } + break; + } + } + + return problemStrings; + }, + + /** + * @param {!chromeos.networkDiagnostics.mojom.RoutineVerdict} verdict + * @return {string} String for a network diagnostic verdict used for feedback + * @private + */ + getRoutineVerdictFeedbackString_(verdict) { + switch (verdict) { + case diagnosticsMojom.RoutineVerdict.kNoProblem: + return 'Passed'; + case diagnosticsMojom.RoutineVerdict.kNotRun: + return 'Not Run'; + case diagnosticsMojom.RoutineVerdict.kProblem: + return 'Failed'; + } + return 'Unknown'; + }, +}); diff --git a/chromium/ui/webui/resources/cr_components/chromeos/os_cr_components.gni b/chromium/ui/webui/resources/cr_components/chromeos/os_cr_components.gni new file mode 100644 index 00000000000..a99f39d8bbc --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/chromeos/os_cr_components.gni @@ -0,0 +1,22 @@ +# 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. + +import("//third_party/closure_compiler/compile_js.gni") + +cr_components_chromeos_namespace_rewrites = [ + "network_config.MojoInterfaceProvider|MojoInterfaceProvider", + "settings.receivedEventFromKeyboard|receivedEventFromKeyboard", + "settings.LockScreenProgress|LockScreenProgress", + "cellular_setup.MojoInterfaceProvider|MojoInterfaceProvider", +] + +cr_components_chromeos_auto_imports = [ + "ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.html|CrPolicyIndicatorType", + "ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.html|CrPolicyNetworkBehaviorMojo", + "ui/webui/resources/cr_components/chromeos/network/onc_mojo.html|OncMojo", + "ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.html|NetworkListenerBehavior", + "ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.html|MojoInterfaceProviderImpl,MojoInterfaceProvider", + "ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html|recordLockScreenProgress,LockScreenProgress", + "ui/webui/resources/html/assert.html|assert,assertNotReached", +] diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn index a27e999205e..03c04595dce 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn +++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn @@ -3,6 +3,9 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/polymer.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") +import("../os_cr_components.gni") js_type_check("closure_compile") { deps = [ @@ -13,6 +16,7 @@ js_type_check("closure_compile") { js_library("pin_keyboard") { deps = [ + ":lock_screen_constants", "//ui/webui/resources/cr_elements/cr_input:cr_input", "//ui/webui/resources/js:i18n_behavior", ] @@ -36,28 +40,31 @@ js_library("setup_pin_keyboard") { extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ] } -# TODO: Uncomment as the Polymer3 migration makes progress. -# js_type_check("closure_compile_module") { -# is_polymer3 = true -# deps = [ -# ":lock_screen_constants.m", -# ":pin_keyboard.m", -# ":setup_pin_keyboard.m" -# ] -# } +js_type_check("closure_compile_module") { + is_polymer3 = true + deps = [ + ":lock_screen_constants.m", + ":pin_keyboard.m", + ":setup_pin_keyboard.m", + ] +} js_library("lock_screen_constants.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.m.js" ] deps = [ - # TODO: Fill those in. + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_profile_avatar_selector:cr_profile_avatar_selector.m", + "//ui/webui/resources/js:cr.m", ] - extra_deps = [ ":lock_screen_constants_module" ] + extra_deps = [ ":modulize" ] } js_library("pin_keyboard.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.m.js" ] deps = [ - # TODO: Fill those in. + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_input:cr_input.m", + "//ui/webui/resources/js:i18n_behavior.m", ] extra_deps = [ ":pin_keyboard_module" ] } @@ -65,8 +72,14 @@ js_library("pin_keyboard.m") { js_library("setup_pin_keyboard.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.m.js" ] deps = [ - # TODO: Fill those in. + ":lock_screen_constants.m", + ":pin_keyboard.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_components/chromeos/quick_unlock:lock_screen_constants.m", + "//ui/webui/resources/js:i18n_behavior.m", ] + externs_list = [ "$externs_path/quick_unlock_private.js" ] + extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ] extra_deps = [ ":setup_pin_keyboard_module" ] } @@ -74,26 +87,36 @@ import("//tools/polymer/polymer.gni") group("polymer3_elements") { public_deps = [ - ":lock_screen_constants_module", + ":modulize", + ":pin_keyboard_icon_module", ":pin_keyboard_module", ":setup_pin_keyboard_module", ] } -polymer_modulizer("lock_screen_constants") { - js_file = "lock_screen_constants.js" - html_file = "lock_screen_constants.html" - html_type = "dom-module" -} - polymer_modulizer("pin_keyboard") { js_file = "pin_keyboard.js" html_file = "pin_keyboard.html" html_type = "dom-module" + namespace_rewrites = cr_components_chromeos_namespace_rewrites + auto_imports = cr_components_chromeos_auto_imports } polymer_modulizer("setup_pin_keyboard") { js_file = "setup_pin_keyboard.js" html_file = "setup_pin_keyboard.html" html_type = "dom-module" + namespace_rewrites = cr_components_chromeos_namespace_rewrites + auto_imports = cr_components_chromeos_auto_imports +} + +js_modulizer("modulize") { + input_files = [ "lock_screen_constants.js" ] + namespace_rewrites = cr_components_chromeos_namespace_rewrites +} + +polymer_modulizer("pin_keyboard_icon") { + js_file = "pin_keyboard_icon.m.js" + html_file = "pin_keyboard_icon.html" + html_type = "iron-iconset" } diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.js b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.js index dbc85a36812..fd1606d2d22 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.js @@ -16,7 +16,7 @@ cr.define('settings', function() { * Stages the user can enter while setting up pin unlock. * @enum {number} */ - const LockScreenProgress = { + /* #export */ const LockScreenProgress = { START_SCREEN_LOCK: 0, ENTER_PASSWORD_CORRECTLY: 1, CHOOSE_PIN_OR_PASSWORD: 2, @@ -29,7 +29,7 @@ cr.define('settings', function() { * histogram. * @param {settings.LockScreenProgress} currentProgress */ - const recordLockScreenProgress = function(currentProgress) { + /* #export */ const recordLockScreenProgress = function(currentProgress) { if (currentProgress >= LockScreenProgress.MAX_BUCKET) { console.error( 'Expected a enumeration value of ' + LockScreenProgress.MAX_BUCKET + diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html index 1dc6eb3d818..74d26d2f35c 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html +++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html @@ -1,7 +1,3 @@ -<!-- TODO(crbug.com/603217): Use i18n instead of string literals. Figure out - what i18n to use for keypad, ie, does 1 ABC make - sense in every scenario? --> - <link rel="import" href="../../../html/polymer.html"> <link rel="import" href="../../../cr_elements/cr_button/cr_button.html"> @@ -267,3 +263,7 @@ </template> <script src="pin_keyboard.js"></script> </dom-module> + +<!-- TODO(crbug.com/603217): Use i18n instead of string literals. Figure out + what i18n to use for keypad, ie, does 1 ABC make + sense in every scenario? --> diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js index 1443e8fee07..eeebe765de4 100644 --- a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js +++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js @@ -10,9 +10,6 @@ * */ -(function() { -'use strict'; - /** * Keep in sync with the string keys provided by settings. * @enum {string} @@ -383,5 +380,3 @@ Polymer({ ''; }, }); - -})(); diff --git a/chromium/ui/webui/resources/cr_components/cr_components_images.grdp b/chromium/ui/webui/resources/cr_components/cr_components_images.grdp index 70d2a577251..04457a9e837 100644 --- a/chromium/ui/webui/resources/cr_components/cr_components_images.grdp +++ b/chromium/ui/webui/resources/cr_components/cr_components_images.grdp @@ -1,5 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> + <!-- CustomizeThemes Images --> + <include name="IDR_WEBUI_CR_COMPONENTS_CUSTOMIZE_THEMES_COLORIZE_ICON_SVG" + file="cr_components/customize_themes/colorize.svg" + type="BINDATA" /> + <include name="IDR_WEBUI_CR_COMPONENTS_CUSTOMIZE_THEMES_BRUSH_ICON_SVG" + file="cr_components/customize_themes/brush.svg" + type="BINDATA" /> <if expr="chromeos"> <!-- MultiDeviceSetup Images --> <include name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_START_SETUP_ICON_1X_PNG" diff --git a/chromium/ui/webui/resources/cr_components/cr_components_resources.grdp b/chromium/ui/webui/resources/cr_components/cr_components_resources.grdp index 2e2468044c8..61c6cd77fa0 100644 --- a/chromium/ui/webui/resources/cr_components/cr_components_resources.grdp +++ b/chromium/ui/webui/resources/cr_components/cr_components_resources.grdp @@ -134,6 +134,12 @@ <structure name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_CELLULAR_SETUP_JS" file="cr_components/chromeos/cellular_setup/cellular_setup.js" type="chrome_html" /> + <structure name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_PSIM_FLOW_HTML" + file="cr_components/chromeos/cellular_setup/psim_flow_ui.html" + type="chrome_html" /> + <structure name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_PSIM_FLOW_JS" + file="cr_components/chromeos/cellular_setup/psim_flow_ui.js" + type="chrome_html" /> <structure name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_MOJO_INTERFACE_PROVIDER_HTML" file="cr_components/chromeos/cellular_setup/mojo_interface_provider.html" type="chrome_html" /> @@ -264,6 +270,12 @@ <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_HEALTH_SUMMARY_JS" file="cr_components/chromeos/network_health/network_health_summary.js" type="chrome_html" /> + <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_DIAGNOSTICS_HTML" + file="cr_components/chromeos/network_health/network_diagnostics.html" + type="chrome_html" /> + <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_DIAGNOSTICS_JS" + file="cr_components/chromeos/network_health/network_diagnostics.js" + type="chrome_html" /> <!-- Shared between settings and add new share flow. --> <structure name="IDR_WEBUI_CHROMEOS_SMB_SHARES_SMB_BROWSER_PROXY_HTML" @@ -280,6 +292,18 @@ type="chrome_html" /> <!-- Used to render network-list and related subcomponents. --> + <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_CR_POLICY_NETWORK_BEHAVIOR_MOJO_HTML" + file="cr_components/chromeos/network/cr_policy_network_behavior_mojo.html" + type="chrome_html" /> + <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_CR_POLICY_NETWORK_BEHAVIOR_MOJO_JS" + file="cr_components/chromeos/network/cr_policy_network_behavior_mojo.js" + type="chrome_html" /> + <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_CR_POLICY_NETWORK_INDICATOR_MOJO_HTML" + file="cr_components/chromeos/network/cr_policy_network_indicator_mojo.html" + type="chrome_html" /> + <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_CR_POLICY_NETWORK_INDICATOR_MOJO_JS" + file="cr_components/chromeos/network/cr_policy_network_indicator_mojo.js" + type="chrome_html" /> <structure name="IDR_CR_COMPONENTS_CHROMEOS_NETWORK_ICON_HTML" file="cr_components/chromeos/network/network_icon.html" type="chrome_html" /> diff --git a/chromium/ui/webui/resources/cr_components/cr_components_resources_v3.grdp b/chromium/ui/webui/resources/cr_components/cr_components_resources_v3.grdp index 96b5ae7929a..5924dd69a8e 100644 --- a/chromium/ui/webui/resources/cr_components/cr_components_resources_v3.grdp +++ b/chromium/ui/webui/resources/cr_components/cr_components_resources_v3.grdp @@ -9,6 +9,24 @@ file="${root_gen_dir}/ui/webui/resources/cr_components/omnibox/cr_autocomplete_match_list.js" use_base_dir="false" type="BINDATA" /> + + <!-- customize_themes --> + <include name="IDR_WEBUI_CR_COMPONENTS_CUSTOMIZE_THEMES_CUSTOMIZE_THEMES_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/customize_themes/customize_themes.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CR_COMPONENTS_CUSTOMIZE_THEMES_THEME_ICON_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/customize_themes/theme_icon.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_CUSTOMIZE_THEMES_MOJOM_LITE_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/customize_themes/customize_themes.mojom-lite.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CR_COMPONENTS_CUSTOMIZE_THEMES_BROWSER_PROXY_JS" + file="cr_components/customize_themes/browser_proxy.js" + type="BINDATA" /> + <if expr="chromeos"> <include name="IDR_WEBUI_CHROMEOS_SMB_SHARES_ADD_SMB_SHARE_DIALOG_M_JS" file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.m.js" @@ -22,6 +40,94 @@ file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_dialog.m.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_CR_POLICY_NETWORK_BEHAVIOR_MOJO_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_behavior_mojo.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_CR_POLICY_NETWORK_INDICATOR_MOJO_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/cr_policy_network_indicator_mojo.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_CONFIG_ELEMENT_BEHAVIOR_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_config_element_behavior.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_LISTENER_BEHAVIOR_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_LIST_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_list.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_LIST_ITEM_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_list_item.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_LIST_TYPES_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_list_types.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_PASSWORD_INPUT_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_password_input.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_SHARED_CSS_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_shared_css.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_ONC_MOJOM_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/onc_mojo.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_MOJO_INTERFACE_PROVIDER_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_ICON_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_icon.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_NETWORK_ICONS_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_icons.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_SCREEN_CONSTANTS_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_SETUP_PIN_KEYBOARD_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_PIN_KEYBOARD_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_PIN_KEYBOARD_ICON_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard_icon.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_BASE_PAGE_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/cellular_setup/base_page.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_FINAL_PAGE_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/cellular_setup/final_page.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_MOJO_INTERFACE_PROVIDER_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/cellular_setup/mojo_interface_provider.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_WEBVIEW_POST_UTIL_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/cellular_setup/webview_post_util.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_WEBUI_CHROMEOS_CELLULAR_SETUP_SIM_DETECT_PAGE_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/cellular_setup/sim_detect_page.m.js" + use_base_dir="false" + type="BINDATA" /> </if> <if expr="use_nss_certs"> <include name="IDR_WEBUI_CA_TRUST_EDIT_DIALOG_JS" diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/BUILD.gn b/chromium/ui/webui/resources/cr_components/customize_themes/BUILD.gn new file mode 100644 index 00000000000..2f2f94cf709 --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/BUILD.gn @@ -0,0 +1,64 @@ +# 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. + +import("//mojo/public/tools/bindings/mojom.gni") +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +group("web_components") { + public_deps = [ + ":mojom_js", + ":web_components_local", + ] +} + +mojom("mojom") { + sources = [ "customize_themes.mojom" ] + + public_deps = [ + "//mojo/public/mojom/base", + "//skia/public/mojom", + ] +} + +html_to_js("web_components_local") { + js_files = [ + "customize_themes.js", + "theme_icon.js", + ] +} + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ + ":browser_proxy", + ":customize_themes", + ":theme_icon", + ] +} + +js_library("customize_themes") { + deps = [ + ":browser_proxy", + ":mojom_js_library_for_compile", + ":theme_icon", + "//skia/public/mojom:mojom_js_library_for_compile", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_grid", + "//ui/webui/resources/js:i18n_behavior.m", + ] +} + +js_library("theme_icon") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} + +js_library("browser_proxy") { + deps = [ + ":mojom_js_library_for_compile", + "//ui/webui/resources/js:cr.m", + ] +} diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/OWNERS b/chromium/ui/webui/resources/cr_components/customize_themes/OWNERS new file mode 100644 index 00000000000..3e630904d62 --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/OWNERS @@ -0,0 +1,9 @@ +aee@chromium.org +alexilin@chromium.org +mahmadi@chromium.org +tiborg@chromium.org + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS + +# COMPONENT: UI>Browser>Themes diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/browser_proxy.js b/chromium/ui/webui/resources/cr_components/customize_themes/browser_proxy.js new file mode 100644 index 00000000000..a5d2c2a92df --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/browser_proxy.js @@ -0,0 +1,62 @@ +// 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. + +/** + * @fileoverview A helper object used by the customize-themes component to + * interact with the browser. + */ + +import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; +import 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-lite.js'; +import './customize_themes.mojom-lite.js'; + +import {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; + +/** @interface */ +export class CustomizeThemesBrowserProxy { + /** @return {customizeThemes.mojom.CustomizeThemesHandlerInterface} */ + handler() {} + + /** @return {customizeThemes.mojom.CustomizeThemesClientCallbackRouter} */ + callbackRouter() {} + + /** @param {string} url */ + open(url) {} +} + +/** @implements {CustomizeThemesBrowserProxy} */ +export class CustomizeThemesBrowserProxyImpl { + constructor() { + /** @private {customizeThemes.mojom.CustomizeThemesHandlerRemote} */ + this.handler_ = new customizeThemes.mojom.CustomizeThemesHandlerRemote(); + + /** @private {customizeThemes.mojom.CustomizeThemesClientCallbackRouter} */ + this.callbackRouter_ = + new customizeThemes.mojom.CustomizeThemesClientCallbackRouter(); + + /** @type {customizeThemes.mojom.CustomizeThemesHandlerFactoryRemote} */ + const factory = + customizeThemes.mojom.CustomizeThemesHandlerFactory.getRemote(); + factory.createCustomizeThemesHandler( + this.callbackRouter_.$.bindNewPipeAndPassRemote(), + this.handler_.$.bindNewPipeAndPassReceiver()); + } + + /** @override */ + handler() { + return this.handler_; + } + + /** @override */ + callbackRouter() { + return this.callbackRouter_; + } + + /** @override */ + open(url) { + window.open(url, '_blank'); + } +} + +addSingletonGetter(CustomizeThemesBrowserProxyImpl); diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/brush.svg b/chromium/ui/webui/resources/cr_components/customize_themes/brush.svg new file mode 100644 index 00000000000..f6d29d556ac --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/brush.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M7 14c-1.66 0-3 1.34-3 3 0 1.31-1.16 2-2 2 .92 1.22 2.49 2 4 2 2.21 0 4-1.79 4-4 0-1.66-1.34-3-3-3zm13.71-9.37l-1.34-1.34a.996.996 0 0 0-1.41 0L9 12.25 11.75 15l8.96-8.96a.996.996 0 0 0 0-1.41z"/></svg>
\ No newline at end of file diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/colorize.svg b/chromium/ui/webui/resources/cr_components/customize_themes/colorize.svg new file mode 100644 index 00000000000..984de18801f --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/colorize.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M17.66 5.41l.92.92-2.69 2.69-.92-.92 2.69-2.69M17.67 3c-.26 0-.51.1-.71.29l-3.12 3.12-1.93-1.91-1.41 1.41 1.42 1.42L3 16.25V21h4.75l8.92-8.92 1.42 1.42 1.41-1.41-1.92-1.92 3.12-3.12c.4-.4.4-1.03.01-1.42l-2.34-2.34c-.2-.19-.45-.29-.7-.29zM6.92 19L5 17.08l8.06-8.06 1.92 1.92L6.92 19z"/></svg>
\ No newline at end of file diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.html b/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.html new file mode 100644 index 00000000000..3f73e993044 --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.html @@ -0,0 +1,152 @@ +<style include="cr-hidden-style cr-icons"> + :host { + --cr-customize-themes-grid-gap: 20px; + --cr-customize-themes-icon-size: 72px; + } + + #thirdPartyThemeContainer { + max-width: 544px; + width: 100%; + } + + #thirdPartyTheme { + align-items: center; + border: 1px solid var(--google-grey-refresh-300); + border-radius: 5px; + color: var(--cr-primary-text-color); + display: flex; + flex-direction: row; + margin-bottom: 24px; + padding: 0 16px; + } + + @media (prefers-color-scheme: dark) { + #thirdPartyTheme { + border-color: var(--google-grey-refresh-700); + } + } + + #thirdPartyBrushIcon { + -webkit-mask-image: url(chrome://resources/cr_components/customize_themes/brush.svg); + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: 100%; + background-color: var(--cr-primary-text-color); + margin-inline-end: 20px; + min-height: 24px; + min-width: 24px; + } + + #thirdPartyThemeNameContainer { + flex-grow: 1; + margin-inline-end: 24px; + } + + #thirdPartyThemeName { + font-weight: bold; + } + + #thirdPartyLink { + --cr-icon-button-fill-color: var(--cr-primary-text-color); + margin-inline-end: 24px; + } + + #uninstallThirdPartyButton { + margin: 16px 0; + } + + #themesContainer { + --cr-grid-gap: var(--cr-customize-themes-grid-gap); + } + + #themesContainer > * { + outline-width: 0; + } + + :host-context(.focus-outline-visible) #themesContainer > *:focus { + box-shadow: 0 0 0 2px rgba(var(--google-blue-600-rgb), .4); + } + + #autogeneratedThemeContainer { + display: flex; + position: relative; + } + + #colorPickerIcon { + -webkit-mask-image: url(chrome://resources/cr_components/customize_themes/colorize.svg); + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: 100%; + background-color: var(--google-grey-refresh-700); + height: 20px; + left: calc(50% - 10px); + position: absolute; + top: calc(50% - 10px); + width: 20px; + } + + cr-theme-icon { + --cr-theme-icon-size: var(--cr-customize-themes-icon-size); + } + + #autogeneratedTheme { + --cr-theme-icon-frame-color: var(--google-grey-refresh-100); + --cr-theme-icon-active-tab-color: white; + --cr-theme-icon-stroke-color: var(--google-grey-refresh-300); + } + + #defaultTheme { + --cr-theme-icon-frame-color: rgb(222, 225, 230); + --cr-theme-icon-active-tab-color: white; + } + + @media (prefers-color-scheme: dark) { + #defaultTheme { + --cr-theme-icon-frame-color: rgb(var(--google-grey-900-rgb)); + --cr-theme-icon-active-tab-color: rgb(50, 54, 57); + } + } + +</style> +<div id="thirdPartyThemeContainer" hidden="[[!isThirdPartyTheme_(selectedTheme)]]"> + <div id="thirdPartyTheme"> + <div id="thirdPartyBrushIcon"></div> + <div id="thirdPartyThemeNameContainer"> + <div id="thirdPartyThemeName" > + [[selectedTheme.info.thirdPartyThemeInfo.name]] + </div> + <div>[[i18n('thirdPartyThemeDescription')]]</div> + </div> + <cr-icon-button id="thirdPartyLink" class="icon-external" role="link" + on-click="onThirdPartyLinkButtonClick_"> + </cr-icon-button> + <cr-button id="uninstallThirdPartyButton" + on-click="onUninstallThirdPartyThemeClick_"> + [[i18n('uninstallThirdPartyThemeButton')]] + </cr-button> + </div> +</div> +<input id="colorPicker" type="color" on-change="onCustomFrameColorChange_" + hidden> +</input> +<cr-grid id="themesContainer" columns="6"> + <div id="autogeneratedThemeContainer" title="[[i18n('colorPickerLabel')]]" + tabindex="0" on-click="onAutogeneratedThemeClick_"> + <cr-theme-icon id="autogeneratedTheme" + selected$="[[isThemeIconSelected_('autogenerated', selectedTheme)]]"> + </cr-theme-icon> + <div id="colorPickerIcon"></div> + </div> + <cr-theme-icon id="defaultTheme" title="[[i18n('defaultThemeLabel')]]" + on-click="onDefaultThemeClick_" tabindex="0" + selected$="[[isThemeIconSelected_('default', selectedTheme)]]"> + </cr-theme-icon> + <template is="dom-repeat" id="themes" items="[[chromeThemes_]]"> + <cr-theme-icon title="[[item.label]]" on-click="onChromeThemeClick_" + style="--cr-theme-icon-frame-color: + [[skColorToRgba_(item.colors.frame)]]; + --cr-theme-icon-active-tab-color: + [[skColorToRgba_(item.colors.activeTab)]];" + tabindex="0" + selected$="[[isThemeIconSelected_(item.id, selectedTheme)]]"> + </cr-theme-icon> + </template> +</cr-grid> diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.js b/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.js new file mode 100644 index 00000000000..4862ee29f59 --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.js @@ -0,0 +1,197 @@ +// 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. + +import '../../cr_elements/cr_button/cr_button.m.js'; +import '../../cr_elements/cr_icon_button/cr_icon_button.m.js'; +import '../../cr_elements/cr_icons_css.m.js'; +import '../../cr_elements/cr_grid/cr_grid.js'; +import '../../cr_elements/shared_vars_css.m.js'; +import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; +import 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-lite.js'; +import './customize_themes.mojom-lite.js'; +import './theme_icon.js'; + +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {assert} from '../../js/assert.m.js'; +import {hexColorToSkColor, skColorToRgba} from '../../js/color_utils.js'; +import {I18nBehavior} from '../../js/i18n_behavior.m.js'; + +import {CustomizeThemesBrowserProxyImpl} from './browser_proxy.js'; + +/** + * Element that lets the user configure the autogenerated theme. + * @polymer + * @extends {PolymerElement} + */ +export class CustomizeThemesElement extends mixinBehaviors +([I18nBehavior], PolymerElement) { + static get is() { + return 'cr-customize-themes'; + } + + static get template() { + return html`{__html_template__}`; + } + + static get properties() { + return { + /** @type {!customizeThemes.mojom.Theme} */ + selectedTheme: { + type: Object, + observer: 'onThemeChange_', + notify: true, + }, + + /** @private {!Array<!customizeThemes.mojom.ChromeTheme>} */ + chromeThemes_: Array, + }; + } + + constructor() { + super(); + /** @private {customizeThemes.mojom.CustomizeThemesHandlerRemote} */ + this.handler_ = CustomizeThemesBrowserProxyImpl.getInstance().handler(); + + /** @private {customizeThemes.mojom.CustomizeThemesClientCallbackRouter} */ + this.callbackRouter_ = + CustomizeThemesBrowserProxyImpl.getInstance().callbackRouter(); + + /** @private {?number} */ + this.setThemeListenerId_ = null; + } + + /** @override */ + connectedCallback() { + super.connectedCallback(); + this.handler_.getChromeThemes().then(({chromeThemes}) => { + this.chromeThemes_ = chromeThemes; + }); + + this.setThemeListenerId_ = + this.callbackRouter_.setTheme.addListener(theme => { + this.selectedTheme = theme; + }); + } + + /** @override */ + disconnectedCallback() { + super.disconnectedCallback(); + this.callbackRouter_.removeListener(assert(this.setThemeListenerId_)); + } + + confirmThemeChanges() { + this.handler_.confirmThemeChanges(); + } + + revertThemeChanges() { + this.handler_.revertThemeChanges(); + } + + /** + * @param {!Event} e + * @private + */ + onCustomFrameColorChange_(e) { + this.handler_.applyAutogeneratedTheme(hexColorToSkColor(e.target.value)); + } + + /** @private */ + onAutogeneratedThemeClick_() { + this.$.colorPicker.click(); + } + + /** @private */ + onDefaultThemeClick_() { + this.handler_.applyDefaultTheme(); + } + + /** + * @param {!Event} e + * @private + */ + onChromeThemeClick_(e) { + this.handler_.applyChromeTheme(this.$.themes.itemForElement(e.target).id); + } + + /** @private */ + onThemeChange_() { + if (this.selectedTheme.type !== + customizeThemes.mojom.ThemeType.kAutogenerated) { + return; + } + const rgbaFrameColor = + skColorToRgba(this.selectedTheme.info.autogeneratedThemeColors.frame); + const rgbaActiveTabColor = skColorToRgba( + this.selectedTheme.info.autogeneratedThemeColors.activeTab); + this.$.autogeneratedTheme.style.setProperty( + '--cr-theme-icon-frame-color', rgbaFrameColor); + this.$.autogeneratedTheme.style.setProperty( + '--cr-theme-icon-stroke-color', rgbaFrameColor); + this.$.autogeneratedTheme.style.setProperty( + '--cr-theme-icon-active-tab-color', rgbaActiveTabColor); + this.$.colorPickerIcon.style.setProperty( + 'background-color', + skColorToRgba( + this.selectedTheme.info.autogeneratedThemeColors.activeTabText)); + } + + /** + * @param {!Event} e + * @private + */ + onUninstallThirdPartyThemeClick_(e) { + this.handler_.applyDefaultTheme(); + this.handler_.confirmThemeChanges(); + } + + /** @private */ + onThirdPartyLinkButtonClick_() { + CustomizeThemesBrowserProxyImpl.getInstance().open( + `https://chrome.google.com/webstore/detail/${ + this.selectedTheme.info.thirdPartyThemeInfo.id}`); + } + + /** + * @param {string|number} id + * @return {boolean} + * @private + */ + isThemeIconSelected_(id) { + if (!this.selectedTheme) { + return false; + } + if (id === 'autogenerated') { + return this.selectedTheme.type === + customizeThemes.mojom.ThemeType.kAutogenerated; + } else if (id === 'default') { + return this.selectedTheme.type === + customizeThemes.mojom.ThemeType.kDefault; + } else { + return this.selectedTheme.type === + customizeThemes.mojom.ThemeType.kChrome && + id === this.selectedTheme.info.chromeThemeId; + } + } + + /** + * @return {boolean} + * @private + */ + isThirdPartyTheme_() { + return this.selectedTheme.type === + customizeThemes.mojom.ThemeType.kThirdParty; + } + + /** + * @param {skia.mojom.SkColor} skColor + * @return {string} + * @private + */ + skColorToRgba_(skColor) { + return skColorToRgba(skColor); + } +} + +customElements.define(CustomizeThemesElement.is, CustomizeThemesElement); diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.mojom b/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.mojom new file mode 100644 index 00000000000..4d800e7b822 --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/customize_themes.mojom @@ -0,0 +1,83 @@ +// 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. + +module customize_themes.mojom; + +import "skia/public/mojom/skcolor.mojom"; + +struct ThemeColors { + // The theme's frame color. + skia.mojom.SkColor frame; + // The theme's active tab color. + skia.mojom.SkColor active_tab; + // The theme's text color that has enough contrast with `active_tab`. + skia.mojom.SkColor active_tab_text; +}; + +struct ChromeTheme { + // Theme identifier. + int32 id; + // Localized string of the theme name. + string label; + ThemeColors colors; +}; + +// Additional info for third-party themes. +struct ThirdPartyThemeInfo { + // ID in the Chrome Web Store. + string id; + // Human-readable theme name. + string name; +}; + +enum ThemeType { + kDefault, + kAutogenerated, + kChrome, + kThirdParty +}; + +union ThemeInfo { + // Set if the theme type is `kChrome`. + int32 chrome_theme_id; + // Set if the theme type is `kAutogenerated`. + ThemeColors autogenerated_theme_colors; + // Set if the theme type is `kThirdParty`. + ThirdPartyThemeInfo third_party_theme_info; +}; + +struct Theme { + // The theme's type (e.g. default or third-party). + ThemeType type; + // Additional info about the theme depending on the type. + ThemeInfo info; +}; + +// Used by the component to bootstrap bidirectional communication. +interface CustomizeThemesHandlerFactory { + // The component calls this method when it is first initialized. + CreateCustomizeThemesHandler( + pending_remote<CustomizeThemesClient> client, + pending_receiver<CustomizeThemesHandler> handler); +}; + +interface CustomizeThemesHandler { + // Applies the autogenerated theme for the given color. + ApplyAutogeneratedTheme(skia.mojom.SkColor frame_color); + // Applies the predefined Chrome theme with the given ID. + ApplyChromeTheme(int32 id); + // Applies the default theme. + ApplyDefaultTheme(); + // Returns the pre-defined Chrome themes. + GetChromeThemes() => (array<ChromeTheme> chromeThemes); + // Confirms changes made to the theme. + ConfirmThemeChanges(); + // Reverts changes made to the theme. + RevertThemeChanges(); +}; + +interface CustomizeThemesClient { + // Sets the current theme. + SetTheme(Theme theme); +}; diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/theme_icon.html b/chromium/ui/webui/resources/cr_components/customize_themes/theme_icon.html new file mode 100644 index 00000000000..7a56940625d --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/theme_icon.html @@ -0,0 +1,77 @@ +<style> + :host { + --cr-theme-icon-size: 72px; + } + + :host, + svg { + height: var(--cr-theme-icon-size); + width: var(--cr-theme-icon-size); + } + + #ring { + fill: rgba(var(--google-blue-600-rgb), 0.4); + visibility: hidden; + } + + #checkMark { + visibility: hidden; + } + + :host([selected]) #ring, + :host([selected]) #checkMark { + visibility: visible; + } + + #circle { + fill: url(#gradient); + stroke: var(--cr-theme-icon-stroke-color, + var(--cr-theme-icon-frame-color)); + stroke-width: 1; + } + + #leftColor { + stop-color: var(--cr-theme-icon-active-tab-color); + } + + #rightColor { + stop-color: var(--cr-theme-icon-frame-color); + } + + #checkMark circle { + fill: var(--google-blue-600); + } + + #checkMark path { + fill: white; + } + + @media (prefers-color-scheme: dark) { + #checkMark circle { + fill: var(--google-blue-refresh-300); + } + + #checkMark path { + fill: var(--google-grey-900); + } + } +</style> +<svg viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <defs> + <linearGradient id="gradient" gradientUnits="objectBoundingBox" + x1="50%" y1="0" x2="50.01%" y2="0"> + <stop id="leftColor" offset="0%"></stop> + <stop id="rightColor" offset="100%"></stop> + </linearGradient> + </defs> + <circle id="ring" cx="36" cy="36" r="36"></circle> + <circle id="circle" cx="36" cy="36" r="32"></circle> + <g id="checkMark" transform="translate(48.5, 3.5)"> + <circle cx="10" cy="10" r="10"></circle> + <path d="m 2.9885708,9.99721 5.0109458,4.98792 0.00275,-0.003 + 0.024151,0.0227 8.9741604,-9.01557 -1.431323,-1.42476 -7.5742214,7.6092 + -3.6031671,-3.58665 z"> + </path> + </g> +</svg> diff --git a/chromium/ui/webui/resources/cr_components/customize_themes/theme_icon.js b/chromium/ui/webui/resources/cr_components/customize_themes/theme_icon.js new file mode 100644 index 00000000000..dd934076c54 --- /dev/null +++ b/chromium/ui/webui/resources/cr_components/customize_themes/theme_icon.js @@ -0,0 +1,25 @@ +// 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. + +import '../../cr_elements/shared_vars_css.m.js'; + +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +/** + * Represents a theme. Displayed as a circle with each half colored based on + * the custom CSS properties |--cr-theme-icon-frame-color| and + * |--cr-theme-icon-active-tab-color|. Can be selected by setting the + * |selected| attribute. + */ +export class ThemeIconElement extends PolymerElement { + static get is() { + return 'cr-theme-icon'; + } + + static get template() { + return html`{__html_template__}`; + } +} + +customElements.define(ThemeIconElement.is, ThemeIconElement); diff --git a/chromium/ui/webui/resources/cr_elements/BUILD.gn b/chromium/ui/webui/resources/cr_elements/BUILD.gn index b57828b74c0..a32aa0ea8f6 100644 --- a/chromium/ui/webui/resources/cr_elements/BUILD.gn +++ b/chromium/ui/webui/resources/cr_elements/BUILD.gn @@ -16,6 +16,7 @@ group("closure_compile") { "cr_drawer:closure_compile", "cr_expand_button:closure_compile", "cr_fingerprint:closure_compile", + "cr_grid:closure_compile", "cr_icon_button:closure_compile", "cr_input:closure_compile", "cr_link_row:closure_compile", @@ -169,6 +170,7 @@ group("polymer3_elements") { "cr_drawer:cr_drawer_module", "cr_expand_button:cr_expand_button_module", "cr_fingerprint:polymer3_elements", + "cr_grid:web_components", "cr_icon_button:cr_icon_button_module", "cr_input:polymer3_elements", "cr_lazy_render:cr_lazy_render_module", diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/BUILD.gn b/chromium/ui/webui/resources/cr_elements/chromeos/BUILD.gn index 33cc937da69..da86dbedc1d 100644 --- a/chromium/ui/webui/resources/cr_elements/chromeos/BUILD.gn +++ b/chromium/ui/webui/resources/cr_elements/chromeos/BUILD.gn @@ -19,7 +19,7 @@ group("closure_compile") { group("polymer3_elements") { public_deps = [ ":cros_color_overrides_module", - "cr_picture:modulize", + "cr_picture:polymer3_elements", ] } diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn index be7345ede35..ea1ba540ca8 100644 --- a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn +++ b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn @@ -3,7 +3,9 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/polymer.gni") import("//ui/webui/resources/tools/js_modulizer.gni") +import("../os_cr_elements.gni") js_type_check("closure_compile") { deps = [ @@ -44,12 +46,20 @@ js_library("png") { } js_modulizer("modulize") { - input_files = [ "png.js" ] + input_files = [ + "png.js", + "cr_picture_types.js", + ] } js_type_check("closure_compile_module") { - uses_js_modules = true - deps = [ ":png.m" ] + is_polymer3 = true + deps = [ + ":cr_camera.m", + ":cr_picture_list.m", + ":cr_picture_pane.m", + ":png.m", + ] } js_library("png.m") { @@ -63,3 +73,75 @@ js_library("png.m") { ] extra_deps = [ ":modulize" ] } + +js_library("cr_picture_types.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_types.m.js" ] + extra_deps = [ ":modulize" ] +} + +group("polymer3_elements") { + public_deps = [ + ":cr_camera_module", + ":cr_picture_list_module", + ":cr_picture_pane_module", + ":icons_module", + ":modulize", + ] +} + +js_library("cr_picture_pane.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.m.js" ] + deps = [ + ":cr_camera.m", + ":cr_picture_types.m", + ":png.m", + ] + extra_deps = [ ":cr_picture_pane_module" ] +} + +js_library("cr_camera.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.m.js" ] + deps = [ ":png.m" ] + extra_deps = [ ":cr_camera_module" ] +} + +js_library("cr_picture_list.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.m.js" ] + deps = [ + ":cr_picture_types.m", + ":png.m", + "//third_party/polymer/v3_0/components-chromium/iron-selector:iron-selector", + "//ui/webui/resources/js:assert.m", + ] + extra_deps = [ ":cr_picture_list_module" ] +} + +polymer_modulizer("cr_camera") { + js_file = "cr_camera.js" + html_file = "cr_camera.html" + html_type = "dom-module" + namespace_rewrites = cr_elements_chromeos_namespace_rewrites + auto_imports = cr_elements_chromeos_auto_imports +} + +polymer_modulizer("cr_picture_list") { + js_file = "cr_picture_list.js" + html_file = "cr_picture_list.html" + html_type = "dom-module" + namespace_rewrites = cr_elements_chromeos_namespace_rewrites + auto_imports = cr_elements_chromeos_auto_imports +} + +polymer_modulizer("cr_picture_pane") { + js_file = "cr_picture_pane.js" + html_file = "cr_picture_pane.html" + html_type = "dom-module" + namespace_rewrites = cr_elements_chromeos_namespace_rewrites + auto_imports = cr_elements_chromeos_auto_imports +} + +polymer_modulizer("icons") { + js_file = "icons.m.js" + html_file = "icons.html" + html_type = "iron-iconset" +} diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js index 11be58740ed..1b14deab74d 100644 --- a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js +++ b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.js @@ -129,8 +129,11 @@ Polymer({ const interval = setInterval(() => { /** Stop capturing frames when all allocated frames have been consumed. */ if (frames.length) { - capturedFrames.push( - this.captureFrame_(this.$.cameraVideo, frames.pop())); + capturedFrames.push(this.captureFrame_( + /** + * @type {!HTMLVideoElement} + */ + (this.$.cameraVideo), frames.pop())); } else { clearInterval(interval); this.fire( diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js index 3ce3dd7e099..6630fd546e0 100644 --- a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js +++ b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js @@ -120,7 +120,11 @@ Polymer({ if (!selected) { return; } - this.setSelectedImage_(this.$.profileImage); + this.setSelectedImage_( + /** + * @type {!CrPicture.ImageElement} + */ + (this.$.profileImage)); }, /** @@ -131,7 +135,11 @@ Polymer({ return image.dataset.url === imageUrl; }); if (image) { - this.setSelectedImage_(image); + this.setSelectedImage_( + /** + * @type {!CrPicture.ImageElement} + */ + (image)); this.selectedImageUrl_ = ''; } else { this.selectedImageUrl_ = imageUrl; @@ -159,9 +167,17 @@ Polymer({ } else if ( this.fallbackImage_ && this.fallbackImage_.dataset.type !== CrPicture.SelectionTypes.OLD) { - this.selectImage_(this.fallbackImage_, true /* activate */); + this.selectImage_( + /** + * @type {!CrPicture.ImageElement} + */ + (this.fallbackImage_), true /* activate */); } else { - this.selectImage_(this.$.profileImage, true /* activate */); + this.selectImage_( + /** + * @type {!CrPicture.ImageElement} + */ + (this.$.profileImage), true /* activate */); } }, diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_types.js b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_types.js index 8afb666d23e..cf6c7f3f960 100644 --- a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_types.js +++ b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_types.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -const CrPicture = {}; +/* #export */ const CrPicture = {}; /** * Contains the possible types for picture list image elements. diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/os_cr_elements.gni b/chromium/ui/webui/resources/cr_elements/chromeos/os_cr_elements.gni new file mode 100644 index 00000000000..ad32b62a9c3 --- /dev/null +++ b/chromium/ui/webui/resources/cr_elements/chromeos/os_cr_elements.gni @@ -0,0 +1,15 @@ +# 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. + +import("//third_party/closure_compiler/compile_js.gni") + +cr_elements_chromeos_namespace_rewrites = [ + "cr.png.convertImageSequenceToPng|convertImageSequenceToPng", + "cr.png.isEncodedPngDataUrlAnimated|isEncodedPngDataUrlAnimated", +] + +cr_elements_chromeos_auto_imports = [ + "ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_types.html|CrPicture", + "ui/webui/resources/cr_elements/chromeos/cr_picture/png.html|convertImageSequenceToPng,isEncodedPngDataUrlAnimated", +] diff --git a/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html b/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html index cb1dc2e0360..302cff77fdc 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html +++ b/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html @@ -11,7 +11,7 @@ :host dialog { --drawer-width: 256px; --transition-timing: 200ms ease; - background-color: #fff; + background-color: var(--cr-drawer-background-color, #fff); border: none; bottom: 0; left: calc(-1 * var(--drawer-width)); @@ -26,7 +26,7 @@ @media (prefers-color-scheme: dark) { :host dialog { - background: var(--google-grey-900) + background: var(--cr-drawer-background-color, var(--google-grey-900)) linear-gradient(rgba(255, 255, 255, .04), rgba(255, 255, 255, .04)); } } diff --git a/chromium/ui/webui/resources/cr_elements/cr_fingerprint/BUILD.gn b/chromium/ui/webui/resources/cr_elements/cr_fingerprint/BUILD.gn index 7f9b6638be6..bf19ba93144 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_fingerprint/BUILD.gn +++ b/chromium/ui/webui/resources/cr_elements/cr_fingerprint/BUILD.gn @@ -10,6 +10,7 @@ js_type_check("closure_compile") { } js_library("cr_fingerprint_progress_arc") { + deps = [ "../cr_lottie:cr_lottie" ] } group("polymer3_elements") { @@ -39,6 +40,7 @@ js_type_check("closure_compile_module") { js_library("cr_fingerprint_progress_arc.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.m.js" ] deps = [ + "../cr_lottie:cr_lottie.m", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] extra_deps = [ ":cr_fingerprint_progress_arc_module" ] diff --git a/chromium/ui/webui/resources/cr_elements/cr_fingerprint/OWNERS b/chromium/ui/webui/resources/cr_elements/cr_fingerprint/OWNERS new file mode 100644 index 00000000000..16332070ea9 --- /dev/null +++ b/chromium/ui/webui/resources/cr_elements/cr_fingerprint/OWNERS @@ -0,0 +1 @@ +nsatragno@chromium.org diff --git a/chromium/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.html b/chromium/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.html index d76130c087c..0373979a468 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.html +++ b/chromium/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.html @@ -1,5 +1,6 @@ <link rel="import" href="../../html/polymer.html"> <link rel="import" href="cr_fingerprint_icon.html"> +<link rel="import" href="../cr_lottie/cr_lottie.html"> <dom-module id="cr-fingerprint-progress-arc"> <template> @@ -8,51 +9,34 @@ user-select: none; } - #canvasDiv { - height: 240px; - width: 460px; - } - - /* Put the image in a separate div with 0 height, otherwise the div will - take the height of the image, leaving us with a row of whitespace when - we position the #image to be inside #arc. */ - #imageDiv { - height: 0; - } - - #scanningAnimation { + .translucent { opacity: 0.3; - position: relative; } - #enrollmentDone { + #canvasDiv { + height: 240px; + overflow: hidden; position: relative; + width: 460px; } - #checkmarkDiv { - height: 0; + cr-lottie { + display: inline-block; + position: absolute; } - #checkmarkAnimation { - position: relative; + #enrollmentDone { + position: absolute; } </style> <div id="canvasDiv"> <canvas id="canvas" height="240" width="460"></canvas> - </div> - <div id="imageDiv"> - <img id="scanningAnimation" - src="chrome://theme/IDR_FINGERPRINT_ICON_ANIMATION" - aria-hidden="true"> + <cr-lottie id="scanningAnimation" aria-hidden="true" autoplay> + </cr-lottie> <iron-icon id="enrollmentDone" icon="cr-fingerprint-icon:enrollment-done" hidden> </iron-icon> </div> - <div id="checkmarkDiv" hidden> - <img id="checkmarkAnimation" - src="chrome://theme/IDR_FINGERPRINT_COMPLETE_TICK" - aria-hidden="true"> - </div> </template> <script src="cr_fingerprint_progress_arc.js"></script> </dom-module> diff --git a/chromium/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.js b/chromium/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.js index 07a78baa633..1350b9dc6fe 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.js +++ b/chromium/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.js @@ -2,6 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// #import {CrLottieElement} from '../cr_lottie/cr_lottie.m.js'; + +/** @type {string} */ +/* #export */ const FINGEPRINT_TICK_DARK_URL = + 'chrome://theme/IDR_FINGERPRINT_COMPLETE_TICK_DARK'; + +/** @type {string} */ +/* #export */ const FINGEPRINT_TICK_LIGHT_URL = + 'chrome://theme/IDR_FINGERPRINT_COMPLETE_TICK'; + (function() { /** @@ -127,10 +137,36 @@ Polymer({ */ updateTimerId_: undefined, + /** + * Media query for dark mode. + * @type {MediaQueryList|undefined} + * @private + */ + darkModeQuery_: undefined, + + /** + * Dark mode change listener callback. + * @type {function(MediaQueryList)|undefined} + * @private + */ + darkModeListener_: undefined, + /** @override */ attached() { this.scale_ = this.circleRadius / DEFAULT_CANVAS_CIRCLE_RADIUS; this.updateImages_(); + + this.darkModeListener_ = this.updateAnimationAsset_.bind(this); + this.darkModeQuery_ = window.matchMedia('(prefers-color-scheme: dark)'); + this.darkModeQuery_.addListener(this.darkModeListener_); + this.updateAnimationAsset_(); + }, + + /** @override */ + detached() { + this.darkModeQuery_.removeListener( + /** @type {function(MediaQueryList)} */ (this.darkModeListener_)); + this.darkModeListener_ = undefined; }, /** @@ -227,6 +263,24 @@ Polymer({ } }, + /** + * Updates the lottie animation taking into account the current state and + * whether dark mode is enabled. + * @private + */ + updateAnimationAsset_() { + const scanningAnimation = + /** @type {CrLottieElement} */ (this.$.scanningAnimation); + if (this.isComplete_) { + scanningAnimation.animationUrl = this.darkModeQuery_.matches ? + FINGEPRINT_TICK_DARK_URL : + FINGEPRINT_TICK_LIGHT_URL; + return; + } + scanningAnimation.animationUrl = + 'chrome://theme/IDR_FINGERPRINT_ICON_ANIMATION'; + }, + /* * Cleans up any pending animation update created by setInterval(). * @private @@ -247,10 +301,14 @@ Polymer({ * @private */ animateScanComplete_() { - this.$.checkmarkDiv.hidden = false; + const scanningAnimation = + /** @type {CrLottieElement|HTMLElement} */ (this.$.scanningAnimation); + scanningAnimation.singleLoop = true; + scanningAnimation.classList.remove('translucent'); + this.updateAnimationAsset_(); + this.resizeCheckMark_(scanningAnimation); + this.$.enrollmentDone.hidden = false; - this.$.scanningAnimation.hidden = true; - this.$.enrollmentDone.style.opacity = 1; }, /** @@ -259,12 +317,8 @@ Polymer({ */ animateScanProgress_() { this.$.enrollmentDone.hidden = false; - this.$.enrollmentDone.style.opacity = 0.3; - this.$.scanningAnimation.hidden = true; this.updateTimerId_ = window.setTimeout(() => { this.$.enrollmentDone.hidden = true; - this.$.enrollmentDone.style.opacity = 1; - this.$.scanningAnimation.hidden = false; }, FINGERPRINT_SCAN_SUCCESS_MS); }, @@ -287,8 +341,14 @@ Polymer({ this.isComplete_ = false; this.drawBackgroundCircle(); this.$.enrollmentDone.hidden = true; - this.$.scanningAnimation.hidden = false; - this.$.checkmarkDiv.hidden = true; + + const scanningAnimation = + /** @type {CrLottieElement|HTMLElement} */ (this.$.scanningAnimation); + scanningAnimation.singleLoop = false; + scanningAnimation.classList.add('translucent'); + this.updateAnimationAsset_(); + this.resizeAndCenterIcon_(scanningAnimation); + scanningAnimation.hidden = false; }, /** @@ -300,8 +360,6 @@ Polymer({ /** @type {!HTMLElement} */ (this.$.scanningAnimation)); this.resizeAndCenterIcon_( /** @type {!HTMLElement} */ (this.$.enrollmentDone)); - this.resizeCheckMark_( - /** @type {!HTMLElement} */ (this.$.checkmarkAnimation)); }, /** @@ -317,7 +375,7 @@ Polymer({ // Place in the center of the canvas. const left = this.$.canvas.width / 2 - ICON_WIDTH * this.scale_ / 2; - const top = 0 - ICON_HEIGHT * this.scale_ / 2 - this.$.canvas.height / 2; + const top = this.$.canvas.height / 2 - ICON_HEIGHT * this.scale_ / 2; target.style.left = left + 'px'; target.style.top = top + 'px'; }, @@ -334,9 +392,8 @@ Polymer({ target.style.height = CHECK_MARK_SIZE * this.scale_ + 'px'; // Place it in the left bottom corner of fingerprint progress circle. - const top = 0 - - (CHECK_MARK_SIZE * this.scale_ + this.$.canvas.height / 2 - - this.circleRadius); + const top = this.$.canvas.height / 2 + this.circleRadius - + CHECK_MARK_SIZE * this.scale_; const left = this.$.canvas.width / 2 + this.circleRadius - CHECK_MARK_SIZE * this.scale_; target.style.left = left + 'px'; diff --git a/chromium/ui/webui/resources/cr_elements/cr_grid/BUILD.gn b/chromium/ui/webui/resources/cr_elements/cr_grid/BUILD.gn new file mode 100644 index 00000000000..161ddd82153 --- /dev/null +++ b/chromium/ui/webui/resources/cr_elements/cr_grid/BUILD.gn @@ -0,0 +1,21 @@ +# 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. + +import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/html_to_js.gni") + +html_to_js("web_components") { + js_files = [ "cr_grid.js" ] +} + +js_type_check("closure_compile") { + is_polymer3 = true + deps = [ ":cr_grid" ] +} + +js_library("cr_grid") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} diff --git a/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.html b/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.html new file mode 100644 index 00000000000..65e0208e395 --- /dev/null +++ b/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.html @@ -0,0 +1,21 @@ +<style> + :host { + --cr-grid-gap: 0px; + } + + #grid { + display: grid; + grid-column-gap: var(--cr-grid-gap); + grid-row-gap: var(--cr-grid-gap); + grid-template-columns: repeat(var(--cr-grid-columns), auto); + width: fit-content; + } + + ::slotted(*) { + align-self: center; + justify-self: center; + } +</style> +<div id="grid" on-keydown="onKeyDown_"> + <slot id="items"></slot> +</div> diff --git a/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.js b/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.js new file mode 100644 index 00000000000..03203ca71f7 --- /dev/null +++ b/chromium/ui/webui/resources/cr_elements/cr_grid/cr_grid.js @@ -0,0 +1,88 @@ +// 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. + +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +// Displays children in a two-dimensional grid and supports focusing children +// with arrow keys. +export class CrGridElement extends PolymerElement { + static get is() { + return 'cr-grid'; + } + + static get template() { + return html`{__html_template__}`; + } + + static get properties() { + return { + /** @type {number} */ + columns: { + type: Number, + value: 1, + observer: 'onColumnsChange_', + }, + }; + } + + /** @private */ + onColumnsChange_() { + this.updateStyles({'--cr-grid-columns': this.columns}); + } + + /** + * @param {!Event} e + * @private + */ + onKeyDown_(e) { + if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) { + e.preventDefault(); + const items = this.$.items.assignedElements().filter( + (el) => + (!!(el.offsetWidth || el.offsetHeight || + el.getClientRects().length))); + const currentIndex = items.indexOf(e.target); + const isRtl = window.getComputedStyle(this)['direction'] === 'rtl'; + const bottomRowColumns = items.length % this.columns; + const direction = ['ArrowRight', 'ArrowDown'].includes(e.key) ? 1 : -1; + const inEdgeRow = direction === 1 ? + currentIndex >= items.length - bottomRowColumns : + currentIndex < this.columns; + let delta = 0; + switch (e.key) { + case 'ArrowLeft': + case 'ArrowRight': + delta = direction * (isRtl ? -1 : 1); + break; + case 'ArrowUp': + case 'ArrowDown': + delta = direction * (inEdgeRow ? bottomRowColumns : this.columns); + break; + } + // Handle cases where we move to an empty space in a non-full bottom row + // and have to jump to the next row. + if (e.key === 'ArrowUp' && inEdgeRow && + currentIndex >= bottomRowColumns) { + delta -= this.columns; + } else if ( + e.key === 'ArrowDown' && !inEdgeRow && + currentIndex + delta >= items.length) { + delta += bottomRowColumns; + } + const mod = function(m, n) { + return ((m % n) + n) % n; + }; + const newIndex = mod(currentIndex + delta, items.length); + items[newIndex].focus(); + } + + if (['Enter', ' '].includes(e.key)) { + e.preventDefault(); + e.stopPropagation(); + e.target.click(); + } + } +} + +customElements.define(CrGridElement.is, CrGridElement); diff --git a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html index 58ec0a3faff..20f893f5237 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html +++ b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html @@ -107,7 +107,7 @@ } #input[type='search']::-webkit-search-cancel-button { - -webkit-appearance: none; + display: none; } :host-context([dir=rtl]) #input[type=url] { diff --git a/chromium/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.html b/chromium/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.html index b6510ba45bd..59ef33450b8 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.html +++ b/chromium/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.html @@ -9,7 +9,7 @@ width: 100%; } </style> - <canvas id="canvas"></canvas> + <canvas id="canvas" hidden="[[hidden]]"></canvas> </template> <script src="cr_lottie.js"></script> </dom-module> diff --git a/chromium/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.js b/chromium/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.js index 7100161c006..58f4216022c 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.js +++ b/chromium/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.js @@ -10,6 +10,7 @@ * initialized. * Fires a 'cr-lottie-playing' event when the animation starts playing. * Fires a 'cr-lottie-paused' event when the animation has paused. + * Fires a 'cr-lottie-stopped' event when animation has stopped. * Fires a 'cr-lottie-resized' event when the canvas the animation is being * drawn on is resized. */ @@ -18,7 +19,8 @@ * The resource url for the lottier web worker script. * @const {string} */ -const LOTTIE_JS_URL = 'chrome://resources/lottie/lottie_worker.min.js'; +/* #export */ const LOTTIE_JS_URL = + 'chrome://resources/lottie/lottie_worker.min.js'; Polymer({ is: 'cr-lottie', @@ -27,28 +29,49 @@ Polymer({ animationUrl: { type: String, value: '', + observer: 'animationUrlChanged_', }, + autoplay: { type: Boolean, value: false, }, + + hidden: { + type: Boolean, + value: false, + }, + + singleLoop: { + type: Boolean, + value: false, + }, }, /** @private {?HTMLCanvasElement} */ canvasElement_: null, - /** @private {boolean} True if the animation has loaded successfully */ + /** @private {boolean} Whether the animation has loaded successfully */ isAnimationLoaded_: false, /** @private {?OffscreenCanvas} */ offscreenCanvas_: null, + /** + * @private {boolean} Whether the canvas has been transferred to the worker + * thread. + */ + hasTransferredCanvas_: false, + /** @private {?ResizeObserver} */ resizeObserver_: null, /** @private {?Worker} */ worker_: null, + /** @private {?XMLHttpRequest} The current in-flight request. */ + xhr_: null, + /** @override */ attached() { // CORS blocks loading worker script from a different origin but @@ -72,6 +95,10 @@ Polymer({ this.worker_.terminate(); this.worker_ = null; } + if (this.xhr_) { + this.xhr_.abort(); + this.xhr_ = null; + } }, /** @@ -110,6 +137,32 @@ Polymer({ }, /** + * Updates the animation that is being displayed. + * @param {string} animationUrl the new animation URL. + * @param {string} oldAnimationUrl the previous animation URL. + * @private + */ + animationUrlChanged_(animationUrl, oldAnimationUrl) { + if (!this.worker_) { + // The worker hasn't loaded yet. We will load the new animation once the + // worker loads. + return; + } + if (this.xhr_) { + // There is an in-flight request to load the previous animation. Abort it + // before loading a new image. + this.xhr_.abort(); + this.xhr_ = null; + } + if (this.isAnimationLoaded_) { + this.worker_.postMessage({control: {stop: true}}); + this.isAnimationLoaded_ = false; + } + this.sendXmlHttpRequest_( + this.animationUrl, 'json', this.initAnimation_.bind(this)); + }, + + /** * Computes the draw buffer size for the canvas. This ensures that the * rasterization is crisp and sharp rather than blurry. * @return {Object} Size of the canvas draw buffer @@ -152,13 +205,19 @@ Polymer({ */ sendXmlHttpRequest_(url, responseType, successCallback) { assert(this.isValidUrl_(url), 'Invalid scheme or data url used.'); - const xhr = new XMLHttpRequest(); - xhr.open('GET', url, true); - xhr.responseType = responseType; - xhr.send(); - xhr.onreadystatechange = function() { - if (xhr.readyState === 4 && xhr.status === 200) { - successCallback(xhr.response); + assert(!this.xhr_); + + this.xhr_ = new XMLHttpRequest(); + this.xhr_.open('GET', url, true); + this.xhr_.responseType = responseType; + this.xhr_.send(); + this.xhr_.onreadystatechange = () => { + if (this.xhr_.readyState === 4 && this.xhr_.status === 200) { + // |successCallback| might trigger another xhr, so we set to null before + // calling it. + const response = this.xhr_.response; + this.xhr_ = null; + successCallback(response); } }; }, @@ -181,14 +240,17 @@ Polymer({ * @private */ initAnimation_(animationData) { - this.worker_.postMessage( - { - canvas: this.offscreenCanvas_, - animationData: animationData, - drawSize: this.getCanvasDrawBufferSize_(), - params: {loop: true, autoplay: this.autoplay} - }, - [this.offscreenCanvas_]); + const message = [{ + animationData, + drawSize: this.getCanvasDrawBufferSize_(), + params: {loop: !this.singleLoop, autoplay: this.autoplay} + }]; + if (!this.hasTransferredCanvas_) { + message[0].canvas = this.offscreenCanvas_; + message.push([this.offscreenCanvas_]); + this.hasTransferredCanvas_ = true; + } + this.worker_.postMessage(...message); }, /** @@ -204,6 +266,8 @@ Polymer({ this.fire('cr-lottie-playing'); } else if (event.data.name === 'paused') { this.fire('cr-lottie-paused'); + } else if (event.data.name === 'stopped') { + this.fire('cr-lottie-stopped'); } else if (event.data.name === 'resized') { this.fire('cr-lottie-resized', event.data.size); } diff --git a/chromium/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn b/chromium/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn index 26a228344a2..c1855e35727 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn +++ b/chromium/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn @@ -7,13 +7,23 @@ import("//tools/polymer/polymer.gni") import("../../tools/js_modulizer.gni") js_type_check("closure_compile") { - deps = [ ":cr_radio_button" ] + deps = [ + ":cr_card_radio_button", + ":cr_radio_button", + ] } js_library("cr_radio_button") { deps = [ ":cr_radio_button_behavior" ] } +js_library("cr_card_radio_button") { + deps = [ + ":cr_radio_button_behavior", + "//third_party/polymer/v1_0/components-chromium/iron-icon:iron-icon-extracted", + ] +} + js_library("cr_radio_button_behavior") { deps = [ "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted" ] } @@ -22,6 +32,7 @@ js_library("cr_radio_button_behavior") { group("polymer3_elements") { public_deps = [ + ":cr_card_radio_button_module", ":cr_radio_button_module", ":cr_radio_button_style_css_module", ":modulize", @@ -41,6 +52,13 @@ polymer_modulizer("cr_radio_button") { auto_imports = [ "ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.html|CrRadioButtonBehavior" ] } +polymer_modulizer("cr_card_radio_button") { + js_file = "cr_card_radio_button.js" + html_file = "cr_card_radio_button.html" + html_type = "dom-module" + auto_imports = [ "ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.html|CrRadioButtonBehavior" ] +} + polymer_modulizer("cr_radio_button_style_css") { js_file = "cr_radio_button_style_css.m.js" html_file = "cr_radio_button_style_css.html" @@ -50,6 +68,7 @@ polymer_modulizer("cr_radio_button_style_css") { js_type_check("closure_compile_module") { is_polymer3 = true deps = [ + ":cr_card_radio_button.m", ":cr_radio_button.m", ":cr_radio_button_behavior.m", ] @@ -64,6 +83,16 @@ js_library("cr_radio_button.m") { extra_deps = [ ":cr_radio_button_module" ] } +js_library("cr_card_radio_button.m") { + sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.m.js" ] + deps = [ + ":cr_radio_button_behavior.m", + "//third_party/polymer/v3_0/components-chromium/iron-icon", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] + extra_deps = [ ":cr_card_radio_button_module" ] +} + js_library("cr_radio_button_behavior.m") { sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js" ] deps = [ "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior" ] diff --git a/chromium/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.html b/chromium/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.html new file mode 100644 index 00000000000..8f5ff9bb3c8 --- /dev/null +++ b/chromium/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.html @@ -0,0 +1,68 @@ +<link rel="import" href="../../html/polymer.html"> + +<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> +<link rel="import" href="cr_radio_button_behavior.html"> +<link rel="import" href="cr_radio_button_style_css.html"> +<link rel="import" href="../icons.html"> +<link rel="import" href="../shared_vars_css.html"> + +<dom-module id="cr-card-radio-button"> + <template> + <style include="cr-radio-button-style"> + :host { + background-color: var(--cr-card-background-color); + border: solid 2px; + border-radius: 8px; + box-shadow: var(--cr-elevation-1); + margin: var(--cr-card-radio-button-margin, 8px); + width: var(--cr-card-radio-button-width, 200px); + } + + :host([checked]) { + border-color: var(--cr-checked-color); + } + + :host(:not([checked])) { + border-color: var(--cr-card-background-color); + } + + #button { + height: var(--cr-card-radio-button-height, auto); + padding: var(--cr-card-radio-button-padding, 24px); + position: relative; + width: 100%; + } + + #checkMark { + position: absolute; + right: var(--cr-button-edge-spacing); + top: var(--cr-button-edge-spacing); + } + + :host(:not([checked])) #checkMark { + display: none; + } + + #slottedContent { + padding: var(--cr-card-radio-button-slotted-content-padding); + } + + #checkMark { + fill: var(--cr-checked-color); + } + </style> + <div id="button" role="radio" + aria-checked$="[[getAriaChecked_(checked)]]" + aria-describedby="slotted-content" + aria-disabled$="[[getAriaDisabled_(disabled)]]" + tabindex$="[[buttonTabIndex_]]" + aria-labelledby="slotted-content" + on-keydown="onInputKeydown_"> + <iron-icon id="checkMark" icon="cr:check-circle"></iron-icon> + <span id="slottedContent"> + <slot></slot> + </span> + </div> + </template> + <script src="cr_card_radio_button.js"></script> +</dom-module> diff --git a/chromium/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.js b/chromium/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.js new file mode 100644 index 00000000000..2de0052679c --- /dev/null +++ b/chromium/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.js @@ -0,0 +1,16 @@ +// 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. + +/** + * @fileoverview + * 'cr-card-radio-button' is a radio button in the style of a card. A checkmark + * is displayed in the upper right hand corner if the radio button is selected. + */ +Polymer({ + is: 'cr-card-radio-button', + + behaviors: [ + CrRadioButtonBehavior, + ], +}); diff --git a/chromium/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js b/chromium/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js index 2d5e83c0279..115f054e170 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js +++ b/chromium/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js @@ -32,7 +32,7 @@ selectableElements: { type: String, - value: 'cr-radio-button, controlled-radio-button', + value: 'cr-radio-button, cr-card-radio-button, controlled-radio-button', }, /** diff --git a/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js index 86adfdd2267..99ec7838878 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js +++ b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js @@ -137,3 +137,37 @@ return true; }, }; + +/** @interface */ +/* #export */ class CrSearchFieldBehaviorInterface { + constructor() { + /** @type {string} */ + this.label; + + /** @type {string} */ + this.clearLabel; + + /** @type {boolean} */ + this.hasSearchText; + } + + /** + * @return {!HTMLInputElement} The input field element the behavior should + * use. + */ + getSearchInput() {} + + /** @return {string} The value of the search field. */ + getValue() {} + + /** + * @param {string} value + * @param {boolean=} opt_noEvent Whether to prevent a 'search-changed' event + * firing for this change. + */ + setValue(value, opt_noEvent) {} + + onSearchTermSearch() {} + + onSearchTermInput() {} +} diff --git a/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js b/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js index 80c589c23bb..06823f7b8f6 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js +++ b/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js @@ -265,7 +265,7 @@ Polymer({ if (this.readonly) { return; } - if (event.code === 'Enter') { + if (event.key === 'Enter') { this.openDropdown_(); // Stop the default submit action. event.preventDefault(); @@ -274,7 +274,7 @@ Polymer({ } event.stopPropagation(); - switch (event.code) { + switch (event.key) { case 'Tab': // Pressing tab will cause the input field to lose focus. Since the // dropdown visibility is tied to focus, close the dropdown. @@ -287,7 +287,7 @@ Polymer({ if (items.length === 0) { break; } - this.updateSelected_(items, selected, event.code === 'ArrowDown'); + this.updateSelected_(items, selected, event.key === 'ArrowDown'); break; } case 'Enter': { diff --git a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html index 82e0d5f1481..da7259f3012 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html +++ b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html @@ -180,7 +180,7 @@ label="[[searchPrompt]]" clear-label="[[clearLabel]]" spinner-active="[[spinnerActive]]" showing-search="{{showingSearch_}}" - autofocus> + autofocus$="[[autofocus]]"> </cr-toolbar-search-field> <iron-media-query query="(max-width: [[narrowThreshold]]px)" query-matches="{{narrow}}"> diff --git a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.js b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.js index 70254a876c2..23640a9a3b3 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.js +++ b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.js @@ -38,6 +38,13 @@ Polymer({ // Controls whether the search field is shown. showSearch: {type: Boolean, value: true}, + // Controls whether the search field is autofocused. + autofocus: { + type: Boolean, + value: false, + reflectToAttribute: true, + }, + // True when the toolbar is displaying in narrow mode. narrow: { type: Boolean, diff --git a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html index 2854d6a9d85..86e320ea2a3 100644 --- a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html +++ b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html @@ -118,8 +118,7 @@ } input[type='search']::-webkit-search-cancel-button { - -webkit-appearance: none; - margin: 0; + display: none; } :host([narrow]) { diff --git a/chromium/ui/webui/resources/cr_elements/icons.html b/chromium/ui/webui/resources/cr_elements/icons.html index 45ea1fcf770..5790b5860e6 100644 --- a/chromium/ui/webui/resources/cr_elements/icons.html +++ b/chromium/ui/webui/resources/cr_elements/icons.html @@ -30,6 +30,13 @@ blurry at 20 px). Please use 20 px icons when available. <g id="menu"> <path d="M2 4h16v2H2zM2 9h16v2H2zM2 14h16v2H2z"></path> </g> + <if expr="chromeos"> + <g id="banner-warning"> + <path fill-rule="evenodd" clip-rule="evenodd" + d="M9.13177 1.50386C9.51566 0.832046 10.4844 0.832046 10.8683 1.50386L18.8683 15.5039C19.2492 16.1705 18.7678 17 18 17H2.00001C1.23219 17 0.750823 16.1705 1.13177 15.5039L9.13177 1.50386ZM10 4.01556L3.72321 15H16.2768L10 4.01556ZM9 11H11V7H9V11ZM11 14H9V12H11V14Z" fill="#E8710A"> + </path> + </g> + </if> </svg> </iron-iconset-svg> @@ -80,6 +87,11 @@ blurry at 20 px). Please use 20 px icons when available. d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"> </path> </g> + <g id="check-circle"> + <path + d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"> + </path> + </g> </if> <g id="cancel"> <path @@ -238,12 +250,6 @@ blurry at 20 px). Please use 20 px icons when available. <g id="star"> <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path> </g> - <g id="supervisor-account" viewBox="0 0 48 48"> - <path d="M0 0h48v48H0z" fill="none"></path> - <path - d="M33 24c2.76 0 4.98-2.24 4.98-5s-2.22-5-4.98-5c-2.76 0-5 2.24-5 5s2.24 5 5 5zm-15-2c3.31 0 5.98-2.69 5.98-6s-2.67-6-5.98-6c-3.31 0-6 2.69-6 6s2.69 6 6 6zm15 6c-3.67 0-11 1.84-11 5.5V38h22v-4.5c0-3.66-7.33-5.5-11-5.5zm-15-2c-4.67 0-14 2.34-14 7v5h14v-4.5c0-1.7.67-4.67 4.74-6.94C21 26.19 19.31 26 18 26z"> - </path> - </g> <g id="sync"> <path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"> diff --git a/chromium/ui/webui/resources/cr_elements/policy/BUILD.gn b/chromium/ui/webui/resources/cr_elements/policy/BUILD.gn index 22f8e5f9b25..0e61e9f13cc 100644 --- a/chromium/ui/webui/resources/cr_elements/policy/BUILD.gn +++ b/chromium/ui/webui/resources/cr_elements/policy/BUILD.gn @@ -14,12 +14,6 @@ js_type_check("closure_compile") { ":cr_policy_pref_indicator", ":cr_tooltip_icon", ] - if (is_chromeos) { - deps += [ - ":cr_policy_network_behavior_mojo", - ":cr_policy_network_indicator_mojo", - ] - } } js_library("cr_policy_indicator") { @@ -42,26 +36,6 @@ js_library("cr_policy_pref_indicator") { externs_list = [ "$externs_path/settings_private.js" ] } -if (is_chromeos) { - # TODO(jonmann): These cr_policy_network_* libs should be moved to cr_components. - js_library("cr_policy_network_behavior_mojo") { - deps = [ - ":cr_policy_indicator_behavior", - "//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile", - "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider", - "//ui/webui/resources/cr_components/chromeos/network:onc_mojo", - ] - } - - js_library("cr_policy_network_indicator_mojo") { - deps = [ - ":cr_policy_indicator_behavior", - ":cr_policy_network_behavior_mojo", - ":cr_tooltip_icon", - ] - } -} - js_library("cr_tooltip_icon") { } diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior_mojo.html b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior_mojo.html deleted file mode 100644 index 3a1174c3436..00000000000 --- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior_mojo.html +++ /dev/null @@ -1,3 +0,0 @@ -<link rel="import" href="../../html/polymer.html"> -<link rel="import" href="cr_policy_indicator_behavior.html"> -<script src="cr_policy_network_behavior_mojo.js"></script> diff --git a/chromium/ui/webui/resources/cr_elements/shared_vars_css.html b/chromium/ui/webui/resources/cr_elements/shared_vars_css.html index 4f4c0b03cbd..6d0cf07bc83 100644 --- a/chromium/ui/webui/resources/cr_elements/shared_vars_css.html +++ b/chromium/ui/webui/resources/cr_elements/shared_vars_css.html @@ -29,6 +29,9 @@ --google-red-600-rgb: 217, 48, 37; /* #d93025 */ --google-red-600: rgb(var(--google-red-600-rgb)); + --google-yellow-50-rgb: 254, 247, 224; /* #fef7e0 */ + --google-yellow-50: rgb(var(--google-yellow-50-rgb)); + /* -refresh differentiate from polymer's color.html. */ --google-blue-refresh-100-rgb: 210, 227, 252; /* #d2e3fc */ --google-blue-refresh-100: rgb(var(--google-blue-refresh-100-rgb)); @@ -155,16 +158,6 @@ --cr-section-indent-padding: calc( var(--cr-section-padding) + var(--cr-section-indent-width)); - /* TODO(crbug.com/973674): Do not use this mixin. Use the class cr-row - * from shared_style_css.html instead. */ - --cr-section: { - align-items: center; - border-top: var(--cr-separator-line); - display: flex; - min-height: var(--cr-section-min-height); - padding: 0 var(--cr-section-padding); - } - --cr-section-vertical-margin: 21px; --cr-centered-card-max-width: 680px; diff --git a/chromium/ui/webui/resources/cr_elements_resources.grdp b/chromium/ui/webui/resources/cr_elements_resources.grdp index 60a58298ff0..b2f7c58f833 100644 --- a/chromium/ui/webui/resources/cr_elements_resources.grdp +++ b/chromium/ui/webui/resources/cr_elements_resources.grdp @@ -98,6 +98,12 @@ <structure name="IDR_CR_ELEMENTS_CR_RADIO_BUTTON_JS" file="cr_elements/cr_radio_button/cr_radio_button.js" type="chrome_html" /> + <structure name="IDR_CR_ELEMENTS_CR_CARD_RADIO_BUTTON_HTML" + file="cr_elements/cr_radio_button/cr_card_radio_button.html" + type="chrome_html" /> + <structure name="IDR_CR_ELEMENTS_CR_CARD_RADIO_BUTTON_JS" + file="cr_elements/cr_radio_button/cr_card_radio_button.js" + type="chrome_html" /> <structure name="IDR_CR_ELEMENTS_CR_RADIO_BUTTON_BEHAVIOR_HTML" file="cr_elements/cr_radio_button/cr_radio_button_behavior.html" type="chrome_html" /> @@ -189,20 +195,6 @@ <structure name="IDR_CR_ELEMENTS_CR_POLICY_INDICATOR_BEHAVIOR_JS" file="cr_elements/policy/cr_policy_indicator_behavior.js" type="chrome_html" /> - <if expr="chromeos"> - <structure name="IDR_CR_ELEMENTS_CR_POLICY_NETWORK_BEHAVIOR_MOJO_HTML" - file="cr_elements/policy/cr_policy_network_behavior_mojo.html" - type="chrome_html" /> - <structure name="IDR_CR_ELEMENTS_CR_POLICY_NETWORK_BEHAVIOR_MOJO_JS" - file="cr_elements/policy/cr_policy_network_behavior_mojo.js" - type="chrome_html" /> - <structure name="IDR_CR_ELEMENTS_CR_POLICY_NETWORK_INDICATOR_MOJO_JS" - file="cr_elements/policy/cr_policy_network_indicator_mojo.js" - type="chrome_html" /> - <structure name="IDR_CR_ELEMENTS_CR_POLICY_NETWORK_INDICATOR_MOJO_HTML" - file="cr_elements/policy/cr_policy_network_indicator_mojo.html" - type="chrome_html" /> - </if> <structure name="IDR_CR_ELEMENTS_CR_POLICY_PREF_BEHAVIOR_HTML" file="cr_elements/policy/cr_policy_pref_behavior.html" type="chrome_html" /> diff --git a/chromium/ui/webui/resources/cr_elements_resources_v3.grdp b/chromium/ui/webui/resources/cr_elements_resources_v3.grdp index d8c2e3d035a..45ded9f61e8 100644 --- a/chromium/ui/webui/resources/cr_elements_resources_v3.grdp +++ b/chromium/ui/webui/resources/cr_elements_resources_v3.grdp @@ -29,6 +29,10 @@ file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.m.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_CR_ELEMENTS_CR_EXPAND_BUTTON_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.m.js" + use_base_dir="false" + type="BINDATA" /> <include name="IDR_CR_ELEMENTS_CR_FINGERPRINT_ICON_M_JS" file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_icon.m.js" use_base_dir="false" @@ -37,8 +41,8 @@ file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_fingerprint/cr_fingerprint_progress_arc.m.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_CR_ELEMENTS_CR_EXPAND_BUTTON_M_JS" - file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.m.js" + <include name="IDR_CR_ELEMENTS_CR_GRID_JS" + file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_grid/cr_grid.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_CR_ELEMENTS_CR_ICON_BUTTON_M_JS" @@ -77,6 +81,10 @@ file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector_grid.m.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_CR_ELEMENTS_CR_CARD_RADIO_BUTTON_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_radio_button/cr_card_radio_button.m.js" + use_base_dir="false" + type="BINDATA" /> <include name="IDR_CR_ELEMENTS_CR_RADIO_BUTTON_M_JS" file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.m.js" use_base_dir="false" @@ -202,6 +210,27 @@ file="${root_gen_dir}/ui/webui/resources/cr_elements/chromeos/cr_picture/png.m.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_CAMERA_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_camera.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_PICTURE_LIST_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_PICTURE_PANE_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_pane.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_PICTURE_TYPES_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_types.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_ICONS_M_JS" + file="${root_gen_dir}/ui/webui/resources/cr_elements/chromeos/cr_picture/icons.m.js" + use_base_dir="false" + preprocess="true" + type="BINDATA" /> </if> <include name="IDR_CR_ELEMENTS_LOTTIE_M_JS" file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_lottie/cr_lottie.m.js" diff --git a/chromium/ui/webui/resources/css/BUILD.gn b/chromium/ui/webui/resources/css/BUILD.gn deleted file mode 100644 index 49dfa4a1a96..00000000000 --- a/chromium/ui/webui/resources/css/BUILD.gn +++ /dev/null @@ -1,12 +0,0 @@ -# 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. - -import("//tools/style_variable_generator/style_variable_generator.gni") - -style_variable_generator("cros_colors") { - sources = [ - "cros_colors.json5", - "cros_palette.json5", - ] -} diff --git a/chromium/ui/webui/resources/css/cros_colors.json5 b/chromium/ui/webui/resources/css/cros_colors.json5 deleted file mode 100644 index db08320259e..00000000000 --- a/chromium/ui/webui/resources/css/cros_colors.json5 +++ /dev/null @@ -1,160 +0,0 @@ -/* 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. */ - -/* - * Chrome OS semantic colors. - * - * Colors that are used across all Chrome OS WebUIS and System Web Apps should - * be semantically represented here. - */ -{ - colors: { - /* - * Core colors. - */ - cros_default_text_color: { - light: "$google_grey_900", - dark: "$google_grey_200", - }, - cros_default_text_color_secondary: { - light: "$google_grey_700", - dark: "$google_grey_500", - }, - - cros_default_bg_color: { - light: "#ffffff", - dark: "$google_grey_900", - }, - - cros_default_icon_color_primary: { - light: "$google_grey_700", - dark: "$google_grey_200", - }, - - cros_default_icon_color_prominent: { - light: "$google_blue_600", - dark: "$google_blue_300", - }, - - /* - * Component colors. - */ - cros_default_toolbar_bg_color: "#ffffff", - cros_default_toolbar_search_bg_color: "$google_grey_100", - - cros_menu_button_bg_color_active: "$google_blue_50", - cros_menu_button_bg_color_hover: "$google_grey_100", - cros_menu_button_outline_color_focused: "$google_blue_600", - - cros_toggle_color: "$cros_default_icon_color_prominent", - cros_toggle_bg_color_inactive: "$google_grey_400", - cros_toggle_button_color_inactive: "#ffffff", - cros_toggle_ripple_color: "rgba($cros_toggle_color_rgb, .2)", - cros_toggle_ripple_color_inactive: "rgba($google_grey_600_rgb, .15)", - - cros_radio_button_color: "$cros_default_icon_color_prominent", - cros_radio_button_ripple_color: "rgba($cros_radio_button_color_rgb, .2)", - cros_radio_button_color_unchecked: "$google_grey_700", - cros_radio_button_ripple_color_unchecked: "rgba($google_grey_600_rgb, .15)", - - cros_separator_color: "rgba(0, 0, 0, 0.12)", - - cros_link_color: "$google_blue_700", - - /* button-primary */ - cros_default_button_background_color_primary: - "$cros_default_icon_color_prominent", - cros_default_button_label_color_primary: { - light: "$google_grey_200", - dark: "$google_grey_900", - }, - /* button-primary:hover */ - /* TODO(calamity): Generate a linear-gradient() to use for compositing - backgrounds */ - cros_default_button_background_color_primary_hover_overlay: { - light: "rgba(255, 255, 255, 0.08)", - dark: "rgba(0, 0, 0, 0.08)", - }, - /* button-primary[disabled] */ - cros_default_button_background_color_primary_disabled: { - light: "$google_grey_100", - dark: "$google_grey_800", - }, - cros_default_button_label_color_primary_disabled: { - light: "$google_grey_600", - dark: "$google_grey_500", - }, - - /* button-secondary */ - cros_default_button_label_color_secondary: - "$cros_default_icon_color_prominent", - cros_default_button_stroke_color_secondary: { - light: "$google_grey_300", - dark: "$google_grey_700", - }, - /* button-secondary:hover */ - cros_default_button_background_color_secondary_hover: - "rgba($cros_default_icon_color_prominent_rgb, 0.04)", - /* button-secondary[disabled] */ - cros_default_button_label_color_secondary_disabled: { - light: "$google_grey_600", - dark: "$google_grey_500", - }, - cros_default_button_stroke_color_secondary_disabled: { - light: "$google_grey_100", - dark: "$google_grey_800", - }, - - /* textfield */ - default_textfield_background_color: { - light: "$google_grey_100", - dark: "rgba(0, 0, 0, 0.3)", - }, - default_texfield_label_color: { - light: "$google_grey_700", - dark: "rgba(255, 255, 255, 0.6)", - }, - default_texfield_input_color: { - light: "$google_grey_900", - dark: "rgba(255, 255, 255, 0.87)", - }, - /* textfield:focus */ - default_texfield_label_color_focus: "$cros_default_icon_color_prominent", - /* textfield[error] */ - default_texfield_label_color_error: { - light: "$google_red_600", - dark: "$google_red_300", - }, - /* textfield[disabled] */ - default_textfield_background_color_disabled: { - light: "rgba($google_grey_100_rgb, 0.38)", - dark: "rgba(0, 0, 0, 0.11)", - }, - default_texfield_label_color_disabled: { - light: "rgba($google_grey_700_rgb, 0.38)", - dark: "rgba(0, 0, 0, 0.23)", - }, - default_texfield_input_color_disabled: { - light: "rgba($google_grey_900_rgb, 0.38)", - dark: "rgba(255, 255, 255, 0.33)", - }, - - /* - * One_offs. - * - * List your project's one_off colors below here. If a semantic color comes - * up repeatedly, consider speaking to UX about pulling out a common - * variable above. - */ - - /* OS Settings */ - cros_error_color: "$google_red_700", - cros_success_color: "$google_green_700", - - cros_search_page_question_icon_color: "$google_grey_500", - cros_app_management_permission_icon_color: "$google_grey_600", - - cros_user_icon_color_secondary: "rgb(210, 210, 212)", - }, -} diff --git a/chromium/ui/webui/resources/css/cros_palette.json5 b/chromium/ui/webui/resources/css/cros_palette.json5 deleted file mode 100644 index b26d8170e8c..00000000000 --- a/chromium/ui/webui/resources/css/cros_palette.json5 +++ /dev/null @@ -1,68 +0,0 @@ -/* 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. */ - -/* - * Chrome OS color palette. - * - * All colors used in Chrome OS WebUIs and System Web Apps should be specified - * here. - */ -{ - colors: { - google_blue_50: "#e8f0fe", - google_blue_100: "#d2e3fc", - google_blue_200: "#aecbfa", - google_blue_300: "#8ab4f8", - google_blue_400: "#669df6", - google_blue_500: "#4285f4", - google_blue_600: "#1a73e8", - google_blue_700: "#1967d2", - google_blue_800: "#185abc", - google_blue_900: "#174ea6", - - google_green_50: "#e6f4ea", - google_green_100: "#ceead6", - google_green_200: "#a8dab5", - google_green_300: "#81c995", - google_green_400: "#5bb974", - google_green_500: "#34a853", - google_green_600: "#1e8e3e", - google_green_700: "#188038", - google_green_800: "#137333", - google_green_900: "#0d652d", - - google_grey_50: "#f8f9fa", - google_grey_100: "#f1f3f4", - google_grey_200: "#e8eaed", - google_grey_300: "#dadce0", - google_grey_400: "#bdc1c6", - google_grey_500: "#9aa0a6", - google_grey_600: "#80868b", - google_grey_700: "#5f6368", - google_grey_800: "#3c4043", - google_grey_900: "#202124", - - google_red_50: "#fce8e6", - google_red_100: "#fad2cf", - google_red_200: "#f6aea9", - google_red_300: "#f28b82", - google_red_400: "#ee675c", - google_red_500: "#ea4335", - google_red_600: "#d93025", - google_red_700: "#c5221f", - google_red_800: "#b31412", - google_red_900: "#a50e0e", - - google_yellow_50: "#fef7e0", - google_yellow_100: "#feefc3", - google_yellow_200: "#fde293", - google_yellow_300: "#fdd663", - google_yellow_400: "#fcc934", - google_yellow_500: "#fbbc04", - google_yellow_600: "#f9ab00", - google_yellow_700: "#f29900", - google_yellow_800: "#ea8600", - google_yellow_900: "#e37400", - } -} diff --git a/chromium/ui/webui/resources/js/color_utils.js b/chromium/ui/webui/resources/js/color_utils.js new file mode 100644 index 00000000000..e5b6c530cb7 --- /dev/null +++ b/chromium/ui/webui/resources/js/color_utils.js @@ -0,0 +1,38 @@ +// 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. + +/** + * @fileoverview Helper functions for color manipulations. + */ + +import 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-lite.js'; + +/** + * Converts an SkColor object to a string in the form + * "rgba(<red>, <green>, <blue>, <alpha>)". + * @param {skia.mojom.SkColor} skColor The input color. + * @return {string} The rgba string. + */ +export function skColorToRgba(skColor) { + const a = (skColor.value >> 24) & 0xff; + const r = (skColor.value >> 16) & 0xff; + const g = (skColor.value >> 8) & 0xff; + const b = skColor.value & 0xff; + return `rgba(${r}, ${g}, ${b}, ${(a / 255).toFixed(2)})`; +} + +/** + * Converts a string of the form "#rrggbb" to an SkColor object. + * @param {string} hexColor The color string. + * @return {!skia.mojom.SkColor} The SkColor object, + */ +export function hexColorToSkColor(hexColor) { + if (!/^#[0-9a-f]{6}$/.test(hexColor)) { + return {value: 0}; + } + const r = parseInt(hexColor.substring(1, 3), 16); + const g = parseInt(hexColor.substring(3, 5), 16); + const b = parseInt(hexColor.substring(5, 7), 16); + return {value: 0xff000000 + (r << 16) + (g << 8) + b}; +} diff --git a/chromium/ui/webui/resources/js/cr/ui/bubble.js b/chromium/ui/webui/resources/js/cr/ui/bubble.js index 62eb3469cdc..7623e1513b5 100644 --- a/chromium/ui/webui/resources/js/cr/ui/bubble.js +++ b/chromium/ui/webui/resources/js/cr/ui/bubble.js @@ -77,6 +77,18 @@ cr.define('cr.ui', function() { */ BubbleBase.MIN_VIEWPORT_EDGE_MARGIN = 2; + /** + * This is used to create TrustedHTML. + * @type {!TrustedTypePolicy} + */ + const staticHtmlPolicy = trustedTypes.createPolicy('cr-ui-bubble-js-static', { + createHTML: () => { + return '<div class="bubble-content"></div>' + + '<div class="bubble-shadow"></div>' + + '<div class="bubble-arrow"></div>'; + }, + }); + BubbleBase.prototype = { // Set up the prototype chain. __proto__: HTMLDivElement.prototype, @@ -92,9 +104,10 @@ cr.define('cr.ui', function() { */ decorate() { this.className = 'bubble'; - this.innerHTML = '<div class="bubble-content"></div>' + - '<div class="bubble-shadow"></div>' + - '<div class="bubble-arrow"></div>'; + // TODO(Jun.Kokatsu@microsoft.com): remove an empty string argument + // once supported. + // https://github.com/w3c/webappsec-trusted-types/issues/278 + this.innerHTML = staticHtmlPolicy.createHTML(''); this.hidden = true; this.bubbleAlignment = cr.ui.BubbleAlignment.ENTIRELY_VISIBLE; }, @@ -123,7 +136,7 @@ cr.define('cr.ui', function() { } const bubbleContent = this.querySelector('.bubble-content'); - bubbleContent.innerHTML = ''; + bubbleContent.innerHTML = trustedTypes.emptyHTML; bubbleContent.appendChild(node); }, diff --git a/chromium/ui/webui/resources/js/cr/ui/tree.js b/chromium/ui/webui/resources/js/cr/ui/tree.js index 87e16056481..7e8b2e91b15 100644 --- a/chromium/ui/webui/resources/js/cr/ui/tree.js +++ b/chromium/ui/webui/resources/js/cr/ui/tree.js @@ -305,16 +305,15 @@ cr.define('cr.ui', function() { /** * This is used to create TrustedHTML. * - * @type {TrustedTypePolicy} + * @type {!TrustedTypePolicy} */ - const staticHTMLPolicy = - trustedTypes.createPolicy('cr-ui-tree-js-static', { - createHTML: () => { - return htmlString; - }, - }); - - treeItem.innerHTML = staticHTMLPolicy.createHTML(''); + const staticHtmlPolicy = trustedTypes.createPolicy( + 'cr-ui-tree-js-static', {createHTML: () => htmlString}); + + // TODO(Jun.Kokatsu@microsoft.com): remove an empty string argument + // once supported. + // https://github.com/w3c/webappsec-trusted-types/issues/278 + treeItem.innerHTML = staticHtmlPolicy.createHTML(''); } else { treeItem.innerHTML = htmlString; } diff --git a/chromium/ui/webui/resources/js/i18n_template_no_process.js b/chromium/ui/webui/resources/js/i18n_template_no_process.js index 9778a6fd3de..5a3f971386f 100644 --- a/chromium/ui/webui/resources/js/i18n_template_no_process.js +++ b/chromium/ui/webui/resources/js/i18n_template_no_process.js @@ -104,12 +104,6 @@ var i18nTemplate = (function() { const prefixes = ['']; - // Only look through shadow DOM when it's supported. As of April 2015, iOS - // Chrome doesn't support shadow DOM. - if (Element.prototype.createShadowRoot) { - prefixes.push('* /deep/ '); - } - const attributeNames = Object.keys(handlers); const selector = prefixes .map(function(prefix) { diff --git a/chromium/ui/webui/resources/js/parse_html_subset.js b/chromium/ui/webui/resources/js/parse_html_subset.js index a1432098eb9..b5d25c37a42 100644 --- a/chromium/ui/webui/resources/js/parse_html_subset.js +++ b/chromium/ui/webui/resources/js/parse_html_subset.js @@ -81,19 +81,16 @@ const allowedOptionalTags = new Set(['IMG']); /** - * This is used to create TrustedHTML. - * @type {TrustedTypePolicy|undefined} + * This policy maps a given string to a `TrustedHTML` object + * without performing any validation. Callsites must ensure + * that the resulting object will only be used in inert + * documents. + * @type {!TrustedTypePolicy} */ - let untrustedHTMLPolicy; + let unsanitizedPolicy; if (window.trustedTypes) { - untrustedHTMLPolicy = trustedTypes.createPolicy('parse-html-subset', { - createHTML: untrustedHTML => { - // This is safe because the untrusted HTML will be sanitized - // later in this function. We are adding this so that - // the sanitization will not cause a Trusted Types violation. - return untrustedHTML; - }, - }); + unsanitizedPolicy = trustedTypes.createPolicy( + 'parse-html-subset', {createHTML: untrustedHTML => untrustedHTML}); } /** @@ -157,7 +154,7 @@ r.selectNode(doc.body); if (window.trustedTypes) { - s = untrustedHTMLPolicy.createHTML(s); + s = unsanitizedPolicy.createHTML(s); } // This does not execute any scripts because the document has no view. diff --git a/chromium/ui/webui/resources/js/util.js b/chromium/ui/webui/resources/js/util.js index d04b82440db..08680c98783 100644 --- a/chromium/ui/webui/resources/js/util.js +++ b/chromium/ui/webui/resources/js/util.js @@ -100,12 +100,13 @@ } /** - * Disables text selection and dragging, with optional whitelist callbacks. + * Disables text selection and dragging, with optional callbacks to specify + * overrides. * @param {function(Event):boolean=} opt_allowSelectStart Unless this function * is defined and returns true, the onselectionstart event will be - * surpressed. + * suppressed. * @param {function(Event):boolean=} opt_allowDragStart Unless this function - * is defined and returns true, the ondragstart event will be surpressed. + * is defined and returns true, the ondragstart event will be suppressed. */ /* #export */ function disableTextSelectAndDrag( opt_allowSelectStart, opt_allowDragStart) { diff --git a/chromium/ui/webui/resources/js/webui_resource_test.js b/chromium/ui/webui/resources/js/webui_resource_test.js index 0c6396ba60b..603f02713af 100644 --- a/chromium/ui/webui/resources/js/webui_resource_test.js +++ b/chromium/ui/webui/resources/js/webui_resource_test.js @@ -227,7 +227,14 @@ function startTesting() { setTimeout(startTesting, 1000); return; } - continueTesting(); + + if (window.HTMLImports && window.HTMLImports.whenReady) { + /// When there is a HTML Import polyfill wait all imports to finish before + // starting the test. + window.HTMLImports.whenReady(continueTesting); + } else { + continueTesting(); + } } /** diff --git a/chromium/ui/webui/resources/polymer_resources.grdp b/chromium/ui/webui/resources/polymer_resources.grdp index 6ea0af91cc1..929c3700fe1 100644 --- a/chromium/ui/webui/resources/polymer_resources.grdp +++ b/chromium/ui/webui/resources/polymer_resources.grdp @@ -329,26 +329,6 @@ <structure name="IDR_POLYMER_1_0_PAPER_TOOLTIP_PAPER_TOOLTIP_HTML" file="../../../third_party/polymer/v1_0/components-chromium/paper-tooltip/paper-tooltip.html" type="chrome_html" /> - <if expr="chromeos"> - <structure name="IDR_POLYMER_1_0_POLYMER_POLYMER_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js" - type="chrome_html" /> - <structure name="IDR_POLYMER_1_0_POLYMER_POLYMER_MICRO_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/polymer/polymer-micro-extracted.js" - type="chrome_html" /> - <structure name="IDR_POLYMER_1_0_POLYMER_POLYMER_MICRO_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/polymer/polymer-micro.html" - type="chrome_html" /> - <structure name="IDR_POLYMER_1_0_POLYMER_POLYMER_MINI_EXTRACTED_JS" - file="../../../third_party/polymer/v1_0/components-chromium/polymer/polymer-mini-extracted.js" - type="chrome_html" /> - <structure name="IDR_POLYMER_1_0_POLYMER_POLYMER_MINI_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/polymer/polymer-mini.html" - type="chrome_html" /> - <structure name="IDR_POLYMER_1_0_POLYMER_POLYMER_HTML" - file="../../../third_party/polymer/v1_0/components-chromium/polymer/polymer.html" - type="chrome_html" /> - </if> <structure name="IDR_POLYMER_1_0_POLYMER2_POLYMER_EXTRACTED_JS" file="../../../third_party/polymer/v1_0/components-chromium/polymer2/polymer-extracted.js" type="chrome_html" /> diff --git a/chromium/ui/webui/resources/webui_resources.grd b/chromium/ui/webui/resources/webui_resources.grd index 8f3ae51103c..902d266f663 100644 --- a/chromium/ui/webui/resources/webui_resources.grd +++ b/chromium/ui/webui/resources/webui_resources.grd @@ -86,6 +86,8 @@ without changes to the corresponding grd file. --> <include name="IDR_WEBUI_JS_ASSERT_M_JS" file="${root_gen_dir}/ui/webui/resources/js/assert.m.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_WEBUI_JS_COLOR_UTILS_JS" + file="js/color_utils.js" type="BINDATA" /> <include name="IDR_WEBUI_JS_CR_EVENT_TARGET_M_JS" file="${root_gen_dir}/ui/webui/resources/js/cr/event_target.m.js" use_base_dir="false" type="BINDATA" /> @@ -209,8 +211,9 @@ without changes to the corresponding grd file. --> file="html/promise_resolver.html" type="chrome_html" /> <if expr="chromeos"> - <structure name="IDR_WEBUI_CSS_CROS_COLORS" - file="${root_gen_dir}/ui/webui/resources/css/cros_colors.generated.css" type="chrome_html" + <structure name="IDR_WEBUI_CROS_COLORS_CSS" + file="${root_gen_dir}/ui/chromeos/colors/cros_colors.generated.css" + type="chrome_html" use_base_dir="false" /> </if> diff --git a/chromium/ui/webui/webui_allowlist.cc b/chromium/ui/webui/webui_allowlist.cc index 62b5ca69231..525848a9d2f 100644 --- a/chromium/ui/webui/webui_allowlist.cc +++ b/chromium/ui/webui/webui_allowlist.cc @@ -89,6 +89,13 @@ void WebUIAllowlist::RegisterAutoGrantedPermission(const url::Origin& origin, } } +void WebUIAllowlist::RegisterAutoGrantedPermissions( + const url::Origin& origin, + std::initializer_list<ContentSettingsType> types) { + for (const ContentSettingsType& type : types) + RegisterAutoGrantedPermission(origin, type); +} + void WebUIAllowlist::SetWebUIAllowlistProvider( WebUIAllowlistProvider* provider) { provider_ = provider; diff --git a/chromium/ui/webui/webui_allowlist.h b/chromium/ui/webui/webui_allowlist.h index 91aec49307d..b1623b89f5e 100644 --- a/chromium/ui/webui/webui_allowlist.h +++ b/chromium/ui/webui/webui_allowlist.h @@ -5,6 +5,7 @@ #ifndef UI_WEBUI_WEBUI_ALLOWLIST_H_ #define UI_WEBUI_WEBUI_ALLOWLIST_H_ +#include <initializer_list> #include <map> #include "base/supports_user_data.h" @@ -32,11 +33,26 @@ class WebUIAllowlist : public base::SupportsUserData::Data { ~WebUIAllowlist() override; // Register auto-granted |type| permission for |origin|. + // + // WebUIAllowlist comes with no permission by default. Users can deny + // permissions (e.g. Settings > Site Settings) unless they are registered + // here. + // + // Most WebUIs would want to declare these: + // COOKIES: use persistent storage (e.g. localStorage) + // JAVASCRIPT: run JavaScript + // IMAGES: show images + // SOUND: play sounds void RegisterAutoGrantedPermission( const url::Origin& origin, ContentSettingsType type, ContentSetting setting = CONTENT_SETTING_ALLOW); + // Register auto-granted |types| permissions for |origin|. + void RegisterAutoGrantedPermissions( + const url::Origin& origin, + std::initializer_list<ContentSettingsType> types); + std::unique_ptr<content_settings::RuleIterator> GetRuleIterator( ContentSettingsType content_type) const; diff --git a/chromium/ui/webui/webui_features.gni b/chromium/ui/webui/webui_features.gni index 8ed14a40380..2c037396837 100644 --- a/chromium/ui/webui/webui_features.gni +++ b/chromium/ui/webui/webui_features.gni @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chrome_build.gni") + declare_args() { # Optimize parts of Chrome's UI written with web technologies (HTML/CSS/JS) # for runtime performance purposes. This does more work at compile time for @@ -10,4 +12,10 @@ declare_args() { # Enable the WebUI version of the browser's tab strip. enable_webui_tab_strip = is_chromeos || is_linux || is_win + + # Enable tab search only on a branded desktop build. + # In order to get commit queue coverage for C++ tests, + # this flag only gates the html/js webui resources, not the C++ + # files + enable_tab_search = !is_android && !is_ios && is_chrome_branded } |