summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/resources/settings
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-24 11:30:15 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-30 12:56:19 +0000
commit6036726eb981b6c4b42047513b9d3f4ac865daac (patch)
tree673593e70678e7789766d1f732eb51f613a2703b /chromium/chrome/browser/resources/settings
parent466052c4e7c052268fd931888cd58961da94c586 (diff)
BASELINE: Update Chromium to 70.0.3538.78
Change-Id: Ie634710bf039e26c1957f4ae45e101bd4c434ae7 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/chrome/browser/resources/settings')
-rw-r--r--chromium/chrome/browser/resources/settings/BUILD.gn6
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html17
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js25
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.html22
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.js9
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page.html4
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/about_page.js16
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html2
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html6
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/home_url_input.js2
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/basic_page.html26
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/basic_page.js2
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html68
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js26
-rw-r--r--chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js2
-rw-r--r--chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html2
-rw-r--r--chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html37
-rw-r--r--chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js72
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn1
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html54
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js124
-rw-r--r--chromium/chrome/browser/resources/settings/controls/BUILD.gn11
-rw-r--r--chromium/chrome/browser/resources/settings/controls/controlled_button.html8
-rw-r--r--chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html2
-rw-r--r--chromium/chrome/browser/resources/settings/controls/extension_controlled_indicator.html6
-rw-r--r--chromium/chrome/browser/resources/settings/controls/password_prompt_dialog.html (renamed from chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.html)4
-rw-r--r--chromium/chrome/browser/resources/settings/controls/password_prompt_dialog.js (renamed from chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.js)103
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_checkbox.html2
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_slider.html8
-rw-r--r--chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html4
-rw-r--r--chromium/chrome/browser/resources/settings/date_time_page/timezone_subpage.html2
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/device_page.html4
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/device_page.js13
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/display.html76
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/display.js31
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/display_size_slider.html19
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/display_size_slider.js28
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/keyboard.html37
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/keyboard.js26
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/pointers.html6
-rw-r--r--chromium/chrome/browser/resources/settings/device_page/storage.html6
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn3
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.html22
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.js40
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/downloads_browser_proxy.js14
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html7
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js40
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/smb_browser_proxy.js1
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.html13
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.js29
-rw-r--r--chromium/chrome/browser/resources/settings/find_shortcut_behavior.html2
-rw-r--r--chromium/chrome/browser/resources/settings/find_shortcut_behavior.js111
-rw-r--r--chromium/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html8
-rw-r--r--chromium/chrome/browser/resources/settings/icons.html5
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/BUILD.gn11
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html35
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js84
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html2
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_page.html15
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_page.js74
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html6
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html12
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js33
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_listener_behavior.html1
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_listener_behavior.js94
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html4
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html16
-rw-r--r--chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js23
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html6
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js19
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html3
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages.js90
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/languages_page.html8
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/BUILD.gn41
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_browser_proxy.js54
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js80
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_behavior.html4
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_behavior.js181
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.html49
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.js37
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_toggle.html17
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_toggle.js76
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html80
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js238
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.html10
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js35
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html118
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.js89
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_tether_item.html34
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/multidevice_tether_item.js163
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/BUILD.gn16
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html11
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js20
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html138
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js234
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html4
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html2
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.js7
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html13
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js11
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_export_dialog.html2
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html4
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js41
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html13
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.html154
-rw-r--r--chromium/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.js421
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/BUILD.gn38
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/account_manager.html20
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/account_manager.js36
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js14
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/change_picture.html8
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html3
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js11
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/fingerprint_progress_arc.html23
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/fingerprint_progress_arc.js171
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/lock_screen.html75
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/lock_screen.js38
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/lock_screen_password_prompt_dialog.html16
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/lock_screen_password_prompt_dialog.js119
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/people_page.html99
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/people_page.js143
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html59
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js140
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.js2
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/signout_dialog.html78
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/signout_dialog.js120
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_account_control.html8
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_account_control.js55
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.js22
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_page.html111
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/sync_page.js49
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/user_list.html2
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/users_page.html2
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/BUILD.gn11
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html20
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js45
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html58
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.js44
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html103
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js141
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html16
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js14
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html2
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn2
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/personalization_options.html4
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html67
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js115
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.js8
-rw-r--r--chromium/chrome/browser/resources/settings/route.js3
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html2
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html2
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry_css.html2
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html4
-rw-r--r--chromium/chrome/browser/resources/settings/search_page/search_page.html8
-rw-r--r--chromium/chrome/browser/resources/settings/search_page/search_page.js2
-rw-r--r--chromium/chrome/browser/resources/settings/search_settings.js16
-rw-r--r--chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html12
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/BUILD.gn1
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html1
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js32
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_section.html4
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html7
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js36
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html25
-rw-r--r--chromium/chrome/browser/resources/settings/settings_resources.grd79
-rw-r--r--chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd2
-rw-r--r--chromium/chrome/browser/resources/settings/settings_shared_css.html26
-rw-r--r--chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js31
-rw-r--r--chromium/chrome/browser/resources/settings/settings_vars_css.html4
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/BUILD.gn17
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/all_sites.html19
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/all_sites.js252
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js33
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html2
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_data.html2
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_data.js26
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details.html7
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details.js8
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html11
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js58
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_entry.html34
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_entry.js133
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list.html73
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list.js139
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list_entry.html80
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_list_entry.js145
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js39
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/usb_devices.html2
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html50
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/zoom_levels.js20
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn1
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html3
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js7
193 files changed, 5143 insertions, 2576 deletions
diff --git a/chromium/chrome/browser/resources/settings/BUILD.gn b/chromium/chrome/browser/resources/settings/BUILD.gn
index a21d2781afe..94da713a1ce 100644
--- a/chromium/chrome/browser/resources/settings/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/BUILD.gn
@@ -22,6 +22,10 @@ if (optimize_webui) {
"vulcanized.html",
"lazy_load.vulcanized.html",
]
+ html_out_files_polymer2 = [
+ "vulcanized.p2.html",
+ "lazy_load.vulcanized.p2.html",
+ ]
insert_in_head = "<base href=\"chrome://settings\">"
input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir)
js_out_files = [
@@ -124,9 +128,9 @@ js_library("extension_control_browser_proxy") {
js_library("find_shortcut_behavior") {
deps = [
- "//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js/cr/ui:command",
]
}
diff --git a/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
index 0d071105c46..e9e35f21160 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
+++ b/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -15,21 +15,21 @@
<template>
<style include="settings-shared">
h2 {
- -webkit-padding-start: var(--settings-box-row-padding);
+ padding-inline-start: var(--settings-box-row-padding);
}
.sub-item {
- -webkit-margin-start: var(--settings-indent-width);
+ margin-inline-start: var(--settings-indent-width);
}
h2 ~ .settings-box,
h2 ~ settings-toggle-button,
iron-collapse .settings-box,
iron-collapse settings-toggle-button {
- -webkit-margin-end: var(--settings-box-row-padding);
- -webkit-margin-start: var(--settings-box-row-indent);
- -webkit-padding-end: 0;
- -webkit-padding-start: 0;
+ margin-inline-end: var(--settings-box-row-padding);
+ margin-inline-start: var(--settings-box-row-indent);
+ padding-inline-end: 0;
+ padding-inline-start: 0;
}
</style>
<div class="settings-box row first">
@@ -244,6 +244,11 @@
pref="{{prefs.settings.a11y.mono_audio}}"
label="$i18n{monoAudioLabel}">
</settings-toggle-button>
+ <settings-toggle-button id="startupSoundEnabled" class="first"
+ pref=" "
+ on-change="toggleStartupSoundEnabled_"
+ label="$i18n{startupSoundLabel}">
+ </settings-toggle-button>
<template is="dom-if" if="[[!isGuest_]]">
<a class="settings-box two-line inherit-color no-outline" tabindex="-1"
diff --git a/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js b/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js
index 2466b990bbe..d8acc989fc0 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js
+++ b/chromium/chrome/browser/resources/settings/a11y_page/manage_a11y_page.js
@@ -114,6 +114,14 @@ Polymer({
chrome.send('initializeKeyboardWatcher');
},
+ /** @override */
+ ready: function() {
+ this.addWebUIListener(
+ 'startup-sound-enabled-updated',
+ this.updateStartupSoundEnabled_.bind(this));
+ chrome.send('getStartupSoundEnabled');
+ },
+
/**
* Updates the Select-to-Speak description text based on:
* 1. Whether Select-to-Speak is enabled.
@@ -133,6 +141,23 @@ Polymer({
hasKeyboard ? keyboardString : noKeyboardString;
},
+ /**
+ * @param {!CustomEvent} e
+ * @private
+ */
+ toggleStartupSoundEnabled_: function(e) {
+ let checked = /** @type {boolean} */ (e.detail);
+ chrome.send('setStartupSoundEnabled', [checked]);
+ },
+
+ /**
+ * @param {boolean} enabled
+ * @private
+ */
+ updateStartupSoundEnabled_: function(enabled) {
+ this.$.startupSoundEnabled.checked = enabled;
+ },
+
/** @private */
onManageTtsSettingsTap_: function() {
settings.navigateTo(settings.routes.MANAGE_TTS_SETTINGS);
diff --git a/chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.html b/chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.html
index 565e2243c62..47e2e5abf5b 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.html
+++ b/chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.html
@@ -16,14 +16,14 @@
<template>
<style include="settings-shared md-select">
h2 {
- -webkit-padding-start: var(--settings-box-row-padding);
+ padding-inline-start: var(--settings-box-row-padding);
}
.settings-box {
- -webkit-margin-end: var(--settings-box-row-padding);
- -webkit-margin-start: var(--settings-box-row-indent);
- -webkit-padding-end: 0;
- -webkit-padding-start: 0;
+ margin-inline-end: var(--settings-box-row-padding);
+ margin-inline-start: var(--settings-box-row-indent);
+ padding-inline-end: 0;
+ padding-inline-start: 0;
}
#previewInput {
@@ -32,7 +32,7 @@
}
#previewInput paper-button {
- -webkit-margin-start: 8px;
+ margin-inline-start: 8px;
}
</style>
@@ -147,15 +147,11 @@
<div id="extension_name_[[index]]" class="start">
[[extension.name]]
</div>
- <a href="[[extension.optionsPage]]"
- tabindex=-1
- target="_blank"
+ <paper-button on-click="onEngineSettingsTap_"
aria-describedby$="extension_name_[[index]]"
hidden$="[[!extension.optionsPage]]">
- <paper-button>
- $i18n{settings}
- </paper-button>
- </a>
+ $i18n{settings}
+ </paper-button>
</div>
</template>
</template>
diff --git a/chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.js b/chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.js
index f6e16daae7f..0e27875f62b 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.js
+++ b/chromium/chrome/browser/resources/settings/a11y_page/tts_subpage.js
@@ -360,4 +360,13 @@ Polymer({
chrome.metricsPrivate.recordSparseHashable(
'TextToSpeech.Settings.DefaultVoicePicked', newDefault);
},
+
+ /**
+ * @param {{model:Object}} event
+ * @private
+ */
+ onEngineSettingsTap_: function(event) {
+ chrome.send('wakeTtsEngine');
+ window.open(event.model.extension.optionsPage);
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page.html b/chromium/chrome/browser/resources/settings/about_page/about_page.html
index 720a636c74c..4bc8e37370d 100644
--- a/chromium/chrome/browser/resources/settings/about_page/about_page.html
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page.html
@@ -53,11 +53,11 @@
}
img {
- -webkit-margin-end: var(--about-page-image-space);
+ margin-inline-end: var(--about-page-image-space);
}
iron-icon {
- -webkit-margin-end: var(--about-page-image-space);
+ margin-inline-end: var(--about-page-image-space);
min-width: 32px; /* The width of the product-logo img. */
}
diff --git a/chromium/chrome/browser/resources/settings/about_page/about_page.js b/chromium/chrome/browser/resources/settings/about_page/about_page.js
index 0274720ac5a..e03fda011c3 100644
--- a/chromium/chrome/browser/resources/settings/about_page/about_page.js
+++ b/chromium/chrome/browser/resources/settings/about_page/about_page.js
@@ -41,7 +41,10 @@ Polymer({
regulatoryInfo_: Object,
/** @private */
- hasEndOfLife_: Boolean,
+ hasEndOfLife_: {
+ type: Boolean,
+ value: false,
+ },
/** @private */
showCrostini: Boolean,
@@ -72,18 +75,25 @@ Polymer({
// </if>
/** @private */
- showUpdateStatus_: Boolean,
+ showUpdateStatus_: {
+ type: Boolean,
+ value: false,
+ },
/** @private */
showButtonContainer_: Boolean,
/** @private */
- showRelaunch_: Boolean,
+ showRelaunch_: {
+ type: Boolean,
+ value: false,
+ },
// <if expr="chromeos">
/** @private */
showRelaunchAndPowerwash_: {
type: Boolean,
+ value: false,
computed: 'computeShowRelaunchAndPowerwash_(' +
'currentUpdateStatusEvent_, targetChannel_, currentChannel_)',
},
diff --git a/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html b/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html
index e0c6761e7be..c604d6dd566 100644
--- a/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html
+++ b/chromium/chrome/browser/resources/settings/about_page/detailed_build_info.html
@@ -14,7 +14,7 @@
<template>
<style include="settings-shared">
cr-policy-indicator {
- -webkit-margin-start: var(--cr-controlled-by-spacing);
+ margin-inline-start: var(--cr-controlled-by-spacing);
}
/* The command line string can contain very long substrings that
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
index e3e305c9e18..720d25d126a 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chromium/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -23,7 +23,7 @@
<template>
<style include="settings-shared md-select iron-flex">
.secondary-button ~ .secondary-button {
- -webkit-margin-start: 12px;
+ margin-inline-start: 12px;
}
/* Lines up with cr-input. */
@@ -40,11 +40,11 @@
* grit expressions and dom-if templates. That leads to a tricky thing
* to style correctly, these are a workaround. */
#themeRow paper-button {
- -webkit-margin-end: 20px;
+ margin-inline-end: 20px;
}
#themeRow .separator {
- -webkit-margin-start: 0;
+ margin-inline-start: 0;
}
</style>
<settings-animated-pages id="pages" section="appearance"
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.js b/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.js
index a9939ce9517..870e6c10fa7 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.js
+++ b/chromium/chrome/browser/resources/settings/appearance_page/home_url_input.js
@@ -123,7 +123,7 @@ Polymer({
/**
* This function prevents unwanted change of selection of the containing
* paper-radio-group, when the user traverses the input with arrow keys.
- * @param {!Event} event
+ * @param {!Event} e
* @private
*/
stopKeyEventPropagation_: function(e) {
diff --git a/chromium/chrome/browser/resources/settings/basic_page/basic_page.html b/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
index e3369e5ef3b..ec867412506 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chromium/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -85,7 +85,7 @@
}
iron-icon {
- -webkit-margin-start: 16px;
+ margin-inline-start: 16px;
}
</style>
<template is="dom-if" if="[[showBasicPage_(
@@ -110,18 +110,6 @@
</settings-internet-page>
</settings-section>
</template>
- <template is="dom-if"
- if="[[canShowMultideviceSection_(showMultidevice, pageVisibility)]]"
- restamp>
- <settings-section page-title="$i18n{multidevicePageTitle}"
- section="multidevice"
- hidden$="[[!doesAccountSupportMultiDeviceSection_]]">
- <settings-multidevice-page-container prefs="{{prefs}}"
- does-potential-connected-phone-exist=
- "{{doesAccountSupportMultiDeviceSection_}}">
- </settings-multidevice-page-container>
- </settings-section>
- </template>
<template is="dom-if" if="[[showPage_(pageVisibility.bluetooth)]]"
restamp>
<settings-section page-title="$i18n{bluetoothPageTitle}"
@@ -130,6 +118,18 @@
</settings-bluetooth-page>
</settings-section>
</template>
+ <template is="dom-if"
+ if="[[canShowMultideviceSection_(showMultidevice, pageVisibility)]]"
+ restamp>
+ <settings-section page-title="$i18n{multidevicePageTitle}"
+ section="multidevice"
+ hidden$="[[!doesChromebookSupportMultiDeviceSection_]]">
+ <settings-multidevice-page-container
+ does-chromebook-support-multi-device-features=
+ "{{doesChromebookSupportMultiDeviceSection_}}">
+ </settings-multidevice-page-container>
+ </settings-section>
+ </template>
</if>
<template is="dom-if" if="[[showChangePassword]]" restamp>
<settings-section section="changePassword">
diff --git a/chromium/chrome/browser/resources/settings/basic_page/basic_page.js b/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
index b0e03709417..0a99b639d16 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
+++ b/chromium/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -95,7 +95,7 @@ Polymer({
* section.
* @private {boolean}
*/
- doesAccountSupportMultiDeviceSection_: {
+ doesChromebookSupportMultiDeviceSection_: {
type: Boolean,
value: false,
},
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
index 36872d0208c..cb249bebe13 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
@@ -3,6 +3,7 @@
<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../i18n_setup.html">
@@ -21,36 +22,47 @@
<settings-animated-pages id="pages" section="bluetooth"
focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
- <div id="bluetoothDevices"
- class="settings-box two-line" actionable on-click="onTap_">
- <iron-icon icon="[[getIcon_(bluetoothToggleState_)]]"></iron-icon>
- <div class="middle">
- $i18n{bluetoothPageTitle}
- <div class="secondary" id="bluetoothSecondary">
- [[getOnOffString_(bluetoothToggleState_,
- '$i18nPolymer{deviceOn}', '$i18nPolymer{deviceOff}')]]
+ <template is="dom-if" if="[[!isSecondaryUser_]]">
+ <div id="bluetoothDevices"
+ class="settings-box two-line" actionable on-click="onTap_">
+ <iron-icon icon="[[getIcon_(bluetoothToggleState_)]]"></iron-icon>
+ <div class="middle">
+ $i18n{bluetoothPageTitle}
+ <div class="secondary" id="bluetoothSecondary">
+ [[getOnOffString_(bluetoothToggleState_,
+ '$i18nPolymer{deviceOn}', '$i18nPolymer{deviceOff}')]]
+ </div>
</div>
+ <cr-policy-pref-indicator
+ icon-aria-label="$i18n{bluetoothPageTitle}"
+ pref="[[prefs.cros.device.allow_bluetooth]]"
+ hidden="[[prefs.cros.device.allow_bluetooth.value]]">
+ </cr-policy-pref-indicator>
+ <template is="dom-if" if="[[bluetoothToggleState_]]">
+ <paper-icon-button-light class="subpage-arrow">
+ <button on-click="onSubpageArrowTap_"
+ aria-label="$i18n{bluetoothPageTitle}"
+ aria-describedby="bluetoothSecondary">
+ </button>
+ </paper-icon-button-light>
+ </template>
+ <div class="separator"></div>
+ <cr-toggle id="enableBluetooth"
+ checked="{{bluetoothToggleState_}}"
+ disabled$="[[!isToggleEnabled_(
+ adapterState_, stateChangeInProgress_)]]"
+ aria-label="$i18n{bluetoothToggleA11yLabel}">
+ </cr-toggle>
</div>
- <cr-policy-pref-indicator icon-aria-label="$i18n{bluetoothPageTitle}"
- pref="[[prefs.cros.device.allow_bluetooth]]"
- hidden="[[prefs.cros.device.allow_bluetooth.value]]">
- </cr-policy-pref-indicator>
- <template is="dom-if" if="[[bluetoothToggleState_]]">
- <paper-icon-button-light class="subpage-arrow">
- <button on-click="onSubpageArrowTap_"
- aria-label="$i18n{bluetoothPageTitle}"
- aria-describedby="bluetoothSecondary">
- </button>
- </paper-icon-button-light>
- </template>
- <div class="separator"></div>
- <cr-toggle id="enableBluetooth"
- checked="{{bluetoothToggleState_}}"
- disabled$=
- "[[!isToggleEnabled_(adapterState_, stateChangeInProgress_)]]"
- aria-label="$i18n{bluetoothToggleA11yLabel}">
- </cr-toggle>
- </div>
+ </template>
+ <template is="dom-if" if="[[isSecondaryUser_]]">
+ <div id="bluetoothDevices" class="settings-box two-line">
+ <iron-icon class="policy" icon="cr:group"></iron-icon>
+ <div class="middle">
+ [[i18n('bluetoothPrimaryUserControlled', primaryUserEmail_)]]
+ </div>
+ </div>
+ </template>
</neon-animatable>
<template is="dom-if" route-path="/bluetoothDevices">
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
index ec86e09ad87..f532340394a 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.js
@@ -25,7 +25,7 @@ const bluetoothApis = window['bluetoothApis'] || {
Polymer({
is: 'settings-bluetooth-page',
- behaviors: [PrefsBehavior],
+ behaviors: [I18nBehavior, PrefsBehavior],
properties: {
/** Preferences state. */
@@ -99,6 +99,30 @@ Polymer({
type: Object,
value: chrome.bluetoothPrivate,
},
+
+ /**
+ * Whether the user is a secondary user.
+ * @private
+ */
+ isSecondaryUser_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('isSecondaryUser');
+ },
+ readOnly: true,
+ },
+
+ /**
+ * Email address for the primary user.
+ * @private
+ */
+ primaryUserEmail_: {
+ type: String,
+ value: function() {
+ return loadTimeData.getString('primaryUserEmail');
+ },
+ readOnly: true,
+ },
},
observers: ['deviceListChanged_(deviceList_.*)'],
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
index 476a45012b2..a29bb4d3afa 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
+++ b/chromium/chrome/browser/resources/settings/bluetooth_page/bluetooth_subpage.js
@@ -271,7 +271,7 @@ Polymer({
* @private
*/
updateDeviceList_: function() {
- if (!this.bluetoothToggleState) {
+ if (!this.adapterState || !this.adapterState.powered) {
this.deviceList_ = [];
return;
}
diff --git a/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html b/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html
index dc7ebec5125..8bb78adddca 100644
--- a/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html
+++ b/chromium/chrome/browser/resources/settings/change_password_page/change_password_page.html
@@ -11,7 +11,7 @@
<template>
<style include="settings-shared">
.icon-container {
- -webkit-padding-end: var(--settings-box-row-padding);
+ padding-inline-end: var(--settings-box-row-padding);
}
.change-password-icon {
diff --git a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
index 2a309a7a43d..dbab0d8557f 100644
--- a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
+++ b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.html
@@ -1,11 +1,9 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
@@ -13,7 +11,6 @@
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="../controls/controlled_button.html">
<link rel="import" href="../controls/settings_toggle_button.html">
-<link rel="import" href="../icons.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="chrome_cleanup_proxy.html">
<link rel="import" href="items_to_remove_list.html">
@@ -22,6 +19,7 @@
<template>
<style include="settings-shared">
#waiting-spinner {
+ flex-shrink: 0;
height: 20px;
width: 20px;
}
@@ -43,28 +41,6 @@
height: 22px;
}
- #status-icon {
- height: 20px;
- vertical-align: top;
- width: 20px;
- }
-
- .status-icon-container {
- -webkit-padding-end: var(--settings-box-row-padding);
- }
-
- .status-icon-remove {
- --iron-icon-fill-color: var(--google-grey-refresh-700);
- }
-
- .status-icon-done {
- --iron-icon-fill-color: var(--google-blue-500);
- }
-
- .status-icon-warning {
- --iron-icon-fill-color: var(--google-red-700);
- }
-
.top-aligned-settings-box {
align-items: center;
/* override settings-box min-height since we use vertical padding */
@@ -74,14 +50,6 @@
</style>
<div class$="settings-box first
[[getTopSettingsBoxClass_(showExplanation_)]]">
- <div class="status-icon-container">
- <paper-spinner-lite id="waiting-spinner"
- hidden="[[!isWaitingForResult_]]" active="[[isWaitingForResult_]]">
- </paper-spinner-lite>
- <iron-icon id="status-icon" hidden="[[isWaitingForResult_]]"
- icon="[[statusIcon_]]" class$="[[statusIconClassName_]]">
- </iron-icon>
- </div>
<div class="start">
<div id="status-title" role="status" inner-h-t-m-l="[[title_]]"></div>
<div hidden="[[!showExplanation_]]">
@@ -91,6 +59,9 @@
<cr-policy-pref-indicator
pref="[[prefs.software_reporter.enabled]]">
</cr-policy-pref-indicator>
+ <paper-spinner-lite id="waiting-spinner"
+ hidden="[[!isWaitingForResult_]]" active="[[isWaitingForResult_]]">
+ </paper-spinner-lite>
<template is="dom-if" if="[[showActionButton_]]">
<div class="separator"></div>
<paper-button id="action-button" class="action-button"
diff --git a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
index 8c6329255bf..e61a4d7aa0a 100644
--- a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
+++ b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.js
@@ -60,14 +60,6 @@ settings.ChromeCleanupOngoingAction = {
/**
* @typedef {{
- * statusIcon: string,
- * statusIconClassName: string,
- * }}
- */
-settings.ChromeCleanupCardIcon;
-
-/**
- * @typedef {{
* label: string,
* doAction: !function(),
* }}
@@ -78,7 +70,6 @@ settings.ChromeCleanupCardActionButton;
* @typedef {{
* title: ?string,
* explanation: ?string,
- * icon: ?settings.ChromeCleanupCardIcon,
* actionButton: ?settings.ChromeCleanupCardActionButton,
* flags: number,
* }}
@@ -214,18 +205,6 @@ Polymer({
computed: 'computeHasExtensionsToShow_(scannerResults_)',
},
- /** @private */
- statusIcon_: {
- type: String,
- value: '',
- },
-
- /** @private */
- statusIconClassName_: {
- type: String,
- value: '',
- },
-
/** @private {chrome.settingsPrivate.PrefObject} */
logsUploadPref_: {
type: Object,
@@ -521,28 +500,11 @@ Polymer({
this.title_ = components.title || '';
this.explanation_ = components.explanation || '';
- this.updateIcon_(components.icon);
this.updateActionButton_(components.actionButton);
this.updateCardFlags_(components.flags);
},
/**
- * Updates the icon on the cleanup card to show the current state.
- * @param {?settings.ChromeCleanupCardIcon} icon The icon to
- * render, or null if no icon should be shown.
- * @private
- */
- updateIcon_: function(icon) {
- if (!icon) {
- this.statusIcon_ = '';
- this.statusIconClassName_ = '';
- } else {
- this.statusIcon_ = icon.statusIcon;
- this.statusIconClassName_ = icon.statusIconClassName;
- }
- },
-
- /**
* Updates the action button on the cleanup card as the action expected for
* the current state.
* @param {?settings.ChromeCleanupCardActionButton} actionButton
@@ -663,30 +625,6 @@ Polymer({
*/
buildCardStateToComponentsMap_: function() {
/**
- * The icons to show on the card.
- * @enum {settings.ChromeCleanupCardIcon}
- */
- const icons = {
- // Card's icon indicates a cleanup offer.
- SYSTEM: {
- statusIcon: 'cr:security',
- statusIconClassName: 'status-icon-remove',
- },
-
- // Card's icon indicates a warning (in case of failure).
- WARNING: {
- statusIcon: 'cr:error',
- statusIconClassName: 'status-icon-warning',
- },
-
- // Card's icon indicates completion or reboot required.
- DONE: {
- statusIcon: 'settings:check-circle',
- statusIconClassName: 'status-icon-done',
- },
- };
-
- /**
* The action buttons to show on the card.
* @enum {settings.ChromeCleanupCardActionButton}
*/
@@ -719,7 +657,6 @@ Polymer({
settings.ChromeCleanerCardState.CLEANUP_OFFERED, {
title: this.i18n('chromeCleanupTitleRemove'),
explanation: this.i18n('chromeCleanupExplanationRemove'),
- icon: icons.SYSTEM,
actionButton: actionButtons.REMOVE,
flags: settings.ChromeCleanupCardFlags.SHOW_LOGS_PERMISSIONS |
settings.ChromeCleanupCardFlags.SHOW_ITEMS_TO_REMOVE,
@@ -729,7 +666,6 @@ Polymer({
settings.ChromeCleanerCardState.CLEANING, {
title: this.i18n('chromeCleanupTitleRemoving'),
explanation: this.i18n('chromeCleanupExplanationRemoving'),
- icon: null,
actionButton: null,
flags: settings.ChromeCleanupCardFlags.WAITING_FOR_RESULT |
settings.ChromeCleanupCardFlags.SHOW_ITEMS_TO_REMOVE,
@@ -739,7 +675,6 @@ Polymer({
settings.ChromeCleanerCardState.REBOOT_REQUIRED, {
title: this.i18n('chromeCleanupTitleRestart'),
explanation: null,
- icon: icons.DONE,
actionButton: actionButtons.RESTART_COMPUTER,
flags: settings.ChromeCleanupCardFlags.NONE,
}
@@ -748,7 +683,6 @@ Polymer({
settings.ChromeCleanerCardState.CLEANUP_SUCCEEDED, {
title: this.i18nAdvanced('chromeCleanupTitleRemoved', {tags: ['a']}),
explanation: null,
- icon: icons.DONE,
actionButton: null,
flags: settings.ChromeCleanupCardFlags.NONE,
}
@@ -757,7 +691,6 @@ Polymer({
settings.ChromeCleanerCardState.CLEANING_FAILED, {
title: this.i18n('chromeCleanupTitleErrorCantRemove'),
explanation: this.i18n('chromeCleanupExplanationCleanupError'),
- icon: icons.WARNING,
actionButton: null,
flags: settings.ChromeCleanupCardFlags.NONE,
}
@@ -766,7 +699,6 @@ Polymer({
settings.ChromeCleanerCardState.SCANNING_OFFERED, {
title: this.i18n('chromeCleanupTitleFindAndRemove'),
explanation: this.i18n('chromeCleanupExplanationFindAndRemove'),
- icon: icons.SYSTEM,
actionButton: actionButtons.FIND,
flags: settings.ChromeCleanupCardFlags.SHOW_LOGS_PERMISSIONS,
}
@@ -775,7 +707,6 @@ Polymer({
settings.ChromeCleanerCardState.SCANNING, {
title: this.i18n('chromeCleanupTitleScanning'),
explanation: null,
- icon: null,
actionButton: null,
flags: settings.ChromeCleanupCardFlags.WAITING_FOR_RESULT,
}
@@ -785,7 +716,6 @@ Polymer({
settings.ChromeCleanerCardState.SCANNING_FOUND_NOTHING, {
title: this.i18n('chromeCleanupTitleNothingFound'),
explanation: null,
- icon: icons.DONE,
actionButton: null,
flags: settings.ChromeCleanupCardFlags.NONE,
}
@@ -794,7 +724,6 @@ Polymer({
settings.ChromeCleanerCardState.SCANNING_FAILED, {
title: this.i18n('chromeCleanupTitleScanningFailed'),
explanation: this.i18n('chromeCleanupExplanationScanError'),
- icon: icons.WARNING,
actionButton: null,
flags: settings.ChromeCleanupCardFlags.NONE,
}
@@ -806,7 +735,6 @@ Polymer({
// connectivity and cleanups being disabled by the server.
title: this.i18n('chromeCleanupTitleCleanupUnavailable'),
explanation: this.i18n('chromeCleanupExplanationCleanupUnavailable'),
- icon: icons.WARNING,
actionButton: actionButtons.TRY_SCAN_AGAIN,
flags: settings.ChromeCleanupCardFlags.NONE,
},
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
index cf04a888e8d..272d36e080d 100644
--- a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
@@ -22,6 +22,7 @@ js_library("clear_browsing_data_dialog") {
deps = [
":clear_browsing_data_browser_proxy",
"../device_page:keyboard",
+ "../people_page:sync_browser_proxy",
"//third_party/polymer/v1_0/components-chromium/iron-pages:iron-pages-extracted",
"//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted",
"//ui/webui/resources/js:cr",
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
index 48df5d399b4..ba93834005d 100644
--- a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
@@ -2,6 +2,7 @@
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/paper_tabs_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
@@ -46,6 +47,12 @@
padding-top: 8px;
}
+ #clearBrowsingDataDialog [slot=footer] {
+ background: var(--paper-grey-50);
+ border-top: none;
+ padding: 0;
+ }
+
.row {
align-items: center;
display: flex;
@@ -53,8 +60,8 @@
}
paper-spinner-lite {
- -webkit-margin-end: 16px;
margin-bottom: auto;
+ margin-inline-end: 16px;
margin-top: auto;
}
@@ -81,13 +88,23 @@
}
.time-range-select {
- -webkit-margin-start: 12px;
+ margin-inline-start: 12px;
}
[slot=title] .secondary {
font-size: calc(13 / 15 * 100%);
padding-top: 8px;
}
+
+ .divider {
+ border-top: var(--settings-separator-line);
+ margin: 0 16px;
+ }
+
+ #footer-description {
+ color: var(--cr-secondary-text-color);
+ padding: 16px;
+ }
</style>
<cr-dialog id="clearBrowsingDataDialog"
@@ -127,7 +144,7 @@
pref="{{prefs.browser.clear_data.browsing_history_basic}}"
label="$i18n{clearBrowsingHistory}"
sub-label-html="[[browsingCheckboxLabel_(
- isSignedIn_, isSyncingHistory_,
+ isSignedIn_, isSyncingHistory_, syncStatus.hasError,
'$i18nPolymer{clearBrowsingHistorySummary}',
'$i18nPolymer{clearBrowsingHistorySummarySignedIn}',
'$i18nPolymer{clearBrowsingHistorySummarySynced}')]]"
@@ -239,6 +256,37 @@
$i18n{clearData}
</paper-button>
</div>
+ <div slot="footer"
+ hidden="[[!shouldShowFooter_(syncStatus.signedIn, diceEnabled_)]]">
+ <settings-sync-account-control sync-status="[[syncStatus]]"
+ hide-buttons>
+ </settings-sync-account-control>
+ <div class="divider"></div>
+ <div id="footer-description" on-tap="onSyncDescriptionLinkClicked_">
+ <template is="dom-if" if="[[!syncStatus.hasError]]">
+ <span id="sync-info">
+ $i18nRaw{clearBrowsingDataWithSync}
+ </span>
+ </template>
+ <template is="dom-if" if="[[syncStatus.hasError]]">
+ <template is="dom-if" if="[[isSyncPaused_]]">
+ <span id="sync-paused-info">
+ $i18nRaw{clearBrowsingDataWithSyncPaused}
+ </span>
+ </template>
+ <template is="dom-if" if="[[hasPassphraseError_]]">
+ <span id="sync-passphrase-error-info">
+ $i18nRaw{clearBrowsingDataWithSyncPassphraseError}
+ </span>
+ </template>
+ <template is="dom-if" if="[[hasOtherSyncError_]]">
+ <span id="sync-other-error-info">
+ $i18nRaw{clearBrowsingDataWithSyncError}
+ </span>
+ </template>
+ </template>
+ </div>
+ </div>
</cr-dialog>
<template is="dom-if" if="[[showHistoryDeletionDialog_]]" restamp>
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
index fd323fc5f5a..a3e35cf4a9e 100644
--- a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.js
@@ -21,6 +21,12 @@ Polymer({
},
/**
+ * The current sync status, supplied by SyncBrowserProxy.
+ * @type {?settings.SyncStatus}
+ */
+ syncStatus: Object,
+
+ /**
* Results of browsing data counters, keyed by the suffix of
* the corresponding data type deletion preference, as reported
* by the C++ side.
@@ -94,6 +100,43 @@ Polymer({
value: false,
},
+ /** @private */
+ isSyncPaused_: {
+ type: Boolean,
+ value: false,
+ computed: 'computeIsSyncPaused_(syncStatus)',
+ },
+
+ /** @private */
+ hasPassphraseError_: {
+ type: Boolean,
+ value: false,
+ computed: 'computeHasPassphraseError_(syncStatus)',
+ },
+
+ /** @private */
+ hasOtherSyncError_: {
+ type: Boolean,
+ value: false,
+ computed:
+ 'computeHasOtherError_(syncStatus, isSyncPaused_, hasPassphraseError_)',
+ },
+
+ /**
+ * This flag is used to conditionally show the footer for the dialog.
+ * @private
+ */
+ diceEnabled_: {
+ type: Boolean,
+ value: function() {
+ let diceEnabled = false;
+ // <if expr="not chromeos">
+ diceEnabled = loadTimeData.getBoolean('diceEnabled');
+ // </if>
+ return diceEnabled;
+ },
+ },
+
/**
* Time in ms, when the dialog was opened.
* @private
@@ -109,8 +152,17 @@ Polymer({
/** @private {settings.ClearBrowsingDataBrowserProxy} */
browserProxy_: null,
+ /** @private {?settings.SyncBrowserProxy} */
+ syncBrowserProxy_: null,
+
/** @override */
ready: function() {
+ this.syncBrowserProxy_ = settings.SyncBrowserProxyImpl.getInstance();
+ this.syncBrowserProxy_.getSyncStatus().then(
+ this.handleSyncStatus_.bind(this));
+ this.addWebUIListener(
+ 'sync-status-changed', this.handleSyncStatus_.bind(this));
+
this.addWebUIListener(
'update-sync-state', this.updateSyncState_.bind(this));
this.addWebUIListener(
@@ -128,6 +180,15 @@ Polymer({
},
/**
+ * Handler for when the sync state is pushed from the browser.
+ * @param {?settings.SyncStatus} syncStatus
+ * @private
+ */
+ handleSyncStatus_: function(syncStatus) {
+ this.syncStatus = syncStatus;
+ },
+
+ /**
* Returns true if either clearing is in progress or no data type is selected.
* @param {boolean} clearingInProgress
* @param {boolean} clearButtonDisabled
@@ -193,9 +254,9 @@ Polymer({
* @private
*/
browsingCheckboxLabel_: function(
- isSignedIn, isSyncingHistory, historySummary, historySummarySignedIn,
- historySummarySynced) {
- if (isSyncingHistory) {
+ isSignedIn, isSyncingHistory, hasSyncError, historySummary,
+ historySummarySignedIn, historySummarySynced) {
+ if (isSyncingHistory && !hasSyncError) {
return historySummarySynced;
} else if (isSignedIn) {
return historySummarySignedIn;
@@ -318,4 +379,61 @@ Polymer({
'ClearBrowsingData_SwitchTo_AdvancedTab');
}
},
+
+ /**
+ * Called when the user clicks the link in the footer.
+ * @param {!Event} e
+ * @private
+ */
+ onSyncDescriptionLinkClicked_: function(e) {
+ if (e.target.tagName === 'A') {
+ e.preventDefault();
+ if (!this.syncStatus.hasError) {
+ this.syncBrowserProxy_.pauseSync();
+ return;
+ }
+
+ if (this.isSyncPaused_) {
+ this.syncBrowserProxy_.startSignIn();
+ } else {
+ // In any other error case, navigate to the sync page.
+ settings.navigateTo(settings.routes.SYNC);
+ }
+ }
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeIsSyncPaused_: function() {
+ return !!this.syncStatus.hasError &&
+ this.syncStatus.statusAction === settings.StatusAction.REAUTHENTICATE;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeHasPassphraseError_: function() {
+ return !!this.syncStatus.hasError &&
+ this.syncStatus.statusAction === settings.StatusAction.ENTER_PASSPHRASE;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeHasOtherError_: function() {
+ return !!this.syncStatus.hasError && !this.isSyncPaused_ &&
+ !this.hasPassphraseError_;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ shouldShowFooter_: function() {
+ return this.diceEnabled_ && !!this.syncStatus.signedIn;
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/controls/BUILD.gn b/chromium/chrome/browser/resources/settings/controls/BUILD.gn
index 8e938f25335..7baf0b551a4 100644
--- a/chromium/chrome/browser/resources/settings/controls/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/controls/BUILD.gn
@@ -9,6 +9,7 @@ js_type_check("closure_compile") {
":controlled_button",
":controlled_radio_button",
":extension_controlled_indicator",
+ ":password_prompt_dialog",
":pref_control_behavior",
":settings_boolean_control_behavior",
":settings_checkbox",
@@ -47,6 +48,16 @@ js_library("extension_controlled_indicator") {
]
}
+js_library("password_prompt_dialog") {
+ deps = [
+ "..:route",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
+ "//ui/webui/resources/cr_elements/cr_input:cr_input",
+ ]
+ externs_list = [ "$externs_path/quick_unlock_private.js" ]
+ extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ]
+}
+
js_library("pref_control_behavior") {
deps = [
"../prefs:prefs_types",
diff --git a/chromium/chrome/browser/resources/settings/controls/controlled_button.html b/chromium/chrome/browser/resources/settings/controls/controlled_button.html
index f1d81142250..e76e3584ea7 100644
--- a/chromium/chrome/browser/resources/settings/controls/controlled_button.html
+++ b/chromium/chrome/browser/resources/settings/controls/controlled_button.html
@@ -31,14 +31,14 @@
}
:host(:not([end-justified])) cr-policy-pref-indicator {
- -webkit-margin-end: calc(
+ margin-inline-end: calc(
var(--cr-controlled-by-spacing) - var(--justify-margin));
- -webkit-margin-start: var(--cr-controlled-by-spacing);
+ margin-inline-start: var(--cr-controlled-by-spacing);
}
:host([end-justified]) cr-policy-pref-indicator {
- -webkit-margin-end: var(--cr-controlled-by-spacing);
- -webkit-margin-start: calc(
+ margin-inline-end: var(--cr-controlled-by-spacing);
+ margin-inline-start: calc(
var(--cr-controlled-by-spacing) - var(--justify-margin));
order: -1;
}
diff --git a/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html b/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html
index a8260c24312..e3b26b4205b 100644
--- a/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html
+++ b/chromium/chrome/browser/resources/settings/controls/controlled_radio_button.html
@@ -22,7 +22,7 @@
}
cr-policy-pref-indicator {
- -webkit-margin-start: var(--settings-controlled-by-spacing);
+ margin-inline-start: var(--settings-controlled-by-spacing);
/* Enable pointer events for the indicator so :hover works. Disable
* clicks/taps via onIndicatorTap_ so outer on-tap doesn't trigger. */
pointer-events: all;
diff --git a/chromium/chrome/browser/resources/settings/controls/extension_controlled_indicator.html b/chromium/chrome/browser/resources/settings/controls/extension_controlled_indicator.html
index 50e3313c33c..15be87a78f0 100644
--- a/chromium/chrome/browser/resources/settings/controls/extension_controlled_indicator.html
+++ b/chromium/chrome/browser/resources/settings/controls/extension_controlled_indicator.html
@@ -10,23 +10,23 @@
<template>
<style include="settings-shared">
:host {
- -webkit-margin-start: 36px;
align-items: center;
display: flex;
+ margin-inline-start: 36px;
min-height: var(--settings-row-min-height);
}
img {
@apply --cr-icon-height-width;
- -webkit-margin-end: 16px;
+ margin-inline-end: 16px;
}
/* Using ">" operator to ensure that this CSS rule will not accidentally
* be applied to a search highlight span (which is inserted dynamically if
* when search "hit" occurs within this element. */
:host > span {
- -webkit-margin-end: 8px;
flex: 1;
+ margin-inline-end: 8px;
}
</style>
<img role="presentation" src="chrome://extension-icon/[[extensionId]]/40/1">
diff --git a/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.html b/chromium/chrome/browser/resources/settings/controls/password_prompt_dialog.html
index 3425c33c812..b8afbd0e4a8 100644
--- a/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.html
+++ b/chromium/chrome/browser/resources/settings/controls/password_prompt_dialog.html
@@ -3,8 +3,6 @@
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="lock_screen_constants.html">
-<link rel="import" href="lock_state_behavior.html">
<link rel="import" href="../settings_shared_css.html">
<dom-module id="settings-password-prompt-dialog">
@@ -23,7 +21,7 @@
<div slot="title">$i18n{passwordPromptTitle}</div>
<div slot="body">
<div class="settings-box first">
- [[selectPasswordPromptEnterPasswordString(hasPinLogin)]]
+ [[passwordPromptText]]
</div>
<cr-input id="passwordInput" type="password"
placeholder="$i18n{passwordPromptPasswordLabel}"
diff --git a/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.js b/chromium/chrome/browser/resources/settings/controls/password_prompt_dialog.js
index a633c83a40b..2ed8e8b55dd 100644
--- a/chromium/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
+++ b/chromium/chrome/browser/resources/settings/controls/password_prompt_dialog.js
@@ -8,20 +8,15 @@
* 'settings-password-prompt-dialog' shows a dialog which asks for the user to
* enter their password. It validates the password is correct. Once the user has
* entered their account password, the page fires an 'authenticated' event and
- * updates the setModes binding.
- *
- * The setModes binding is a wrapper around chrome.quickUnlockPrivate.setModes
- * which has a prebound account password. The account password by itself is not
- * available for other elements to access.
+ * updates the authToken binding.
*
* Example:
*
* <settings-password-prompt-dialog
* id="passwordPrompt"
- * set-modes="[[setModes]]">
+ * password-prompt-text="{{passwordPromptText}}"
+ * auth-token="{{authToken}}">
* </settings-password-prompt-dialog>
- *
- * this.$.passwordPrompt.open()
*/
(function() {
@@ -30,27 +25,21 @@
Polymer({
is: 'settings-password-prompt-dialog',
- behaviors: [
- LockStateBehavior,
- ],
-
properties: {
/**
- * A wrapper around chrome.quickUnlockPrivate.setModes with the account
- * password already supplied. If this is null, the authentication screen
- * needs to be redisplayed. This property will be cleared after the timeout
- * returned by quickUnlockPrivate.getAuthToken.
- * @type {?Object}
+ * The subtext to be displayed above the password input field. Embedders
+ * may choose to change this value for their specific use case.
+ * @type {string}
*/
- setModes: {
- type: Object,
+ passwordPromptText: {
+ type: String,
notify: true,
},
/**
- * Authentication token used when calling setModes, returned by
- * quickUnlockPrivate.getAuthToken. Reflected to lock-screen.
- * @private
+ * Authentication token returned by quickUnlockPrivate.getAuthToken().
+ * Should be passed to API calls which require authentication.
+ * @type {string}
*/
authToken: {
type: String,
@@ -58,17 +47,17 @@ Polymer({
},
/**
- * @private
+ * @private {string}
*/
inputValue_: {
- type: Boolean,
+ type: String,
value: '',
observer: 'onInputValueChange_',
},
/**
* Helper property which marks password as valid/invalid.
- * @private
+ * @private {boolean}
*/
passwordInvalid_: {
type: Boolean,
@@ -76,18 +65,11 @@ Polymer({
},
/**
- * writeUma_ is a function that handles writing uma stats. It may be
- * overridden for tests.
- *
- * @type {Function}
- * @private
+ * Interface for chrome.quickUnlockPrivate calls. May be overridden by
+ * tests.
+ * @type {QuickUnlockPrivate}
*/
- writeUma_: {
- type: Object,
- value: function() {
- return settings.recordLockScreenProgress;
- }
- },
+ quickUnlockPrivate: {type: Object, value: chrome.quickUnlockPrivate},
},
/** @return {!CrInputElement} */
@@ -97,13 +79,14 @@ Polymer({
/** @override */
attached: function() {
- this.writeUma_(LockScreenProgress.START_SCREEN_LOCK);
this.$.dialog.showModal();
// This needs to occur at the next paint otherwise the password input will
// not receive focus.
this.async(() => {
+ // TODO(crbug.com/876377): This is unusual; the 'autofocus' attribute on
+ // the cr-input element should work. Investigate.
this.passwordInput.focus();
- }, 1);
+ }, 1 /* waitTime */);
},
/** @private */
@@ -113,11 +96,18 @@ Polymer({
},
/**
+ * The timeout ID to pass to clearTimeout() to cancel auth token
+ * invalidation.
+ * @private {number|undefined}
+ */
+ clearAccountPasswordTimeoutId_: undefined,
+
+ /**
* Run the account password check.
* @private
*/
submitPassword_: function() {
- clearTimeout(this.clearAccountPasswordTimeout_);
+ clearTimeout(this.clearAccountPasswordTimeoutId_);
const password = this.passwordInput.value;
// The user might have started entering a password and then deleted it all.
@@ -138,35 +128,19 @@ Polymer({
this.authToken = tokenInfo.token;
this.passwordInvalid_ = false;
- // Create the |this.setModes| closure and automatically clear it after
- // tokenInfo.lifetimeSeconds.
- this.setModes = (modes, credentials, onComplete) => {
- this.quickUnlockPrivate.setModes(
- tokenInfo.token, modes, credentials, () => {
- let result = true;
- if (chrome.runtime.lastError) {
- console.error(
- 'setModes failed: ' + chrome.runtime.lastError.message);
- result = false;
- }
- onComplete(result);
- });
- };
-
- // Subtract time from the exiration time to account for IPC delays.
+ // Clear |this.authToken| after tokenInfo.lifetimeSeconds.
+ // Subtract time from the expiration time to account for IPC delays.
// Treat values less than the minimum as 0 for testing.
const IPC_SECONDS = 2;
const lifetimeMs = tokenInfo.lifetimeSeconds > IPC_SECONDS ?
(tokenInfo.lifetimeSeconds - IPC_SECONDS) * 1000 :
0;
- this.clearAccountPasswordTimeout_ = setTimeout(() => {
- this.setModes = null;
+ this.clearAccountPasswordTimeoutId_ = setTimeout(() => {
+ this.authToken = '';
}, lifetimeMs);
if (this.$.dialog.open)
this.$.dialog.close();
-
- this.writeUma_(LockScreenProgress.ENTER_PASSWORD_CORRECTLY);
});
},
@@ -179,16 +153,5 @@ Polymer({
isConfirmEnabled_: function() {
return !this.passwordInvalid_ && this.inputValue_;
},
-
- /**
- * Looks up the translation id, which depends on PIN login support.
- * @param {boolean} hasPinLogin
- * @private
- */
- selectPasswordPromptEnterPasswordString(hasPinLogin) {
- if (hasPinLogin)
- return this.i18n('passwordPromptEnterPasswordLoginLock');
- return this.i18n('passwordPromptEnterPasswordLock');
- },
});
})();
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html b/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
index ec8f7cfed6e..d8856d5402e 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_checkbox.html
@@ -27,7 +27,7 @@
}
cr-policy-pref-indicator {
- -webkit-margin-start: var(--settings-controlled-by-spacing);
+ margin-inline-start: var(--settings-controlled-by-spacing);
}
</style>
<div id="outerRow" noSubLabel$="[[!hasSubLabel_(subLabel, subLabelHtml)]]">
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_slider.html b/chromium/chrome/browser/resources/settings/controls/settings_slider.html
index c1015b40593..f58423c9724 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_slider.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_slider.html
@@ -9,15 +9,15 @@
<style>
:host {
--calculated-paper-slider-height: var(--paper-slider-height, 2px);
+ display: inline-flex;
/* Counteract the margin on #sliderContainer in paper-slider.html. */
- -webkit-margin-end:
+ margin-inline-end:
calc(-15px - var(--calculated-paper-slider-height) / 2);
- display: inline-flex;
}
cr-policy-pref-indicator {
- -webkit-margin-start: var(--settings-controlled-by-spacing);
align-self: center;
+ margin-inline-start: var(--settings-controlled-by-spacing);
}
#labels[disabled] {
@@ -44,7 +44,7 @@
}
#label-begin {
- -webkit-margin-end: 4px;
+ margin-inline-end: 4px;
}
#label-end {
diff --git a/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html b/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html
index 0965fc374fa..dcf511439de 100644
--- a/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html
+++ b/chromium/chrome/browser/resources/settings/controls/settings_toggle_button.html
@@ -46,11 +46,11 @@
#labelWrapper,
::slotted([slot='more-actions']) {
- -webkit-margin-end: var(--settings-control-label-spacing);
+ margin-inline-end: var(--settings-control-label-spacing);
}
cr-policy-pref-indicator {
- -webkit-margin-end: var(--settings-controlled-by-spacing);
+ margin-inline-end: var(--settings-controlled-by-spacing);
}
</style>
<div id="outerRow" noSubLabel$="[[!subLabel]]">
diff --git a/chromium/chrome/browser/resources/settings/date_time_page/timezone_subpage.html b/chromium/chrome/browser/resources/settings/date_time_page/timezone_subpage.html
index e2953defea0..2ae2ba3226e 100644
--- a/chromium/chrome/browser/resources/settings/date_time_page/timezone_subpage.html
+++ b/chromium/chrome/browser/resources/settings/date_time_page/timezone_subpage.html
@@ -20,7 +20,7 @@
}
#timeZoneResolveMethodDropdown,
#timezoneSelector {
- -webkit-padding-start: 28px;
+ padding-inline-start: 28px;
}
</style>
<div class="settings-box block first">
diff --git a/chromium/chrome/browser/resources/settings/device_page/device_page.html b/chromium/chrome/browser/resources/settings/device_page/device_page.html
index 7d8d94f311d..d9a55adb6d6 100644
--- a/chromium/chrome/browser/resources/settings/device_page/device_page.html
+++ b/chromium/chrome/browser/resources/settings/device_page/device_page.html
@@ -57,8 +57,8 @@
<button aria-label="$i18n{displayTitle}"></button>
</paper-icon-button-light>
</div>
- <div id="storageRow" class="settings-box" on-click="onStorageTap_"
- actionable>
+ <div id="storageRow" hidden="[[hideStorageInfo_]]" class="settings-box"
+ on-click="onStorageTap_" actionable>
<div class="start">$i18n{storageTitle}</div>
<paper-icon-button-light class="subpage-arrow">
<button aria-label="$i18n{storageTitle}"></button>
diff --git a/chromium/chrome/browser/resources/settings/device_page/device_page.js b/chromium/chrome/browser/resources/settings/device_page/device_page.js
index 2dac5e6137f..46c32cde32e 100644
--- a/chromium/chrome/browser/resources/settings/device_page/device_page.js
+++ b/chromium/chrome/browser/resources/settings/device_page/device_page.js
@@ -54,6 +54,19 @@ Polymer({
readOnly: true,
},
+ /**
+ * Whether storage management info should be hidden.
+ * @private
+ */
+ hideStorageInfo_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.valueExists('hideStorageInfo') &&
+ loadTimeData.getBoolean('hideStorageInfo');
+ },
+ readOnly: true,
+ },
+
/** @private {!Map<string, string>} */
focusConfig_: {
type: Object,
diff --git a/chromium/chrome/browser/resources/settings/device_page/display.html b/chromium/chrome/browser/resources/settings/device_page/display.html
index 577ec094628..f271dcdc49b 100644
--- a/chromium/chrome/browser/resources/settings/device_page/display.html
+++ b/chromium/chrome/browser/resources/settings/device_page/display.html
@@ -26,8 +26,8 @@
<template>
<style include="settings-shared md-select iron-flex iron-flex-alignment paper-tabs-style">
.indented {
- -webkit-margin-start: var(--cr-section-indent-padding);
align-self: stretch;
+ margin-inline-start: var(--cr-section-indent-padding);
padding: 0;
}
@@ -52,7 +52,7 @@
}
.settings-box > paper-button:first-child {
- -webkit-padding-start: 0
+ padding-inline-start: 0
}
#controlsDiv > .settings-box:first-of-type {
@@ -137,57 +137,39 @@
</div>
</template>
- <!-- Slider for selecting resolution when display zoom is disabled -->
- <template is="dom-if" if="[[!showDisplayZoomSetting_]]">
- <div class="settings-box indented two-line">
- <div class="start text-area layout vertical">
- <div>$i18n{displayResolutionTitle}</div>
- <div class="secondary self-start">
- [[getResolutionText_(selectedDisplay, selectedModePref_.value)]]
- </div>
- </div>
- <settings-slider disabled="[[!enableSetResolution_(selectedDisplay)]]"
- tick-values="[[modeValues_]]" pref="{{selectedModePref_}}"
- on-change="onSelectedModeSliderChange_">
- </settings-slider>
- </div>
- </template>
-
<!-- Display zoom selection slider -->
- <template is="dom-if" if="[[showDisplayZoomSetting_]]">
- <div class="settings-box indented two-line">
- <div class="start text-area layout vertical">
- <div>$i18n{displayZoomTitle}</div>
- <div class="secondary self-start">$i18n{displayZoomSublabel}</div>
- <div class="secondary self-start"
- hidden$="[[!logicalResolutionText_]]">
- [[logicalResolutionText_]]
- </div>
+ <div class="settings-box indented two-line">
+ <div class="start text-area layout vertical">
+ <div>$i18n{displayZoomTitle}</div>
+ <div class="secondary self-start">$i18n{displayZoomSublabel}</div>
+ <div class="secondary self-start"
+ hidden$="[[!logicalResolutionText_]]">
+ [[logicalResolutionText_]]
</div>
- <display-size-slider id="displaySizeSlider"
- ticks="[[zoomValues_]]" pref="{{selectedZoomPref_}}"
- min-label="$i18n{displaySizeSliderMinLabel}"
- max-label="$i18n{displaySizeSliderMaxLabel}"
- on-immediate-value-changed="onDisplaySizeSliderDrag_">
- </display-size-slider>
</div>
+ <display-size-slider id="displaySizeSlider"
+ ticks="[[zoomValues_]]" pref="{{selectedZoomPref_}}"
+ min-label="$i18n{displaySizeSliderMinLabel}"
+ max-label="$i18n{displaySizeSliderMaxLabel}"
+ on-immediate-value-changed="onDisplaySizeSliderDrag_">
+ </display-size-slider>
+ </div>
- <!-- Drop down select menu for resolution -->
- <div class="settings-box indented two-line"
- hidden$="[[!showDropDownResolutionSetting_(selectedDisplay)]]">
- <div class="start text-area layout vertical">
- <div>$i18n{displayResolutionTitle}</div>
- <div class="secondary self-start">
- $i18n{displayResolutionSublabel}
- </div>
+ <!-- Drop down select menu for resolution -->
+ <div class="settings-box indented two-line"
+ hidden$="[[!showDropDownResolutionSetting_(selectedDisplay)]]">
+ <div class="start text-area layout vertical">
+ <div>$i18n{displayResolutionTitle}</div>
+ <div class="secondary self-start">
+ $i18n{displayResolutionSublabel}
</div>
- <settings-dropdown-menu id="displayModeSelector"
- pref="{{selectedModePref_}}"
- label="Display Mode Menu"
- menu-options="[[displayModeList_]]">
- </settings-dropdown-menu>
</div>
- </template>
+ <settings-dropdown-menu id="displayModeSelector"
+ pref="{{selectedModePref_}}"
+ label="Display Mode Menu"
+ menu-options="[[displayModeList_]]">
+ </settings-dropdown-menu>
+ </div>
<template is="dom-if" if="[[!unifiedDesktopMode_]]" restamp>
<div class="settings-box indented">
<div id="displayOrientation" class="start text-area">
diff --git a/chromium/chrome/browser/resources/settings/device_page/display.js b/chromium/chrome/browser/resources/settings/device_page/display.js
index 3443c71cd57..cde11aeae41 100644
--- a/chromium/chrome/browser/resources/settings/device_page/display.js
+++ b/chromium/chrome/browser/resources/settings/device_page/display.js
@@ -170,12 +170,6 @@ Polymer({
},
/** @private */
- showDisplayZoomSetting_: {
- type: Boolean,
- value: loadTimeData.getBoolean('enableDisplayZoomSetting'),
- },
-
- /** @private */
nightLightScheduleSubLabel_: String,
/** @private */
@@ -370,14 +364,12 @@ Polymer({
const numModes = selectedDisplay.modes.length;
this.modeValues_ = numModes == 0 ? [] : Array.from(Array(numModes).keys());
- if (this.showDisplayZoomSetting_) {
- // Note that the display zoom values has the same number of ticks for all
- // displays, so the above problem doesn't apply here.
- this.zoomValues_ = this.getZoomValues_(selectedDisplay);
- this.set(
- 'selectedZoomPref_.value',
- this.getSelectedDisplayZoom_(selectedDisplay));
- }
+ // Note that the display zoom values has the same number of ticks for all
+ // displays, so the above problem doesn't apply here.
+ this.zoomValues_ = this.getZoomValues_(selectedDisplay);
+ this.set(
+ 'selectedZoomPref_.value',
+ this.getSelectedDisplayZoom_(selectedDisplay));
this.displayModeList_ = this.getDisplayModeOptionList_(selectedDisplay);
// Set |selectedDisplay| first since only the resolution slider depends
@@ -401,8 +393,7 @@ Polymer({
* @private
*/
showDropDownResolutionSetting_: function(display) {
- return !display.isInternal &&
- loadTimeData.getBoolean('enableDisplayZoomSetting');
+ return !display.isInternal;
},
/**
@@ -600,7 +591,7 @@ Polymer({
* @private
*/
updateLogicalResolutionText_: function(zoomFactor) {
- if (!this.showDisplayZoomSetting_ || !this.selectedDisplay.isInternal) {
+ if (!this.selectedDisplay.isInternal) {
this.logicalResolutionText_ = '';
return;
}
@@ -718,11 +709,7 @@ Polymer({
*/
onSelectedModeChange_: function(newModeIndex) {
// We want to ignore all value changes to the pref due to the slider being
- // dragged. Since this can only happen when the slider is present which is
- // when display zoom is disabled, we can use this check.
- // See http://crbug/845712 for more info.
- if (!this.showDisplayZoomSetting_)
- return;
+ // dragged. See http://crbug/845712 for more info.
if (this.currentSelectedModeIndex_ == newModeIndex)
return;
this.onSelectedModeSliderChange_();
diff --git a/chromium/chrome/browser/resources/settings/device_page/display_size_slider.html b/chromium/chrome/browser/resources/settings/device_page/display_size_slider.html
index 631200d711c..93757c4ef6f 100644
--- a/chromium/chrome/browser/resources/settings/device_page/display_size_slider.html
+++ b/chromium/chrome/browser/resources/settings/device_page/display_size_slider.html
@@ -14,13 +14,14 @@
<template>
<style>
:host {
- /* Counteract the margin on #sliderContainer and match the margin from
- settings-slider.html */
- -webkit-margin-end: -16px;
-
cursor: default;
display: inline-flex;
font-weight: 500;
+
+ /* Counteract the margin on #sliderContainer and match the margin from
+ settings-slider.html */
+ margin-inline-end: -16px;
+
min-width: 200px;
text-align: center;
user-select: none;
@@ -142,14 +143,12 @@
.slider-knob-inner {
background-color: var(--google-blue-600);
- border: 2px solid var(--google-blue-600);
+ border: 0;
border-radius: 50%;
- box-sizing: border-box;
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.4);
+ box-sizing: content-box;
height: 10px;
margin: 11px;
- transition-duration: 180ms;
- transition-property: transform, background-color, border;
- transition-timing-function: ease;
width: 10px;
}
@@ -192,6 +191,8 @@
.slider-knob-inner[disabled] {
background-color: var(--google-grey-600);
border: 2px solid white;
+ box-shadow: unset;
+ margin: 9px;
}
</style>
<div id="sliderContainer" class$="[[getClassNames_(disabled, dragging)]]">
diff --git a/chromium/chrome/browser/resources/settings/device_page/display_size_slider.js b/chromium/chrome/browser/resources/settings/device_page/display_size_slider.js
index 924c9bfd5ff..7dd8f904aaa 100644
--- a/chromium/chrome/browser/resources/settings/device_page/display_size_slider.js
+++ b/chromium/chrome/browser/resources/settings/device_page/display_size_slider.js
@@ -128,6 +128,16 @@ Polymer({
'pageup end': 'resetToMaxIndex_',
},
+ /** @override */
+ ready: function() {
+ chrome.settingsPrivate.onPrefsChanged.addListener((prefs) => {
+ prefs.forEach((pref) => {
+ if (pref.key == this.pref.key && this.pref.value != pref.value)
+ this.pref.value = pref.value;
+ });
+ });
+ },
+
/** @private {boolean} */
usedMouse_: false,
@@ -469,18 +479,20 @@ Polymer({
updateIndex_: function() {
if (!this.ticks || this.ticks.length == 0)
return;
- if (!this.pref)
+ if (!this.pref || typeof(this.pref.value) != 'number')
return;
+ let resolvedTick = this.ticks.length - 1;
for (let i = 0; i < this.ticks.length; i++) {
- if (this.ticks[i].value == this.pref.value) {
- this._setIndex(i);
- this.setAttribute(
- 'aria-valuenow',
- this.getAriaValueForIndex_(this.ticks, this.index));
- this.setAttribute(
- 'aria-valuetext', this.getLabelForIndex_(this.ticks, this.index));
+ if (this.ticks[i].value >= this.pref.value) {
+ resolvedTick = i;
+ break;
}
}
+ this._setIndex(resolvedTick);
+ this.setAttribute(
+ 'aria-valuenow', this.getAriaValueForIndex_(this.ticks, this.index));
+ this.setAttribute(
+ 'aria-valuetext', this.getLabelForIndex_(this.ticks, this.index));
},
/**
diff --git a/chromium/chrome/browser/resources/settings/device_page/keyboard.html b/chromium/chrome/browser/resources/settings/device_page/keyboard.html
index 6f88254da9c..415d4d62a62 100644
--- a/chromium/chrome/browser/resources/settings/device_page/keyboard.html
+++ b/chromium/chrome/browser/resources/settings/device_page/keyboard.html
@@ -34,15 +34,6 @@
menu-options="[[keyMapTargets_]]">
</settings-dropdown-menu>
</div>
- <template is="dom-if" if="[[showCapsLock_]]">
- <div class="settings-box" id="capsLockKey">
- <div class="start">$i18n{keyboardKeyCapsLock}</div>
- <settings-dropdown-menu label="$i18n{keyboardKeyCapsLock}"
- pref="{{prefs.settings.language.remap_caps_lock_key_to}}"
- menu-options="[[keyMapTargets_]]">
- </settings-dropdown-menu>
- </div>
- </template>
<template is="dom-if" if="[[showDiamondKey_]]">
<div class="settings-box" id="diamondKey">
<div class="start">$i18n{keyboardKeyDiamond}</div>
@@ -66,6 +57,34 @@
menu-options="[[keyMapTargets_]]">
</settings-dropdown-menu>
</div>
+ <template is="dom-if" if="[[showCapsLock_]]">
+ <div class="settings-box" id="capsLockKey">
+ <div class="start">$i18n{keyboardKeyCapsLock}</div>
+ <settings-dropdown-menu label="$i18n{keyboardKeyCapsLock}"
+ pref="{{prefs.settings.language.remap_caps_lock_key_to}}"
+ menu-options="[[keyMapTargets_]]">
+ </settings-dropdown-menu>
+ </div>
+ </template>
+ <template is="dom-if" if="[[showExternalMetaKey_]]">
+ <div class="settings-box" id="externalMetaKey">
+ <div class="start">$i18n{keyboardKeyExternalMeta}</div>
+ <settings-dropdown-menu label="$i18n{keyboardKeyExternalMeta}"
+ pref="{{prefs.settings.language.remap_external_meta_key_to}}"
+ menu-options="[[keyMapTargets_]]">
+ </settings-dropdown-menu>
+ </div>
+ </template>
+ <template is="dom-if" if="[[showAppleCommandKey_]]">
+ <div class="settings-box" id="externalCommandKey">
+ <div class="start">$i18n{keyboardKeyExternalCommand}</div>
+ <settings-dropdown-menu
+ label="$i18n{keyboardKeyExternalCommand}"
+ pref="{{prefs.settings.language.remap_external_command_key_to}}"
+ menu-options="[[keyMapTargets_]]">
+ </settings-dropdown-menu>
+ </div>
+ </template>
<settings-toggle-button
pref="{{prefs.settings.language.send_function_keys}}"
label="$i18n{keyboardSendFunctionKeys}"
diff --git a/chromium/chrome/browser/resources/settings/device_page/keyboard.js b/chromium/chrome/browser/resources/settings/device_page/keyboard.js
index e10766d145b..204013c2fd2 100644
--- a/chromium/chrome/browser/resources/settings/device_page/keyboard.js
+++ b/chromium/chrome/browser/resources/settings/device_page/keyboard.js
@@ -39,6 +39,21 @@ Polymer({
/** @private Whether to show diamond key options. */
showDiamondKey_: Boolean,
+ /**
+ * Whether to show a remapping option for external keyboard's Meta key
+ * (Search/Windows keys). This is true only when there's an external
+ * keyboard connected that is a non-Apple keyboard.
+ * @private
+ */
+ showExternalMetaKey_: Boolean,
+
+ /**
+ * Whether to show a remapping option for the Command key. This is true when
+ * one of the connected keyboards is an Apple keyboard.
+ * @private
+ */
+ showAppleCommandKey_: Boolean,
+
/** @private {!DropdownMenuOptionList} Menu items for key mapping. */
keyMapTargets_: Object,
@@ -114,13 +129,14 @@ Polymer({
/**
* Handler for updating which keys to show.
- * @param {boolean} showCapsLock
- * @param {boolean} showDiamondKey
+ * @param {Object} keyboardParams
* @private
*/
- onShowKeysChange_: function(showCapsLock, showDiamondKey) {
- this.showCapsLock_ = showCapsLock;
- this.showDiamondKey_ = showDiamondKey;
+ onShowKeysChange_: function(keyboardParams) {
+ this.showCapsLock_ = keyboardParams['showCapsLock'];
+ this.showDiamondKey_ = keyboardParams['showDiamondKey'];
+ this.showExternalMetaKey_ = keyboardParams['showExternalMetaKey'];
+ this.showAppleCommandKey_ = keyboardParams['showAppleCommandKey'];
},
onShowKeyboardShortcutsOverlayTap_: function() {
diff --git a/chromium/chrome/browser/resources/settings/device_page/pointers.html b/chromium/chrome/browser/resources/settings/device_page/pointers.html
index 0595aa2bf6e..0ae8891c9cc 100644
--- a/chromium/chrome/browser/resources/settings/device_page/pointers.html
+++ b/chromium/chrome/browser/resources/settings/device_page/pointers.html
@@ -11,12 +11,12 @@
<template>
<style include="settings-shared">
h2 {
- -webkit-padding-start: var(--settings-box-row-padding);
+ padding-inline-start: var(--settings-box-row-padding);
}
.subsection {
- -webkit-padding-end: var(--settings-box-row-padding);
- -webkit-padding-start: var(--settings-box-row-indent);
+ padding-inline-end: var(--settings-box-row-padding);
+ padding-inline-start: var(--settings-box-row-indent);
}
.subsection > settings-toggle-button,
diff --git a/chromium/chrome/browser/resources/settings/device_page/storage.html b/chromium/chrome/browser/resources/settings/device_page/storage.html
index 27bef12bff6..7b7c8d91bc8 100644
--- a/chromium/chrome/browser/resources/settings/device_page/storage.html
+++ b/chromium/chrome/browser/resources/settings/device_page/storage.html
@@ -55,20 +55,20 @@
}
.message-area {
- -webkit-padding-end: 48px;
- -webkit-padding-start: 16px;
background-color: var(--google-grey-100);
border-radius: 2px;
display: flex;
margin: 14px 0 16px;
padding-bottom: 12px;
+ padding-inline-end: 48px;
+ padding-inline-start: 16px;
padding-top: 16px;
width: 100%;
}
.message-area > iron-icon {
- -webkit-padding-end: 16px;
flex: none;
+ padding-inline-end: 16px;
}
.message-title {
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn b/chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn
index 77ad172d70c..a4c1ddd2ed5 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn
@@ -24,6 +24,7 @@ js_library("downloads_browser_proxy") {
js_library("smb_shares_page") {
deps = [
":add_smb_share_dialog",
+ "..:route",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
@@ -32,6 +33,7 @@ js_library("add_smb_share_dialog") {
deps = [
":smb_browser_proxy",
"//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
]
}
@@ -47,6 +49,7 @@ js_library("downloads_page") {
":smb_browser_proxy",
"..:page_visibility",
"..:route",
+ "../prefs:prefs_behavior",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:util",
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.html b/chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.html
index 155c13f9f75..5dab706aaa2 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.html
+++ b/chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.html
@@ -2,7 +2,9 @@
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="../settings_vars_css.html">
@@ -11,12 +13,21 @@
<dom-module id="settings-add-smb-share-dialog">
<template>
<style include="settings-shared">
+ #dialog [slot=body] {
+ height: 350px;
+ }
+
cr-input {
--cr-input-error-display: none;
- width: var(--settings-input-max-width);
}
- cr-input:not(:last-child) {
+ cr-searchable-drop-down {
+ display: block;
+ --cr-searchable-drop-down-width: 472px;
+ }
+
+ cr-input:not(:last-child),
+ cr-searchable-drop-down {
margin-bottom: var(--cr-form-field-bottom-spacing);
}
</style>
@@ -24,9 +35,10 @@
<cr-dialog id="dialog">
<div slot="title">$i18n{addSmbShare}</div>
<div slot="body" spellcheck="false">
- <cr-input id="address" label="$i18n{smbShareUrl}" value="{{mountUrl_}}"
- autofocus>
- </cr-input>
+ <cr-searchable-drop-down id="address" label="$i18n{smbShareUrl}"
+ value="{{mountUrl_}}" items="[[discoveredShares_]]"
+ update-value-on-input autofocus>
+ </cr-searchable-drop-down>
<cr-input id="name" label="$i18n{smbShareName}" value="{{mountName_}}"
maxlength="64">
</cr-input>
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.js b/chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.js
index 0156d6df0fc..67273f283d3 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.js
+++ b/chromium/chrome/browser/resources/settings/downloads_page/add_smb_share_dialog.js
@@ -9,18 +9,39 @@
Polymer({
is: 'settings-add-smb-share-dialog',
+ behaviors: [WebUIListenerBehavior],
+
properties: {
/** @private {string} */
- mountUrl_: String,
+ mountUrl_: {
+ type: String,
+ value: '',
+ },
/** @private {string} */
- mountName_: String,
+ mountName_: {
+ type: String,
+ value: '',
+ },
/** @private {string} */
- username_: String,
+ username_: {
+ type: String,
+ value: '',
+ },
/** @private {string} */
- password_: String,
+ password_: {
+ type: String,
+ value: '',
+ },
+ /** @private {!Array<string>}*/
+ discoveredShares_: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
},
/** @private {?settings.SmbBrowserProxy} */
@@ -35,6 +56,8 @@ Polymer({
attached: function() {
this.browserProxy_.startDiscovery();
this.$.dialog.showModal();
+
+ this.addWebUIListener('on-shares-found', this.onSharesFound_.bind(this));
},
/** @private */
@@ -56,4 +79,13 @@ Polymer({
canAddShare_: function() {
return !!this.mountUrl_;
},
+
+ /**
+ * @param {!Array<string>} shares
+ * @private
+ */
+ onSharesFound_: function(shares) {
+ this.discoveredShares_ = this.discoveredShares_.concat(shares);
+ },
+
});
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/downloads_browser_proxy.js b/chromium/chrome/browser/resources/settings/downloads_page/downloads_browser_proxy.js
index 88c41dbafbc..0ce7ea25259 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/downloads_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/downloads_page/downloads_browser_proxy.js
@@ -8,6 +8,13 @@ cr.define('settings', function() {
initializeDownloads() {}
selectDownloadLocation() {}
resetAutoOpenFileTypes() {}
+ // <if expr="chromeos">
+ /**
+ * @param {string} path path to sanitze.
+ * @return {!Promise<string>} string to display in UI.
+ */
+ getDownloadLocationText(path) {}
+ // </if>
}
/**
@@ -28,6 +35,13 @@ cr.define('settings', function() {
resetAutoOpenFileTypes() {
chrome.send('resetAutoOpenFileTypes');
}
+
+ // <if expr="chromeos">
+ /** @override */
+ getDownloadLocationText(path) {
+ return cr.sendWithPromise('getDownloadLocationText', path);
+ }
+ // </if>
}
cr.addSingletonGetter(DownloadsBrowserProxyImpl);
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html b/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html
index 90e4ca90487..69dbf529286 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html
+++ b/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.html
@@ -4,6 +4,7 @@
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="../controls/controlled_button.html">
<link rel="import" href="../controls/settings_toggle_button.html">
+<link rel="import" href="../prefs/prefs_behavior.html">
<link rel="import" href="../route.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="downloads_browser_proxy.html">
@@ -24,12 +25,12 @@
<div class="settings-box first two-line">
<div class="start">
<div>$i18n{downloadLocation}</div>
- <div class="secondary">
+ <div class="secondary" id="defaultDownloadPath">
<if expr="not chromeos">
[[prefs.download.default_directory.value]]
</if>
<if expr="chromeos">
- [[getDownloadLocation_(prefs.download.default_directory.value)]]
+ [[downloadLocation_]]
</if>
</div>
</div>
@@ -80,7 +81,7 @@
<settings-subpage
associated-control="[[$$('#smbShares')]]"
page-title="$i18n{smbSharesTitle}">
- <settings-smb-shares-page>
+ <settings-smb-shares-page prefs="[[prefs]]">
</settings-smb-shares-page>
</settings-subpage>
</template>
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js b/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js
index 11a50db0904..11c89e7c8c4 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js
+++ b/chromium/chrome/browser/resources/settings/downloads_page/downloads_page.js
@@ -18,7 +18,7 @@
Polymer({
is: 'settings-downloads-page',
- behaviors: [WebUIListenerBehavior],
+ behaviors: [WebUIListenerBehavior, PrefsBehavior],
properties: {
/**
@@ -53,6 +53,11 @@ Polymer({
},
readOnly: true,
},
+
+ /**
+ * The download location string that is suitable to display in the UI.
+ */
+ downloadLocation_: String,
// </if>
/** @private {!Map<string, string>} */
@@ -73,13 +78,22 @@ Polymer({
},
+ // <if expr="chromeos">
+ observers: [
+ 'handleDownloadLocationChanged_(prefs.download.default_directory.value)'
+ ],
+ // </if>
+
/** @private {?settings.DownloadsBrowserProxy} */
browserProxy_: null,
/** @override */
- attached: function() {
+ created: function() {
this.browserProxy_ = settings.DownloadsBrowserProxyImpl.getInstance();
+ },
+ /** @override */
+ ready: function() {
this.addWebUIListener('auto-open-downloads-changed', autoOpen => {
this.autoOpenDownloads_ = autoOpen;
});
@@ -99,25 +113,17 @@ Polymer({
onTapSmbShares_: function() {
settings.navigateTo(settings.routes.SMB_SHARES);
},
- // </if>
-
- // <if expr="chromeos">
/**
- * @param {string} path
- * @return {string} The download location string that is suitable to display
- * in the UI.
* @private
*/
- getDownloadLocation_: function(path) {
- // Replace /special/drive-<hash>/root with "Google Drive" for remote files,
- // /home/chronos/user/Downloads or /home/chronos/u-<hash>/Downloads with
- // "Downloads" for local paths, and '/' with ' \u203a ' (angled quote sign)
- // everywhere. It is used only for display purpose.
- path = path.replace(/^\/special\/drive[^\/]*\/root/, 'Google Drive');
- path = path.replace(/^\/home\/chronos\/(user|u-[^\/]*)\//, '');
- path = path.replace(/\//g, ' \u203a ');
- return path;
+ handleDownloadLocationChanged_: function() {
+ this.browserProxy_
+ .getDownloadLocationText(/** @type {string} */ (
+ this.getPref('download.default_directory').value))
+ .then(text => {
+ this.downloadLocation_ = text;
+ });
},
// </if>
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/smb_browser_proxy.js b/chromium/chrome/browser/resources/settings/downloads_page/smb_browser_proxy.js
index e32cc6e4a62..5085ce6b042 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/smb_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/downloads_page/smb_browser_proxy.js
@@ -19,6 +19,7 @@ const SmbMountResult = {
NOT_FOUND: 3,
UNSUPPORTED_DEVICE: 4,
MOUNT_EXISTS: 5,
+ INVALID_URL: 6,
};
cr.define('settings', function() {
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.html b/chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
index 83406eaf117..584488ae30d 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
+++ b/chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.html
@@ -7,6 +7,7 @@
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
+<link rel="import" href="../route.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="../settings_vars_css.html">
<link rel="import" href="add_smb_share_dialog.html">
@@ -17,15 +18,23 @@
<div class="settings-box first">
<div class="start">
<span>$i18n{smbSharesLearnMoreLabel}</span>
- <a href="http://support.google.com" target="_blank">
+ <a href="$i18n{smbSharesLearnMoreURL}" target="_blank">
$i18n{learnMore}
</a>
<div class="secondary" hidden="false">
$i18n{requireNetworkMessage}
</div>
</div>
+ <template is="dom-if" if="[[!prefs.network_file_shares.allowed.value]]"
+ restamp>
+ <cr-policy-pref-indicator
+ pref="[[prefs.network_file_shares.allowed]]"
+ icon-aria-label="$i18n{smbSharesTitle}">
+ </cr-policy-pref-indicator>
+ </template>
<paper-button class="action-button" id="addShare"
- on-click="onAddShareTap_">
+ on-click="onAddShareTap_"
+ disabled="[[!prefs.network_file_shares.allowed.value]]">
$i18n{addSmbShare}
</paper-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.js b/chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.js
index 04829640903..f9a8ecc35d1 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.js
+++ b/chromium/chrome/browser/resources/settings/downloads_page/smb_shares_page.js
@@ -5,9 +5,20 @@
Polymer({
is: 'settings-smb-shares-page',
- behaviors: [WebUIListenerBehavior],
+ behaviors: [
+ WebUIListenerBehavior,
+ settings.RouteObserverBehavior,
+ ],
properties: {
+ /**
+ * Preferences state.
+ */
+ prefs: {
+ type: Object,
+ notify: true,
+ },
+
/** @private */
showAddSmbDialog_: Boolean,
@@ -15,6 +26,18 @@ Polymer({
addShareResultText_: String,
},
+ /**
+ * Overridden from settings.RouteObserverBehavior.
+ * @param {!settings.Route} route
+ * @protected
+ */
+ currentRouteChanged: function(route) {
+ if (route == settings.routes.SMB_SHARES) {
+ this.showAddSmbDialog_ =
+ settings.getQueryParameters().get('showAddShare') == 'true';
+ }
+ },
+
/** @override */
attached: function() {
this.addWebUIListener('on-add-smb-share', this.onAddShare_.bind(this));
@@ -56,6 +79,10 @@ Polymer({
this.addShareResultText_ =
loadTimeData.getString('smbShareAddedMountExistsMessage');
break;
+ case SmbMountResult.INVALID_URL:
+ this.addShareResultText_ =
+ loadTimeData.getString('smbShareAddedInvalidURLMessage');
+ break;
default:
this.addShareResultText_ =
loadTimeData.getString('smbShareAddedErrorMessage');
diff --git a/chromium/chrome/browser/resources/settings/find_shortcut_behavior.html b/chromium/chrome/browser/resources/settings/find_shortcut_behavior.html
index 4fedd0e11f1..50b4f350f43 100644
--- a/chromium/chrome/browser/resources/settings/find_shortcut_behavior.html
+++ b/chromium/chrome/browser/resources/settings/find_shortcut_behavior.html
@@ -1,4 +1,4 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
+<link rel="import" href="chrome://resources/html/cr/ui/command.html">
<script src="find_shortcut_behavior.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/find_shortcut_behavior.js b/chromium/chrome/browser/resources/settings/find_shortcut_behavior.js
index 51103e5b683..0beae62528a 100644
--- a/chromium/chrome/browser/resources/settings/find_shortcut_behavior.js
+++ b/chromium/chrome/browser/resources/settings/find_shortcut_behavior.js
@@ -3,49 +3,80 @@
// found in the LICENSE file.
/**
- * @fileoverview Listens for a find keyboard shortcut (i.e. Ctrl/Cmd+f) wherever
- * this behavior is applied and invokes canHandleFindShortcut(). If
- * canHandleFindShortcut() returns true, handleFindShortcut() will be called.
- * Override these methods in your element in order to use this behavior.
+ * @fileoverview Listens for a find keyboard shortcut (i.e. Ctrl/Cmd+f)
+ * and keeps track of an stack of potential listeners. Only the listener at the
+ * top of the stack will be notified that a find shortcut has been invoked.
*/
-cr.exportPath('settings');
-
-/** @polymerBehavior */
-settings.FindShortcutBehaviorImpl = {
- keyBindings: {
- // <if expr="is_macosx">
- 'meta+f': 'onFindShortcut_',
- // </if>
- // <if expr="not is_macosx">
- 'ctrl+f': 'onFindShortcut_',
- // </if>
- },
-
- /** @private */
- onFindShortcut_: function(e) {
- if (!e.defaultPrevented && this.canHandleFindShortcut()) {
- this.handleFindShortcut();
- e.preventDefault();
+cr.define('settings', function() {
+ /**
+ * Stack of listeners. Only the top listener will handle the shortcut.
+ * @type {!Array<!HTMLElement>}
+ */
+ const listeners = [];
+
+ /**
+ * Tracks if any modal context is open in settings. This assumes only one
+ * modal can be open at a time. The modals that are being tracked include
+ * cr-dialog and cr-drawer.
+ * @type {boolean}
+ */
+ let modalContextOpen = false;
+
+ const shortcut =
+ new cr.ui.KeyboardShortcutList(cr.isMac ? 'meta|f' : 'ctrl|f');
+
+ window.addEventListener('keydown', e => {
+ if (e.defaultPrevented || listeners.length == 0)
+ return;
+
+ if (shortcut.matchesEvent(e)) {
+ const listener = /** @type {!{handleFindShortcut: function(boolean)}} */ (
+ listeners[listeners.length - 1]);
+ if (listener.handleFindShortcut(modalContextOpen))
+ e.preventDefault();
}
- },
+ });
+
+ window.addEventListener('cr-dialog-open', () => {
+ modalContextOpen = true;
+ });
+
+ window.addEventListener('cr-drawer-opened', () => {
+ modalContextOpen = true;
+ });
+
+ window.addEventListener('close', e => {
+ if (['CR-DIALOG', 'CR-DRAWER'].includes(e.composedPath()[0].nodeName))
+ modalContextOpen = false;
+ });
/**
- * @return {boolean}
- * @protected
+ * Used to determine how to handle find shortcut invocations.
+ * @polymerBehavior
*/
- canHandleFindShortcut: function() {
- assertNotReached();
- },
-
- /** @protected */
- handleFindShortcut: function() {
- assertNotReached();
- },
-};
-
-/** @polymerBehavior */
-settings.FindShortcutBehavior = [
- Polymer.IronA11yKeysBehavior,
- settings.FindShortcutBehaviorImpl,
-];
+ const FindShortcutBehavior = {
+ /**
+ * If handled, return true.
+ * @param {boolean} modalContextOpen
+ * @return {boolean}
+ * @protected
+ */
+ handleFindShortcut(modalContextOpen) {
+ assertNotReached();
+ },
+
+ becomeActiveFindShortcutListener() {
+ assert(listeners.length == 0 || listeners[listeners.length - 1] != this);
+ listeners.push(this);
+ },
+
+ removeSelfAsFindShortcutListener() {
+ assert(listeners.pop() == this);
+ },
+ };
+
+ return {
+ FindShortcutBehavior,
+ };
+});
diff --git a/chromium/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html b/chromium/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
index fdfd106a425..e87f2d0f2f0 100644
--- a/chromium/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
+++ b/chromium/chrome/browser/resources/settings/google_assistant_page/google_assistant_page.html
@@ -37,6 +37,14 @@
sub-label="$i18n{googleAssistantEnableHotwordDescription}">
</settings-toggle-button>
</template>
+ <template is="dom-if" if="[[assistantFeatureEnabled_]]">
+ <settings-toggle-button id="googleAssistantNotificationEnable"
+ class="continuation indented"
+ pref="{{prefs.settings.voice_interaction.notification.enabled}}"
+ label="$i18n{googleAssistantEnableNotification}"
+ sub-label="$i18n{googleAssistantEnableNotificationDescription}">
+ </settings-toggle-button>
+ </template>
<div id="googleAssistantSettings" class="settings-box"
on-click="onGoogleAssistantSettingsTapped_" actionable>
<div class="start">
diff --git a/chromium/chrome/browser/resources/settings/icons.html b/chromium/chrome/browser/resources/settings/icons.html
index 0f361f4f1cc..ae8db8c7760 100644
--- a/chromium/chrome/browser/resources/settings/icons.html
+++ b/chromium/chrome/browser/resources/settings/icons.html
@@ -49,8 +49,9 @@ List icons here rather than importing large sets of (e.g. Polymer) icons.
</g>
<!-- Icons for MultiDevice Settings UI -->
- <g id="smart-lock" fill="#9AA0A6" fill-rule="nonzero"><path d="M18,9 L17,9 L17,7 C17,4.24 14.76,2 12,2 C9.24,2 7,4.24 7,7 L7,9 L6,9 C4.9,9 4,9.9 4,11 L4,21 C4,22.1 4.9,23 6,23 L18,23 C19.1,23 20,22.1 20,21 L20,11 C20,9.9 19.1,9 18,9 Z M9,7 C9,5.34 10.34,4 12,4 C13.66,4 15,5.34 15,7 L15,9 L9,9 L9,7 Z M18,21 L6,21 L6,11 L18,11 L18,21 Z M12,18 C13.1,18 14,17.1 14,16 C14,14.9 13.1,14 12,14 C10.9,14 10,14.9 10,16 C10,17.1 10.9,18 12,18 Z"></path></g>
-
+ <g id="multidevice-better-together-suite" fill="#9AA0A6" fill-rule="nonzero"><path d="M17,1.01 L7,1 C5.9,1 5,1.9 5,3 L5,21 C5,22.1 5.9,23 7,23 L17,23 C18.1,23 19,22.1 19,21 L19,3 C19,1.9 18.1,1.01 17,1.01 Z M17,21 L7,21 L7,20 L17,20 L17,21 Z M17,18 L7,18 L7,6 L17,6 L17,18 Z M7,4 L7,3 L17,3 L17,4 L7,4 Z"></path></g>
+ <g id="multidevice-smart-lock" fill="#9AA0A6" fill-rule="nonzero"><path d="M18,9 L17,9 L17,7 C17,4.24 14.76,2 12,2 C9.24,2 7,4.24 7,7 L7,9 L6,9 C4.9,9 4,9.9 4,11 L4,21 C4,22.1 4.9,23 6,23 L18,23 C19.1,23 20,22.1 20,21 L20,11 C20,9.9 19.1,9 18,9 Z M9,7 C9,5.34 10.34,4 12,4 C13.66,4 15,5.34 15,7 L15,9 L9,9 L9,7 Z M18,21 L6,21 L6,11 L18,11 L18,21 Z M12,18 C13.1,18 14,17.1 14,16 C14,14.9 13.1,14 12,14 C10.9,14 10,14.9 10,16 C10,17.1 10.9,18 12,18 Z"></path></g>
+ <g id="multidevice-messages" fill="#9AA0A6" fill-rule="nonzero"><path d="M19.9593506,2 C21.0593506,2 22,2.89658203 22,3.99658203 L22,16.0036621 C22,17.1036621 21.0593506,18.0036621 19.9593506,18.0036621 L6.00878906,18.0036621 L2.00878906,22.4 L2.01878906,3.99658203 C2.01878906,2.89658203 2.90878906,2 4.00878906,2 L19.9593506,2 Z M8,8.56896973 L4.5,12 L8,15.6103516 L8,13 L14,13 L14,11 L8,11 L8,8.56896973 Z M20.5688477,7 L17,3.57207031 L17,6 L11,6 L11,8 L17,8 L17,10.5720703 L20.5688477,7 Z"></path></g>
</if>
<!-- Protected Content SVG -->
diff --git a/chromium/chrome/browser/resources/settings/internet_page/BUILD.gn b/chromium/chrome/browser/resources/settings/internet_page/BUILD.gn
index 19d20ec040e..02cd35af1eb 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/internet_page/BUILD.gn
@@ -12,7 +12,6 @@ js_type_check("closure_compile") {
":internet_page",
":internet_page_browser_proxy",
":internet_subpage",
- ":network_listener_behavior",
":network_proxy_section",
":network_summary",
":network_summary_item",
@@ -24,9 +23,9 @@ js_library("internet_page") {
deps = [
":internet_config",
":internet_page_browser_proxy",
- ":network_listener_behavior",
"..:route",
"../settings_page:settings_animated_pages",
+ "//ui/webui/resources/cr_elements/chromeos/network:cr_network_listener_behavior",
"//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
@@ -101,14 +100,6 @@ js_library("internet_subpage") {
extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
}
-js_library("network_listener_behavior") {
- deps = [
- "//ui/webui/resources/js:assert",
- ]
- externs_list = [ "$externs_path/networking_private.js" ]
- extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
-}
-
js_library("network_proxy_section") {
deps = [
"..:route",
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html
index a7c1e4f2f18..5eaadd83c65 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -38,16 +38,16 @@
}
iron-icon {
- -webkit-margin-end: 10px;
+ margin-inline-end: 10px;
}
cr-toggle {
- -webkit-margin-start: var(--settings-control-label-spacing);
+ margin-inline-start: var(--settings-control-label-spacing);
}
cr-policy-network-indicator,
cr-policy-indicator {
- -webkit-margin-start: var(--settings-controlled-by-spacing);
+ margin-inline-start: var(--settings-controlled-by-spacing);
}
.settings-box:first-of-type {
@@ -93,13 +93,16 @@
$i18n{networkButtonActivate}
</paper-button>
<paper-button on-click="onConfigureTap_"
- hidden$="[[!showConfigure_(networkProperties, globalPolicy)]]">
+ hidden$="[[!showConfigure_(networkProperties, globalPolicy,
+ managedNetworkAvailable)]]">
$i18n{networkButtonConfigure}
</paper-button>
<paper-button class="action-button" on-click="onConnectTap_"
- hidden$="[[!showConnect_(networkProperties, globalPolicy)]]"
+ hidden$="[[!showConnect_(networkProperties, globalPolicy,
+ managedNetworkAvailable)]]"
disabled="[[!enableConnect_(networkProperties, defaultNetwork,
- networkPropertiesReceived_, outOfRange_, globalPolicy)]]">
+ networkPropertiesReceived_, outOfRange_, globalPolicy,
+ managedNetworkAvailable)]]">
$i18n{networkButtonConnect}
</paper-button>
<paper-button class="action-button" on-click="onDisconnectTap_"
@@ -110,12 +113,14 @@
<!-- Disabled by policy / Shared messages. -->
<div class="settings-box continuation"
- hidden$="[[!isBlockedByPolicy_(networkProperties, globalPolicy)]]">
+ hidden$="[[!isBlockedByPolicy_(networkProperties, globalPolicy,
+ managedNetworkAvailable)]]">
<iron-icon class="policy" icon="cr20:domain"></iron-icon>
<div>$i18n{networkConnectNotAllowed}</div>
</div>
<div class="settings-box continuation"
- hidden$="[[!showShared_(networkProperties, globalPolicy)]]">
+ hidden$="[[!showShared_(networkProperties, globalPolicy,
+ managedNetworkAvailable)]]">
$i18n{networkShared}
</div>
@@ -132,7 +137,8 @@
<template is="dom-if" if="[[!isSecondaryUser_]]">
<!-- Prefer this network. -->
<template is="dom-if"
- if="[[showPreferNetwork_(networkProperties, globalPolicy)]]">
+ if="[[showPreferNetwork_(networkProperties, globalPolicy,
+ managedNetworkAvailable)]]">
<div class="settings-box">
<div id="preferNetworkToggleLabel"class="start">
$i18n{networkPrefer}
@@ -148,7 +154,8 @@
</template>
<!-- Autoconnect. -->
<template is="dom-if"
- if="[[showAutoConnect_(networkProperties, globalPolicy)]]">
+ if="[[showAutoConnect_(networkProperties, globalPolicy,
+ managedNetworkAvailable)]]">
<div class="settings-box">
<div id="autoConnectToggleLabel" class="start">
$i18n{networkAutoConnect}
@@ -227,8 +234,8 @@
</iron-collapse>
</template>
- <template is="dom-if"
- if="[[hasNetworkSection_(networkProperties, globalPolicy)]]">
+ <template is="dom-if" if="[[hasNetworkSection_(networkProperties,
+ globalPolicy, managedNetworkAvailable)]]">
<!-- Network toggle -->
<div class="settings-box" actionable on-click="toggleNetworkExpanded_">
<div class="start">$i18n{networkSectionNetwork}</div>
@@ -270,8 +277,8 @@
</iron-collapse>
</template>
- <template is="dom-if"
- if="[[hasProxySection_(networkProperties, globalPolicy)]]">
+ <template is="dom-if" if="[[hasProxySection_(networkProperties,
+ globalPolicy, managedNetworkAvailable)]]">
<!-- Proxy toggle -->
<div class="settings-box" actionable on-click="toggleProxyExpanded_">
<div class="start">$i18n{networkSectionProxy}</div>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js
index 0c6b717312d..399bbfd6179 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -90,6 +90,14 @@ Polymer({
value: null,
},
+ /** Whether a managed network is available in the visible network list.
+ * @private {boolean}
+ */
+ managedNetworkAvailable: {
+ type: Boolean,
+ value: false,
+ },
+
/**
* Interface for networkingPrivate calls, passed from internet_page.
* @type {NetworkingPrivate}
@@ -137,7 +145,7 @@ Polymer({
listeners: {
'network-list-changed': 'checkNetworkExists_',
- 'networks-changed': 'updateNetworkDetails_',
+ 'networks-changed': 'updateNetworkDetails_'
},
/** @private {boolean} */
@@ -468,30 +476,36 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean}
* @private
*/
- isBlockedByPolicy_: function(networkProperties, globalPolicy) {
+ isBlockedByPolicy_: function(
+ networkProperties, globalPolicy, managedNetworkAvailable) {
if (networkProperties.Type != CrOnc.Type.WI_FI ||
- this.isPolicySource(networkProperties.Source)) {
+ this.isPolicySource(networkProperties.Source) || !globalPolicy) {
return false;
}
- return !!globalPolicy &&
- (!!globalPolicy.AllowOnlyPolicyNetworksToConnect ||
- (!!networkProperties.WiFi && !!networkProperties.WiFi.HexSSID &&
- !!globalPolicy.BlacklistedHexSSIDs &&
- globalPolicy.BlacklistedHexSSIDs.includes(
- CrOnc.getStateOrActiveString(networkProperties.WiFi.HexSSID))));
+ return !!globalPolicy.AllowOnlyPolicyNetworksToConnect ||
+ (!!globalPolicy.AllowOnlyPolicyNetworksToConnectIfAvailable &&
+ !!managedNetworkAvailable) ||
+ (!!networkProperties.WiFi && !!networkProperties.WiFi.HexSSID &&
+ !!globalPolicy.BlacklistedHexSSIDs &&
+ globalPolicy.BlacklistedHexSSIDs.includes(
+ CrOnc.getStateOrActiveString(networkProperties.WiFi.HexSSID)));
},
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean}
* @private
*/
- showConnect_: function(networkProperties, globalPolicy) {
- if (this.isBlockedByPolicy_(networkProperties, globalPolicy))
+ showConnect_: function(
+ networkProperties, globalPolicy, managedNetworkAvailable) {
+ if (this.isBlockedByPolicy_(
+ networkProperties, globalPolicy, managedNetworkAvailable))
return false;
// TODO(lgcheng@) support connect Arc VPN from UI once Android support API
// to initiate a VPN session.
@@ -549,13 +563,16 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean}
* @private
*/
- showConfigure_: function(networkProperties, globalPolicy) {
+ showConfigure_: function(
+ networkProperties, globalPolicy, managedNetworkAvailable) {
if (this.isSecondaryUser_)
return false;
- if (this.isBlockedByPolicy_(networkProperties, globalPolicy))
+ if (this.isBlockedByPolicy_(
+ networkProperties, globalPolicy, managedNetworkAvailable))
return false;
const type = networkProperties.Type;
if (type == CrOnc.Type.CELLULAR || type == CrOnc.Type.TETHER)
@@ -621,13 +638,15 @@ Polymer({
* @param {boolean} networkPropertiesReceived
* @param {boolean} outOfRange
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean} Whether or not to enable the network connect button.
* @private
*/
enableConnect_: function(
networkProperties, defaultNetwork, networkPropertiesReceived, outOfRange,
- globalPolicy) {
- if (!this.showConnect_(networkProperties, globalPolicy))
+ globalPolicy, managedNetworkAvailable) {
+ if (!this.showConnect_(
+ networkProperties, globalPolicy, managedNetworkAvailable))
return false;
if (!networkPropertiesReceived || outOfRange)
return false;
@@ -880,26 +899,32 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean} True if the shared message should be shown.
* @private
*/
- showShared_: function(networkProperties, globalPolicy) {
+ showShared_: function(
+ networkProperties, globalPolicy, managedNetworkAvailable) {
return (networkProperties.Source == 'Device' ||
networkProperties.Source == 'DevicePolicy') &&
- !this.isBlockedByPolicy_(networkProperties, globalPolicy);
+ !this.isBlockedByPolicy_(
+ networkProperties, globalPolicy, managedNetworkAvailable);
},
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean} True if the AutoConnect checkbox should be shown.
* @private
*/
- showAutoConnect_: function(networkProperties, globalPolicy) {
+ showAutoConnect_: function(
+ networkProperties, globalPolicy, managedNetworkAvailable) {
return networkProperties.Type != CrOnc.Type.ETHERNET &&
this.isRemembered_(networkProperties) &&
!this.isArcVpn_(networkProperties) &&
- !this.isBlockedByPolicy_(networkProperties, globalPolicy);
+ !this.isBlockedByPolicy_(
+ networkProperties, globalPolicy, managedNetworkAvailable);
},
/**
@@ -930,15 +955,18 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean} True if the prefer network checkbox should be shown.
* @private
*/
- showPreferNetwork_: function(networkProperties, globalPolicy) {
+ showPreferNetwork_: function(
+ networkProperties, globalPolicy, managedNetworkAvailable) {
// TODO(stevenjb): Resolve whether or not we want to allow "preferred" for
// networkProperties.Type == CrOnc.Type.ETHERNET.
return this.isRemembered_(networkProperties) &&
!this.isArcVpn_(networkProperties) &&
- !this.isBlockedByPolicy_(networkProperties, globalPolicy);
+ !this.isBlockedByPolicy_(
+ networkProperties, globalPolicy, managedNetworkAvailable);
},
/**
@@ -1109,16 +1137,19 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean}
* @private
*/
- hasNetworkSection_: function(networkProperties, globalPolicy) {
+ hasNetworkSection_: function(
+ networkProperties, globalPolicy, managedNetworkAvailable) {
if (networkProperties.Type == CrOnc.Type.TETHER) {
// These settings apply to the underlying WiFi network, not the Tether
// network.
return false;
}
- if (this.isBlockedByPolicy_(networkProperties, globalPolicy))
+ if (this.isBlockedByPolicy_(
+ networkProperties, globalPolicy, managedNetworkAvailable))
return false;
if (networkProperties.Type == CrOnc.Type.CELLULAR)
return true;
@@ -1128,16 +1159,19 @@ Polymer({
/**
* @param {!CrOnc.NetworkProperties} networkProperties
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean}
* @private
*/
- hasProxySection_: function(networkProperties, globalPolicy) {
+ hasProxySection_: function(
+ networkProperties, globalPolicy, managedNetworkAvailable) {
if (networkProperties.Type == CrOnc.Type.TETHER) {
// Proxy settings apply to the underlying WiFi network, not the Tether
// network.
return false;
}
- if (this.isBlockedByPolicy_(networkProperties, globalPolicy))
+ if (this.isBlockedByPolicy_(
+ networkProperties, globalPolicy, managedNetworkAvailable))
return false;
return this.isRememberedOrConnected_(networkProperties);
},
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html b/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html
index 35babb87473..82af6eeacb9 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html
@@ -10,7 +10,7 @@
<template>
<style include="internet-shared iron-flex">
cr-policy-indicator {
- -webkit-margin-start: var(--settings-controlled-by-spacing);
+ margin-inline-start: var(--settings-controlled-by-spacing);
}
</style>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_page.html b/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
index 41701b4c97a..5544462d263 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_page.html
@@ -1,5 +1,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_listener_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
@@ -17,16 +18,15 @@
<link rel="import" href="internet_detail_page.html">
<link rel="import" href="internet_known_networks_page.html">
<link rel="import" href="internet_subpage.html">
-<link rel="import" href="network_listener_behavior.html">
<link rel="import" href="network_summary.html">
<dom-module id="settings-internet-page">
<template>
<style include="settings-shared">
iron-icon.policy {
- -webkit-margin-end: 12px;
- -webkit-margin-start: 4px;
height: 24px;
+ margin-inline-end: 12px;
+ margin-inline-start: 4px;
width: 24px;
}
</style>
@@ -37,7 +37,8 @@
device-states="{{deviceStates}}"
networking-private="[[networkingPrivate]]">
</network-summary>
- <template is="dom-if" if="[[allowAddConnection_(globalPolicy_)]]">
+ <template is="dom-if" if="[[allowAddConnection_(globalPolicy_,
+ managedNetworkAvailable)]]">
<div actionable class="settings-box two-line"
on-click="onExpandAddConnectionsTap_">
<div class="start layout horizontal center">
@@ -88,7 +89,8 @@
</div>
</template>
</template>
- <template is="dom-if" if="[[!allowAddConnection_(globalPolicy_)]]">
+ <template is="dom-if" if="[[!allowAddConnection_(globalPolicy_,
+ managedNetworkAvailable)]]">
<div class="settings-box">
<iron-icon class="policy" icon="cr20:domain"></iron-icon>
<div>$i18n{internetAddConnectionNotAllowed}</div>
@@ -101,7 +103,8 @@
<settings-internet-detail-page prefs="{{prefs}}"
default-network="[[defaultNetwork]]"
global-policy="[[globalPolicy_]]"
- networking-private="[[networkingPrivate]]">
+ networking-private="[[networkingPrivate]]"
+ managed-network-available="[[managedNetworkAvailable]]">
</settings-internet-detail-page>
</settings-subpage>
</template>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_page.js b/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
index 3f01b7f2ea7..103624689c5 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_page.js
@@ -12,7 +12,7 @@ Polymer({
behaviors: [
I18nBehavior, settings.RouteObserverBehavior, WebUIListenerBehavior,
- NetworkListenerBehavior
+ CrNetworkListenerBehavior
],
properties: {
@@ -39,6 +39,7 @@ Polymer({
deviceStates: {
type: Object,
notify: true,
+ observer: 'onDeviceStatesChanged_',
},
/**
@@ -78,7 +79,19 @@ Polymer({
},
/** @private {!chrome.networkingPrivate.GlobalPolicy|undefined} */
- globalPolicy_: Object,
+ globalPolicy_: {
+ type: Object,
+ value: null,
+ },
+
+ /**
+ * Whether a managed network is available in the visible network list.
+ * @private {boolean}
+ */
+ managedNetworkAvailable: {
+ type: Boolean,
+ value: false,
+ },
/** Overridden from NetworkListenerBehavior. */
networkListChangeSubscriberSelectors_: {
@@ -125,7 +138,7 @@ Polymer({
}
},
- /** @private {!Map<string, string>} */
+ /** @private {!Map<string, Element>} */
focusConfig_: {
type: Object,
value: function() {
@@ -239,18 +252,21 @@ Polymer({
return;
// Focus the subpage arrow where appropriate.
- let selector;
+ let element;
if (route == settings.routes.INTERNET_NETWORKS) {
// iron-list makes the correct timing to focus an item in the list
// very complicated, and the item may not exist, so just focus the
// entire list for now.
- selector = '* /deep/ #networkList';
+ let subPage = this.$$('settings-internet-subpage');
+ if (subPage)
+ element = subPage.$$('#networkList');
} else if (this.detailType_) {
- selector =
- '* /deep/ #' + this.detailType_ + ' /deep/ .subpage-arrow button';
+ element = this.$$('network-summary')
+ .$$(`#${this.detailType_}`)
+ .$$('.subpage-arrow button');
}
- if (selector && this.querySelector(selector))
- this.focusConfig_.set(oldRoute.path, selector);
+ if (element)
+ this.focusConfig_.set(oldRoute.path, element);
else
this.focusConfig_.delete(oldRoute.path);
},
@@ -274,10 +290,14 @@ Polymer({
*/
onShowConfig_: function(event) {
const properties = event.detail;
- let configAndConnect = !properties.GUID; // New configuration
- this.showConfig_(
- configAndConnect, properties.Type, properties.GUID,
- CrOnc.getNetworkName(properties));
+ if (!properties.GUID) {
+ // New configuration
+ this.showConfig_(true /* configAndConnect */, properties.Type);
+ } else {
+ this.showConfig_(
+ false /* configAndConnect */, properties.Type, properties.GUID,
+ CrOnc.getNetworkName(properties));
+ }
},
/**
@@ -354,6 +374,21 @@ Polymer({
},
/**
+ * @param {!CrOnc.DeviceStateProperties|undefined} newValue
+ * @param {!CrOnc.DeviceStateProperties|undefined} oldValue
+ * @private
+ */
+ onDeviceStatesChanged_: function(newValue, oldValue) {
+ let wifiDeviceState = this.getDeviceState_(CrOnc.Type.WI_FI, newValue);
+ let managedNetworkAvailable = false;
+ if (!!wifiDeviceState)
+ managedNetworkAvailable = !!wifiDeviceState.ManagedNetworkAvailable;
+
+ if (this.managedNetworkAvailable != managedNetworkAvailable)
+ this.managedNetworkAvailable = managedNetworkAvailable;
+ },
+
+ /**
* @param {!{detail: {type: string}}} event
* @private
*/
@@ -517,10 +552,16 @@ Polymer({
/**
* @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
+ * @param {boolean} managedNetworkAvailable
* @return {boolean}
*/
- allowAddConnection_: function(globalPolicy) {
- return !globalPolicy.AllowOnlyPolicyNetworksToConnect;
+ allowAddConnection_: function(globalPolicy, managedNetworkAvailable) {
+ if (!globalPolicy)
+ return true;
+
+ return !globalPolicy.AllowOnlyPolicyNetworksToConnect &&
+ (!globalPolicy.AllowOnlyPolicyNetworksToConnectIfAvailable ||
+ !managedNetworkAvailable);
},
/**
@@ -528,7 +569,8 @@ Polymer({
* @return {string}
*/
getAddThirdPartyVpnLabel_: function(provider) {
- return this.i18n('internetAddThirdPartyVPN', provider.ProviderName);
+ return this.i18n(
+ 'internetAddThirdPartyVPN', provider.ProviderName || '');
},
/**
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html b/chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html
index 39d86fdfa70..a3b39fb5c99 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_shared_css.html
@@ -6,15 +6,15 @@
<template>
<style include="settings-shared">
cr-network-icon {
- -webkit-padding-end: var(--settings-box-row-padding);
+ padding-inline-end: var(--settings-box-row-padding);
}
iron-icon.policy {
- -webkit-margin-end: var(--cr-controlled-by-spacing);
+ margin-inline-end: var(--cr-controlled-by-spacing);
}
.indented {
- -webkit-margin-start: var(--settings-box-row-padding);
+ margin-inline-start: var(--settings-box-row-padding);
}
.stretch {
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html
index 2889a2e4f56..40ef55b8d7b 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.html
@@ -20,13 +20,13 @@
separator lines can fill the entire width of the page. */
#networkListDiv > * {
/* cr-network-list is padded to the right to allow space for a ripple */
- -webkit-padding-end: calc(var(--settings-box-row-padding) -
+ padding-inline-end: calc(var(--settings-box-row-padding) -
var(--cr-icon-ripple-padding));
- -webkit-padding-start: var(--settings-box-row-padding);
+ padding-inline-start: var(--settings-box-row-padding);
}
#addButton {
- -webkit-margin-end: var(--settings-control-label-spacing);
+ margin-inline-end: var(--settings-control-label-spacing);
}
#onOff {
@@ -38,9 +38,9 @@
}
.vpn-header {
- -webkit-margin-end: 12px;
- -webkit-margin-start: 4px;
margin-bottom: 8px;
+ margin-inline-end: 12px;
+ margin-inline-start: 4px;
margin-top: 8px;
}
@@ -71,8 +71,8 @@
#gmscore-notifications-instructions {
@apply --cr-secondary-text;
- -webkit-padding-start: 15px;
margin: 0;
+ padding-inline-start: 15px;
}
</style>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js
index 7f61083c696..003c91a13f6 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/internet_subpage.js
@@ -363,7 +363,8 @@ Polymer({
* @private
*/
getAddThirdPartyVpnA11yString_: function(vpnState) {
- return this.i18n('internetAddThirdPartyVPN', vpnState.ProviderName);
+ return this.i18n(
+ 'internetAddThirdPartyVPN', vpnState.ProviderName || '');
},
/**
@@ -509,7 +510,7 @@ Polymer({
assert(this.defaultNetwork !== undefined);
const state = e.detail;
e.target.blur();
- if (this.canConnect_(state, this.defaultNetwork, this.globalPolicy)) {
+ if (this.canConnect_(state)) {
this.fire('network-connect', {networkProperties: state});
return;
}
@@ -518,35 +519,35 @@ Polymer({
/**
* @param {!CrOnc.NetworkStateProperties} state The network state.
- * @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @private
*/
- isBlockedByPolicy_: function(state, globalPolicy) {
- if (state.Type != CrOnc.Type.WI_FI || this.isPolicySource(state.Source)) {
+ isBlockedByPolicy_: function(state) {
+ if (state.Type != CrOnc.Type.WI_FI || this.isPolicySource(state.Source) ||
+ !this.globalPolicy) {
return false;
}
- return !!globalPolicy &&
- (!!globalPolicy.AllowOnlyPolicyNetworksToConnect ||
- (!!state.WiFi && !!state.WiFi.HexSSID &&
- !!globalPolicy.BlacklistedHexSSIDs &&
- globalPolicy.BlacklistedHexSSIDs.includes(state.WiFi.HexSSID)));
+ return !!this.globalPolicy.AllowOnlyPolicyNetworksToConnect ||
+ (!!this.globalPolicy.AllowOnlyPolicyNetworksToConnectIfAvailable &&
+ !!this.deviceState && !!this.deviceState.ManagedNetworkAvailable) ||
+ (!!state.WiFi && !!state.WiFi.HexSSID &&
+ !!this.globalPolicy.BlacklistedHexSSIDs &&
+ this.globalPolicy.BlacklistedHexSSIDs.includes(state.WiFi.HexSSID));
},
/**
* Determines whether or not a network state can be connected to.
* @param {!CrOnc.NetworkStateProperties} state The network state.
- * @param {?CrOnc.NetworkStateProperties} defaultNetwork
- * @param {!chrome.networkingPrivate.GlobalPolicy} globalPolicy
* @private
*/
- canConnect_: function(state, defaultNetwork, globalPolicy) {
+ canConnect_: function(state) {
if (state.ConnectionState != CrOnc.ConnectionState.NOT_CONNECTED)
return false;
- if (this.isBlockedByPolicy_(state, globalPolicy))
+ if (this.isBlockedByPolicy_(state))
return false;
if (state.Type == CrOnc.Type.VPN &&
- (!defaultNetwork ||
- defaultNetwork.ConnectionState != CrOnc.ConnectionState.CONNECTED)) {
+ (!this.defaultNetwork ||
+ this.defaultNetwork.ConnectionState !=
+ CrOnc.ConnectionState.CONNECTED)) {
return false;
}
return true;
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_listener_behavior.html b/chromium/chrome/browser/resources/settings/internet_page/network_listener_behavior.html
deleted file mode 100644
index f564a7461d6..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_listener_behavior.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src="network_listener_behavior.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_listener_behavior.js b/chromium/chrome/browser/resources/settings/internet_page/network_listener_behavior.js
deleted file mode 100644
index 665cc54069c..00000000000
--- a/chromium/chrome/browser/resources/settings/internet_page/network_listener_behavior.js
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2018 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 behavior for alerting specified child elements of
- * changes to the devices network data.
- */
-
-/** @polymerBehavior */
-const NetworkListenerBehavior = {
- properties: {
- /**
- * Array of selectors specifying all children to alert of changes to the
- * network list.
- * @private {!Array<string>}
- */
- networkListChangeSubscriberSelectors_: Array,
-
- /**
- * Array of selectors specifying all children to alert of important changes
- * to the specific networks.
- * @private {!Array<string>}
- */
- networksChangeSubscriberSelectors_: Array,
-
- /** @type {!NetworkingPrivate} */
- networkingPrivate: Object,
- },
-
- /** @private {?function(!Array<string>)} */
- networkListChangedListener_: null,
-
- /** @private {?function(!Array<string>)} */
- networksChangedListener_: null,
-
- /** @override */
- attached: function() {
- this.networkListChangedListener_ = this.networkListChangedListener_ ||
- this.onNetworkListChanged_.bind(this);
- this.networkingPrivate.onNetworkListChanged.addListener(
- this.networkListChangedListener_);
-
- this.networksChangedListener_ =
- this.networksChangedListener_ || this.onNetworksChanged_.bind(this);
- this.networkingPrivate.onNetworksChanged.addListener(
- this.networksChangedListener_);
- },
-
- /** @override */
- detached: function() {
- this.networkingPrivate.onNetworkListChanged.removeListener(
- assert(this.networkListChangedListener_));
- this.networkingPrivate.onNetworksChanged.removeListener(
- assert(this.networksChangedListener_));
- },
-
- /**
- * This event is triggered when the list of networks changes.
- * |networkIds| contains the ids for all visible or configured networks.
- * networkingPrivate.onNetworkListChanged event callback.
- * @param {!Array<string>} networkIds
- * @private
- */
- onNetworkListChanged_: function(networkIds) {
- const event = new CustomEvent('network-list-changed', {detail: networkIds});
- this.networkListChangeSubscriberSelectors_.forEach(
- selector => this.maybeDispatchEvent_(selector, event));
- },
-
- /**
- * This event is triggered when interesting properties of a network change.
- * |networkIds| contains the ids for networks whose properties have changed.
- * networkingPrivate.onNetworksChanged event callback.
- * @param {!Array<string>} networkIds
- * @private
- */
- onNetworksChanged_: function(networkIds) {
- const event = new CustomEvent('networks-changed', {detail: networkIds});
- this.networksChangeSubscriberSelectors_.forEach(
- selector => this.maybeDispatchEvent_(selector, event));
- },
-
- /**
- * @param {!Event} event
- * @private
- */
- maybeDispatchEvent_: function(selectors, event) {
- const element = this.$$(selectors);
- if (!element)
- return;
- element.dispatchEvent(event);
- },
-};
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html
index 146da4c1ceb..9d718a9df80 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_proxy_section.html
@@ -22,11 +22,11 @@
<template>
<style include="internet-shared cr-hidden-style iron-flex iron-flex-alignment">
cr-policy-network-indicator {
- -webkit-margin-end: 10px;
+ margin-inline-end: 10px;
}
extension-controlled-indicator {
- -webkit-margin-start: 0;
+ margin-inline-start: 0;
width: 100%;
}
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html
index 930197efe7d..7edbb1cd5f2 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.html
@@ -15,7 +15,12 @@
<template>
<style include="internet-shared iron-flex">
network-siminfo {
- -webkit-padding-start: var(--settings-box-row-padding);
+ padding-inline-start: var(--settings-box-row-padding);
+ }
+
+ #outerBox {
+ padding: 0 var(--settings-box-row-padding);
+ @apply(--network-summary-item-outer-box);
}
#details {
@@ -24,9 +29,10 @@
flex: auto;
}
- #networkName {
+ #networkTitleText {
color: #333;
font-weight: 500;
+ @apply(--network-summary-item-title);
}
#networkState {
@@ -35,7 +41,7 @@
font-weight: 400;
}
</style>
- <div class="settings-box two-line">
+ <div id="outerBox" class="settings-box two-line">
<div actionable class="flex layout horizontal center"
on-click="onShowDetailsTap_">
<div id="details" no-flex$="[[showSimInfo_(deviceState)]]">
@@ -43,7 +49,9 @@
device-state="[[deviceState]]">
</cr-network-icon>
<div class="flex">
- <div id="networkName">[[getNetworkName_(activeNetworkState)]]</div>
+ <div id="networkTitleText">
+ [[getTitleText_(activeNetworkState)]]
+ </div>
<div id="networkState">
[[getNetworkStateText_(activeNetworkState, deviceState)]]
</div>
diff --git a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js
index ab3be60ec47..b4a8f8892ea 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js
+++ b/chromium/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -51,14 +51,14 @@ Polymer({
* @type {!NetworkingPrivate}
*/
networkingPrivate: Object,
- },
- /**
- * @return {string}
- * @private
- */
- getNetworkName_: function() {
- return CrOncStrings['OncType' + this.activeNetworkState.Type];
+ /**
+ * Title line describing the network type to appear in the row's top line.
+ * If it is undefined, the title text is a default from CrOncStrings (see
+ * this.getTitleText_() below).
+ * @type {string|undefined}
+ */
+ networkTitleText: String,
},
/**
@@ -335,6 +335,15 @@ Polymer({
},
/**
+ * @return {string}
+ * @private
+ */
+ getTitleText_: function() {
+ return this.networkTitleText ||
+ CrOncStrings['OncType' + this.activeNetworkState.Type];
+ },
+
+ /**
* Make sure events in embedded components do not propagate to onDetailsTap_.
* @param {!Event} event
* @private
diff --git a/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html b/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
index 9c0daa34a25..62c848ce669 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.html
@@ -16,7 +16,7 @@
<style include="settings-shared">
cr-dialog {
--cr-dialog-body: {
- -webkit-padding-end: 0;
+ padding-inline-end: 0;
display: flex;
flex-direction: column;
height: 350px;
@@ -25,7 +25,7 @@
}
settings-subpage-search {
- -webkit-padding-end: 24px;
+ padding-inline-end: 24px;
}
iron-list {
@@ -34,7 +34,7 @@
.ripple-padding {
/* Create a little extra space for checkbox ink ripple to flow into. */
- -webkit-padding-start: 20px;
+ padding-inline-start: 20px;
}
cr-checkbox {
diff --git a/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js b/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js
index 4e38bc5f976..77c6b94a521 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/add_languages_dialog.js
@@ -48,16 +48,23 @@ Polymer({
/** @override */
attached: function() {
this.$.dialog.showModal();
+ this.becomeActiveFindShortcutListener();
},
- // Override settings.FindShortcutBehavior methods.
- canHandleFindShortcut: function() {
- return true;
+ /** @override */
+ detached: function() {
+ this.removeSelfAsFindShortcutListener();
},
- handleFindShortcut: function() {
- this.$.search.getSearchInput().scrollIntoViewIfNeeded();
- this.$.search.getSearchInput().focus();
+ // Override settings.FindShortcutBehavior methods.
+ handleFindShortcut: function(modalContextOpen) {
+ // Assumes this is the only open modal.
+ const searchInput = this.$.search.getSearchInput();
+ if (searchInput != this.$.search.shadowRoot.activeElement) {
+ searchInput.scrollIntoViewIfNeeded();
+ searchInput.focus();
+ }
+ return true;
},
/**
diff --git a/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html b/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
index d8957326506..cef2743fea8 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/edit_dictionary_page.html
@@ -37,7 +37,8 @@
invalid="[[isWordInvalid_(newWordValue_)]]"
error-message="[[isWordInvalid_(newWordValue_,
'$i18nPolymer{addDictionaryWordDuplicateError}',
- '$i18nPolymer{addDictionaryWordLengthError}')]]">
+ '$i18nPolymer{addDictionaryWordLengthError}')]]"
+ spellcheck="false">
<paper-button class="secondary-button" on-click="onAddWordTap_"
disabled="[[disableAddButton_(newWordValue_)]]" id="addWord"
slot="suffix">
diff --git a/chromium/chrome/browser/resources/settings/languages_page/languages.js b/chromium/chrome/browser/resources/settings/languages_page/languages.js
index 6acc1a9601f..6c81d0d59f5 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages.js
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages.js
@@ -174,6 +174,12 @@ Polymer({
// <if expr="chromeos">
/** @private {?InputMethodPrivate} */
inputMethodPrivate_: null,
+
+ /** @private {?Function} */
+ boundOnInputMethodAdded_: null,
+
+ /** @private {?Function} */
+ boundOnInputMethodRemoved_: null,
// </if>
/** @override */
@@ -251,6 +257,12 @@ Polymer({
this.boundOnInputMethodChanged_ = this.onInputMethodChanged_.bind(this);
this.inputMethodPrivate_.onChanged.addListener(
assert(this.boundOnInputMethodChanged_));
+ this.boundOnInputMethodAdded_ = this.onInputMethodAdded_.bind(this);
+ this.languageSettingsPrivate_.onInputMethodAdded.addListener(
+ this.boundOnInputMethodAdded_);
+ this.boundOnInputMethodRemoved_ = this.onInputMethodRemoved_.bind(this);
+ this.languageSettingsPrivate_.onInputMethodRemoved.addListener(
+ this.boundOnInputMethodRemoved_);
}
},
@@ -260,6 +272,12 @@ Polymer({
this.inputMethodPrivate_.onChanged.removeListener(
assert(this.boundOnInputMethodChanged_));
this.boundOnInputMethodChanged_ = null;
+ this.languageSettingsPrivate_.onInputMethodAdded.removeListener(
+ assert(this.boundOnInputMethodAdded_));
+ this.boundOnInputMethodAdded_ = null;
+ this.languageSettingsPrivate_.onInputMethodRemoved.removeListener(
+ assert(this.boundOnInputMethodRemoved_));
+ this.boundOnInputMethodRemoved_ = null;
}
// <if expr="not is_macosx">
@@ -414,25 +432,7 @@ Polymer({
}
if (supportedInputMethods) {
- // Populate the hash map of supported input methods.
- for (let j = 0; j < supportedInputMethods.length; j++) {
- const inputMethod = supportedInputMethods[j];
- inputMethod.enabled = !!inputMethod.enabled;
- inputMethod.isProhibitedByPolicy = !!inputMethod.isProhibitedByPolicy;
- // Add the input method to the map of IDs.
- this.supportedInputMethodMap_.set(inputMethod.id, inputMethod);
- // Add the input method to the list of input methods for each language
- // it supports.
- for (let k = 0; k < inputMethod.languageCodes.length; k++) {
- const languageCode = inputMethod.languageCodes[k];
- if (!this.supportedLanguageMap_.has(languageCode))
- continue;
- if (!this.languageInputMethods_.has(languageCode))
- this.languageInputMethods_.set(languageCode, [inputMethod]);
- else
- this.languageInputMethods_.get(languageCode).push(inputMethod);
- }
- }
+ this.createInputMethodModel_(supportedInputMethods);
}
let prospectiveUILanguage;
@@ -475,6 +475,37 @@ Polymer({
},
/**
+ * Constructs the input method part of the languages model.
+ * @param {!Array<!chrome.languageSettingsPrivate.InputMethod>}
+ * supportedInputMethods Input methods.
+ * @private
+ */
+ createInputMethodModel_: function(supportedInputMethods) {
+ assert(cr.isChromeOS);
+ // Populate the hash map of supported input methods.
+ this.supportedInputMethodMap_.clear();
+ this.languageInputMethods_.clear();
+ for (let j = 0; j < supportedInputMethods.length; j++) {
+ const inputMethod = supportedInputMethods[j];
+ inputMethod.enabled = !!inputMethod.enabled;
+ inputMethod.isProhibitedByPolicy = !!inputMethod.isProhibitedByPolicy;
+ // Add the input method to the map of IDs.
+ this.supportedInputMethodMap_.set(inputMethod.id, inputMethod);
+ // Add the input method to the list of input methods for each language
+ // it supports.
+ for (let k = 0; k < inputMethod.languageCodes.length; k++) {
+ const languageCode = inputMethod.languageCodes[k];
+ if (!this.supportedLanguageMap_.has(languageCode))
+ continue;
+ if (!this.languageInputMethods_.has(languageCode))
+ this.languageInputMethods_.set(languageCode, [inputMethod]);
+ else
+ this.languageInputMethods_.get(languageCode).push(inputMethod);
+ }
+ }
+ },
+
+ /**
* Returns a list of LanguageStates for each enabled language in the supported
* languages list.
* @param {string} translateTarget Language code of the default translate
@@ -589,6 +620,23 @@ Polymer({
},
/** @private */
+ updateSupportedInputMethods_: function() {
+ assert(cr.isChromeOS);
+ const promise = new Promise(resolve => {
+ this.languageSettingsPrivate_.getInputMethodLists(function(lists) {
+ resolve(
+ lists.componentExtensionImes.concat(lists.thirdPartyExtensionImes));
+ });
+ });
+ promise.then(result => {
+ const supportedInputMethods = result;
+ this.createInputMethodModel_(supportedInputMethods);
+ this.set('languages.inputMethods.supported', supportedInputMethods);
+ this.updateEnabledInputMethods_();
+ });
+ },
+
+ /** @private */
updateEnabledInputMethods_: function() {
assert(cr.isChromeOS);
const enabledInputMethods = this.getEnabledInputMethods_();
@@ -932,12 +980,12 @@ Polymer({
/** @param {string} id Added input method ID. */
onInputMethodAdded_: function(id) {
- this.updateEnabledInputMethods_();
+ this.updateSupportedInputMethods_();
},
/** @param {string} id Removed input method ID. */
onInputMethodRemoved_: function(id) {
- this.updateEnabledInputMethods_();
+ this.updateSupportedInputMethods_();
},
// </if>
});
diff --git a/chromium/chrome/browser/resources/settings/languages_page/languages_page.html b/chromium/chrome/browser/resources/settings/languages_page/languages_page.html
index 75a6eb93028..a979b391e55 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chromium/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -67,13 +67,13 @@
cr-checkbox.dropdown-item {
--cr-action-menu-disabled-item-opacity: 0.38;
- -webkit-margin-start: 0;
+ margin-inline-start: 0;
}
.icon-external {
/* The negative margin messes up the outline border. These are in an
indented list so this looks fine until moved: crbug.com/708286. */
- -webkit-margin-end: 0;
+ margin-inline-end: 0;
}
#uiLanguageItem:focus,
@@ -102,7 +102,7 @@
iron-icon[icon='cr:error'] {
@apply --cr-icon-height-width;
--iron-icon-fill-color: var(--google-red-700);
- -webkit-margin-end: 8px;
+ margin-inline-end: 8px;
}
.name-with-error-list[disabled] {
@@ -110,7 +110,7 @@
}
iron-icon.policy {
- -webkit-margin-start: 10px;
+ margin-inline-start: 10px;
}
</style>
<settings-languages languages="{{languages}}" prefs="{{prefs}}"
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/BUILD.gn b/chromium/chrome/browser/resources/settings/multidevice_page/BUILD.gn
index ed7d9c960e0..46e84a108f6 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/BUILD.gn
@@ -8,15 +8,19 @@ js_type_check("closure_compile") {
deps = [
":multidevice_browser_proxy",
":multidevice_constants",
+ ":multidevice_feature_behavior",
":multidevice_feature_item",
+ ":multidevice_feature_toggle",
":multidevice_page",
":multidevice_page_container",
":multidevice_subpage",
+ ":multidevice_tether_item",
]
}
js_library("multidevice_browser_proxy") {
deps = [
+ ":multidevice_constants",
"//ui/webui/resources/js:cr",
]
}
@@ -27,26 +31,45 @@ js_library("multidevice_constants") {
]
}
+js_library("multidevice_feature_behavior") {
+ deps = [
+ ":multidevice_constants",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+}
+
js_library("multidevice_feature_item") {
deps = [
+ ":multidevice_constants",
+ ":multidevice_feature_behavior",
"..:route",
"//ui/webui/resources/js:cr",
]
}
+js_library("multidevice_feature_toggle") {
+ deps = [
+ ":multidevice_constants",
+ ":multidevice_feature_behavior",
+ ]
+}
+
js_library("multidevice_page") {
deps = [
":multidevice_browser_proxy",
":multidevice_constants",
+ ":multidevice_feature_behavior",
+ "../controls:password_prompt_dialog",
"//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
]
}
js_library("multidevice_page_container") {
deps = [
+ ":multidevice_browser_proxy",
":multidevice_constants",
- ":multidevice_page",
+ ":multidevice_feature_behavior",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
@@ -54,7 +77,19 @@ js_library("multidevice_page_container") {
js_library("multidevice_subpage") {
deps = [
+ ":multidevice_constants",
+ ":multidevice_feature_behavior",
"..:route",
- "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/cr_elements/chromeos/network:cr_network_listener_behavior",
+ ]
+ externs_list = [ "$externs_path/networking_private.js" ]
+ extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
+}
+
+js_library("multidevice_tether_item") {
+ deps = [
+ "//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
]
+ externs_list = [ "$externs_path/networking_private.js" ]
+ extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
}
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_browser_proxy.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_browser_proxy.js
index 594d6de3e80..bdc01201447 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_browser_proxy.js
@@ -7,8 +7,29 @@ cr.define('settings', function() {
class MultiDeviceBrowserProxy {
showMultiDeviceSetupDialog() {}
- /** @return Promise<!MultiDevicePageContentData> */
+ /** @return {!Promise<!MultiDevicePageContentData>} */
getPageContentData() {}
+
+ /**
+ * @param {!settings.MultiDeviceFeature} feature The feature whose state
+ * should be set.
+ * @param {boolean} enabled Whether the feature should be turned off or on.
+ * @param {string=} opt_authToken Proof that the user is authenticated.
+ * Needed to enable Smart Lock, and Better Together Suite if the Smart
+ * Lock user pref is enabled.
+ * @return {!Promise<boolean>} Whether the operation was successful.
+ */
+ setFeatureEnabledState(feature, enabled, opt_authToken) {}
+
+ removeHostDevice() {}
+
+ retryPendingHostSetup() {}
+
+ /**
+ * Called when the "Set Up" button is clicked to open the Android Messages
+ * PWA.
+ */
+ setUpAndroidSms() {}
}
/**
@@ -22,15 +43,28 @@ cr.define('settings', function() {
/** @override */
getPageContentData() {
- // TODO(jordynass): change method content to
- // return cr.sendWithPromise('getPageContentData');
- // once handler is built.
- return Promise.resolve({
- mode: settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED,
- hostDevice: {
- name: 'Pixel XL',
- },
- });
+ return cr.sendWithPromise('getPageContentData');
+ }
+
+ /** @override */
+ setFeatureEnabledState(feature, enabled, opt_authToken) {
+ return cr.sendWithPromise(
+ 'setFeatureEnabledState', feature, enabled, opt_authToken);
+ }
+
+ /** @override */
+ removeHostDevice() {
+ chrome.send('removeHostDevice');
+ }
+
+ /** @override */
+ retryPendingHostSetup() {
+ chrome.send('retryPendingHostSetup');
+ }
+
+ /** @override */
+ setUpAndroidSms() {
+ chrome.send('setUpAndroidSms');
}
}
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js
index 585611f3ab4..b254dd07c2f 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js
@@ -19,70 +19,62 @@ cr.define('settings', function() {
};
/**
- * MultiDevice software features. Note that this is copied from (and must
- * include an analog of all values in) the enum of the same name in
- * //components/cryptauth/proto/cryptauth_api.proto.
+ * Enum of MultiDevice features. Note that this is copied from (and must
+ * include an analog of all values in) the Feature enum in
+ * //chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.
* @enum {number}
*/
- MultiDeviceSoftwareFeature = {
- UNKNOWN_FEATURE: 0,
- BETTER_TOGETHER_HOST: 1,
- BETTER_TOGETHER_CLIENT: 2,
- EASY_UNLOCK_HOST: 3,
- EASY_UNLOCK_CLIENT: 4,
- MAGIC_TETHER_HOST: 5,
- MAGIC_TETHER_CLIENT: 6,
- SMS_CONNECT_HOST: 7,
- SMS_CONNECT_CLIENT: 8,
+ MultiDeviceFeature = {
+ BETTER_TOGETHER_SUITE: 0,
+ INSTANT_TETHERING: 1,
+ MESSAGES: 2,
+ SMART_LOCK: 3,
};
/**
- * Possible states of MultiDevice software features. Note that this is based
- * on (and must include an analog of all values in) the enum of the same name
- * in //components/cryptauth/software_feature_state.h.
+ * Possible states of MultiDevice features. Note that this is copied from (and
+ * must include an analog of all values in) the FeatureState enum in
+ * //chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.
* @enum {number}
*/
- MultiDeviceSoftwareFeatureState = {
- NOT_SUPPORTED: 0,
- SUPPORTED: 1,
- ENABLED: 2,
+ MultiDeviceFeatureState = {
+ PROHIBITED_BY_POLICY: 0,
+ DISABLED_BY_USER: 1,
+ ENABLED_BY_USER: 2,
+ NOT_SUPPORTED_BY_CHROMEBOOK: 3,
+ NOT_SUPPORTED_BY_PHONE: 4,
+ UNAVAILABLE_NO_VERIFIED_HOST: 5,
+ UNAVAILABLE_INSUFFICIENT_SECURITY: 6,
+ UNAVAILABLE_SUITE_DISABLED: 7,
};
return {
MultiDeviceSettingsMode: MultiDeviceSettingsMode,
- MultiDeviceSoftwareFeature: MultiDeviceSoftwareFeature,
- MultiDeviceSoftwareFeatureState: MultiDeviceSoftwareFeatureState,
+ MultiDeviceFeature: MultiDeviceFeature,
+ MultiDeviceFeatureState: MultiDeviceFeatureState,
};
});
/**
- * Represents a multidevice host, i.e. a phone set by the user to connect to
- * their Chromebook(s). The type is a subset of the RemoteDevice structure
- * defined by CryptAuth (components/cryptauth/remote_device.h). It contains the
- * host device's name (e.g. Pixel, Nexus 5) and the map softwareFeatures
- * sending each MultiDevice feature to the host device's state with regards to
- * that feature.
- *
- * @typedef {{
- * name: string,
- * softwareFeatures:
- * !Object<settings.MultiDeviceSoftwareFeature,
- * settings.MultiDeviceSoftwareFeatureState>
- * }}
- */
-let RemoteDevice;
-
-/**
* Container for the initial data that the page requires in order to display
* the correct content. It is also used for receiving status updates during
- * use. Note that the host may be verified (enabled or disabled), awaiting
- * verification, or it may have failed setup because it was not able to connect
- * to the server. If the property is null or undefined, then no host has been
- * set up, although there may be potential hosts on the account.
+ * use. Note that the host device may be verified (enabled or disabled),
+ * awaiting verification, or it may have failed setup because it was not able
+ * to connect to the server.
+ *
+ * For each MultiDevice feature (including the "suite" feature, which acts as a
+ * gatekeeper for the others), the corresponding *State property is an enum
+ * containing the data necessary to display it. Note that hostDeviceName should
+ * be undefined if and only if no host has been set up, regardless of whether
+ * there are potential hosts on the account.
*
* @typedef {{
* mode: !settings.MultiDeviceSettingsMode,
- * hostDevice: (?RemoteDevice|undefined)
+ * hostDeviceName: (string|undefined),
+ * betterTogetherState: !settings.MultiDeviceFeatureState,
+ * instantTetheringState: !settings.MultiDeviceFeatureState,
+ * messagesState: !settings.MultiDeviceFeatureState,
+ * smartLockState: !settings.MultiDeviceFeatureState,
* }}
*/
let MultiDevicePageContentData;
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_behavior.html b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_behavior.html
new file mode 100644
index 00000000000..709413725c9
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_behavior.html
@@ -0,0 +1,4 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="multidevice_constants.html">
+<script src="multidevice_feature_behavior.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_behavior.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_behavior.js
new file mode 100644
index 00000000000..4179e9c94c7
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_behavior.js
@@ -0,0 +1,181 @@
+// Copyright 2018 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 behavior for dealing with MultiDevice features. It is
+ * intended to facilitate passing data between elements in the MultiDevice page
+ * cleanly and concisely. It includes some constants and utility methods.
+ */
+cr.exportPath('settings');
+
+/** @polymerBehavior */
+const MultiDeviceFeatureBehaviorImpl = {
+ properties: {
+ /** @type {MultiDevicePageContentData} */
+ pageContentData: Object,
+
+ /**
+ * Enum defined in multidevice_constants.js.
+ * @type {Object<string, number>}
+ */
+ MultiDeviceFeature: {
+ type: Object,
+ value: settings.MultiDeviceFeature,
+ },
+ },
+
+ /**
+ * Whether the gatekeeper pref for the whole Better Together feature suite is
+ * on.
+ * @return {boolean}
+ */
+ isSuiteOn: function() {
+ return this.pageContentData.betterTogetherState ===
+ settings.MultiDeviceFeatureState.ENABLED_BY_USER;
+ },
+
+ /**
+ * Whether the gatekeeper pref for the whole Better Together feature suite is
+ * allowed by policy.
+ * @return {boolean}
+ */
+ isSuiteAllowedByPolicy: function() {
+ return this.pageContentData.betterTogetherState !==
+ settings.MultiDeviceFeatureState.PROHIBITED_BY_POLICY;
+ },
+
+ /**
+ * Whether an individual feature is allowed by policy.
+ * @param {!settings.MultiDeviceFeature} feature
+ * @return {boolean}
+ */
+ isFeatureAllowedByPolicy: function(feature) {
+ return this.getFeatureState(feature) !==
+ settings.MultiDeviceFeatureState.PROHIBITED_BY_POLICY;
+ },
+
+ /**
+ * @param {!settings.MultiDeviceFeature} feature
+ * @return {boolean}
+ */
+ isFeatureSupported: function(feature) {
+ return ![settings.MultiDeviceFeatureState.NOT_SUPPORTED_BY_CHROMEBOOK,
+ settings.MultiDeviceFeatureState.NOT_SUPPORTED_BY_PHONE,
+ ].includes(this.getFeatureState(feature));
+ },
+
+ /**
+ * Whether the user is prevented from attempted to change a given feature. In
+ * the UI this corresponds to a disabled toggle.
+ * @param {!settings.MultiDeviceFeature} feature
+ * @return {boolean}
+ */
+ isFeatureStateEditable: function(feature) {
+ // The suite is off and the toggle corresponds to an individual feature
+ // (as opposed to the full suite).
+ if (feature !== settings.MultiDeviceFeature.BETTER_TOGETHER_SUITE &&
+ !this.isSuiteOn()) {
+ return false;
+ }
+
+ return [
+ settings.MultiDeviceFeatureState.DISABLED_BY_USER,
+ settings.MultiDeviceFeatureState.ENABLED_BY_USER
+ ].includes(this.getFeatureState(feature));
+ },
+
+ /**
+ * The localized string representing the name of the feature.
+ * @param {!settings.MultiDeviceFeature} feature
+ * @return {string}
+ */
+ getFeatureName: function(feature) {
+ switch (feature) {
+ case settings.MultiDeviceFeature.INSTANT_TETHERING:
+ return this.i18n('multideviceInstantTetheringItemTitle');
+ case settings.MultiDeviceFeature.MESSAGES:
+ return this.i18n('multideviceAndroidMessagesItemTitle');
+ case settings.MultiDeviceFeature.SMART_LOCK:
+ return this.i18n('multideviceSmartLockItemTitle');
+ default:
+ return '';
+ }
+ },
+
+ /**
+ * The full icon name used provided by the containing iron-iconset-svg
+ * (i.e. [iron-iconset-svg name]:[SVG <g> tag id]) for a given feature.
+ * @param {!settings.MultiDeviceFeature} feature
+ * @return {string}
+ */
+ getIconName: function(feature) {
+ switch (feature) {
+ case settings.MultiDeviceFeature.BETTER_TOGETHER_SUITE:
+ return 'settings:multidevice-better-together-suite';
+ case settings.MultiDeviceFeature.MESSAGES:
+ return 'settings:multidevice-messages';
+ case settings.MultiDeviceFeature.SMART_LOCK:
+ return 'settings:multidevice-smart-lock';
+ default:
+ return '';
+ }
+ },
+
+ /**
+ * The localized string providing a description or useful status information
+ * concerning a given feature.
+ * @param {!settings.MultiDeviceFeature} feature
+ * @return {string}
+ */
+ getFeatureSummaryHtml: function(feature) {
+ switch (feature) {
+ case settings.MultiDeviceFeature.SMART_LOCK:
+ return this.i18nAdvanced('multideviceSmartLockItemSummary');
+ case settings.MultiDeviceFeature.MESSAGES:
+ return this.i18nAdvanced('multideviceAndroidMessagesItemSummary');
+ default:
+ return '';
+ }
+ },
+
+ /**
+ * Extracts the MultiDeviceFeatureState enum value describing the given
+ * feature from this.pageContentData. Returns null if the feature is not
+ * an accepted value (e.g. testing fake).
+ * @param {!settings.MultiDeviceFeature} feature
+ * @return {?settings.MultiDeviceFeatureState}
+ */
+ getFeatureState: function(feature) {
+ switch (feature) {
+ case settings.MultiDeviceFeature.BETTER_TOGETHER_SUITE:
+ return this.pageContentData.betterTogetherState;
+ case settings.MultiDeviceFeature.INSTANT_TETHERING:
+ return this.pageContentData.instantTetheringState;
+ case settings.MultiDeviceFeature.MESSAGES:
+ return this.pageContentData.messagesState;
+ case settings.MultiDeviceFeature.SMART_LOCK:
+ return this.pageContentData.smartLockState;
+ default:
+ return null;
+ }
+ },
+
+ /**
+ * Whether a host phone has been set by the user (not necessarily verified).
+ * @return {boolean}
+ */
+ isHostSet: function() {
+ return [
+ settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER,
+ settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION,
+ settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED,
+ ].includes(this.pageContentData.mode);
+ },
+};
+
+/** @polymerBehavior */
+const MultiDeviceFeatureBehavior = [
+ I18nBehavior,
+ MultiDeviceFeatureBehaviorImpl,
+];
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.html b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.html
index e4a2b503647..2be742bad0e 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.html
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.html
@@ -7,37 +7,64 @@
<link rel="import" href="../icons.html">
<link rel="import" href="../route.html">
<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="../settings_vars_css.html">
+<link rel="import" href="multidevice_constants.html">
+<link rel="import" href="multidevice_feature_behavior.html">
+<link rel="import" href="multidevice_feature_toggle.html">
<dom-module id="settings-multidevice-feature-item">
<template>
<style include="settings-shared">
+ #card {
+ border-top: var(--settings-separator-line);
+ border-top-style: var(--feature-item-border-top-style, solid);
+ padding: var(--feature-item-row-padding);
+ }
+
iron-icon {
padding: 2px;
}
- #item-text-container {
- -webkit-padding-start: 18px;
+ cr-policy-indicator {
+ padding: 0 var(--cr-controlled-by-spacing);
}
</style>
- <div class="settings-box two-line first"
+ <div id="card"
+ class="settings-box two-line"
on-click="handleItemClick_"
- actionable$="[[hasSubpageClickHandler_(subpageRoute)]]">
- <iron-icon icon="[[iconName]]"></iron-icon>
+ actionable$="[[hasSubpageClickHandler_(
+ subpageRoute, pageContentData, feature)]]">
+ <iron-icon icon="[[getIconName(feature)]]"></iron-icon>
<div id="item-text-container" class="middle">
- [[featureName]]
+ [[getFeatureName(feature)]]
<div class="secondary"
id="featureSecondary"
- inner-h-t-m-l="[[featureSummaryHtml]]">
+ inner-h-t-m-l="[[getFeatureSummaryHtml(feature)]]">
</div>
</div>
- <template is="dom-if" if="[[hasSubpageClickHandler_(subpageRoute)]]">
+ <template is="dom-if"
+ if="[[hasSubpageClickHandler_(
+ subpageRoute, pageContentData, feature)]]"
+ restamp>
<paper-icon-button-light class="subpage-arrow">
- <button aria-label="[[featureName]]"
- aria-describedby="featureSecondary"></button>
+ <button aria-label="[[getFeatureName(feature)]]"
+ aria-describedby="featureSecondary"></button>
</paper-icon-button-light>
<div class="separator"></div>
</template>
- <cr-toggle on-change="onChangeToggle_"></cr-toggle>
+ <template is="dom-if"
+ if="[[!isFeatureAllowedByPolicy(feature, pageContentData)]]"
+ restamp>
+ <cr-policy-indicator indicator-type="userPolicy"></cr-policy-indicator>
+ </template>
+ <slot name="feature-controller">
+ <!-- This settings-multidevice-feature-toggle is the default controller.
+ If an element with slot="feature-controller" is attached, it will
+ replace this one. -->
+ <settings-multidevice-feature-toggle feature="[[feature]]"
+ page-content-data="[[pageContentData]]">
+ </settings-multidevice-feature-toggle>
+ </slot>
</div>
</template>
<script src="multidevice_feature_item.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.js
index 6b71b219733..55783509adb 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.js
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_item.js
@@ -15,30 +15,15 @@ cr.exportPath('settings');
Polymer({
is: 'settings-multidevice-feature-item',
- properties: {
- /**
- * The localized string representing the name of the feature.
- * @type {string}
- */
- featureName: String,
-
- /**
- * The localized string providing a description or useful status information
- * concertning the feature.
- * @type {string}
- */
- featureSummaryHtml: String,
+ behaviors: [MultiDeviceFeatureBehavior],
- /**
- * The full icon name used provided by the containing iron-iconset-svg
- * (i.e. [iron-iconset-svg name]:[SVG <g> tag id]
- * @type {string}
- */
- iconName: String,
+ properties: {
+ /** @type {!settings.MultiDeviceFeature} */
+ feature: Number,
/**
- * If it is non-null, the item should be actionable and clicking on it
- * should navigate there. If it is undefined, the item is simply not
+ * If it is truthy, the item should be actionable and clicking on it should
+ * navigate to the provided route. Otherwise, the item is simply not
* actionable.
* @type {settings.Route|undefined}
*/
@@ -50,18 +35,12 @@ Polymer({
* @private
*/
hasSubpageClickHandler_: function() {
- return !!this.subpageRoute;
- },
-
- /** @private */
- onChangeToggle_: function() {
- // TODO (jordynass): Trigger the correct workflow.
- console.log('Toggle changed');
+ return !!this.subpageRoute && this.isFeatureAllowedByPolicy(this.feature);
},
/** @private */
handleItemClick_: function(event) {
- if (!this.subpageRoute)
+ if (!this.hasSubpageClickHandler_())
return;
// We do not navigate away if the click was on a link.
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_toggle.html b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_toggle.html
new file mode 100644
index 00000000000..b52a7be4e64
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_toggle.html
@@ -0,0 +1,17 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
+<link rel="import" href="multidevice_browser_proxy.html">
+<link rel="import" href="multidevice_constants.html">
+<link rel="import" href="multidevice_feature_behavior.html">
+
+<dom-module id="settings-multidevice-feature-toggle">
+ <template>
+ <cr-toggle id="toggle"
+ checked="{{checked_}}"
+ disabled="[[!isFeatureStateEditable(feature, pageContentData)]]"
+ on-change="onChange_">
+ </cr-toggle>
+ </template>
+ <script src="multidevice_feature_toggle.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_toggle.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_toggle.js
new file mode 100644
index 00000000000..83350e86cb8
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_feature_toggle.js
@@ -0,0 +1,76 @@
+// Copyright 2018 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 toggle button specially suited for the MultiDevice Settings UI use-case.
+ * Instead of changing on clicks, it requests a pref change from the
+ * MultiDevice service and/or triggers a password check to grab an auth token
+ * for the user. It also receives real time updates on feature states and
+ * reflects them in the toggle status.
+ */
+Polymer({
+ is: 'settings-multidevice-feature-toggle',
+
+ behaviors: [MultiDeviceFeatureBehavior],
+
+ properties: {
+ /** @type {!settings.MultiDeviceFeature} */
+ feature: Number,
+
+ /** @private {boolean} */
+ checked_: Boolean,
+ },
+
+ listeners: {
+ 'click': 'onDisabledInnerToggleClick_',
+ },
+
+ // Note that, although this.feature does not change throughout the element's
+ // lifecycle, it must be listed as an observer dependency to ensure that
+ // this.feature is defined by the time of the observer's first call.
+ observers: ['resetChecked_(feature, pageContentData)'],
+
+ /**
+ * Because MultiDevice prefs are only meant to be controlled via the
+ * MultiDevice mojo service, we need the cr-toggle to appear not to change
+ * when pressed. This method resets it before a change is visible to the
+ * user.
+ * @private
+ */
+ resetChecked_: function() {
+ this.checked_ = this.getFeatureState(this.feature) ===
+ settings.MultiDeviceFeatureState.ENABLED_BY_USER;
+ },
+
+ /**
+ * This handles the edge case in which the inner toggle (i.e., the cr-toggle)
+ * is disabled. For context, the cr-toggle element naturally stops clicks
+ * from propagating as long as its disabled attribute is false. However, if
+ * the cr-toggle's disabled attribute is set to true, its pointer-event CSS
+ * property is set to 'none' automatically. Thus, if the cr-toggle is clicked
+ * while it is disabled, the click event targets the parent element directly
+ * instead of propagating through the cr-toggle. This handler prevents such a
+ * click from unintentionally bubbling up the tree.
+ * @private
+ */
+ onDisabledInnerToggleClick_: function(event) {
+ event.stopPropagation();
+ },
+
+ /**
+ * Callback for clicking on the toggle. It attempts to toggle the feature's
+ * status if the user is allowed.
+ * @private
+ */
+ onChange_: function() {
+ this.resetChecked_();
+
+ // Pass the negation of |this.checked_|: this indicates that if the toggle
+ // is checked, the intent is for it to be unchecked, and vice versa.
+ this.fire(
+ 'feature-toggle-clicked',
+ {feature: this.feature, enabled: !this.checked_});
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
index 1708c06a264..c9c8c666188 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
@@ -1,66 +1,106 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
-<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../i18n_setup.html">
+<link rel="import" href="../icons.html">
<link rel="import" href="../route.html">
+<link rel="import" href="../controls/password_prompt_dialog.html">
<link rel="import" href="../settings_page/settings_animated_pages.html">
<link rel="import" href="../settings_page/settings_subpage.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="multidevice_browser_proxy.html">
<link rel="import" href="multidevice_constants.html">
+<link rel="import" href="multidevice_feature_behavior.html">
+<link rel="import" href="multidevice_feature_toggle.html">
<link rel="import" href="multidevice_subpage.html">
<dom-module id="settings-multidevice-page">
<template>
- <style include="settings-shared"></style>
+ <style include="settings-shared">
+ cr-policy-indicator {
+ padding: 0 var(--cr-controlled-by-spacing);
+ }
+ </style>
<settings-animated-pages id="pages" section="multidevice"
focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
<div id="multidevice-item"
- class="settings-box two-line first"
+ class="settings-box two-line"
on-click="handleItemClick_"
actionable$="[[doesClickOpenSubpage_(pageContentData)]]">
- <div class="start">
+ <template is="dom-if" if="[[isHostSet(pageContentData)]]" restamp>
+ <iron-icon icon=
+ "[[getIconName(MultiDeviceFeature.BETTER_TOGETHER_SUITE)]]">
+ </iron-icon>
+ </template>
+ <div class$=
+ "[[getMultiDeviceItemLabelBlockCssClass_(pageContentData)]]">
<div id="multidevice-label">[[getLabelText_(pageContentData)]]</div>
- <div class="secondary" id="mutltideviceSubLabel" inner-h-t-m-l=
- "[[getSubLabelInnerHtml_(pageContentData, hostEnabled_)]]">
+ <div id="mutltideviceSubLabel" class="secondary"
+ inner-h-t-m-l="[[getSubLabelInnerHtml_(pageContentData)]]">
</div>
</div>
<template is="dom-if"
- if="[[doesClickOpenSubpage_(pageContentData)]]">
- <paper-icon-button-light class="subpage-arrow">
- <button aria-label="[[getLabelText_(pageContentData)]]"
- aria-describedby="mutltideviceSubLabel"></button>
- </paper-icon-button-light>
+ if="[[!isSuiteAllowedByPolicy(pageContentData)]]"
+ restamp>
+ <cr-policy-indicator indicator-type="userPolicy">
+ </cr-policy-indicator>
+ <settings-multidevice-feature-toggle
+ feature="[[MultiDeviceFeature.BETTER_TOGETHER_SUITE]]"
+ page-content-data="[[pageContentData]]">
+ </settings-multidevice-feature-toggle>
+ </template>
+ <template is="dom-if"
+ if="[[shouldShowSeparatorAndSubpageArrow_(pageContentData)]]"
+ restamp>
+ <template is="dom-if"
+ if="[[doesClickOpenSubpage_(pageContentData)]]"
+ restamp>
+ <paper-icon-button-light class="subpage-arrow">
+ <button aria-label="[[getLabelText_(pageContentData)]]"
+ aria-describedby="mutltideviceSubLabel"></button>
+ </paper-icon-button-light>
+ </template>
+ <div class="separator"></div>
</template>
- <div class="separator"></div>
- <template is="dom-if" if="[[showButton_(pageContentData)]]" restamp>
+ <template is="dom-if"
+ if="[[shouldShowButton_(pageContentData)]]"
+ restamp>
<paper-button class="secondary-button"
+ disabled$="[[shouldDisableButton_(pageContentData)]]"
on-click="handleButtonClick_">
[[getButtonText_(pageContentData)]]
</paper-button>
</template>
- <template is="dom-if" if="[[showToggle_(pageContentData)]]" restamp>
- <cr-toggle checked="{{hostEnabled_}}"></cr-toggle>
+ <template is="dom-if"
+ if="[[shouldShowToggle_(pageContentData)]]"
+ restamp>
+ <settings-multidevice-feature-toggle
+ feature="[[MultiDeviceFeature.BETTER_TOGETHER_SUITE]]"
+ page-content-data="[[pageContentData]]">
+ </settings-multidevice-feature-toggle>
</template>
</div>
</neon-animatable>
- <template is="dom-if" route-path="/multidevice/features">
+ <template is="dom-if" route-path="/multidevice/features" restamp>
<settings-subpage associated-control="[[$$('#multidevice-item')]]"
- page-title="[[pageContentData.hostDevice.name]]">
- <settings-multidevice-subpage prefs="{{prefs}}"
- page-content-data="[[pageContentData]]"
- host-enabled="{{hostEnabled_}}">
+ page-title="[[pageContentData.hostDeviceName]]">
+ <settings-multidevice-subpage
+ page-content-data="[[pageContentData]]">
</settings-multidevice-subpage>
</settings-subpage>
</template>
</settings-animated-pages>
+ <template is="dom-if" if="[[showPasswordPromptDialog_]]" restamp>
+ <settings-password-prompt-dialog id="passwordPrompt">
+ </settings-password-prompt-dialog>
+ </template>
</template>
<script src="multidevice_page.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js
index 9172aa548a2..f6dec83fc24 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page.js
@@ -11,30 +11,9 @@ cr.exportPath('settings');
Polymer({
is: 'settings-multidevice-page',
- behaviors: [I18nBehavior],
+ behaviors: [MultiDeviceFeatureBehavior],
properties: {
- /** SettingsPrefsElement 'prefs' Object reference. See prefs.js. */
- prefs: {
- type: Object,
- notify: true,
- },
-
- /** @type {MultiDevicePageContentData} */
- pageContentData: Object,
-
- // TODO(jordynass): Set this variable once the information is retrieved from
- // prefs.
- /**
- * True if the multidevice setup is complete and the paired phone has been
- * verified; otherwise, false.
- * @private {boolean}
- */
- hostEnabled_: {
- type: Boolean,
- value: true,
- },
-
/**
* A Map specifying which element should be focused when exiting a subpage.
* The key of the map holds a settings.Route path, and the value holds a
@@ -52,6 +31,42 @@ Polymer({
return map;
},
},
+
+ /**
+ * Authentication token provided by password-prompt-dialog.
+ * @private {string}
+ */
+ authToken_: {
+ type: String,
+ value: '',
+ observer: 'authTokenChanged_',
+ },
+
+ /**
+ * Feature which the user has requested to be enabled but could not be
+ * enabled immediately because authentication (i.e., entering a password) is
+ * required. This value is initialized to null, is set when the password
+ * dialog is opened, and is reset to null again once the password dialog is
+ * closed.
+ * @private {?settings.MultiDeviceFeature}
+ */
+ featureToBeEnabledOnceAuthenticated_: {
+ type: Number,
+ value: null,
+ },
+
+ /** @private {boolean} */
+ showPasswordPromptDialog_: {
+ type: Boolean,
+ value: false,
+ },
+ },
+
+ listeners: {
+ 'auth-token-changed': 'onAuthTokenChanged_',
+ 'close': 'onPasswordPromptDialogClose_',
+ 'feature-toggle-clicked': 'onFeatureToggleClicked_',
+ 'forget-device-requested': 'onForgetDeviceRequested_',
},
/** @private {?settings.MultiDeviceBrowserProxy} */
@@ -63,12 +78,22 @@ Polymer({
},
/**
+ * CSS class for the <div> containing all the text in the multidevice-item
+ * <div>, i.e. the label and sublabel. If the host is set, the Better Together
+ * icon appears so before the text (i.e. text div is 'middle' class).
+ * @return {string}
+ * @private
+ */
+ getMultiDeviceItemLabelBlockCssClass_: function() {
+ return this.isHostSet() ? 'middle' : 'start';
+ },
+
+ /**
* @return {string} Translated item label.
* @private
*/
getLabelText_: function() {
- return !!this.pageContentData.hostDevice ?
- this.pageContentData.hostDevice.name :
+ return this.pageContentData.hostDeviceName ||
this.i18n('multideviceSetupItemHeading');
},
@@ -77,7 +102,11 @@ Polymer({
* @private
*/
getSubLabelInnerHtml_: function() {
+ if (!this.isSuiteAllowedByPolicy())
+ return this.i18nAdvanced('multideviceSetupSummary');
switch (this.pageContentData.mode) {
+ case settings.MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS:
+ return this.i18nAdvanced('multideviceNoHostText');
case settings.MultiDeviceSettingsMode.NO_HOST_SET:
return this.i18nAdvanced('multideviceSetupSummary');
case settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER:
@@ -85,8 +114,8 @@ Polymer({
case settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION:
return this.i18nAdvanced('multideviceVerificationText');
default:
- return this.hostEnabled_ ? this.i18n('multideviceEnabled') :
- this.i18n('multideviceDisabled');
+ return this.isSuiteOn() ? this.i18n('multideviceEnabled') :
+ this.i18n('multideviceDisabled');
}
},
@@ -99,7 +128,7 @@ Polymer({
case settings.MultiDeviceSettingsMode.NO_HOST_SET:
return this.i18n('multideviceSetupButton');
case settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER:
- return this.i18n('retry');
+ return this.i18n('multideviceVerifyButton');
case settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION:
return this.i18n('multideviceVerifyButton');
default:
@@ -111,36 +140,56 @@ Polymer({
* @return {boolean}
* @private
*/
- showButton_: function() {
- return this.pageContentData.mode !=
- settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED;
+ shouldShowButton_: function() {
+ return [
+ settings.MultiDeviceSettingsMode.NO_HOST_SET,
+ settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER,
+ settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION,
+ ].includes(this.pageContentData.mode);
},
/**
* @return {boolean}
* @private
*/
- showToggle_: function() {
- return this.pageContentData.mode ==
+ shouldDisableButton_: function() {
+ return this.pageContentData.mode ===
+ settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ shouldShowToggle_: function() {
+ return this.pageContentData.mode ===
settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED;
},
/**
+ * Whether to show the separator bar and, if the state calls for a chevron
+ * (a.k.a. subpage arrow) routing to the subpage, the chevron.
+ * @return {boolean}
+ * @private
+ */
+ shouldShowSeparatorAndSubpageArrow_: function() {
+ return this.pageContentData.mode !==
+ settings.MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS;
+ },
+
+ /**
* @return {boolean}
* @private
*/
doesClickOpenSubpage_: function() {
- return [
- settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER,
- settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION,
- settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED,
- ].includes(this.pageContentData.mode);
+ return this.isHostSet();
},
/** @private */
handleItemClick_: function() {
- if (!this.doesClickOpenSubpage_())
+ if (!this.isHostSet())
return;
+
settings.navigateTo(settings.routes.MULTIDEVICE_FEATURES);
},
@@ -152,13 +201,114 @@ Polymer({
this.browserProxy_.showMultiDeviceSetupDialog();
return;
case settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER:
- // TODO(jordynass): Implement this when API is ready.
- console.log('Trying to connect to server again.');
- return;
+ // Intentional fall-through.
case settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION:
- // TODO(jordynass): Implement this when API is ready.
- console.log('Trying to verify multidevice connection.');
- return;
+ // If this device is waiting for action on the server or the host
+ // device, clicking the button should trigger this action.
+ this.browserProxy_.retryPendingHostSetup();
+ }
+ },
+
+ /** @private */
+ openPasswordPromptDialog_: function() {
+ this.showPasswordPromptDialog_ = true;
+ },
+
+ /** @private */
+ onPasswordPromptDialogClose_: function() {
+ // The password prompt should only be shown when there is a feature waiting
+ // to be enabled.
+ assert(this.featureToBeEnabledOnceAuthenticated_ !== null);
+
+ // If |this.authToken_| is set when the dialog has been closed, this means
+ // that the user entered the correct password into the dialog. Thus, send
+ // all pending features to be enabled.
+ if (this.authToken_) {
+ this.browserProxy_.setFeatureEnabledState(
+ this.featureToBeEnabledOnceAuthenticated_, true /* enabled */,
+ this.authToken_);
+
+ // Reset |this.authToken_| now that it has been used. This ensures that
+ // users cannot keep an old auth token and reuse it on an subsequent
+ // request.
+ this.authToken_ = '';
+ }
+
+ // Either the feature was enabled above or the user canceled the request by
+ // clicking "Cancel" on the password dialog. Thus, there is no longer a need
+ // to track any pending feature.
+ this.featureToBeEnabledOnceAuthenticated_ = null;
+
+ // Remove the password prompt dialog from the DOM.
+ this.showPasswordPromptDialog_ = false;
+ },
+
+ /**
+ * @param {!{detail: !Object}} event
+ * @private
+ */
+ onAuthTokenChanged_: function(event) {
+ this.authToken_ = event.detail.value;
+ },
+
+ /**
+ * Attempt to enable the provided feature. If not authenticated (i.e.,
+ * |authToken_| is invalid), display the password prompt to begin the
+ * authentication process.
+ *
+ * @param {!{detail: !Object}} event
+ * @private
+ */
+ onFeatureToggleClicked_: function(event) {
+ let feature = event.detail.feature;
+ let enabled = event.detail.enabled;
+
+ // Disabling any feature does not require authentication, and enable some
+ // features does not require authentication.
+ if (!enabled || !this.isAuthenticationRequiredToEnable_(feature)) {
+ this.browserProxy_.setFeatureEnabledState(feature, enabled);
+ return;
}
+
+ // If the feature required authentication to be enabled, open the password
+ // prompt dialog. This is required every time the user enables a security-
+ // sensitive feature (i.e., use of stale auth tokens is not acceptable).
+ this.featureToBeEnabledOnceAuthenticated_ = feature;
+ this.openPasswordPromptDialog_();
+ },
+
+ /**
+ * @param {!settings.MultiDeviceFeature} feature The feature to enable.
+ * @return {boolean} Whether authentication is required to enable the feature.
+ * @private
+ */
+ isAuthenticationRequiredToEnable_: function(feature) {
+ // Enabling SmartLock always requires authentication.
+ if (feature == settings.MultiDeviceFeature.SMART_LOCK)
+ return true;
+
+ // Enabling any feature besides SmartLock and the Better Together suite does
+ // not require authentication.
+ if (feature != settings.MultiDeviceFeature.BETTER_TOGETHER_SUITE)
+ return false;
+
+ const smartLockState =
+ this.getFeatureState(settings.MultiDeviceFeature.SMART_LOCK);
+
+ // If the user is enabling the Better Together suite and this change would
+ // result in SmartLock being implicitly enabled, authentication is required.
+ // SmartLock is implicitly enabled if it is only currently not enabled due
+ // to the suite being disabled or due to the SmartLock host device not
+ // having a lock screen set.
+ return smartLockState ==
+ settings.MultiDeviceFeatureState.UNAVAILABLE_SUITE_DISABLED ||
+ smartLockState ==
+ settings.MultiDeviceFeatureState.UNAVAILABLE_INSUFFICIENT_SECURITY;
+ },
+
+ /** @private */
+ onForgetDeviceRequested_: function() {
+ this.browserProxy_.removeHostDevice();
+ settings.navigateTo(settings.routes.MULTIDEVICE);
},
});
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.html b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.html
index 98b70696a94..c804083150d 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.html
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.html
@@ -2,15 +2,17 @@
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="multidevice_constants.html">
<link rel="import" href="multidevice_browser_proxy.html">
+<link rel="import" href="multidevice_constants.html">
+<link rel="import" href="multidevice_feature_behavior.html">
<link rel="import" href="multidevice_page.html">
<dom-module id="settings-multidevice-page-container">
<template>
- <template is="dom-if" if="[[doesPotentialConnectedPhoneExist]]" restamp>
- <settings-multidevice-page prefs="[[prefs]]"
- page-content-data="[[pageContentData_]]">
+ <template is="dom-if"
+ if="[[doesChromebookSupportMultiDeviceFeatures]]"
+ restamp>
+ <settings-multidevice-page page-content-data="[[pageContentData]]">
</settings-multidevice-page>
</template>
</template>
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js
index 87143142770..dd74a9271a4 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js
@@ -18,28 +18,19 @@ cr.exportPath('settings');
Polymer({
is: 'settings-multidevice-page-container',
- behaviors: [WebUIListenerBehavior],
+ behaviors: [MultiDeviceFeatureBehavior, WebUIListenerBehavior],
properties: {
- /** SettingsPrefsElement 'prefs' Object reference. See prefs.js. */
- prefs: {
- type: Object,
- notify: true,
- },
-
/**
- * Whether a phone was found on the account that is either connected to the
- * Chromebook or has the potential to be.
+ * Whether the Chromebook is capable of enabling Better Together features.
* @type {boolean}
*/
- doesPotentialConnectedPhoneExist: {
+ doesChromebookSupportMultiDeviceFeatures: {
type: Boolean,
- computed: 'computeDoesPotentialConnectedPhoneExist(pageContentData_)',
+ computed:
+ 'computeDoesChromebookSupportMultiDeviceFeatures(pageContentData)',
notify: true,
},
-
- /** @private {MultiDevicePageContentData} */
- pageContentData_: Object,
},
/** @private {?settings.MultiDeviceBrowserProxy} */
@@ -66,13 +57,13 @@ Polymer({
console.error('Invalid status change');
return;
}
- this.pageContentData_ = newData;
+ this.pageContentData = newData;
},
/**
* If the new mode corresponds to no eligible host or unset potential hosts
- * (i.e. NO_ELIGIBLE_HOSTS or NO_HOST_SET), then newHostDevice should be null
- * or undefined. Otherwise it should be defined and non-null.
+ * (i.e. NO_ELIGIBLE_HOSTS or NO_HOST_SET), then newHostDeviceName should be
+ * falsy. Otherwise it should be truthy.
* @param {!MultiDevicePageContentData} newData
* @private
*/
@@ -81,16 +72,16 @@ Polymer({
settings.MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS,
settings.MultiDeviceSettingsMode.NO_HOST_SET,
];
- return !newData.hostDevice == noHostModes.includes(newData.mode);
+ return !newData.hostDeviceName === noHostModes.includes(newData.mode);
},
/**
* @return {boolean}
* @private
*/
- computeDoesPotentialConnectedPhoneExist: function() {
- return !!this.pageContentData_ &&
- this.pageContentData_.mode !=
- settings.MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS;
+ computeDoesChromebookSupportMultiDeviceFeatures: function() {
+ return !!this.pageContentData &&
+ this.isFeatureSupported(
+ settings.MultiDeviceFeature.BETTER_TOGETHER_SUITE);
},
});
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
index 3f78863025d..946ab4a626d 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
@@ -1,44 +1,136 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_network_listener_behavior.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../route.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="../settings_vars_css.html">
+<link rel="import" href="multidevice_constants.html">
+<link rel="import" href="multidevice_feature_behavior.html">
<link rel="import" href="multidevice_feature_item.html">
+<link rel="import" href="multidevice_feature_toggle.html">
+<link rel="import" href="multidevice_tether_item.html">
<dom-module id="settings-multidevice-subpage">
<template>
<style include="settings-shared iron-flex">
+ settings-multidevice-feature-item,
+ settings-multidevice-tether-item {
+ --feature-item-row-padding: 0;
+ }
+
+ settings-multidevice-feature-item:first-of-type {
+ --feature-item-border-top-style: none;
+ }
+
#status-text-container[enabled] {
color: var(--google-green-500);
}
- .feature-item-container {
- -webkit-margin-end: var(--settings-box-row-padding);
- -webkit-margin-start: var(--settings-box-row-indent);
+ #feature-items-container,
+ #forget-device-container {
+ @apply(--settings-list-frame-padding);
+ }
+
+ #forget-device-container {
+ border-top: var(--settings-separator-line);
+ }
+
+ #forget-device {
+ padding: 0;
}
</style>
<div class="settings-box first">
- <div id="status-text-container" class="start" enabled$="[[hostEnabled]]">
- [[getStatusText_(hostEnabled)]]
+ <div id="status-text-container"
+ class="start"
+ enabled$="[[isSuiteOn(pageContentData)]]">
+ [[getStatusText_(pageContentData)]]
</div>
- <cr-toggle id="enable-multidevice" checked="{{hostEnabled}}">
- </cr-toggle>
+ <settings-multidevice-feature-toggle
+ feature="[[MultiDeviceFeature.BETTER_TOGETHER_SUITE]]"
+ page-content-data="[[pageContentData]]">
+ </settings-multidevice-feature-toggle>
</div>
<template is="dom-if"
if="[[shouldShowIndividualFeatures_(pageContentData)]]"
restamp>
- <div class="feature-item-container">
- <settings-multidevice-feature-item icon-name="settings:smart-lock"
- subpage-route="[[routes.LOCK_SCREEN]]"
- feature-name="$i18n{multideviceSmartLockItemTitle}"
- feature-summary-html="$i18n{multideviceSmartLockItemSummary}">
- </settings-multidevice-feature-item>
+ <div id="feature-items-container">
+ <template is="dom-if"
+ if="[[isFeatureSupported(
+ MultiDeviceFeature.SMART_LOCK, pageContentData)]]"
+ restamp>
+ <settings-multidevice-feature-item id="smartLockItem"
+ feature="[[MultiDeviceFeature.SMART_LOCK]]"
+ page-content-data="[[pageContentData]]"
+ subpage-route="[[routes.LOCK_SCREEN]]">
+ </settings-multidevice-feature-item>
+ </template>
+ <template is="dom-if"
+ if="[[isFeatureSupported(
+ MultiDeviceFeature.INSTANT_TETHERING, pageContentData)]]"
+ restamp>
+ <settings-multidevice-tether-item id="instantTetheringItem">
+ </settings-multidevice-tether-item>
+ </template>
+ <template is="dom-if"
+ if="[[isFeatureSupported(
+ MultiDeviceFeature.MESSAGES, pageContentData)]]"
+ restamp>
+ <settings-multidevice-feature-item id="messagesItem"
+ feature="[[MultiDeviceFeature.MESSAGES]]"
+ page-content-data="[[pageContentData]]">
+ <template is="dom-if" if="[[androidMessagesRequiresSetup_]]"
+ restamp>
+ <paper-button on-click="handleAndroidMessagesButtonClick_"
+ slot="feature-controller">
+ $i18n{multideviceSetupButton}
+ </paper-button>
+ </template>
+ </settings-multidevice-feature-item>
+ </template>
</div>
</template>
+ <div id="forget-device-container">
+ <div id="forget-device"
+ class="settings-box two-line first"
+ on-click="handleForgetDeviceClick_"
+ actionable>
+ <div class="start">
+ $i18n{multideviceForgetDevice}
+ <div class="secondary" id="multideviceForgetDeviceSummary">
+ $i18n{multideviceForgetDeviceSummary}
+ </div>
+ </div>
+ <paper-icon-button-light class="subpage-arrow">
+ <button aria-label="$i18n{multideviceForgetDevice}"
+ aria-describedby="multideviceForgetDeviceSummary"></button>
+ </paper-icon-button-light>
+ </div>
+ </div>
+ <cr-dialog id="forgetDeviceDialog" show-close-button="false">
+ <div slot="title">$i18n{multideviceForgetDeviceDialogHeading}</div>
+ <div slot="body">
+ <div class="settings-box first">
+ $i18n{multideviceForgetDeviceDialogMessage}
+ </div>
+ </div>
+ <div slot="button-container">
+ <paper-button class="cancel-button"
+ on-click="onForgetDeviceDialogCancelClick_">
+ $i18n{cancel}
+ </paper-button>
+
+ <paper-button id="confirmButton"
+ class="action-button"
+ on-click="onForgetDeviceDialogConfirmClick_">
+ $i18n{confirm}
+ </paper-button>
+ </div>
+ </cr-dialog>
</template>
<script src="multidevice_subpage.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.js
index 202a2b58d64..a8da00c237d 100644
--- a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.js
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.js
@@ -12,34 +12,71 @@ cr.exportPath('settings');
Polymer({
is: 'settings-multidevice-subpage',
- behaviors: [I18nBehavior],
+ behaviors: [
+ MultiDeviceFeatureBehavior,
+ CrNetworkListenerBehavior,
+ ],
properties: {
- /** SettingsPrefsElement 'prefs' Object reference. See prefs.js. */
- prefs: {
+ /** @type {?SettingsRoutes} */
+ routes: {
type: Object,
- notify: true,
+ value: settings.routes,
+ },
+
+ /** Overridden from NetworkListenerBehavior. */
+ networkingPrivate: {
+ type: Object,
+ value: chrome.networkingPrivate,
+ },
+
+ /** Overridden from NetworkListenerBehavior. */
+ networkListChangeSubscriberSelectors_: {
+ type: Array,
+ value: () => ['settings-multidevice-tether-item'],
+ },
+
+ /** Overridden from NetworkListenerBehavior. */
+ networksChangeSubscriberSelectors_: {
+ type: Array,
+ value: () => ['settings-multidevice-tether-item'],
},
- // TODO(jordynass): Set this based on data in this.prefs.
+ // TODO(jordynass): Once the service provides this data via pageContentData,
+ // replace this property with that path.
/**
- * If a host has been verified, this is true if that host is and enabled and
- * false if it is disabled. Otherwise it is undefined.
- * @type {boolean|undefined}
+ * If SMS Connect requires setup, it displays a paper button prompting the
+ * setup flow. If it is already set up, it displays a regular toggle for the
+ * feature.
+ * @private {boolean}
*/
- hostEnabled: {
+ androidMessagesRequiresSetup_: {
type: Boolean,
- notify: true,
+ value: true,
},
+ },
- /** @type {?SettingsRoutes} */
- routes: {
- type: Object,
- value: settings.routes,
- },
+ /** @private {?settings.MultiDeviceBrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ created: function() {
+ this.browserProxy_ = settings.MultiDeviceBrowserProxyImpl.getInstance();
+ },
+
+ /** @private */
+ handleAndroidMessagesButtonClick_: function() {
+ this.browserProxy_.setUpAndroidSms();
+ },
+
+ listeners: {
+ 'show-networks': 'onShowNetworks_',
+ },
- /** @type {MultiDevicePageContentData} */
- pageContentData: Object,
+ onShowNetworks_: function() {
+ settings.navigateTo(
+ settings.routes.INTERNET_NETWORKS,
+ new URLSearchParams('type=' + CrOnc.Type.TETHER));
},
/**
@@ -51,12 +88,28 @@ Polymer({
settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED;
},
+ /** @private */
+ handleForgetDeviceClick_: function() {
+ this.$.forgetDeviceDialog.showModal();
+ },
+
+ /** @private */
+ onForgetDeviceDialogCancelClick_: function() {
+ this.$.forgetDeviceDialog.close();
+ },
+
+ /** @private */
+ onForgetDeviceDialogConfirmClick_: function() {
+ this.fire('forget-device-requested');
+ this.$.forgetDeviceDialog.close();
+ },
+
/**
* @return {string}
* @private
*/
getStatusText_: function() {
- return this.hostEnabled ? this.i18n('multideviceEnabled') :
+ return this.isSuiteOn() ? this.i18n('multideviceEnabled') :
this.i18n('multideviceDisabled');
},
});
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_tether_item.html b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_tether_item.html
new file mode 100644
index 00000000000..e831086d43e
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_tether_item.html
@@ -0,0 +1,34 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html">
+<link rel="import" href="../i18n_setup.html">
+<link rel="import" href="../internet_page/network_summary_item.html">
+<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="../settings_vars_css.html">
+
+<dom-module id="settings-multidevice-tether-item">
+ <style include="settings-shared">
+ network-summary-item {
+ --network-summary-item-outer-box: {
+ padding: var(--feature-item-row-padding);
+ };
+
+ --network-summary-item-title: {
+ color: var(--cr-primary-text-color);
+ font-weight: 400;
+ };
+ }
+ </style>
+ <template>
+ <network-summary-item id="networkSummaryItem"
+ active-network-state="[[activeNetworkState_]]"
+ device-state="[[deviceState_]]"
+ network-state-list="[[getNetworkStateList_(activeNetworkState_)]]"
+ networking-private="[[networkingPrivate]]"
+ tether-device-state="[[deviceState_]]"
+ network-title-text="$i18n{multideviceInstantTetheringItemTitle}">
+ </network-summary-item>
+ </template>
+ <script src="multidevice_tether_item.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_tether_item.js b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_tether_item.js
new file mode 100644
index 00000000000..468d045f1b6
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/multidevice_page/multidevice_tether_item.js
@@ -0,0 +1,163 @@
+// Copyright 2018 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
+ * This element provides a layer between the settings-multidevice-subpage
+ * element and the internet_page folder's network-summary-item. It is
+ * responsible for loading initial tethering network data from the
+ * chrome.networkingPrivate API as well as updating the data in real time. It
+ * serves a role comparable to the internet_page's network-summary element.
+ */
+
+Polymer({
+ is: 'settings-multidevice-tether-item',
+
+ properties: {
+ /**
+ * Interface for networkingPrivate calls.
+ * @private {!NetworkingPrivate}
+ */
+ networkingPrivate_: {
+ type: Object,
+ value: chrome.networkingPrivate,
+ },
+
+ /**
+ * The device state for tethering.
+ * @private {?CrOnc.DeviceStateProperties|undefined}
+ */
+ deviceState_: Object,
+
+ /**
+ * The network state for a potential tethering host phone. Note that there
+ * is at most one because only one MultiDevice host phone is allowed on an
+ * account at a given time.
+ * @private {?CrOnc.NetworkStateProperties|undefined}
+ */
+ activeNetworkState_: Object,
+ },
+
+ listeners: {
+ 'device-enabled-toggled': 'onDeviceEnabledToggled_',
+ 'network-list-changed': 'updateTetherNetworkState_',
+ // network-changed is fired by the settings-multidevice-subpage element's
+ // CrNetworkListenerBehavior.
+ // TODO (jordynass): Refactor to allow this element to listen to network
+ // changes without requiring the settings-multidevice-subpage to communicate
+ // with the networkingPrivate API.
+ 'networks-changed': 'onNetworksChanged_',
+ },
+
+ /**
+ * Listener function for chrome.networkingPrivate.onDeviceStateListChanged
+ * event.
+ * @private {?function(!Array<string>)}
+ */
+ deviceStateListChangedListener_: null,
+
+ /** @override */
+ attached: function() {
+ this.updateTetherDeviceState_();
+ this.updateTetherNetworkState_();
+
+ this.deviceStateListChangedListener_ =
+ this.deviceStateListChangedListener_ ||
+ this.updateTetherDeviceState_.bind(this);
+ this.networkingPrivate_.onDeviceStateListChanged.addListener(
+ this.deviceStateListChangedListener_);
+ },
+
+ /** @override */
+ detached: function() {
+ this.networkingPrivate_.onDeviceStateListChanged.removeListener(
+ assert(this.deviceStateListChangedListener_));
+ },
+
+ /**
+ * Callback for the a network changing state. Note that any change to leading
+ * to a new active network would fire the 'network-list-changed' event,
+ * triggering updateTetherNetworkState_ and rendering this callback
+ * redundant. As a result, we return early if the active network is not
+ * changed.
+ * @param {{detail: Array<string>}} event stores an array of the GUIDs of all
+ * networks that changed in its detail property.
+ * @private
+ */
+ onNetworksChanged_: function(event) {
+ const id = this.activeNetworkState_.GUID;
+ if (!event.detail.includes(id))
+ return;
+ this.networkingPrivate_.getState(id, newNetworkState => {
+ if (chrome.runtime.lastError) {
+ const message = chrome.runtime.lastError.message;
+ if (message != 'Error.NetworkUnavailable' &&
+ message != 'Error.InvalidNetworkGuid') {
+ console.error(
+ 'Unexpected networkingPrivate.getState error: ' + message +
+ ' For: ' + id);
+ return;
+ }
+ }
+ this.activeNetworkState_ = newNetworkState;
+ });
+ },
+
+ /**
+ * Event triggered by a device state enabled toggle.
+ * @param {!{detail: {enabled: boolean, type: CrOnc.Type}}} event
+ * @private
+ */
+ onDeviceEnabledToggled_: function(event) {
+ if (event.detail.enabled)
+ this.networkingPrivate_.enableNetworkType(CrOnc.Type.TETHER);
+ else
+ this.networkingPrivate_.disableNetworkType(CrOnc.Type.TETHER);
+ },
+
+ /**
+ * Retrieves device states (CrOnc.DeviceStateProperties) and sets
+ * this.deviceState_ to the retrieved Instant Tethering state (or undefined if
+ * there is none) in its callback. Note that the function
+ * chrome.networkingPrivate.getDevicePolicy() retrieves at most one object per
+ * network type (CrOnc.Type) so, in particular there will be at most one state
+ * for Instant Tethering.
+ * @private
+ */
+ updateTetherDeviceState_: function() {
+ this.networkingPrivate_.getDeviceStates(deviceStates => {
+ this.deviceState_ =
+ deviceStates.find(
+ deviceState => deviceState.Type == CrOnc.Type.TETHER) ||
+ {Type: CrOnc.Type.TETHER, State: CrOnc.DeviceState.DISABLED};
+ });
+ },
+
+ /**
+ * Retrieves all Instant Tethering network states
+ * (CrOnc.NetworkStateProperties). Note that there is at most one because
+ * only one host is allowed on an account at a given time. Then it sets
+ * this.activeNetworkState_ to that network if there is one or a dummy object
+ * with an empty string for a GUID otherwise.
+ * @private
+ */
+ updateTetherNetworkState_: function() {
+ this.networkingPrivate_.getNetworks(
+ {networkType: CrOnc.Type.TETHER}, networkStates => {
+ this.activeNetworkState_ =
+ networkStates[0] || {GUID: '', Type: CrOnc.Type.TETHER};
+ });
+ },
+
+ /**
+ * Returns an array containing the active network state if there is one
+ * (note that if there is not GUID will be falsy). Returns an empty array
+ * otherwise.
+ * @return {!Array<CrOnc.NetworkStateProperties>}
+ * @private
+ */
+ getNetworkStateList_: function() {
+ return this.activeNetworkState_.GUID ? [this.activeNetworkState_] : [];
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/BUILD.gn b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/BUILD.gn
index 4f4ba6a686b..a8f8b60e2b6 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/BUILD.gn
@@ -14,6 +14,7 @@ js_type_check("closure_compile") {
":password_manager_proxy",
":passwords_and_forms_page",
":passwords_section",
+ ":payments_section",
":show_password_behavior",
]
}
@@ -22,6 +23,7 @@ js_library("passwords_and_forms_page") {
deps = [
":autofill_section",
":passwords_section",
+ ":payments_section",
"..:route",
"../prefs:prefs_behavior",
"../settings_page:settings_animated_pages",
@@ -37,10 +39,22 @@ js_library("passwords_and_forms_page") {
js_library("autofill_section") {
deps = [
":address_edit_dialog",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ]
+ externs_list = [ "$externs_path/autofill_private.js" ]
+}
+
+js_library("payments_section") {
+ deps = [
":credit_card_edit_dialog",
+ "../people_page:sync_browser_proxy",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
"//ui/webui/resources/js/cr/ui:focus_without_ink",
]
externs_list = [ "$externs_path/autofill_private.js" ]
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html
index 45beb855788..5ceba365497 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html
@@ -18,7 +18,7 @@
}
.address-column {
- -webkit-margin-end: 16px;
+ margin-inline-end: 16px;
width: calc((var(--settings-input-max-width) - 16px) / 2);
}
@@ -77,12 +77,13 @@
<template is="dom-if" if="[[item.isTextArea]]">
<settings-textarea label="[[item.component.fieldName]]"
value="{{item.value}}" on-value-changed="updateCanSave_"
- class$="address-column [[long_(item)]]" autofocus>
+ class$="address-column [[long_(item)]]" autofocus
+ spellcheck="false">
</settings-textarea>
</template>
<template is="dom-if" if="[[!item.isTextArea]]">
<cr-input type="text" label="[[item.component.fieldName]]"
- autofocus value="{{item.value}}"
+ autofocus value="{{item.value}}" spellcheck="false"
on-value-changed="updateCanSave_"
class$="address-column [[long_(item)]]">
</cr-input>
@@ -106,11 +107,11 @@
<div class="address-row">
<cr-input id="phoneInput" type="text" label="$i18n{addressPhone}"
class="address-column last-row" on-value-changed="updateCanSave_"
- value="{{phoneNumber_}}">
+ value="{{phoneNumber_}}" spellcheck="false">
</cr-input>
<cr-input id="emailInput" type="text" label="$i18n{addressEmail}"
on-value-changed="updateCanSave_" value="{{email_}}"
- class="address-column long last-row">
+ class="address-column long last-row" spellcheck="false">
</cr-input>
</div>
</div>
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js
index 1ec36ce4685..a184152c8af 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js
@@ -92,9 +92,23 @@ Polymer({
// Default to the last country used if no country code is provided.
const countryCode = this.countryCode_ || this.countries_[0].countryCode;
this.countryInfo.getAddressFormat(countryCode).then(format => {
- this.addressWrapper_ = format.components.map(
- component => component.row.map(
- c => new settings.address.AddressComponentUI(this.address, c)));
+ let filteredComponent =
+ format.components.map(component => component.row.filter(c => {
+ return (
+ loadTimeData.getBoolean('EnableCompanyName') ||
+ c.field !== chrome.autofillPrivate.AddressField.COMPANY_NAME);
+ }));
+ this.addressWrapper_ =
+ filteredComponent
+ .filter(component => {
+ return (component && component.length > 0);
+ })
+ .map(component => {
+ return component.map(c => {
+ return new settings.address.AddressComponentUI(
+ this.address, c);
+ });
+ });
// Flush dom before resize and savability updates.
Polymer.dom.flush();
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
index 6883353a5c3..e9427a1e447 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
@@ -1,13 +1,8 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
-<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/html/action_link.html">
-<link rel="import" href="chrome://resources/html/action_link_css.html">
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../settings_shared_css.html">
@@ -15,32 +10,11 @@
<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../prefs/prefs.html">
<link rel="import" href="address_edit_dialog.html">
-<link rel="import" href="credit_card_edit_dialog.html">
<link rel="import" href="passwords_shared_css.html">
<dom-module id="settings-autofill-section">
<template>
- <style include="settings-shared passwords-shared action-link">
- .type-column {
- align-items: center;
- flex: 2;
- }
-
- .expiration-column {
- align-items: center;
- display: flex;
- flex: 1;
- }
-
- .expiration-date {
- flex: 1;
- }
-
- .payments-label {
- -webkit-margin-start: 16px;
- color: var(--cr-secondary-text-color);
- }
-
+ <style include="settings-shared passwords-shared">
#addressList .start {
display: flex;
overflow: hidden;
@@ -51,34 +25,22 @@
flex: 1;
overflow: hidden;
}
-
- .ellipses {
- flex: 1;
- max-width: fit-content;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- cr-policy-indicator {
- padding-right: 20px;
- width: 20px;
- }
</style>
- <settings-toggle-button id="autofillToggle"
- class="first"
+ <settings-toggle-button id="autofillProfileToggle"
+ class="settings-box first"
aria-label="$i18n{autofill}" no-extension-indicator
- label="$i18n{autofillFormsLabel}"
- pref="{{prefs.autofill.enabled}}">
+ label="$i18n{enableProfilesLabel}"
+ sub-label="$i18n{enableProfilesSublabel}"
+ pref="{{prefs.autofill.profile_enabled}}">
</settings-toggle-button>
- <template is="dom-if" if="[[prefs.autofill.enabled.extensionId]]">
+ <template is="dom-if" if="[[prefs.autofill.profile_enabled.extensionId]]">
<div class="settings-box continuation">
<extension-controlled-indicator class="start"
id="autofillExtensionIndicator"
- extension-id="[[prefs.autofill.enabled.extensionId]]"
- extension-name="[[prefs.autofill.enabled.controlledByName]]"
+ extension-id="[[prefs.autofill.profile_enabled.extensionId]]"
+ extension-name="[[prefs.autofill.profile_enabled.controlledByName]]"
extension-can-be-disabled="[[
- prefs.autofill.enabled.extensionCanBeDisabled]]">
+ prefs.autofill.profile_enabled.extensionCanBeDisabled]]">
</extension-controlled-indicator>
</div>
</template>
@@ -86,7 +48,8 @@
<h2 class="start">$i18n{addresses}</h2>
<paper-button id="addAddress"
class="secondary-button header-aligned-button"
- on-click="onAddAddressTap_">
+ on-click="onAddAddressTap_"
+ disabled$="[[!prefs.autofill.profile_enabled.value]]">
$i18n{add}
</paper-button>
</div>
@@ -103,9 +66,6 @@
[[item.metadata.summarySublabel]]
</span>
</span>
- <span class="payments-label" hidden$="[[item.metadata.isLocal]]">
- $i18n{googlePayments}
- </span>
</div>
<template is="dom-if" if="[[item.metadata.isLocal]]">
<paper-icon-button-light class="icon-more-vert">
@@ -135,81 +95,9 @@
</cr-action-menu>
<template is="dom-if" if="[[showAddressDialog_]]" restamp>
<settings-address-edit-dialog address="[[activeAddress]]"
- on-close="onAddressDialogClosed_">
+ on-close="onAddressDialogClose_">
</settings-address-edit-dialog>
</template>
- <div class="settings-box first">
- <h2 class="start">$i18n{creditCards}</h2>
- <paper-button id="addCreditCard"
- class="secondary-button header-aligned-button"
- on-click="onAddCreditCardTap_">
- $i18n{add}
- </paper-button>
- </div>
- <div class="list-frame">
- <div id="creditCardsHeading" class="list-item column-header"
- hidden$="[[!hasSome_(creditCards)]]">
- <div class="type-column">$i18n{creditCardType}</div>
- <div class="expiration-column">$i18n{creditCardExpiration}</div>
- </div>
- <div id="creditCardList" class="vertical-list list-with-header">
- <template is="dom-repeat" items="[[creditCards]]">
- <div class="list-item">
- <div class="type-column">
- <span id="creditCardLabel">[[item.metadata.summaryLabel]]</span>
- <span class="payments-label"
- hidden$="[[item.metadata.isLocal]]">
- <span hidden$="[[item.metadata.isCached]]">
- $i18n{googlePayments}
- </span>
- <span hidden$="[[!item.metadata.isCached]]">
- $i18n{googlePaymentsCached}
- </span>
- </span>
- </div>
- <div class="expiration-column">
- <div id="creditCardExpiration"
- class="expiration-date">[[expiration_(item)]]</div>
- <template is="dom-if" if="[[showDots_(item.metadata)]]">
- <paper-icon-button-light class="icon-more-vert">
- <button id="creditCardMenu" title="$i18n{moreActions}"
- on-click="onCreditCardMenuTap_">
- </button>
- </paper-icon-button-light>
- </template>
- <template is="dom-if" if="[[!showDots_(item.metadata)]]">
- <paper-icon-button-light actionable class="icon-external">
- <button id="remoteCreditCardLink"
- on-click="onRemoteEditCreditCardTap_">
- </button>
- </paper-icon-button-light>
- </template>
- </div>
- </div>
- </template>
- </div>
- <div id="noCreditCardsLabel" class="list-item"
- hidden$="[[hasSome_(creditCards)]]">
- $i18n{noCreditCardsFound}
- </div>
- </div>
- <cr-action-menu id="creditCardSharedMenu">
- <button id="menuEditCreditCard" slot="item" class="dropdown-item"
- on-click="onMenuEditCreditCardTap_">$i18n{edit}</button>
- <button id="menuRemoveCreditCard" slot="item" class="dropdown-item"
- hidden$="[[!activeCreditCard.metadata.isLocal]]"
- on-click="onMenuRemoveCreditCardTap_">$i18n{removeCreditCard}</button>
- <button id="menuClearCreditCard" slot="item" class="dropdown-item"
- on-click="onMenuClearCreditCardTap_"
- hidden$="[[!activeCreditCard.metadata.isCached]]">
- $i18n{clearCreditCard}
- </button>
- </cr-action-menu>
- <template is="dom-if" if="[[showCreditCardDialog_]]" restamp>
- <settings-credit-card-edit-dialog credit-card="[[activeCreditCard]]"
- on-close="onCreditCardDialogClosed_">
- </settings-credit-card-edit-dialog>
- </template>
</template>
<script src="autofill_section.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
index ef0055304d9..25bd70563bf 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
@@ -4,7 +4,7 @@
/**
* @fileoverview 'settings-autofill-section' is the section containing saved
- * addresses and credit cards for use in autofill.
+ * addresses for use in autofill and payments APIs.
*/
/**
@@ -38,44 +38,11 @@ class AutofillManager {
/** @param {string} guid The guid of the address to remove. */
removeAddress(guid) {}
-
- /**
- * Add an observer to the list of credit cards.
- * @param {function(!Array<!AutofillManager.CreditCardEntry>):void} listener
- */
- addCreditCardListChangedListener(listener) {}
-
- /**
- * Remove an observer from the list of credit cards.
- * @param {function(!Array<!AutofillManager.CreditCardEntry>):void} listener
- */
- removeCreditCardListChangedListener(listener) {}
-
- /**
- * Request the list of credit cards.
- * @param {function(!Array<!AutofillManager.CreditCardEntry>):void} callback
- */
- getCreditCardList(callback) {}
-
- /** @param {string} guid The GUID of the credit card to remove. */
- removeCreditCard(guid) {}
-
- /** @param {string} guid The GUID to credit card to remove from the cache. */
- clearCachedCreditCard(guid) {}
-
- /**
- * Saves the given credit card.
- * @param {!AutofillManager.CreditCardEntry} creditCard
- */
- saveCreditCard(creditCard) {}
}
/** @typedef {chrome.autofillPrivate.AddressEntry} */
AutofillManager.AddressEntry;
-/** @typedef {chrome.autofillPrivate.CreditCardEntry} */
-AutofillManager.CreditCardEntry;
-
/**
* Implementation that accesses the private API.
* @implements {AutofillManager}
@@ -105,36 +72,6 @@ class AutofillManagerImpl {
removeAddress(guid) {
chrome.autofillPrivate.removeEntry(assert(guid));
}
-
- /** @override */
- addCreditCardListChangedListener(listener) {
- chrome.autofillPrivate.onCreditCardListChanged.addListener(listener);
- }
-
- /** @override */
- removeCreditCardListChangedListener(listener) {
- chrome.autofillPrivate.onCreditCardListChanged.removeListener(listener);
- }
-
- /** @override */
- getCreditCardList(callback) {
- chrome.autofillPrivate.getCreditCardList(callback);
- }
-
- /** @override */
- removeCreditCard(guid) {
- chrome.autofillPrivate.removeEntry(assert(guid));
- }
-
- /** @override */
- clearCachedCreditCard(guid) {
- chrome.autofillPrivate.maskCreditCard(assert(guid));
- }
-
- /** @override */
- saveCreditCard(creditCard) {
- chrome.autofillPrivate.saveCreditCard(creditCard);
- }
}
cr.addSingletonGetter(AutofillManagerImpl);
@@ -145,8 +82,6 @@ cr.addSingletonGetter(AutofillManagerImpl);
Polymer({
is: 'settings-autofill-section',
- behaviors: [I18nBehavior],
-
properties: {
/**
* An array of saved addresses.
@@ -162,26 +97,10 @@ Polymer({
/** @private */
showAddressDialog_: Boolean,
-
- /**
- * An array of saved credit cards.
- * @type {!Array<!AutofillManager.CreditCardEntry>}
- */
- creditCards: Array,
-
- /**
- * The model for any credit card related action menus or dialogs.
- * @private {?chrome.autofillPrivate.CreditCardEntry}
- */
- activeCreditCard: Object,
-
- /** @private */
- showCreditCardDialog_: Boolean,
},
listeners: {
'save-address': 'saveAddress_',
- 'save-credit-card': 'saveCreditCard_',
},
/**
@@ -203,12 +122,6 @@ Polymer({
*/
setAddressesListener_: null,
- /**
- * @type {?function(!Array<!AutofillManager.CreditCardEntry>)}
- * @private
- */
- setCreditCardsListener_: null,
-
/** @override */
attached: function() {
// Create listener functions.
@@ -217,26 +130,17 @@ Polymer({
this.addresses = list;
};
- /** @type {function(!Array<!AutofillManager.CreditCardEntry>)} */
- const setCreditCardsListener = list => {
- this.creditCards = list;
- };
-
// Remember the bound reference in order to detach.
this.setAddressesListener_ = setAddressesListener;
- this.setCreditCardsListener_ = setCreditCardsListener;
// Set the managers. These can be overridden by tests.
this.autofillManager_ = AutofillManagerImpl.getInstance();
// Request initial data.
this.autofillManager_.getAddressList(setAddressesListener);
- this.autofillManager_.getCreditCardList(setCreditCardsListener);
// Listen for changes.
this.autofillManager_.addAddressListChangedListener(setAddressesListener);
- this.autofillManager_.addCreditCardListChangedListener(
- setCreditCardsListener);
},
/** @override */
@@ -244,19 +148,6 @@ Polymer({
this.autofillManager_.removeAddressListChangedListener(
/** @type {function(!Array<!AutofillManager.AddressEntry>)} */ (
this.setAddressesListener_));
- this.autofillManager_.removeCreditCardListChangedListener(
- /** @type {function(!Array<!AutofillManager.CreditCardEntry>)} */ (
- this.setCreditCardsListener_));
- },
-
- /**
- * Formats the expiration date so it's displayed as MM/YYYY.
- * @param {!chrome.autofillPrivate.CreditCardEntry} item
- * @return {string}
- * @private
- */
- expiration_: function(item) {
- return item.expirationMonth + '/' + item.expirationYear;
},
/**
@@ -297,7 +188,7 @@ Polymer({
},
/** @private */
- onAddressDialogClosed_: function() {
+ onAddressDialogClose_: function() {
this.showAddressDialog_ = false;
cr.ui.focusWithoutInk(assert(this.activeDialogAnchor_));
this.activeDialogAnchor_ = null;
@@ -316,7 +207,7 @@ Polymer({
/** @private */
onRemoteEditAddressTap_: function() {
- window.open(this.i18n('manageAddressesUrl'));
+ window.open(loadTimeData.getString('manageAddressesUrl'));
},
/**
@@ -330,107 +221,6 @@ Polymer({
},
/**
- * Opens the credit card action menu.
- * @param {!Event} e The polymer event.
- * @private
- */
- onCreditCardMenuTap_: function(e) {
- const menuEvent = /** @type {!{model: !{item: !Object}}} */ (e);
-
- /* TODO(scottchen): drop the [dataHost][dataHost] once this bug is fixed:
- https://github.com/Polymer/polymer/issues/2574 */
- // TODO(dpapad): The [dataHost][dataHost] workaround is only necessary for
- // Polymer 1. Remove once migration to Polymer 2 has completed.
- const item = Polymer.DomIf ? menuEvent.model.item :
- menuEvent.model['dataHost']['dataHost'].item;
-
- // Copy item so dialog won't update model on cancel.
- this.activeCreditCard =
- /** @type {!chrome.autofillPrivate.CreditCardEntry} */ (
- Object.assign({}, item));
-
- const dotsButton = /** @type {!HTMLElement} */ (Polymer.dom(e).localTarget);
- /** @type {!CrActionMenuElement} */ (this.$.creditCardSharedMenu)
- .showAt(dotsButton);
- this.activeDialogAnchor_ = dotsButton;
- },
-
- /**
- * Handles tapping on the "Add credit card" button.
- * @param {!Event} e
- * @private
- */
- onAddCreditCardTap_: function(e) {
- e.preventDefault();
- const date = new Date(); // Default to current month/year.
- const expirationMonth = date.getMonth() + 1; // Months are 0 based.
- this.activeCreditCard = {
- expirationMonth: expirationMonth.toString(),
- expirationYear: date.getFullYear().toString(),
- };
- this.showCreditCardDialog_ = true;
- this.activeDialogAnchor_ = this.$.addCreditCard;
- },
-
- /** @private */
- onCreditCardDialogClosed_: function() {
- this.showCreditCardDialog_ = false;
- cr.ui.focusWithoutInk(assert(this.activeDialogAnchor_));
- this.activeDialogAnchor_ = null;
- },
-
- /**
- * Handles tapping on the "Edit" credit card button.
- * @param {!Event} e The polymer event.
- * @private
- */
- onMenuEditCreditCardTap_: function(e) {
- e.preventDefault();
-
- if (this.activeCreditCard.metadata.isLocal)
- this.showCreditCardDialog_ = true;
- else
- this.onRemoteEditCreditCardTap_();
-
- this.$.creditCardSharedMenu.close();
- },
-
- /** @private */
- onRemoteEditCreditCardTap_: function() {
- window.open(this.i18n('manageCreditCardsUrl'));
- },
-
- /**
- * Handles tapping on the "Remove" credit card button.
- * @private
- */
- onMenuRemoveCreditCardTap_: function() {
- this.autofillManager_.removeCreditCard(
- /** @type {string} */ (this.activeCreditCard.guid));
- this.$.creditCardSharedMenu.close();
- },
-
- /**
- * Handles tapping on the "Clear copy" button for cached credit cards.
- * @private
- */
- onMenuClearCreditCardTap_: function() {
- this.autofillManager_.clearCachedCreditCard(
- /** @type {string} */ (this.activeCreditCard.guid));
- this.$.creditCardSharedMenu.close();
- },
-
- /**
- * The 3-dot menu should not be shown if the card is entirely remote.
- * @param {!chrome.autofillPrivate.AutofillMetadata} metadata
- * @return {boolean}
- * @private
- */
- showDots_: function(metadata) {
- return !!(metadata.isLocal || metadata.isCached);
- },
-
- /**
* Returns true if the list exists and has items.
* @param {Array<Object>} list
* @return {boolean}
@@ -448,23 +238,5 @@ Polymer({
saveAddress_: function(event) {
this.autofillManager_.saveAddress(event.detail);
},
-
- /**
- * Listens for the save-credit-card event, and calls the private API.
- * @param {!Event} event
- * @private
- */
- saveCreditCard_: function(event) {
- this.autofillManager_.saveCreditCard(event.detail);
- },
-
- /**
- * @private
- * @param {boolean} toggleValue
- * @return {string}
- */
- getOnOffLabel_: function(toggleValue) {
- return toggleValue ? this.i18n('toggleOn') : this.i18n('toggleOff');
- }
});
})();
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html
index d7228196d7f..7138118d0c4 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/credit_card_edit_dialog.html
@@ -19,7 +19,7 @@
}
.md-select + .md-select {
- -webkit-margin-start: 8px;
+ margin-inline-start: 8px;
}
/* Prevent focus-outline from being chopped by the bottom of dialog body.
@@ -54,7 +54,7 @@
<div slot="title">[[title_]]</div>
<div slot="body">
<cr-input id="nameInput" label="$i18n{creditCardName}"
- value="{{creditCard.name}}" autofocus
+ value="{{creditCard.name}}" autofocus spellcheck="false"
on-input="onCreditCardNameOrNumberChanged_">
</cr-input>
<cr-input id="numberInput" label="$i18n{creditCardNumber}"
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html
index 84ead164afc..9b7f575fca7 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_edit_dialog.html
@@ -35,8 +35,8 @@
}
paper-icon-button-light {
- -webkit-margin-start: 2px;
background-size: 24px; /* Other buttons are sized by --cr-icon-size. */
+ margin-inline-start: 2px;
}
</style>
<cr-dialog id="dialog" close-text="$i18n{close}">
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.js
index 862c1dd4dc3..0c97de354b1 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/password_list_item.js
@@ -10,14 +10,17 @@
Polymer({
is: 'password-list-item',
- behaviors: [FocusRowBehavior, ShowPasswordBehavior],
+ behaviors: [
+ FocusRowBehavior,
+ ShowPasswordBehavior,
+ ],
/**
* Selects the password on tap if revealed.
* @private
*/
onReadonlyInputTap_: function() {
- if (this.password)
+ if (this.item.password)
this.$$('#password').select();
},
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html
index 8a2376f9935..e1282d3061e 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.html
@@ -8,6 +8,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="autofill_section.html">
<link rel="import" href="passwords_section.html">
+<link rel="import" href="payments_section.html">
<link rel="import" href="../controls/extension_controlled_indicator.html">
<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../prefs/prefs.html">
@@ -27,6 +28,10 @@
id="autofillManagerButton" label="$i18n{autofill}"
sub-label="$i18n{autofillDetail}" on-click="onAutofillTap_">
</cr-link-row>
+ <cr-link-row icon-class="subpage-arrow"
+ id="paymentManagerButton" label="$i18n{creditCards}"
+ sub-label="$i18n{creditCardsDetail}" on-click="onPaymentsTap_">
+ </cr-link-row>
<div class="settings-box two-line">
<div class="start two-line" on-click="onPasswordsTap_" actionable
id="passwordManagerButton">
@@ -51,6 +56,14 @@
</settings-autofill-section>
</settings-subpage>
</template>
+ <template is="dom-if" route-path="/payments">
+ <settings-subpage
+ associated-control="[[$$('#paymentManagerButton')]]"
+ page-title="$i18n{creditCards}">
+ <settings-payments-section id="paymentSection" prefs="{{prefs}}">
+ </settings-payments-section>
+ </settings-subpage>
+ </template>
<template is="dom-if" route-path="/passwords">
<settings-subpage
associated-control="[[$$('#passwordManagerButton')]]"
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js
index b5ec2f9ad89..eadb3769d0c 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_and_forms_page.js
@@ -39,11 +39,18 @@ Polymer({
},
/**
+ * Shows the manage payment methods sub page.
+ * @private
+ */
+ onPaymentsTap_: function() {
+ settings.navigateTo(settings.routes.PAYMENTS);
+ },
+
+ /**
* Shows the manage passwords sub page.
- * @param {!Event} event
* @private
*/
- onPasswordsTap_: function(event) {
+ onPasswordsTap_: function() {
settings.navigateTo(settings.routes.MANAGE_PASSWORDS);
},
});
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_export_dialog.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_export_dialog.html
index 33e3643e397..bb85a7e20b2 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_export_dialog.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_export_dialog.html
@@ -13,7 +13,7 @@
--paper-progress-active-color: var(--google-blue-500);
}
.action-button {
- -webkit-margin-start: 8px;
+ margin-inline-start: 8px;
}
</style>
<cr-dialog id="dialog_start" close-text="$i18n{close}">
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
index c9f66d0f5d9..eafabb70dbb 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.html
@@ -30,7 +30,7 @@
* columns. It is necessary due to the absence of the "more actions"
* button in the heading.
*/
- -webkit-padding-end: calc(
+ padding-inline-end: calc(
var(--cr-icon-ripple-size) + var(--cr-icon-button-margin-start));
}
@@ -44,7 +44,7 @@
}
#exportImportMenuButtonContainer {
- -webkit-margin-end: 0;
+ margin-inline-end: 0;
}
</style>
<settings-toggle-button id="passwordToggle"
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js
index 243d81313d8..e5ec2b4ed72 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js
@@ -150,25 +150,30 @@ Polymer({
/** @override */
attached: function() {
+ // The item uid is built from index, origin, and username for the
+ // following reasons: origin and username are enough to describe and
+ // uniquely identify an entry. It is impossible to have two entries
+ // that have the same origin and username, but different passwords,
+ // as the password update logic prevents these cases. The entry is
+ // required to force a refresh of entries, after a removal or undo of
+ // a removal has taken place. All entries before the point of
+ // modification are uneffected, but the ones following need to be
+ // refreshed. Including the index in the uid achieves this effect.
+ // See https://crbug.com/862119 how this could lead to bugs otherwise.
+ const getItemUid =
+ item => [item.entry.index, item.entry.loginPair.urls.origin,
+ item.entry.loginPair.username]
+ .join('_');
+
// Create listener functions.
- const setSavedPasswordsListener = list =>
- this.updateList('savedPasswords', item => {
- // The item uid is built from index, origin, and username for the
- // following reasons: origin and username are enough to describe and
- // uniquely identify an entry. It is impossible to have two entries
- // that have the same origin and username, but different passwords,
- // as the password update logic prevents these cases. The entry is
- // required to force a refresh of entries, after a removal or undo of
- // a removal has taken place. All entries before the point of
- // modification are uneffected, but the ones following need to be
- // refreshed. Including the index in the uid achieves this effect.
- // See https://crbug.com/862119 how this could lead to bugs otherwise.
- return item.entry.index + '_' + item.entry.loginPair.urls.origin +
- '_' + item.entry.loginPair.username;
- }, list.map(entry => ({
- entry: entry,
- password: '',
- })));
+ const setSavedPasswordsListener = list => {
+ const newList = list.map(entry => ({entry: entry, password: ''}));
+ this.updateList('savedPasswords', getItemUid, newList);
+ this.savedPasswords.forEach((item, index) => {
+ item.password = '';
+ this.$.passwordList.notifyPath(`items.${index}.password`);
+ });
+ };
const setPasswordExceptionsListener = list => {
this.passwordExceptions = list;
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
index 5bcd1e903f9..62693628167 100644
--- a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
@@ -34,6 +34,19 @@
height: 20px;
width: 0;
}
+
+ .type-column {
+ align-items: center;
+ flex: 2;
+ }
+
+ .ellipses {
+ flex: 1;
+ max-width: fit-content;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
</style>
</template>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.html b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.html
new file mode 100644
index 00000000000..c35d1f829df
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.html
@@ -0,0 +1,154 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="../i18n_setup.html">
+<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="../controls/settings_toggle_button.html">
+<link rel="import" href="../prefs/prefs.html">
+<link rel="import" href="../people_page/sync_browser_proxy.html">
+<link rel="import" href="credit_card_edit_dialog.html">
+<link rel="import" href="passwords_shared_css.html">
+
+<dom-module id="settings-payments-section">
+ <template>
+ <style include="settings-shared passwords-shared">
+ .expiration-column {
+ align-items: center;
+ display: flex;
+ flex: 1;
+ }
+
+ .expiration-date {
+ flex: 1;
+ }
+
+ .payments-label {
+ color: var(--cr-secondary-text-color);
+ margin-inline-start: 16px;
+ }
+
+ #migrateCreditCards {
+ border-bottom: var(--settings-separator-line);
+ border-top: none;
+ }
+
+ #migrateCreditCardsButton {
+ margin: 0 auto;
+ }
+ </style>
+ <settings-toggle-button id="autofillCreditCardToggle"
+ class="settings-box first"
+ aria-label="$i18n{creditCards}" no-extension-indicator
+ label="$i18n{enableCreditCardsLabel}"
+ sub-label="$i18n{enableCreditCardsSublabel}"
+ pref="{{prefs.autofill.credit_card_enabled}}">
+ </settings-toggle-button>
+ <template is="dom-if"
+ if="[[prefs.autofill.credit_card_enabled.extensionId]]">
+ <div class="settings-box continuation">
+ <extension-controlled-indicator class="start"
+ id="autofillExtensionIndicator"
+ extension-id="[[prefs.autofill.credit_card_enabled.extensionId]]"
+ extension-name="[[
+ prefs.autofill.credit_card_enabled.controlledByName]]"
+ extension-can-be-disabled="[[
+ prefs.autofill.credit_card_enabled.extensionCanBeDisabled]]">
+ </extension-controlled-indicator>
+ </div>
+ </template>
+ <div class="settings-box continuation">
+ <h2 class="start">$i18n{creditCards}</h2>
+ <paper-button id="addCreditCard"
+ class="secondary-button header-aligned-button"
+ on-click="onAddCreditCardTap_"
+ disabled$="[[!prefs.autofill.credit_card_enabled.value]]">
+ $i18n{add}
+ </paper-button>
+ </div>
+ <div class="settings-box two-line" id="migrateCreditCards"
+ hidden$="[[!checkIfMigratable_(syncStatus, creditCards,
+ prefs.autofill.credit_card_enabled.value)]]"
+ on-click="onMigrateCreditCardsClick_" actionable>
+ <div class="start">
+ [[migrateCreditCardsLabel_]]
+ <div class="secondary">
+ [[migratableCreditCardsInfo_]]
+ </div>
+ </div>
+ <paper-icon-button-light id="migrateCreditCardsButton"
+ class="subpage-arrow">
+ <button aria-label="[[migrateCreditCardsLabel_]]"></button>
+ </paper-icon-button-light>
+ </div>
+ <div class="list-frame">
+ <div id="creditCardsHeading" class="list-item column-header"
+ hidden$="[[!hasSome_(creditCards)]]">
+ <div class="type-column">$i18n{creditCardType}</div>
+ <div class="expiration-column">$i18n{creditCardExpiration}</div>
+ </div>
+ <div id="creditCardList" class="vertical-list list-with-header">
+ <template is="dom-repeat" items="[[creditCards]]">
+ <div class="list-item">
+ <div class="type-column">
+ <span id="creditCardLabel">[[item.metadata.summaryLabel]]</span>
+ <span class="payments-label"
+ hidden$="[[item.metadata.isLocal]]">
+ <span hidden$="[[item.metadata.isCached]]">
+ $i18n{googlePayments}
+ </span>
+ <span hidden$="[[!item.metadata.isCached]]">
+ $i18n{googlePaymentsCached}
+ </span>
+ </span>
+ </div>
+ <div class="expiration-column">
+ <div id="creditCardExpiration"
+ class="expiration-date">[[expiration_(item)]]</div>
+ <template is="dom-if" if="[[showDots_(item.metadata)]]">
+ <paper-icon-button-light class="icon-more-vert">
+ <button id="creditCardMenu" title="$i18n{moreActions}"
+ on-click="onCreditCardMenuTap_">
+ </button>
+ </paper-icon-button-light>
+ </template>
+ <template is="dom-if" if="[[!showDots_(item.metadata)]]">
+ <paper-icon-button-light actionable class="icon-external">
+ <button id="remoteCreditCardLink"
+ on-click="onRemoteEditCreditCardTap_">
+ </button>
+ </paper-icon-button-light>
+ </template>
+ </div>
+ </div>
+ </template>
+ </div>
+ <div id="noCreditCardsLabel" class="list-item"
+ hidden$="[[hasSome_(creditCards)]]">
+ $i18n{noCreditCardsFound}
+ </div>
+ </div>
+ <cr-action-menu id="creditCardSharedMenu">
+ <button id="menuEditCreditCard" slot="item" class="dropdown-item"
+ on-click="onMenuEditCreditCardTap_">$i18n{edit}</button>
+ <button id="menuRemoveCreditCard" slot="item" class="dropdown-item"
+ hidden$="[[!activeCreditCard.metadata.isLocal]]"
+ on-click="onMenuRemoveCreditCardTap_">$i18n{removeCreditCard}</button>
+ <button id="menuClearCreditCard" slot="item" class="dropdown-item"
+ on-click="onMenuClearCreditCardTap_"
+ hidden$="[[!activeCreditCard.metadata.isCached]]">
+ $i18n{clearCreditCard}
+ </button>
+ </cr-action-menu>
+ <template is="dom-if" if="[[showCreditCardDialog_]]" restamp>
+ <settings-credit-card-edit-dialog credit-card="[[activeCreditCard]]"
+ on-close="onCreditCardDialogClose_">
+ </settings-credit-card-edit-dialog>
+ </template>
+ </template>
+ <script src="payments_section.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.js b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.js
new file mode 100644
index 00000000000..e3c141a86b1
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/passwords_and_forms_page/payments_section.js
@@ -0,0 +1,421 @@
+// Copyright 2018 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 'settings-payments-section' is the section containing saved
+ * credit cards for use in autofill and payments APIs.
+ */
+
+/**
+ * Interface for all callbacks to the payments autofill API.
+ * @interface
+ */
+class PaymentsManager {
+ /**
+ * Add an observer to the list of credit cards.
+ * @param {function(!Array<!PaymentsManager.CreditCardEntry>):void} listener
+ */
+ addCreditCardListChangedListener(listener) {}
+
+ /**
+ * Remove an observer from the list of credit cards.
+ * @param {function(!Array<!PaymentsManager.CreditCardEntry>):void} listener
+ */
+ removeCreditCardListChangedListener(listener) {}
+
+ /**
+ * Request the list of credit cards.
+ * @param {function(!Array<!PaymentsManager.CreditCardEntry>):void} callback
+ */
+ getCreditCardList(callback) {}
+
+ /** @param {string} guid The GUID of the credit card to remove. */
+ removeCreditCard(guid) {}
+
+ /** @param {string} guid The GUID to credit card to remove from the cache. */
+ clearCachedCreditCard(guid) {}
+
+ /**
+ * Saves the given credit card.
+ * @param {!PaymentsManager.CreditCardEntry} creditCard
+ */
+ saveCreditCard(creditCard) {}
+
+ /**
+ * Migrate the local credit cards.
+ */
+ migrateCreditCards() {}
+}
+
+/** @typedef {chrome.autofillPrivate.CreditCardEntry} */
+PaymentsManager.CreditCardEntry;
+
+/**
+ * Implementation that accesses the private API.
+ * @implements {PaymentsManager}
+ */
+class PaymentsManagerImpl {
+ /** @override */
+ addCreditCardListChangedListener(listener) {
+ chrome.autofillPrivate.onCreditCardListChanged.addListener(listener);
+ }
+
+ /** @override */
+ removeCreditCardListChangedListener(listener) {
+ chrome.autofillPrivate.onCreditCardListChanged.removeListener(listener);
+ }
+
+ /** @override */
+ getCreditCardList(callback) {
+ chrome.autofillPrivate.getCreditCardList(callback);
+ }
+
+ /** @override */
+ removeCreditCard(guid) {
+ chrome.autofillPrivate.removeEntry(assert(guid));
+ }
+
+ /** @override */
+ clearCachedCreditCard(guid) {
+ chrome.autofillPrivate.maskCreditCard(assert(guid));
+ }
+
+ /** @override */
+ saveCreditCard(creditCard) {
+ chrome.autofillPrivate.saveCreditCard(creditCard);
+ }
+
+ /** @override */
+ migrateCreditCards() {
+ chrome.autofillPrivate.migrateCreditCards();
+ }
+}
+
+cr.addSingletonGetter(PaymentsManagerImpl);
+
+(function() {
+'use strict';
+
+Polymer({
+ is: 'settings-payments-section',
+
+ behaviors: [
+ WebUIListenerBehavior,
+ I18nBehavior,
+ ],
+
+ properties: {
+ /**
+ * An array of saved credit cards.
+ * @type {!Array<!PaymentsManager.CreditCardEntry>}
+ */
+ creditCards: Array,
+
+ /**
+ * The model for any credit card related action menus or dialogs.
+ * @private {?chrome.autofillPrivate.CreditCardEntry}
+ */
+ activeCreditCard: Object,
+
+ /** @private */
+ showCreditCardDialog_: Boolean,
+
+ /** @private */
+ migrateCreditCardsLabel_: String,
+
+ /** @private */
+ migratableCreditCardsInfo_: String,
+
+ /**
+ * The current sync status, supplied by SyncBrowserProxy.
+ * @type {?settings.SyncStatus}
+ */
+ syncStatus: Object,
+
+ /**
+ * Whether migration local card on settings page is enabled.
+ * @private
+ */
+ migrationEnabled_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('migrationEnabled');
+ },
+ readOnly: true,
+ },
+
+ /**
+ * Whether user has a Google Payments account.
+ * @private
+ */
+ hasGooglePaymentsAccount_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('hasGooglePaymentsAccount');
+ },
+ readOnly: true,
+ },
+ },
+
+ listeners: {
+ 'save-credit-card': 'saveCreditCard_',
+ },
+
+ /**
+ * The element to return focus to, when the currently active dialog is
+ * closed.
+ * @private {?HTMLElement}
+ */
+ activeDialogAnchor_: null,
+
+ /**
+ * @type {PaymentsManager}
+ * @private
+ */
+ PaymentsManager_: null,
+
+ /**
+ * @type {?function(!Array<!PaymentsManager.CreditCardEntry>)}
+ * @private
+ */
+ setCreditCardsListener_: null,
+
+ /** @private {?settings.SyncBrowserProxy} */
+ syncBrowserProxy_: null,
+
+ /** @override */
+ attached: function() {
+ // Create listener function.
+ /** @type {function(!Array<!PaymentsManager.CreditCardEntry>)} */
+ const setCreditCardsListener = list => {
+ this.creditCards = list;
+ };
+
+ // Remember the bound reference in order to detach.
+ this.setCreditCardsListener_ = setCreditCardsListener;
+
+ // Set the managers. These can be overridden by tests.
+ this.paymentsManager_ = PaymentsManagerImpl.getInstance();
+
+ // Request initial data.
+ this.paymentsManager_.getCreditCardList(setCreditCardsListener);
+
+ // Listen for changes.
+ this.paymentsManager_.addCreditCardListChangedListener(
+ setCreditCardsListener);
+
+ this.syncBrowserProxy_ = settings.SyncBrowserProxyImpl.getInstance();
+ this.syncBrowserProxy_.getSyncStatus().then(
+ this.handleSyncStatus_.bind(this));
+ this.addWebUIListener(
+ 'sync-status-changed', this.handleSyncStatus_.bind(this));
+ },
+
+ /** @override */
+ detached: function() {
+ this.paymentsManager_.removeCreditCardListChangedListener(
+ /** @type {function(!Array<!PaymentsManager.CreditCardEntry>)} */ (
+ this.setCreditCardsListener_));
+ },
+
+ /**
+ * Formats the expiration date so it's displayed as MM/YYYY.
+ * @param {!chrome.autofillPrivate.CreditCardEntry} item
+ * @return {string}
+ * @private
+ */
+ expiration_: function(item) {
+ return item.expirationMonth + '/' + item.expirationYear;
+ },
+
+ /**
+ * Opens the credit card action menu.
+ * @param {!Event} e The polymer event.
+ * @private
+ */
+ onCreditCardMenuTap_: function(e) {
+ const menuEvent = /** @type {!{model: !{item: !Object}}} */ (e);
+
+ /* TODO(scottchen): drop the [dataHost][dataHost] once this bug is fixed:
+ https://github.com/Polymer/polymer/issues/2574 */
+ // TODO(dpapad): The [dataHost][dataHost] workaround is only necessary for
+ // Polymer 1. Remove once migration to Polymer 2 has completed.
+ const item = Polymer.DomIf ? menuEvent.model.item :
+ menuEvent.model['dataHost']['dataHost'].item;
+
+ // Copy item so dialog won't update model on cancel.
+ this.activeCreditCard =
+ /** @type {!chrome.autofillPrivate.CreditCardEntry} */ (
+ Object.assign({}, item));
+
+ const dotsButton = /** @type {!HTMLElement} */ (Polymer.dom(e).localTarget);
+ /** @type {!CrActionMenuElement} */ (this.$.creditCardSharedMenu)
+ .showAt(dotsButton);
+ this.activeDialogAnchor_ = dotsButton;
+ },
+
+ /**
+ * Handles tapping on the "Add credit card" button.
+ * @param {!Event} e
+ * @private
+ */
+ onAddCreditCardTap_: function(e) {
+ e.preventDefault();
+ const date = new Date(); // Default to current month/year.
+ const expirationMonth = date.getMonth() + 1; // Months are 0 based.
+ this.activeCreditCard = {
+ expirationMonth: expirationMonth.toString(),
+ expirationYear: date.getFullYear().toString(),
+ };
+ this.showCreditCardDialog_ = true;
+ this.activeDialogAnchor_ = this.$.addCreditCard;
+ },
+
+ /** @private */
+ onCreditCardDialogClose_: function() {
+ this.showCreditCardDialog_ = false;
+ cr.ui.focusWithoutInk(assert(this.activeDialogAnchor_));
+ this.activeDialogAnchor_ = null;
+ this.activeCreditCard = null;
+ },
+
+ /**
+ * Handles tapping on the "Edit" credit card button.
+ * @param {!Event} e The polymer event.
+ * @private
+ */
+ onMenuEditCreditCardTap_: function(e) {
+ e.preventDefault();
+
+ if (this.activeCreditCard.metadata.isLocal)
+ this.showCreditCardDialog_ = true;
+ else
+ this.onRemoteEditCreditCardTap_();
+
+ this.$.creditCardSharedMenu.close();
+ },
+
+ /** @private */
+ onRemoteEditCreditCardTap_: function() {
+ window.open(loadTimeData.getString('manageCreditCardsUrl'));
+ },
+
+ /**
+ * Handles tapping on the "Remove" credit card button.
+ * @private
+ */
+ onMenuRemoveCreditCardTap_: function() {
+ this.paymentsManager_.removeCreditCard(
+ /** @type {string} */ (this.activeCreditCard.guid));
+ this.$.creditCardSharedMenu.close();
+ this.activeCreditCard = null;
+ },
+
+ /**
+ * Handles tapping on the "Clear copy" button for cached credit cards.
+ * @private
+ */
+ onMenuClearCreditCardTap_: function() {
+ this.paymentsManager_.clearCachedCreditCard(
+ /** @type {string} */ (this.activeCreditCard.guid));
+ this.$.creditCardSharedMenu.close();
+ this.activeCreditCard = null;
+ },
+
+ /**
+ * Handles clicking on the "Migrate" button for migrate local credit cards.
+ * @private
+ */
+ onMigrateCreditCardsClick_: function() {
+ this.paymentsManager_.migrateCreditCards();
+ },
+
+ /**
+ * The 3-dot menu should not be shown if the card is entirely remote.
+ * @param {!chrome.autofillPrivate.AutofillMetadata} metadata
+ * @return {boolean}
+ * @private
+ */
+ showDots_: function(metadata) {
+ return !!(metadata.isLocal || metadata.isCached);
+ },
+
+ /**
+ * Returns true if the list exists and has items.
+ * @param {Array<Object>} list
+ * @return {boolean}
+ * @private
+ */
+ hasSome_: function(list) {
+ return !!(list && list.length);
+ },
+
+ /**
+ * Listens for the save-credit-card event, and calls the private API.
+ * @param {!Event} event
+ * @private
+ */
+ saveCreditCard_: function(event) {
+ this.paymentsManager_.saveCreditCard(event.detail);
+ },
+
+ /**
+ * Handler for when the sync state is pushed from the browser.
+ * @param {?settings.SyncStatus} syncStatus
+ * @private
+ */
+ handleSyncStatus_: function(syncStatus) {
+ this.syncStatus = syncStatus;
+ },
+
+ /**
+ * @param {!settings.SyncStatus} syncStatus
+ * @param {!Array<!PaymentsManager.CreditCardEntry>} creditCards
+ * @param {boolean} creditCardEnabled
+ * @return {boolean} Whether to show the migration button. True iff at least
+ * one valid local card, enable migration, signed-in & synced and credit card
+ * pref enabled.
+ * @private
+ */
+ checkIfMigratable_: function(syncStatus, creditCards, creditCardEnabled) {
+ if (syncStatus == undefined)
+ return false;
+
+ // If user not enable migration experimental flag, return false.
+ if (!this.migrationEnabled_)
+ return false;
+
+ // If user does not have Google Payments Account, return false.
+ if (!this.hasGooglePaymentsAccount_)
+ return false;
+
+ // If credit card enabled pref is false, return false.
+ if (!creditCardEnabled)
+ return false;
+
+ // If user not signed-in and synced, return false.
+ if (!syncStatus.signedIn || !syncStatus.syncSystemEnabled)
+ return false;
+
+ let numberOfMigratableCreditCard =
+ creditCards.filter(card => card.metadata.isMigratable).length;
+ // Check whether exist at least one local valid card for migration.
+ if (numberOfMigratableCreditCard == 0)
+ return false;
+
+ // Update the display label depends on the number of migratable credit
+ // cards.
+ this.migrateCreditCardsLabel_ = numberOfMigratableCreditCard == 1 ?
+ this.i18n('migrateCreditCardsLabelSingle') :
+ this.i18n('migrateCreditCardsLabelMultiple');
+ // Update the display text depends on the number of migratable credit cards.
+ this.migratableCreditCardsInfo_ = numberOfMigratableCreditCard == 1 ?
+ this.i18n('migratableCardsInfoSingle') :
+ this.i18n('migratableCardsInfoMultiple');
+
+ return true;
+ },
+
+});
+})();
diff --git a/chromium/chrome/browser/resources/settings/people_page/BUILD.gn b/chromium/chrome/browser/resources/settings/people_page/BUILD.gn
index 6426f36e0e8..c2f8cc39834 100644
--- a/chromium/chrome/browser/resources/settings/people_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/people_page/BUILD.gn
@@ -14,19 +14,19 @@ js_type_check("closure_compile") {
":easy_unlock_turn_off_dialog",
":fingerprint_browser_proxy",
":fingerprint_list",
- ":fingerprint_progress_arc",
":import_data_browser_proxy",
":import_data_dialog",
":lock_screen",
":lock_screen_constants",
+ ":lock_screen_password_prompt_dialog",
":lock_state_behavior",
":manage_profile",
":manage_profile_browser_proxy",
- ":password_prompt_dialog",
":people_page",
":profile_info_browser_proxy",
":setup_fingerprint_dialog",
":setup_pin_dialog",
+ ":signout_dialog",
":sync_account_control",
":sync_browser_proxy",
":sync_page",
@@ -110,12 +110,6 @@ js_library("fingerprint_list") {
externs_list = [ "$externs_path/web_animations.js" ]
}
-js_library("fingerprint_progress_arc") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
-}
-
js_library("import_data_browser_proxy") {
deps = [
"//ui/webui/resources/js:cr",
@@ -128,8 +122,8 @@ js_library("lock_screen") {
":easy_unlock_turn_off_dialog",
":fingerprint_browser_proxy",
":lock_screen_constants",
+ ":lock_screen_password_prompt_dialog",
":lock_state_behavior",
- ":password_prompt_dialog",
"..:route",
"../controls:settings_dropdown_menu",
"../controls:settings_toggle_button",
@@ -176,14 +170,12 @@ js_library("manage_profile_browser_proxy") {
]
}
-js_library("password_prompt_dialog") {
+js_library("lock_screen_password_prompt_dialog") {
deps = [
":lock_screen_constants",
- "..:route",
- "//ui/webui/resources/cr_elements/cr_input:cr_input",
+ ":lock_state_behavior",
+ "../controls:password_prompt_dialog",
]
- externs_list = [ "$externs_path/quick_unlock_private.js" ]
- extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ]
}
js_library("people_page") {
@@ -192,6 +184,7 @@ js_library("people_page") {
":lock_screen_constants",
":lock_state_behavior",
":profile_info_browser_proxy",
+ ":signout_dialog",
":sync_browser_proxy",
"..:page_visibility",
"..:route",
@@ -216,7 +209,7 @@ js_library("profile_info_browser_proxy") {
js_library("setup_fingerprint_dialog") {
deps = [
":fingerprint_browser_proxy",
- ":fingerprint_progress_arc",
+ "//ui/webui/resources/cr_elements/chromeos/fingerprint:cr_fingerprint_progress_arc",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
@@ -225,12 +218,25 @@ js_library("setup_fingerprint_dialog") {
js_library("setup_pin_dialog") {
deps = [
":lock_screen_constants",
- ":password_prompt_dialog",
+ ":lock_screen_password_prompt_dialog",
"..:route",
"//ui/webui/resources/js:i18n_behavior",
]
}
+js_library("signout_dialog") {
+ deps = [
+ ":profile_info_browser_proxy",
+ ":sync_browser_proxy",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
+ "//ui/webui/resources/cr_elements/cr_expand_button:cr_expand_button",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:util",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
js_library("sync_page") {
deps = [
":sync_browser_proxy",
diff --git a/chromium/chrome/browser/resources/settings/people_page/account_manager.html b/chromium/chrome/browser/resources/settings/people_page/account_manager.html
index 95750103025..f910659d1b4 100644
--- a/chromium/chrome/browser/resources/settings/people_page/account_manager.html
+++ b/chromium/chrome/browser/resources/settings/people_page/account_manager.html
@@ -1,9 +1,12 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/icon.html">
<link rel="import" href="chrome://resources/html/util.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.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/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../route.html">
<link rel="import" href="../settings_shared_css.html">
@@ -35,7 +38,7 @@
<h2>$i18n{accountListHeader}</h2>
</div>
<div id="outer" class="layout vertical nowrap">
- <template is="dom-repeat" items="[[accounts_]]">
+ <template is="dom-repeat" id="account-list" items="[[accounts_]]">
<div class="settings-box">
<div class="profile-icon"
style="background-image: [[getIconImageSet_(item.pic)]]"></div>
@@ -45,12 +48,25 @@
<div class="secondary">[[item.email]]</div>
</div>
</div>
+ <paper-icon-button-light class="icon-more-vert"
+ hidden="[[item.isDeviceAccount]]">
+ <button title="$i18n{moreActions}"
+ on-click="onAccountActionsMenuButtonTap_">
+ </button>
+ </paper-icon-button-light>
</div>
</template>
<div id="add-account-button" class="settings-box" on-tap="addAccount_">
$i18n{addAccountLabel}
</div>
<div class="clear settings-box"></div>
+
+ <cr-action-menu>
+ <button slot="item" class="dropdown-item"
+ on-click="onRemoveAccountTap_">
+ $i18n{removeAccountLabel}
+ </button>
+ </cr-action-menu>
</div>
</template>
<script src="account_manager.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/people_page/account_manager.js b/chromium/chrome/browser/resources/settings/people_page/account_manager.js
index f0c6ae8e166..e754d4ca049 100644
--- a/chromium/chrome/browser/resources/settings/people_page/account_manager.js
+++ b/chromium/chrome/browser/resources/settings/people_page/account_manager.js
@@ -27,6 +27,12 @@ Polymer({
return [];
},
},
+
+ /**
+ * The targeted account for menu operations.
+ * @private {?settings.Account}
+ */
+ actionMenuAccount_: Object,
},
/** @private {?settings.AccountManagerBrowserProxy} */
@@ -68,4 +74,34 @@ Polymer({
this.set('accounts_', accounts);
});
},
+
+ /**
+ * Opens the Account actions menu.
+ * @param {!{model: !{item: settings.Account}, target: !Element}} event
+ * @private
+ */
+ onAccountActionsMenuButtonTap_: function(event) {
+ this.actionMenuAccount_ = event.model.item;
+ /** @type {!CrActionMenuElement} */ (this.$$('cr-action-menu'))
+ .showAt(event.target);
+ },
+
+ /**
+ * Closes action menu and resets action menu model.
+ * @private
+ */
+ closeActionMenu_: function() {
+ this.$$('cr-action-menu').close();
+ this.actionMenuAccount_ = null;
+ },
+
+ /**
+ * Removes the account being pointed to by |this.actionMenuAccount_|.
+ * @private
+ */
+ onRemoveAccountTap_: function() {
+ this.browserProxy_.removeAccount(
+ /** @type {?settings.Account} */ (this.actionMenuAccount_));
+ this.closeActionMenu_();
+ }
});
diff --git a/chromium/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js b/chromium/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
index c1257ade2d5..0c5f2e48723 100644
--- a/chromium/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
@@ -12,6 +12,9 @@ cr.exportPath('settings');
/**
* Information for an account managed by Chrome OS AccountManager.
* @typedef {{
+ * id: string,
+ * accountType: number,
+ * isDeviceAccount: boolean,
* fullName: string,
* email: string,
* pic: string,
@@ -32,6 +35,12 @@ cr.define('settings', function() {
* Triggers the 'Add account' flow.
*/
addAccount() {}
+
+ /**
+ * Removes |account| from Account Manager.
+ * @param {?settings.Account} account
+ */
+ removeAccount(account) {}
}
/**
@@ -47,6 +56,11 @@ cr.define('settings', function() {
addAccount() {
chrome.send('addAccount');
}
+
+ /** @override */
+ removeAccount(account) {
+ chrome.send('removeAccount', [account]);
+ }
}
cr.addSingletonGetter(AccountManagerBrowserProxyImpl);
diff --git a/chromium/chrome/browser/resources/settings/people_page/change_picture.html b/chromium/chrome/browser/resources/settings/people_page/change_picture.html
index f14495a8af7..941efeb015c 100644
--- a/chromium/chrome/browser/resources/settings/people_page/change_picture.html
+++ b/chromium/chrome/browser/resources/settings/people_page/change_picture.html
@@ -25,15 +25,15 @@
}
#title {
- -webkit-margin-start: 20px;
height: var(--title-height);
+ margin-inline-start: 20px;
padding-top: var(--title-padding);
}
#container {
- -webkit-margin-start: 20px;
align-items: flex-start;
display: flex;
+ margin-inline-start: 20px;
position: absolute;
top: calc(var(--cr-settings-header-height) +
var(--title-padding) +
@@ -42,9 +42,9 @@
#picturePane {
--cr-picture-image-size: 192px;
- -webkit-margin-end: 24px;
flex-shrink: 0;
height: 288px;
+ margin-inline-end: 24px;
margin-top: 6px;
position: relative;
width: 288px;
@@ -58,7 +58,6 @@
}
#pictureList {
- -webkit-margin-end: 16px;
/* TODO(reveman): Find a way to have height align to viewport
without using fixed position. */
height: calc(100vh -
@@ -66,6 +65,7 @@
var(--cr-settings-header-height) -
var(--title-padding) -
var(--title-height));
+ margin-inline-end: 16px;
margin-top: 0;
min-height: 332px;
overflow-x: hidden;
diff --git a/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html b/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html
index b0168a44cf2..42d5e7fa77c 100644
--- a/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html
+++ b/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.html
@@ -72,7 +72,8 @@
<template is="dom-if" if="[[showSetupFingerprintDialog_]]" restamp>
<settings-setup-fingerprint-dialog
on-add-fingerprint="updateFingerprintsList_"
- on-close="onSetupFingerprintDialogClose_">
+ on-close="onSetupFingerprintDialogClose_"
+ allow-add-another-finger="[[allowAddAnotherFinger_]]">
</settings-setup-fingerprint-dialog>
</template>
</template>
diff --git a/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js b/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js
index ea245c45cc3..7c4ec5f1156 100644
--- a/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js
+++ b/chromium/chrome/browser/resources/settings/people_page/fingerprint_list.js
@@ -35,6 +35,16 @@ Polymer({
/** @private */
showSetupFingerprintDialog_: Boolean,
+
+ /**
+ * Whether add another finger is allowed.
+ * @type {boolean}
+ * @private
+ */
+ allowAddAnotherFinger_: {
+ type: Boolean,
+ value: true,
+ },
},
/** @private {?settings.FingerprintBrowserProxy} */
@@ -118,6 +128,7 @@ Polymer({
// Update iron-list.
this.fingerprints_ = fingerprintInfo.fingerprintsList.slice();
this.$$('.action-button').disabled = fingerprintInfo.isMaxed;
+ this.allowAddAnotherFinger_ = !fingerprintInfo.isMaxed;
},
/**
diff --git a/chromium/chrome/browser/resources/settings/people_page/fingerprint_progress_arc.html b/chromium/chrome/browser/resources/settings/people_page/fingerprint_progress_arc.html
deleted file mode 100644
index cb18a85530e..00000000000
--- a/chromium/chrome/browser/resources/settings/people_page/fingerprint_progress_arc.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<dom-module id="settings-fingerprint-progress-arc">
- <template>
- <style>
- #canvas {
- height: 100%;
- vertical-align: bottom;
- width: 100%;
- }
-
- #canvasDiv {
- height: var(--canvas-height);
- width: var(--canvas-width);
- }
- </style>
-
- <div id="canvasDiv">
- <canvas id="canvas"></canvas>
- </div>
- </template>
- <script src="fingerprint_progress_arc.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/people_page/fingerprint_progress_arc.js b/chromium/chrome/browser/resources/settings/people_page/fingerprint_progress_arc.js
deleted file mode 100644
index 2b3c38c77cc..00000000000
--- a/chromium/chrome/browser/resources/settings/people_page/fingerprint_progress_arc.js
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2017 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.
-
-(function() {
-
-/**
- * The time in milliseconds of the animation updates.
- * @type {number}
- */
-const ANIMATE_TICKS_MS = 20;
-
-/**
- * The duration in milliseconds of the animation of the progress circle when the
- * user is touching the scanner.
- * @type {number}
- */
-const ANIMATE_DURATION_MS = 200;
-
-/**
- * The radius of the add fingerprint progress circle.
- * @type {number}
- */
-const CANVAS_CIRCLE_RADIUS = 50;
-
-/**
- * The thickness of the add fingerprint progress circle.
- * @type {number}
- */
-const CANVAS_CIRCLE_STROKE_WIDTH = 4;
-
-/**
- * The color of the canvas circle background.
- * @type {string}
- */
-const CANVAS_CIRCLE_BACKGROUND_COLOR = 'rgba(66, 66, 66, 1.0)';
-
-/**
- * The color of the arc/circle which indicates setup progress.
- * @type {string}
- */
-const CANVAS_CIRCLE_PROGRESS_COLOR = 'rgba(53, 103, 214, 1.0)';
-
-/**
- * The color of the canvas circle shadow.
- * @type {string}
- */
-const CANVAS_CIRCLE_SHADOW_COLOR = 'rgba(0, 0, 0, 0.5)';
-
-Polymer({
- is: 'settings-fingerprint-progress-arc',
-
- // Also put these values as member values so they can be overriden by tests
- // and the tests do not need to be changed every time the UI is.
- /** @private {number} */
- canvasCircleRadius_: CANVAS_CIRCLE_RADIUS,
- /** @private {number} */
- canvasCircleStrokeWidth_: CANVAS_CIRCLE_STROKE_WIDTH,
- /** @private {string} */
- canvasCircleBackgroundColor_: CANVAS_CIRCLE_BACKGROUND_COLOR,
- /** @private {string} */
- canvasCircleProgressColor_: CANVAS_CIRCLE_PROGRESS_COLOR,
- /** @private {string} */
- canvasCircleShadowColor_: CANVAS_CIRCLE_SHADOW_COLOR,
-
- /**
- * Draws an arc on the canvas element around the center with radius
- * |CANVAS_CIRCLE_RADIUS|.
- * @param {number} startAngle The start angle of the arc we want to draw.
- * @param {number} endAngle The end angle of the arc we want to draw.
- * @param {string} color The color of the arc we want to draw. The string is
- * in the format rgba(r',g',b',a'). r', g', b' are values from [0-255]
- * and a' is a value from [0-1].
- */
- drawArc: function(startAngle, endAngle, color) {
- const c = this.$.canvas;
- const ctx = c.getContext('2d');
-
- ctx.beginPath();
- ctx.arc(
- c.width / 2, c.height / 2, this.canvasCircleRadius_, startAngle,
- endAngle);
- ctx.lineWidth = this.canvasCircleStrokeWidth_;
- ctx.strokeStyle = color;
- ctx.stroke();
- },
-
- /**
- * Draws a circle on the canvas element around the center with radius
- * |CANVAS_CIRCLE_RADIUS| and color |CANVAS_CIRCLE_BACKGROUND_COLOR|.
- */
- drawBackgroundCircle: function() {
- this.drawArc(0, 2 * Math.PI, this.canvasCircleBackgroundColor_);
- },
-
- /**
- * Draws a circular shadow around the center with radius
- * |CANVAS_CIRCLE_RADIUS|.
- * @param {number} blur
- * @param {number} offsetX
- * @param {number} offsetY
- */
- drawShadow: function(blur, offsetX, offsetY) {
- const c = this.$.canvas;
- const ctx = c.getContext('2d');
-
- ctx.beginPath();
- ctx.translate(-c.width, 0);
- ctx.shadowOffsetX = c.width + offsetX;
- ctx.shadowOffsetY = 0;
- ctx.shadowColor = this.canvasCircleShadowColor_;
- ctx.shadowBlur = blur;
- ctx.arc(
- c.width / 2, c.height / 2,
- this.canvasCircleRadius_ - this.canvasCircleStrokeWidth_ / 2 + blur / 2,
- 0, 2 * Math.PI);
- ctx.stroke();
- ctx.translate(c.width, 0);
- },
-
- /**
- * Animates the progress the circle. Animates an arc that starts at the top of
- * the circle to startAngle, to an arc that starts at the top of the circle to
- * endAngle.
- * @param {number} startAngle The start angle of the arc we want to draw.
- * @param {number} endAngle The end angle of the arc we want to draw.
- */
- animateProgress: function(startAngle, endAngle) {
- let currentAngle = startAngle;
- // The value to update the angle by each tick.
- const step =
- (endAngle - startAngle) / (ANIMATE_DURATION_MS / ANIMATE_TICKS_MS);
- const id = setInterval(doAnimate.bind(this), ANIMATE_TICKS_MS);
- // Circles on html canvas have 0 radians on the positive x-axis and go in
- // clockwise direction. We want to start at the top of the circle which is
- // 3pi/2.
- const start = 3 * Math.PI / 2;
-
- // Function that is called every tick of the interval, draws the arc a bit
- // closer to the final destination each tick, until it reaches the final
- // destination.
- function doAnimate() {
- if (currentAngle >= endAngle)
- clearInterval(id);
-
- // Clears the canvas and draws the new progress circle.
- this.clearCanvas();
- // Drawing two arcs to form a circle gives a nicer look than drawing an
- // arc on top of a circle. If |currentAngle| is 0, draw from |start| +
- // |currentAngle| to 7 * Math.PI / 2 (start is 3 * Math.PI / 2) otherwise
- // the regular draw from |start| to |currentAngle| will draw nothing which
- // will cause a flicker for one frame.
- this.drawArc(
- start, start + currentAngle, this.canvasCircleProgressColor_);
- this.drawArc(
- start + currentAngle, currentAngle <= 0 ? 7 * Math.PI / 2 : start,
- this.canvasCircleBackgroundColor_);
- currentAngle += step;
- }
- },
-
- /**
- * Clear the canvas of any renderings.
- */
- clearCanvas: function() {
- const c = this.$.canvas;
- const ctx = c.getContext('2d');
- ctx.clearRect(0, 0, c.width, c.height);
- },
-});
-})();
diff --git a/chromium/chrome/browser/resources/settings/people_page/lock_screen.html b/chromium/chrome/browser/resources/settings/people_page/lock_screen.html
index 49195e5e113..ef82ae02f76 100644
--- a/chromium/chrome/browser/resources/settings/people_page/lock_screen.html
+++ b/chromium/chrome/browser/resources/settings/people_page/lock_screen.html
@@ -13,7 +13,7 @@
<link rel="import" href="fingerprint_browser_proxy.html">
<link rel="import" href="lock_screen_constants.html">
<link rel="import" href="lock_state_behavior.html">
-<link rel="import" href="password_prompt_dialog.html">
+<link rel="import" href="lock_screen_password_prompt_dialog.html">
<link rel="import" href="setup_pin_dialog.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../prefs/prefs_behavior.html">
@@ -26,7 +26,7 @@
<template>
<style include="settings-shared">
cr-policy-indicator {
- -webkit-margin-start: auto;
+ margin-inline-start: auto;
/* Align the indicator with the h2 that it is associated with. */
padding-bottom: 12px;
padding-top: 24px;
@@ -126,32 +126,50 @@
</div>
</template>
+ <template is="dom-if" if="[[lockScreenNotificationsEnabled_]]">
+ <h2 class="settings-box">
+ $i18n{lockScreenNotificationTitle}
+ </h2>
+ <div class="list-frame">
+ <settings-radio-group
+ pref="{{prefs.ash.message_center.lock_screen_mode}}"
+ selectable="cr-radio-button">
+ <template is="dom-if"
+ if="[[lockScreenHideSensitiveNotificationSupported_]]">
+ <cr-radio-button name="hideSensitive" class="list-item underbar"
+ pref="[[prefs.ash.message_center.lock_screen_mode]]"
+ label="$i18n{lockScreenNotificationHideSensitive}">
+ </cr-radio-button>
+ </template>
+ <cr-radio-button name="show" class="list-item underbar"
+ pref="[[prefs.ash.message_center.lock_screen_mode]]"
+ label="$i18n{lockScreenNotificationShow}">
+ </cr-radio-button>
+ <cr-radio-button name="hide" class="list-item"
+ pref="[[prefs.ash.message_center.lock_screen_mode]]"
+ label="$i18n{lockScreenNotificationHide}">
+ </cr-radio-button>
+ </settings-radio-group>
+ </div>
+ </template>
+
<template is="dom-if" if="[[fingerprintUnlockEnabled_]]">
- <div id="fingerprintDiv">
- <settings-toggle-button class="continuation"
- pref="{{prefs.settings.enable_quick_unlock_fingerprint}}"
- label="$i18n{lockScreenFingerprintEnable}">
- </settings-toggle-button>
- <iron-collapse
- opened="[[prefs.settings.enable_quick_unlock_fingerprint.value]]">
- <div class="settings-box continuation">
- <div class="start">
- $i18n{lockScreenEditFingerprints}
- <div class="secondary" id="lockScreenEditFingerprintsSecondary">
- [[getDescriptionText_(numFingerprints_)]]
- </div>
- </div>
- <div class="separator"></div>
- <div class="secondary-action">
- <paper-button class="secondary-button"
- on-click="onEditFingerprints_"
- aria-label="$i18n{lockScreenEditFingerprints}"
- aria-descibedby="lockScreenEditFingerprintsSecondary">
- $i18n{lockScreenSetupFingerprintButton}
- </paper-button>
- </div>
+ <div id="fingerprintDiv" class="settings-box two-line">
+ <div class="start">
+ $i18n{lockScreenEditFingerprints}
+ <div class="secondary" id="lockScreenEditFingerprintsSecondary">
+ [[getDescriptionText_(numFingerprints_)]]
</div>
- </iron-collapse>
+ </div>
+ <div class="separator"></div>
+ <div class="secondary-action">
+ <paper-button class="secondary-button"
+ on-click="onEditFingerprints_"
+ aria-label="$i18n{lockScreenEditFingerprints}"
+ aria-descibedby="lockScreenEditFingerprintsSecondary">
+ $i18n{lockScreenSetupFingerprintButton}
+ </paper-button>
+ </div>
</div>
</template>
@@ -202,10 +220,11 @@
</template>
<template is="dom-if" if="[[showPasswordPromptDialog_]]" restamp>
- <settings-password-prompt-dialog id="passwordPrompt"
+ <settings-lock-screen-password-prompt-dialog
+ id="lockScreenPasswordPrompt"
on-close="onPasswordPromptDialogClose_" set-modes="{{setModes_}}"
auth-token="{{authToken_}}">
- </settings-password-prompt-dialog>
+ </settings-lock-screen-password-prompt-dialog>
</template>
<template is="dom-if" if="[[showSetupPinDialog_]]" restamp>
diff --git a/chromium/chrome/browser/resources/settings/people_page/lock_screen.js b/chromium/chrome/browser/resources/settings/people_page/lock_screen.js
index 9bc50d77a69..d0af6fa31b1 100644
--- a/chromium/chrome/browser/resources/settings/people_page/lock_screen.js
+++ b/chromium/chrome/browser/resources/settings/people_page/lock_screen.js
@@ -52,7 +52,7 @@ Polymer({
},
/**
- * Authentication token provided by password-prompt-dialog.
+ * Authentication token provided by lock-screen-password-prompt-dialog.
* @private
*/
authToken_: String,
@@ -164,6 +164,32 @@ Polymer({
readOnly: true,
},
+ /**
+ * Whether notifications on the lock screen are enable by the feature flag.
+ * @private
+ */
+ lockScreenNotificationsEnabled_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('lockScreenNotificationsEnabled');
+ },
+ readOnly: true,
+ },
+
+ /**
+ * Whether the "hide sensitive notification" option on the lock screen can
+ * be enable by the feature flag.
+ * @private
+ */
+ lockScreenHideSensitiveNotificationSupported_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean(
+ 'lockScreenHideSensitiveNotificationsSupported');
+ },
+ readOnly: true,
+ },
+
/** @private */
showEasyUnlockTurnOffDialog_: {
type: Boolean,
@@ -391,16 +417,6 @@ Polymer({
return enabled ? enabledStr : disabledStr;
},
- /**
- * @param {boolean} easyUnlockEnabled
- * @param {boolean} proximityDetectionAllowed
- * @private
- */
- getShowEasyUnlockToggle_: function(
- easyUnlockEnabled, proximityDetectionAllowed) {
- return easyUnlockEnabled && proximityDetectionAllowed;
- },
-
/** @private */
updateNumFingerprints_: function() {
if (this.fingerprintUnlockEnabled_ && this.fingerprintBrowserProxy_) {
diff --git a/chromium/chrome/browser/resources/settings/people_page/lock_screen_password_prompt_dialog.html b/chromium/chrome/browser/resources/settings/people_page/lock_screen_password_prompt_dialog.html
new file mode 100644
index 00000000000..c11f2730918
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/lock_screen_password_prompt_dialog.html
@@ -0,0 +1,16 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="lock_screen_constants.html">
+<link rel="import" href="lock_state_behavior.html">
+<link rel="import" href="../controls/password_prompt_dialog.html">
+
+<dom-module id="settings-lock-screen-password-prompt-dialog">
+ <template>
+ <settings-password-prompt-dialog
+ id="passwordPrompt"
+ password-prompt-text="[[selectPasswordPromptEnterPasswordString_(hasPinLogin)]]"
+ auth-token="{{authToken}}">
+ </settings-password-prompt-dialog>
+ </template>
+ <script src="lock_screen_password_prompt_dialog.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/people_page/lock_screen_password_prompt_dialog.js b/chromium/chrome/browser/resources/settings/people_page/lock_screen_password_prompt_dialog.js
new file mode 100644
index 00000000000..194495372d5
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/lock_screen_password_prompt_dialog.js
@@ -0,0 +1,119 @@
+// Copyright 2016 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
+ *
+ * 'settings-lock-screen-password-prompt-dialog' displays a password prompt to
+ * the user. Clients can determine if the user has authenticated if either the
+ * |authToken| string or |setModes| closure are present.
+ *
+ * The setModes binding is a wrapper around chrome.quickUnlockPrivate.setModes
+ * which has a prebound account password. The account password by itself is not
+ * available for other elements to access.
+ *
+ * Example:
+ *
+ * <settings-lock-screen-password-prompt-dialog
+ * id="lockScreenPasswordPrompt"
+ * set-modes="[[setModes]]">
+ * </settings-lock-screen-password-prompt-dialog>
+ */
+
+(function() {
+'use strict';
+
+Polymer({
+ is: 'settings-lock-screen-password-prompt-dialog',
+
+ behaviors: [
+ LockStateBehavior,
+ ],
+
+ properties: {
+ /**
+ * Authentication token returned by quickUnlockPrivate.getAuthToken. Should
+ * be passed to API calls which require authentication.
+ * @type {string}
+ */
+ authToken: {
+ type: String,
+ notify: true,
+ observer: 'authTokenChanged_',
+ },
+
+ /**
+ * A wrapper around chrome.quickUnlockPrivate.setModes with the account
+ * password already supplied. If this is null, the authentication screen
+ * needs to be redisplayed. This property will be cleared after the timeout
+ * returned by quickUnlockPrivate.getAuthToken.
+ * @type {?Function}
+ */
+ setModes: {
+ type: Object,
+ notify: true,
+ },
+
+ /**
+ * writeUma_ is a function that handles writing uma stats. It may be
+ * overridden for tests.
+ *
+ * @type {Function}
+ * @private
+ */
+ writeUma_: {
+ type: Object,
+ value: function() {
+ return settings.recordLockScreenProgress;
+ }
+ },
+ },
+
+ /** @override */
+ attached: function() {
+ this.writeUma_(LockScreenProgress.START_SCREEN_LOCK);
+ },
+
+ /**
+ * Called when the authToken changes. If the authToken is valid, that
+ * indicates the user authenticated successfully.
+ * @param {String} authToken
+ * @private
+ */
+ authTokenChanged_: function(authToken) {
+ if (!this.authToken) {
+ this.setModes = null;
+ return;
+ }
+
+ // The user successfully authenticated.
+ this.writeUma_(LockScreenProgress.ENTER_PASSWORD_CORRECTLY);
+
+ this.setModes = (modes, credentials, onComplete) => {
+ this.quickUnlockPrivate.setModes(
+ this.authToken, modes, credentials, () => {
+ let result = true;
+ if (chrome.runtime.lastError) {
+ console.error(
+ 'setModes failed: ' + chrome.runtime.lastError.message);
+ result = false;
+ }
+ onComplete(result);
+ });
+ };
+ },
+
+ /**
+ * Looks up the translation id, which depends on PIN login support.
+ * @param {boolean} hasPinLogin
+ * @return {string}
+ * @private
+ */
+ selectPasswordPromptEnterPasswordString_: function(hasPinLogin) {
+ if (hasPinLogin)
+ return this.i18n('passwordPromptEnterPasswordLoginLock');
+ return this.i18n('passwordPromptEnterPasswordLock');
+ },
+});
+})();
diff --git a/chromium/chrome/browser/resources/settings/people_page/people_page.html b/chromium/chrome/browser/resources/settings/people_page/people_page.html
index aeb069ba45e..6f9a04352a8 100644
--- a/chromium/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/people_page.html
@@ -1,8 +1,5 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
@@ -10,7 +7,6 @@
<link rel="import" href="chrome://resources/html/icon.html">
<link rel="import" href="chrome://resources/html/util.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.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/neon-animation/neon-animatable.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
@@ -25,7 +21,9 @@
<link rel="import" href="../settings_page/settings_subpage.html">
<link rel="import" href="../passwords_and_forms_page/autofill_section.html">
<link rel="import" href="../passwords_and_forms_page/passwords_section.html">
+<link rel="import" href="../passwords_and_forms_page/payments_section.html">
<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="signout_dialog.html">
<if expr="chromeos">
<link rel="import" href="account_manager.html">
@@ -48,7 +46,7 @@
<style include="settings-shared iron-flex">
setting-box.middle {
/* Per spec, middle text is indented 20px in this section. */
- -webkit-margin-start: 20px;
+ margin-inline-start: 20px;
}
#profile-icon {
@@ -96,23 +94,6 @@
width: 40px;
}
- #disconnectDialog [slot=footer] .settings-box {
- --settings-box-row-padding: 0;
- }
-
- .delete-profile-warning {
- -webkit-padding-end: var(--cr-section-padding);
- /* In order to line up with the checkbox text. */
- -webkit-padding-start: var(--cr-section-indent-padding);
- padding-bottom: 10px;
- padding-top: 10px;
- }
-
- #wideFooter {
- /* Override the cr-dialog footer padding. */
- padding: 16px 0;
- }
-
<if expr="not chromeos">
#toast {
color: white;
@@ -231,9 +212,6 @@
<if expr="not chromeos">
</template> <!-- if="[[!diceEnabled_]]" -->
</if>
- <div class="settings-box" hidden="[[syncStatus.signinAllowed]]">
- $i18n{syncDisabledByAdministrator}
- </div>
</template>
<if expr="not chromeos">
@@ -288,10 +266,10 @@
<cr-link-row id="paymentManagerButton"
start-icon="settings20:credit-card"
label="$i18n{creditCards}" icon-class="subpage-arrow"
- on-click="onAutofillTap_"></cr-link-row>
+ on-click="onPaymentsTap_"></cr-link-row>
<cr-link-row id="addressesManagerButton"
start-icon="settings20:location-on"
- label="$i18n{addresses}" icon-class="subpage-arrow"
+ label="$i18n{addressesTitle}" icon-class="subpage-arrow"
on-click="onAutofillTap_"></cr-link-row>
</template>
@@ -323,6 +301,16 @@
aria-describedby="lockScreenSecondary"></button>
</paper-icon-button-light>
</div>
+
+ <template is="dom-if" if="[[isAccountManagerEnabled_]]">
+ <div id="account-manager-subpage-trigger" class="settings-box"
+ actionable on-click="onAccountManagerTap_">
+ <div class="start">$i18n{accountManagerSubMenuLabel}</div>
+ <paper-icon-button-light class="subpage-arrow">
+ <button aria-label="$i18n{accountManagerSubMenuLabel}"></button>
+ </paper-icon-button-light>
+ </div>
+ </template>
</if>
<div id="manage-other-people-subpage-trigger"
@@ -387,6 +375,14 @@
</settings-autofill-section>
</settings-subpage>
</template>
+ <template is="dom-if" route-path="/payments">
+ <settings-subpage
+ associated-control="[[$$('#paymentManagerButton')]]"
+ page-title="$i18n{creditCards}">
+ <settings-payments-section id="paymentsSection" prefs="{{prefs}}">
+ </settings-payments-section>
+ </settings-subpage>
+ </template>
</template>
<if expr="chromeos">
@@ -441,51 +437,10 @@
</if>
</settings-animated-pages>
- <template is="dom-if" if="[[showDisconnectDialog_]]" restamp>
- <cr-dialog id="disconnectDialog"
- ignore-popstate ignore-enter-key
- on-close="onDisconnectClosed_" close-text="$i18n{close}">
- <div slot="title">$i18n{syncDisconnectTitle}</div>
- <div slot="body">
- <div inner-h-t-m-l="[[
- getDisconnectExplanationHtml_(syncStatus.domain)]]">
- </div>
- </div>
- <div slot="button-container">
- <paper-button on-click="onDisconnectCancel_" class="cancel-button">
- $i18n{cancel}
- </paper-button>
- <paper-button id="disconnectConfirm" class="action-button"
- hidden="[[syncStatus.domain]]" on-click="onDisconnectConfirm_">
- $i18n{syncDisconnect}
- </paper-button>
- <paper-button id="disconnectManagedProfileConfirm"
- class="action-button" hidden="[[!syncStatus.domain]]"
- on-click="onDisconnectConfirm_">
- $i18n{syncDisconnectConfirm}
- </paper-button>
- </div>
-<if expr="(not chromeos and is_posix) or is_win or is_macosx">
- <template is="dom-if" if="[[!syncStatus.domain]]">
- <div id="wideFooter" slot="footer">
- <div class="settings-box first">
- <cr-checkbox id="deleteProfile" class="start"
- checked="{{deleteProfile_}}">
- $i18n{syncDisconnectDeleteProfile}
- </cr-checkbox>
- <cr-expand-button expanded="{{deleteProfileWarningVisible_}}"
- alt="$i18n{deleteProfileWarningExpandA11yLabel}">
- </cr-expand-button>
- </div>
- <iron-collapse opened="[[deleteProfileWarningVisible_]]">
- <div class="delete-profile-warning">
- [[deleteProfileWarning_]]
- </div>
- </iron-collapse>
- </div>
- </template>
-</if>
- </cr-dialog>
+ <template is="dom-if" if="[[showSignoutDialog_]]" restamp>
+ <settings-signout-dialog sync-status="[[syncStatus]]"
+ on-close="onDisconnectDialogClosed_">
+ </settings-signout-dialog>
</template>
<template is="dom-if" if="[[showImportDataDialog_]]" restamp>
diff --git a/chromium/chrome/browser/resources/settings/people_page/people_page.js b/chromium/chrome/browser/resources/settings/people_page/people_page.js
index 5302d6ad270..e899dd2bf12 100644
--- a/chromium/chrome/browser/resources/settings/people_page/people_page.js
+++ b/chromium/chrome/browser/resources/settings/people_page/people_page.js
@@ -86,26 +86,6 @@ Polymer({
*/
profileName_: String,
- /**
- * The profile deletion warning. The message indicates the number of
- * profile stats that will be deleted if a non-zero count for the profile
- * stats is returned from the browser.
- * @private
- */
- deleteProfileWarning_: String,
-
- /**
- * True if the profile deletion warning is visible.
- * @private
- */
- deleteProfileWarningVisible_: Boolean,
-
- /**
- * True if the checkbox to delete the profile has been checked.
- * @private
- */
- deleteProfile_: Boolean,
-
// <if expr="not chromeos">
/** @private */
showImportDataDialog_: {
@@ -115,7 +95,7 @@ Polymer({
// </if>
/** @private */
- showDisconnectDialog_: Boolean,
+ showSignoutDialog_: Boolean,
// <if expr="chromeos">
/**
@@ -129,6 +109,18 @@ Polymer({
},
readOnly: true,
},
+
+ /**
+ * True if Chrome OS Account Manager is enabled.
+ * @private
+ */
+ isAccountManagerEnabled_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('isAccountManagerEnabled');
+ },
+ readOnly: true,
+ },
// </if>
/** @private {!Map<string, string>} */
@@ -147,7 +139,10 @@ Polymer({
settings.routes.MANAGE_PASSWORDS.path, '#passwordManagerButton');
}
if (settings.routes.AUTOFILL) {
- map.set(settings.routes.AUTOFILL.path, '#paymentManagerButton');
+ map.set(settings.routes.AUTOFILL.path, '#addressesManagerButton');
+ }
+ if (settings.routes.PAYMENTS) {
+ map.set(settings.routes.PAYMENTS.path, '#paymentManagerButton');
}
// <if expr="not chromeos">
if (settings.routes.MANAGE_PROFILE) {
@@ -172,6 +167,11 @@ Polymer({
settings.routes.ACCOUNTS.path,
'#manage-other-people-subpage-trigger .subpage-arrow button');
}
+ if (settings.routes.ACCOUNT_MANAGER) {
+ map.set(
+ settings.routes.ACCOUNT_MANAGER.path,
+ '#account-manager-subpage-trigger .subpage-arrow button');
+ }
// </if>
return map;
},
@@ -202,9 +202,6 @@ Polymer({
this.addWebUIListener(
'profile-info-changed', this.handleProfileInfo_.bind(this));
- this.addWebUIListener(
- 'profile-stats-count-ready', this.handleProfileStatsCount_.bind(this));
-
this.syncBrowserProxy_ = settings.SyncBrowserProxyImpl.getInstance();
this.syncBrowserProxy_.getSyncStatus().then(
this.handleSyncStatus_.bind(this));
@@ -223,22 +220,14 @@ Polymer({
settings.getCurrentRoute() == settings.routes.IMPORT_DATA;
if (settings.getCurrentRoute() == settings.routes.SIGN_OUT) {
- // <if expr="not chromeos">
- settings.ProfileInfoBrowserProxyImpl.getInstance().getProfileStatsCount();
- // </if>
// If the sync status has not been fetched yet, optimistically display
- // the disconnect dialog. There is another check when the sync status is
- // fetched. The dialog will be closed then the user is not signed in.
+ // the sign-out dialog. There is another check when the sync status is
+ // fetched. The dialog will be closed when the user is not signed in.
if (this.syncStatus && !this.syncStatus.signedIn) {
settings.navigateToPreviousRoute();
} else {
- this.showDisconnectDialog_ = true;
- this.async(() => {
- this.$$('#disconnectDialog').showModal();
- });
+ this.showSignoutDialog_ = true;
}
- } else if (this.showDisconnectDialog_) {
- this.$$('#disconnectDialog').close();
}
},
@@ -276,24 +265,6 @@ Polymer({
},
/**
- * Handler for when the profile stats count is pushed from the browser.
- * @param {number} count
- * @private
- */
- handleProfileStatsCount_: function(count) {
- this.deleteProfileWarning_ = (count > 0) ?
- (count == 1) ? loadTimeData.getStringF(
- 'deleteProfileWarningWithCountsSingular',
- this.syncStatus.signedInUsername) :
- loadTimeData.getStringF(
- 'deleteProfileWarningWithCountsPlural', count,
- this.syncStatus.signedInUsername) :
- loadTimeData.getStringF(
- 'deleteProfileWarningWithoutCounts',
- this.syncStatus.signedInUsername);
- },
-
- /**
* Handler for when the sync state is pushed from the browser.
* @param {?settings.SyncStatus} syncStatus
* @private
@@ -305,9 +276,6 @@ Polymer({
const shouldRecordSigninImpression =
!this.syncStatus && syncStatus && this.showSignin_(syncStatus);
- if (!syncStatus.signedIn && this.showDisconnectDialog_)
- this.$$('#disconnectDialog').close();
-
this.syncStatus = syncStatus;
if (shouldRecordSigninImpression && !this.shouldShowSyncAccountControl_()) {
@@ -341,7 +309,7 @@ Polymer({
},
/**
- * Shows the manage autofill sub page.
+ * Shows the manage autofill addresses sub page.
* @param {!Event} event
* @private
*/
@@ -349,9 +317,18 @@ Polymer({
settings.navigateTo(settings.routes.AUTOFILL);
},
+ /**
+ * Shows the manage payment information sub page.
+ * @param {!Event} event
+ * @private
+ */
+ onPaymentsTap_: function(event) {
+ settings.navigateTo(settings.routes.PAYMENTS);
+ },
+
/** @private */
- onDisconnectClosed_: function() {
- this.showDisconnectDialog_ = false;
+ onDisconnectDialogClosed_: function(e) {
+ this.showSignoutDialog_ = false;
// <if expr="not chromeos">
if (!this.diceEnabled_) {
// If DICE-enabled, this button won't exist here.
@@ -365,7 +342,6 @@ Polymer({
if (settings.getCurrentRoute() == settings.routes.SIGN_OUT)
settings.navigateToPreviousRoute();
- this.fire('signout-dialog-closed');
},
/** @private */
@@ -374,27 +350,6 @@ Polymer({
},
/** @private */
- onDisconnectCancel_: function() {
- this.$$('#disconnectDialog').close();
- },
-
- /** @private */
- onDisconnectConfirm_: function() {
- const deleteProfile = !!this.syncStatus.domain || this.deleteProfile_;
- // Trigger the sign out event after the navigateToPreviousRoute().
- // So that the navigation to the setting page could be finished before the
- // sign out if navigateToPreviousRoute() returns synchronously even the
- // browser is closed after the sign out. Otherwise, the navigation will be
- // finished during session restore if the browser is closed before the async
- // callback executed.
- listenOnce(this, 'signout-dialog-closed', () => {
- this.syncBrowserProxy_.signOut(deleteProfile);
- });
-
- this.$$('#disconnectDialog').close();
- },
-
- /** @private */
onSyncTap_: function() {
// When unified-consent is enabled, users can go to sync subpage regardless
// of sync status.
@@ -453,6 +408,14 @@ Polymer({
e.preventDefault();
settings.navigateTo(settings.routes.LOCK_SCREEN);
},
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onAccountManagerTap_: function(e) {
+ settings.navigateTo(settings.routes.ACCOUNT_MANAGER);
+ },
// </if>
/** @private */
@@ -502,22 +465,6 @@ Polymer({
/**
* @private
- * @param {string} domain
- * @return {string}
- */
- getDisconnectExplanationHtml_: function(domain) {
- // <if expr="not chromeos">
- if (domain) {
- return loadTimeData.getStringF(
- 'syncDisconnectManagedProfileExplanation',
- '<span id="managed-by-domain-name">' + domain + '</span>');
- }
- // </if>
- return loadTimeData.getString('syncDisconnectExplanation');
- },
-
- /**
- * @private
* @param {?settings.SyncStatus} syncStatus
* @return {boolean}
*/
diff --git a/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html b/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
index 87adadc7479..626028ad75a 100644
--- a/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
+++ b/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
@@ -1,5 +1,6 @@
<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/chromeos/fingerprint/cr_fingerprint_progress_arc.html">
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
@@ -10,16 +11,10 @@
<link rel="import" href="../icons.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="fingerprint_browser_proxy.html">
-<link rel="import" href="fingerprint_progress_arc.html">
<dom-module id="settings-setup-fingerprint-dialog">
<template>
<style include="settings-shared">
- #arc {
- --canvas-height: 200px;
- --canvas-width: 450px;
- }
-
#dialog {
--cr-dialog-native: {
min-width: 500px;
@@ -27,30 +22,21 @@
};
}
- #image {
- height: 80px;
- left: 185px;
- min-height: 80px;
- min-width: 80px;
- position: relative;
- top: -140px;
- width: 80px;
+ #scannerLocation {
+ background: url(chrome://theme/IDR_LOGIN_FINGERPRINT_SCANNER_ANIMATION);
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: 298px 205px;
+ height: 240px;
}
- #image[step='3'] {
- --iron-icon-fill-color: var(--google-blue-700);
- }
-
- /* 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;
+ #messageDiv {
+ height: 20px;
}
/* Use this instead of hidden so that the dialog does not resize when the
- problem appears or disappears. */
- #problemDiv[invisible] {
+ message appears or disappears. */
+ #messageDiv[invisible] {
visibility: hidden;
}
</style>
@@ -58,25 +44,20 @@
<cr-dialog id="dialog" on-close="close"
close-text="$i18n{close}">
<div slot="title">$i18n{configureFingerprintTitle}</div>
- <div slot="body">
- <div class="settings-box first">
- <span class="middle">[[getInstructionMessage_(step_)]]</span>
- </div>
- <settings-fingerprint-progress-arc id="arc">
- </settings-fingerprint-progress-arc>
- <div id="imageDiv">
- <iron-icon id="image" icon="settings:fingerprint" step$="[[step_]]">
- </iron-icon>
+ <div slot="body" on-click="fakeScan_">
+ <div id="messageDiv"
+ invisible$="[[!getInstructionMessage_(step_, problemMessage_)]]">
+ <span>[[getInstructionMessage_(step_, problemMessage_)]]</span>
</div>
- <div id="problemDiv" class="settings-box first"
- invisible$="[[!problemMessage_]]">
- <iron-icon icon="cr:warning"></iron-icon>
- <span class="middle">[[problemMessage_]]</span>
+ <div id="scannerLocation" hidden="[[!showScannerLocation_(step_)]]">
</div>
+ <cr-fingerprint-progress-arc id="arc" circle-radius="100"
+ hidden="[[!showArc_(step_)]]">
+ </cr-fingerprint-progress-arc>
</div>
<div slot="button-container">
<paper-button id="addAnotherButton" on-click="onAddAnotherFingerprint_"
- hidden$="[[hideAddAnother_(step_)]]">
+ hidden$="[[hideAddAnother_(step_, allowAddAnotherFinger)]]">
$i18n{configureFingerprintAddAnotherButton}
</paper-button>
diff --git a/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js b/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js
index 2332428b2e3..e41510792dc 100644
--- a/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js
+++ b/chromium/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.js
@@ -17,13 +17,6 @@ settings.FingerprintSetupStep = {
(function() {
/**
- * The duration in ms of a fingerprint icon flash when a user touches the
- * fingerprint sensor during an enroll session.
- * @type {number}
- */
-const FLASH_DURATION_MS = 300;
-
-/**
* The amount of milliseconds after a successful but not completed scan before a
* message shows up telling the user to scan their finger again.
* @type {number}
@@ -37,6 +30,15 @@ Polymer({
properties: {
/**
+ * Whether add another finger is allowed.
+ * @type {boolean}
+ */
+ allowAddAnotherFinger: {
+ type: Boolean,
+ value: true,
+ },
+
+ /**
* The problem message to display.
* @private
*/
@@ -51,6 +53,20 @@ Polymer({
* @private
*/
step_: {type: Number, value: settings.FingerprintSetupStep.LOCATE_SCANNER},
+
+ /**
+ * The percentage of completion that has been received during setup.
+ * This is used to approximate the progress of the setup.
+ * The value within [0, 100] represents the percent of enrollment
+ * completion.
+ * @type {number}
+ * @private
+ */
+ percentComplete_: {
+ type: Number,
+ value: 0,
+ observer: 'onProgressChanged_',
+ },
},
/**
@@ -64,24 +80,13 @@ Polymer({
/** @private {?settings.FingerprintBrowserProxy}*/
browserProxy_: null,
- /**
- * The percentage of completion that has been received during setup.
- * This is used to approximate the progress of the setup.
- * The value within [0, 100] represents the percent of enrollment completion.
- * @type {number}
- * @private
- */
- percentComplete_: 0,
-
/** @override */
attached: function() {
this.addWebUIListener(
'on-fingerprint-scan-received', this.onScanReceived_.bind(this));
this.browserProxy_ = settings.FingerprintBrowserProxyImpl.getInstance();
- this.$.arc.clearCanvas();
- this.$.arc.drawBackgroundCircle();
- this.$.arc.drawShadow(10, 0, 0);
+ this.$.arc.reset();
this.browserProxy_.startEnroll();
this.$.dialog.showModal();
},
@@ -95,9 +100,7 @@ Polymer({
// Note: Reset resets |step_| back to the default, so handle anything that
// checks |step_| before resetting.
- if (this.step_ == settings.FingerprintSetupStep.READY)
- this.fire('add-fingerprint');
- else
+ if (this.step_ != settings.FingerprintSetupStep.READY)
this.browserProxy_.cancelCurrentEnroll();
this.reset_();
@@ -119,7 +122,6 @@ Polymer({
reset_: function() {
this.step_ = settings.FingerprintSetupStep.LOCATE_SCANNER;
this.percentComplete_ = 0;
- this.$.arc.clearCanvas();
this.clearSensorMessageTimeout_();
},
@@ -141,41 +143,21 @@ Polymer({
onScanReceived_: function(scan) {
switch (this.step_) {
case settings.FingerprintSetupStep.LOCATE_SCANNER:
+ this.$.arc.reset();
+ this.step_ = settings.FingerprintSetupStep.MOVE_FINGER;
+ this.percentComplete_ = scan.percentComplete;
+ this.setProblem_(scan.result);
+ break;
case settings.FingerprintSetupStep.MOVE_FINGER:
- if (this.step_ == settings.FingerprintSetupStep.LOCATE_SCANNER) {
- // Clear canvas because there will be shadows present at this step.
- this.$.arc.clearCanvas();
- this.$.arc.drawBackgroundCircle();
-
- this.step_ = settings.FingerprintSetupStep.MOVE_FINGER;
- this.percentComplete_ = 0;
- }
- const slice = 2 * Math.PI / 100;
if (scan.isComplete) {
this.problemMessage_ = '';
this.step_ = settings.FingerprintSetupStep.READY;
- this.$.arc.animateProgress(
- this.percentComplete_ * slice, 2 * Math.PI);
this.clearSensorMessageTimeout_();
+ this.fire('add-fingerprint');
} else {
this.setProblem_(scan.result);
- if (scan.result == settings.FingerprintResultType.SUCCESS) {
- this.problemMessage_ = '';
- // Flash the fingerprint icon blue so that users get some feedback
- // when a successful scan has been registered.
- this.$.image.animate(
- {
- fill: ['var(--google-blue-700)', 'var(--google-grey-500)'],
- opacity: [0.7, 1.0],
- },
- FLASH_DURATION_MS);
- if (scan.percentComplete > this.percentComplete_) {
- this.$.arc.animateProgress(
- this.percentComplete_ * slice, scan.percentComplete * slice);
- this.percentComplete_ = scan.percentComplete;
- }
- }
}
+ this.percentComplete_ = scan.percentComplete;
break;
case settings.FingerprintSetupStep.READY:
break;
@@ -190,14 +172,15 @@ Polymer({
* on.
* @param {!settings.FingerprintSetupStep} step The current step the
* fingerprint setup is on.
+ * @param {string} problemMessage Message for the scan result.
* @private
*/
- getInstructionMessage_: function(step) {
+ getInstructionMessage_: function(step, problemMessage) {
switch (step) {
case settings.FingerprintSetupStep.LOCATE_SCANNER:
return this.i18n('configureFingerprintInstructionLocateScannerStep');
case settings.FingerprintSetupStep.MOVE_FINGER:
- return this.i18n('configureFingerprintInstructionMoveFingerStep');
+ return problemMessage;
case settings.FingerprintSetupStep.READY:
return this.i18n('configureFingerprintInstructionReadyStep');
}
@@ -220,20 +203,11 @@ Polymer({
}, SHOW_TAP_SENSOR_MESSAGE_DELAY_MS);
break;
case settings.FingerprintResultType.PARTIAL:
- this.problemMessage_ = this.i18n('configureFingerprintPartialData');
- break;
case settings.FingerprintResultType.INSUFFICIENT:
- this.problemMessage_ =
- this.i18n('configureFingerprintInsufficientData');
- break;
case settings.FingerprintResultType.SENSOR_DIRTY:
- this.problemMessage_ = this.i18n('configureFingerprintSensorDirty');
- break;
case settings.FingerprintResultType.TOO_SLOW:
- this.problemMessage_ = this.i18n('configureFingerprintTooSlow');
- break;
case settings.FingerprintResultType.TOO_FAST:
- this.problemMessage_ = this.i18n('configureFingerprintTooFast');
+ this.problemMessage_ = this.i18n('configureFingerprintTryAgain');
break;
case settings.FingerprintResultType.IMMOBILE:
this.problemMessage_ = this.i18n('configureFingerprintImmobile');
@@ -271,10 +245,12 @@ Polymer({
/**
* @param {!settings.FingerprintSetupStep} step
+ * @param {boolean} allowAddAnotherFinger
* @private
*/
- hideAddAnother_: function(step) {
- return step != settings.FingerprintSetupStep.READY;
+ hideAddAnother_: function(step, allowAddAnotherFinger) {
+ return step != settings.FingerprintSetupStep.READY ||
+ !allowAddAnotherFinger;
},
/**
@@ -283,11 +259,41 @@ Polymer({
* @private
*/
onAddAnotherFingerprint_: function() {
- this.fire('add-fingerprint');
this.reset_();
- this.$.arc.drawBackgroundCircle();
- this.$.arc.drawShadow(10, 0, 0);
+ this.$.arc.reset();
+ this.step_ = settings.FingerprintSetupStep.MOVE_FINGER;
this.browserProxy_.startEnroll();
},
+
+ /**
+ * Whether scanner location should be shown at the current step.
+ * @private
+ */
+ showScannerLocation_: function() {
+ return this.step_ == settings.FingerprintSetupStep.LOCATE_SCANNER;
+ },
+
+ /**
+ * Whether fingerprint progress circle should be shown at the current step.
+ * @private
+ */
+ showArc_: function() {
+ return this.step_ == settings.FingerprintSetupStep.MOVE_FINGER ||
+ this.step_ == settings.FingerprintSetupStep.READY;
+ },
+
+ /**
+ * Observer for percentComplete_.
+ * @private
+ */
+ onProgressChanged_: function(newValue, oldValue) {
+ // Start a new enrollment, so reset all enrollment related states.
+ if (newValue === 0) {
+ this.$.arc.reset();
+ return;
+ }
+
+ this.$.arc.setProgress(oldValue, newValue, newValue === 100);
+ },
});
})();
diff --git a/chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.js b/chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.js
index bddac27f2d1..39840b9fbba 100644
--- a/chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.js
+++ b/chromium/chrome/browser/resources/settings/people_page/setup_pin_dialog.js
@@ -263,6 +263,8 @@ Polymer({
this.quickUnlockPrivate_.checkCredential(
chrome.quickUnlockPrivate.QuickUnlockMode.PIN,
this.pinKeyboardValue_, this.processPinProblems_.bind(this));
+ } else {
+ this.enableSubmit_ = false;
}
return;
}
diff --git a/chromium/chrome/browser/resources/settings/people_page/signout_dialog.html b/chromium/chrome/browser/resources/settings/people_page/signout_dialog.html
new file mode 100644
index 00000000000..7dce40aec69
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/signout_dialog.html
@@ -0,0 +1,78 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="profile_info_browser_proxy.html">
+<link rel="import" href="sync_browser_proxy.html">
+<link rel="import" href="../settings_shared_css.html">
+
+<dom-module id="settings-signout-dialog">
+ <template>
+ <style include="settings-shared">
+ #dialog [slot=footer] .settings-box {
+ --settings-box-row-padding: 0;
+ }
+
+ .delete-profile-warning {
+ padding-bottom: 10px;
+ padding-inline-end: var(--cr-section-padding);
+ /* In order to line up with the checkbox text. */
+ padding-inline-start: var(--cr-section-indent-padding);
+ padding-top: 10px;
+ }
+
+ #wideFooter {
+ /* Override the cr-dialog footer padding. */
+ padding: 16px 0;
+ }
+ </style>
+
+ <cr-dialog id="dialog" ignore-enter-key close-text="$i18n{close}">
+ <div slot="title">$i18n{syncDisconnectTitle}</div>
+ <div slot="body">
+ <div inner-h-t-m-l="[[
+ getDisconnectExplanationHtml_(syncStatus.domain)]]">
+ </div>
+ </div>
+ <div slot="button-container">
+ <paper-button id="disconnectCancel" class="cancel-button"
+ on-click="onDisconnectCancel_" >
+ $i18n{cancel}
+ </paper-button>
+ <paper-button id="disconnectConfirm" class="action-button"
+ hidden="[[syncStatus.domain]]" on-click="onDisconnectConfirm_">
+ $i18n{syncDisconnect}
+ </paper-button>
+ <paper-button id="disconnectManagedProfileConfirm"
+ class="action-button" hidden="[[!syncStatus.domain]]"
+ on-click="onDisconnectConfirm_">
+ $i18n{syncDisconnectConfirm}
+ </paper-button>
+ </div>
+<if expr="(not chromeos and is_posix) or is_win or is_macosx">
+ <template is="dom-if" if="[[!syncStatus.domain]]">
+ <div id="wideFooter" slot="footer">
+ <div class="settings-box first">
+ <cr-checkbox id="deleteProfile" class="start"
+ checked="{{deleteProfile_}}">
+ $i18n{syncDisconnectDeleteProfile}
+ </cr-checkbox>
+ <cr-expand-button expanded="{{deleteProfileWarningVisible_}}"
+ alt="$i18n{deleteProfileWarningExpandA11yLabel}">
+ </cr-expand-button>
+ </div>
+ <iron-collapse opened="[[deleteProfileWarningVisible_]]">
+ <div class="delete-profile-warning">
+ [[deleteProfileWarning_]]
+ </div>
+ </iron-collapse>
+ </div>
+ </template>
+</if>
+ </cr-dialog>
+ </template>
+ <script src="signout_dialog.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/people_page/signout_dialog.js b/chromium/chrome/browser/resources/settings/people_page/signout_dialog.js
new file mode 100644
index 00000000000..d1564f24c31
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/people_page/signout_dialog.js
@@ -0,0 +1,120 @@
+// Copyright 2018 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 'settings-signout-dialog' is a dialog that allows the
+ * user to turn off sync and sign out of Chromium.
+ */
+Polymer({
+ is: 'settings-signout-dialog',
+
+ behaviors: [WebUIListenerBehavior],
+
+ properties: {
+ /**
+ * The current sync status, supplied by the parent.
+ * @type {?settings.SyncStatus}
+ */
+ syncStatus: {
+ type: Object,
+ observer: 'syncStatusChanged_',
+ },
+
+ /**
+ * True if the checkbox to delete the profile has been checked.
+ * @private
+ */
+ deleteProfile_: Boolean,
+
+ /**
+ * True if the profile deletion warning is visible.
+ * @private
+ */
+ deleteProfileWarningVisible_: Boolean,
+
+ /**
+ * The profile deletion warning. The message indicates the number of
+ * profile stats that will be deleted if a non-zero count for the profile
+ * stats is returned from the browser.
+ * @private
+ */
+ deleteProfileWarning_: String,
+ },
+
+ /** @override */
+ attached: function() {
+ this.addWebUIListener(
+ 'profile-stats-count-ready', this.handleProfileStatsCount_.bind(this));
+ // <if expr="not chromeos">
+ settings.ProfileInfoBrowserProxyImpl.getInstance().getProfileStatsCount();
+ // </if>
+ this.async(() => {
+ this.$.dialog.showModal();
+ });
+ },
+
+ /**
+ * Returns true when the user selected 'Confirm'.
+ * @return {boolean}
+ */
+ wasConfirmed: function() {
+ return this.$.dialog.getNative().returnValue == 'success';
+ },
+
+ /**
+ * Handler for when the profile stats count is pushed from the browser.
+ * @param {number} count
+ * @private
+ */
+ handleProfileStatsCount_: function(count) {
+ const username = this.syncStatus.signedInUsername || '';
+ if (count == 0) {
+ this.deleteProfileWarning_ = loadTimeData.getStringF(
+ 'deleteProfileWarningWithoutCounts', username);
+ } else if (count == 1) {
+ this.deleteProfileWarning_ = loadTimeData.getStringF(
+ 'deleteProfileWarningWithCountsSingular', username);
+ } else {
+ this.deleteProfileWarning_ = loadTimeData.getStringF(
+ 'deleteProfileWarningWithCountsPlural', count, username);
+ }
+ },
+
+ /**
+ * Polymer observer for syncStatus.
+ * @private
+ */
+ syncStatusChanged_: function() {
+ if (!this.syncStatus.signedIn && this.$.dialog.open)
+ this.$.dialog.close();
+ },
+
+ /**
+ * @private
+ * @param {string} domain
+ * @return {string}
+ */
+ getDisconnectExplanationHtml_: function(domain) {
+ // <if expr="not chromeos">
+ if (domain) {
+ return loadTimeData.getStringF(
+ 'syncDisconnectManagedProfileExplanation',
+ '<span id="managed-by-domain-name">' + domain + '</span>');
+ }
+ // </if>
+ return loadTimeData.getString('syncDisconnectExplanation');
+ },
+
+ /** @private */
+ onDisconnectCancel_: function() {
+ this.$.dialog.cancel();
+ },
+
+ /** @private */
+ onDisconnectConfirm_: function() {
+ this.$.dialog.close();
+ const deleteProfile = !!this.syncStatus.domain || this.deleteProfile_;
+ settings.SyncBrowserProxyImpl.getInstance().signOut(deleteProfile);
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_account_control.html b/chromium/chrome/browser/resources/settings/people_page/sync_account_control.html
index fc1875cbb45..7726f002f48 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_account_control.html
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_account_control.html
@@ -24,7 +24,7 @@
setting-box.middle {
/* Per spec, middle text is indented 20px in this section. */
- -webkit-margin-start: 20px;
+ margin-inline-start: 20px;
}
.account-icon {
@@ -44,7 +44,7 @@
}
#menu .dropdown-item span {
- -webkit-margin-start: 8px;
+ margin-inline-start: 8px;
}
.flex {
@@ -54,6 +54,7 @@
}
#avatar-container {
+ height: var(--shown-avatar-size);
position: relative;
}
@@ -192,8 +193,7 @@
<paper-button id="sync-button" class="action-button"
hidden="[[syncStatus.signedIn]]" on-click="onSyncButtonTap_"
disabled="[[syncStatus.setupInProgress]]">
- [[getSubstituteLabel_(
- '$i18nPolymer{syncAsName}', shownAccount_.givenName)]]
+ $i18n{peopleSignIn}
</paper-button>
<paper-button id="turn-off" class="secondary-button"
hidden="[[!shouldShowTurnOffButton_(syncStatus.signedIn)]]"
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_account_control.js b/chromium/chrome/browser/resources/settings/people_page/sync_account_control.js
index 294ad84551f..6baa3667676 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_account_control.js
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_account_control.js
@@ -63,6 +63,14 @@ Polymer({
reflectToAttribute: true,
},
+ // This property should be set by the parent only and should not change
+ // after the element is created.
+ hideButtons: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+
/** @private {boolean} */
shouldShowAvatarRow_: {
type: Boolean,
@@ -162,25 +170,6 @@ Polymer({
},
/**
- * @param {string} syncErrorLabel
- * @param {string} authErrorLabel
- * @return {string}
- * @private
- */
- getErrorLabel_: function(syncErrorLabel, authErrorLabel) {
- if (this.syncStatus.hasError) {
- // Most of the time re-authenticate states are caused by intentional user
- // action, so they will be displayed differently as other errors.
- return this.syncStatus.statusAction ==
- settings.StatusAction.REAUTHENTICATE ?
- authErrorLabel :
- syncErrorLabel;
- }
-
- return '';
- },
-
- /**
* @param {string} label
* @param {string} account
* @return {string}
@@ -209,7 +198,9 @@ Polymer({
* @private
*/
getSyncIconStyle_: function() {
- if (this.syncStatus.hasError) {
+ if (!!this.syncStatus.hasUnrecoverableError)
+ return 'sync-problem';
+ if (!!this.syncStatus.hasError) {
return this.syncStatus.statusAction ==
settings.StatusAction.REAUTHENTICATE ?
'sync-paused' :
@@ -242,13 +233,16 @@ Polymer({
*/
getAvatarRowTitle_: function(
accountName, syncErrorLabel, authErrorLabel, disabledLabel) {
- if (!!this.syncStatus.disabled)
- return disabledLabel;
-
- if (this.syncStatus.hasError)
- return this.getErrorLabel_(syncErrorLabel, authErrorLabel);
-
- return accountName;
+ switch (this.getSyncIconStyle_()) {
+ case 'sync-problem':
+ return syncErrorLabel;
+ case 'sync-paused':
+ return authErrorLabel;
+ case 'sync-disabled':
+ return disabledLabel;
+ default:
+ return accountName;
+ }
},
/**
@@ -256,7 +250,8 @@ Polymer({
* @private
*/
shouldShowTurnOffButton_: function() {
- return !!this.syncStatus.signedIn && !this.embeddedInSubpage;
+ return !this.hideButtons && !!this.syncStatus.signedIn &&
+ !this.embeddedInSubpage;
},
/**
@@ -264,8 +259,8 @@ Polymer({
* @private
*/
shouldShowSigninAgainButton_: function() {
- return !!this.syncStatus.signedIn && this.embeddedInSubpage &&
- !!this.syncStatus.hasError &&
+ return !this.hideButtons && !!this.syncStatus.signedIn &&
+ this.embeddedInSubpage && !!this.syncStatus.hasError &&
this.syncStatus.statusAction == settings.StatusAction.REAUTHENTICATE;
},
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.js b/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.js
index 323a22b48b1..b2ab725ef47 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_browser_proxy.js
@@ -138,6 +138,11 @@ cr.define('settings', function() {
signOut(deleteProfile) {}
/**
+ * Invalidates the Sync token without signing the user out.
+ */
+ pauseSync() {}
+
+ /**
* Opens the multi-profile user manager.
*/
manageOtherPeople() {}
@@ -215,6 +220,13 @@ cr.define('settings', function() {
* Opens the Google Activity Controls url in a new tab.
*/
openActivityControlsUrl() {}
+
+ /**
+ * Function to invoke when the unified consent toggle state changes, to
+ * notify the C++ layer.
+ * @param {boolean} toggleChecked
+ */
+ unifiedConsentToggleChanged(toggleChecked) {}
}
/**
@@ -233,6 +245,11 @@ cr.define('settings', function() {
}
/** @override */
+ pauseSync() {
+ chrome.send('SyncSetupPauseSync');
+ }
+
+ /** @override */
manageOtherPeople() {
chrome.send('SyncSetupManageOtherPeople');
}
@@ -302,6 +319,11 @@ cr.define('settings', function() {
chrome.metricsPrivate.recordUserAction(
'Signin_AccountSettings_GoogleActivityControlsClicked');
}
+
+ /** @override */
+ unifiedConsentToggleChanged(toggleChecked) {
+ chrome.send('UnifiedConsentToggleChanged', [toggleChecked]);
+ }
}
cr.addSingletonGetter(SyncBrowserProxyImpl);
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_page.html b/chromium/chrome/browser/resources/settings/people_page/sync_page.html
index 1e4a02e5852..d1e99ea9e7b 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_page.html
@@ -27,11 +27,17 @@
<dom-module id="settings-sync-page">
<template>
<style include="settings-shared iron-flex">
- #create-password-box,
- #reset-sync-message-box-encryption,
- #reset-sync-message-box-user-events {
+ #sync-section-toggle:not([actionable]) {
+ opacity: var(--cr-disabled-opacity);
+ }
+
+ #create-password-box {
/* In order to line up with the encryption radio box text. */
- -webkit-margin-start: var(--settings-indent-width);
+ margin-inline-start: var(--settings-indent-width);
+ }
+
+ #create-password-box {
+ margin-bottom: 1em;
}
#create-password-box .list-item {
@@ -43,14 +49,14 @@
}
#existingPassphrase {
- /* This particular list frame is not indented. */
- -webkit-padding-start: var(--settings-box-row-padding);
border-bottom: var(--settings-separator-line);
+ /* This particular list frame is not indented. */
+ padding-inline-start: var(--settings-box-row-padding);
}
#submitExistingPassphrase {
/* The submit button for the existing passphrase is on the same line. */
- -webkit-margin-start: 16px;
+ margin-inline-start: 16px;
}
#passphraseRecoverHint {
@@ -65,6 +71,10 @@
border-top: var(--settings-separator-line);
}
+ .passphrase-reset-icon {
+ margin-right: 8px;
+ }
+
<if expr="not chromeos">
#toast {
color: white;
@@ -79,7 +89,7 @@
</if>
</style>
<if expr="not chromeos">
- <template is="dom-if" if="[[shouldShowSyncAccountControl_(diceEnabled,
+ <template is="dom-if" if="[[shouldShowSyncAccountControl_(
unifiedConsentEnabled, syncStatus.syncSystemEnabled,
syncStatus.signinAllowed)]]">
<settings-sync-account-control embedded-in-subpage
@@ -134,7 +144,8 @@
label="$i18n{syncUnifiedConsentToggleTitle}"
on-settings-boolean-control-change="onUnifiedConsentToggleChange_"
hidden="[[!shouldShowUnifiedConsentToggle_(unifiedConsentEnabled,
- syncStatus.disabled, syncStatus.signedIn)]]">
+ syncStatus.disabled, syncStatus.signedIn)]]"
+ disabled="[[syncPrefs.encryptAllData]]">
</settings-toggle-button>
<div class="settings-box two-line" id="sync-section-toggle"
actionable$="[[!syncSectionDisabled_]]"
@@ -352,19 +363,20 @@
<!-- User events is disabled and unchecked if data is encrypted or
typed urls are disabled. -->
<template is="dom-if" if="[[unifiedConsentEnabled]]">
- <div class="layout horizontal list-item"
- hidden="[[!syncPrefs.userEventsRegistered]]">
+ <div hidden="[[!syncPrefs.userEventsRegistered]]"
+ class$="[[getPassphraseHintLines_(syncPrefs.encryptAllData)]]
+ layout horizontal list-item">
<div class="start" id="userEventsCheckboxLabel">
- <div>$i18n{userEventsCheckboxLabel}</div>
+ $i18n{userEventsCheckboxLabel}
<div class="secondary">
$i18n{userEventsCheckboxText}
- </div>
- <div id="reset-sync-message-box-user-events" class="list-item"
- hidden="[[!syncPrefs.encryptAllData]]">
- <span>
- <iron-icon icon="settings:info-outline"></iron-icon>
- $i18nRaw{passphraseResetHint}
- </span>
+ <div id="reset-sync-message-box-user-events"
+ hidden="[[!syncPrefs.encryptAllData]]">
+ <iron-icon icon="settings:info-outline"
+ class="passphrase-reset-icon">
+ </iron-icon>
+ $i18nRaw{passphraseResetHintToggle}
+ </div>
</div>
</div>
<cr-toggle id="userEventsToggle"
@@ -398,8 +410,7 @@
$i18n{personalizeGoogleServicesTitle}
</div>
<paper-icon-button-light actionable class="icon-external">
- <button aria-label="$i18n{personalizeGoogleServicesTitle}">
- </button>
+ <button></button>
</paper-icon-button-light>
</a>
@@ -410,16 +421,25 @@
$i18n{manageSyncedDataTitle}
</div>
<paper-icon-button-light actionable class="icon-external">
- <button aria-label="$i18n{manageSyncedDataTitle}"></button>
+ <button></button>
</paper-icon-button-light>
</a>
<div id="encryptionDescription"
hidden="[[syncPrefs.passphraseRequired]]"
- class$="two-line single-column
+ class$="single-column
+ [[getPassphraseHintLines_(syncPrefs.encryptAllData)]]
[[getListItemClass_(unifiedConsentEnabled)]]">
- <div>$i18n{encryptionOptionsTitle}</div>
- <div class="secondary">$i18n{syncDataEncryptedText}</div>
+ $i18n{encryptionOptionsTitle}
+ <div class="secondary">
+ $i18n{syncDataEncryptedText}
+ <div hidden="[[!syncPrefs.encryptAllData]]">
+ <iron-icon icon="settings:info-outline"
+ class="passphrase-reset-icon">
+ </iron-icon>
+ $i18nRaw{passphraseResetHintEncryption}
+ </div>
+ </div>
</div>
<div id="encryptionRadioGroupContainer" class="list-frame"
@@ -431,31 +451,30 @@
on-paper-radio-group-changed=
"onEncryptionRadioSelectionChanged_">
<cr-radio-button name="encrypt-with-google"
- class="list-item" disabled="[[syncPrefs.encryptAllData]]">
+ class="list-item" disabled="[[syncPrefs.encryptAllData]]"
+ aria-label="$i18n{encryptWithGoogleCredentialsLabel}">
$i18n{encryptWithGoogleCredentialsLabel}
</cr-radio-button>
- <cr-radio-button name="encrypt-with-passphrase"
- class="list-item" disabled="[[syncPrefs.encryptAllData]]">
- <template is="dom-if" if="[[syncPrefs.fullEncryptionBody]]">
- <span>[[syncPrefs.fullEncryptionBody]]</span>
- </template>
- <template is="dom-if" if="[[!syncPrefs.fullEncryptionBody]]">
- <span on-click="onLearnMoreTap_">
+ <template is="dom-if" if="[[syncPrefs.fullEncryptionBody]]">
+ <cr-radio-button name="encrypt-with-passphrase"
+ class="list-item" disabled="[[syncPrefs.encryptAllData]]"
+ aria-labelledby="fullEncryptionBody">
+ <span id="fullEncryptionBody">
+ [[syncPrefs.fullEncryptionBody]]
+ </span>
+ </cr-radio-button>
+ </template>
+ <template is="dom-if" if="[[!syncPrefs.fullEncryptionBody]]">
+ <cr-radio-button name="encrypt-with-passphrase"
+ class="list-item" disabled="[[syncPrefs.encryptAllData]]"
+ aria-labelledby="encryptWithSyncPassphraseLabel">
+ <span id="encryptWithSyncPassphraseLabel"
+ on-click="onLearnMoreTap_">
$i18nRaw{encryptWithSyncPassphraseLabel}
</span>
- </template>
- </cr-radio-button>
+ </cr-radio-button>
+ </template>
</paper-radio-group>
-
- <!-- duplicated from above -->
- <div id="reset-sync-message-box-encryption" class="list-item"
- hidden="[[!syncPrefs.encryptAllData]]">
- <span>
- <iron-icon icon="settings:info-outline"></iron-icon>
- $i18nRaw{passphraseResetHint}
- </span>
- </div>
-
</div>
<template is="dom-if" if="[[creatingNewPassphrase_]]">
@@ -498,7 +517,7 @@
</div>
</div>
<cr-expand-button expanded="{{personalizeSectionOpened_}}"
- alt="$i18n{syncExpandA11yLabel}">
+ alt="$i18n{nonPersonalizedServicesExpandA11yLabel}">
</cr-expand-button>
</div>
<iron-collapse id="personalize-section"
diff --git a/chromium/chrome/browser/resources/settings/people_page/sync_page.js b/chromium/chrome/browser/resources/settings/people_page/sync_page.js
index a5520dbebd4..63aaa3b3af1 100644
--- a/chromium/chrome/browser/resources/settings/people_page/sync_page.js
+++ b/chromium/chrome/browser/resources/settings/people_page/sync_page.js
@@ -88,7 +88,6 @@ Polymer({
/** @type {settings.SyncStatus} */
syncStatus: {
type: Object,
- observer: 'onSyncStatusChanged_',
},
/**
@@ -130,6 +129,14 @@ Polymer({
},
/** @private */
+ signedIn_: {
+ type: Boolean,
+ value: true,
+ computed: 'computeSignedIn_(syncStatus.signedIn)',
+ observer: 'onSignedInChanged_',
+ },
+
+ /** @private */
syncSectionDisabled_: {
type: Boolean,
value: false,
@@ -229,12 +236,20 @@ Polymer({
* @return {boolean}
* @private
*/
- computeSyncSectionDisabled_() {
+ computeSignedIn_: function() {
+ return !!this.syncStatus.signedIn;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeSyncSectionDisabled_: function() {
return !!this.unifiedConsentEnabled &&
(!this.syncStatus.signedIn || !!this.syncStatus.disabled ||
(!!this.syncStatus.hasError &&
- this.syncStatus.statusAction ===
- settings.StatusAction.REAUTHENTICATE));
+ this.syncStatus.statusAction !==
+ settings.StatusAction.ENTER_PASSPHRASE));
},
/** @protected */
@@ -291,7 +306,10 @@ Polymer({
* @private
*/
onUnifiedConsentToggleChange_: function() {
- if(!this.$$('#unifiedConsentToggle').checked){
+ const checked = this.$$('#unifiedConsentToggle').checked;
+ this.browserProxy_.unifiedConsentToggleChanged(checked);
+
+ if (!checked) {
this.syncSectionOpened_ = true;
this.personalizeSectionOpened_ = true;
}
@@ -592,9 +610,12 @@ Polymer({
settings.navigateTo(settings.routes.BASIC);
},
- /** @private */
- onSyncStatusChanged_: function() {
- this.syncSectionOpened_ = !!this.syncStatus.signedIn;
+ /**
+ * Collapses/Expands the sync section if the signedIn state has changed.
+ * @private
+ */
+ onSignedInChanged_: function() {
+ this.syncSectionOpened_ = !!this.signedIn_;
},
/**
@@ -639,13 +660,23 @@ Polymer({
return this.unifiedConsentEnabled ? 'list-item' : 'settings-box';
},
+ /**
+ * When there is a sync passphrase, some items have an additional line for the
+ * passphrase reset hint, making them three lines rather than two.
+ * @return {string}
+ * @private
+ */
+ getPassphraseHintLines_: function() {
+ return this.syncPrefs.encryptAllData ? 'three-line' : 'two-line';
+ },
+
// <if expr="not chromeos">
/**
* @return {boolean}
* @private
*/
shouldShowSyncAccountControl_: function() {
- return !!this.diceEnabled && !!this.unifiedConsentEnabled &&
+ return !!this.unifiedConsentEnabled &&
!!this.syncStatus.syncSystemEnabled && !!this.syncStatus.signinAllowed;
},
// </if>
diff --git a/chromium/chrome/browser/resources/settings/people_page/user_list.html b/chromium/chrome/browser/resources/settings/people_page/user_list.html
index fd03c894e98..1a12c33141c 100644
--- a/chromium/chrome/browser/resources/settings/people_page/user_list.html
+++ b/chromium/chrome/browser/resources/settings/people_page/user_list.html
@@ -32,7 +32,7 @@
}
.user-info {
- -webkit-padding-start: 20px;
+ padding-inline-start: 20px;
}
</style>
<div class="user-list" scrollable>
diff --git a/chromium/chrome/browser/resources/settings/people_page/users_page.html b/chromium/chrome/browser/resources/settings/people_page/users_page.html
index 52376e685f4..fbf44a44520 100644
--- a/chromium/chrome/browser/resources/settings/people_page/users_page.html
+++ b/chromium/chrome/browser/resources/settings/people_page/users_page.html
@@ -19,7 +19,7 @@
#add-user-button {
/* Add user button must be lined up with the start of users' names. */
- -webkit-margin-start: var(--settings-box-row-indent);
+ margin-inline-start: var(--settings-box-row-indent);
}
.block {
diff --git a/chromium/chrome/browser/resources/settings/printing_page/BUILD.gn b/chromium/chrome/browser/resources/settings/printing_page/BUILD.gn
index c609a9e2437..5452ef37925 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/printing_page/BUILD.gn
@@ -8,6 +8,7 @@ js_type_check("closure_compile") {
deps = [
":cloud_printers",
":cups_add_printer_dialog",
+ ":cups_add_printer_dialog_elements",
":cups_add_printer_dialog_util",
":cups_edit_printer_dialog",
":cups_printers",
@@ -34,16 +35,22 @@ js_library("cups_add_printer_dialog") {
]
}
-js_library("cups_add_printer_dialog_util") {
+js_library("cups_add_printer_dialog_elements") {
deps = [
":cups_printers_browser_proxy",
- "//ui/webui/resources/cr_elements:cr_scrollable_behavior",
+ ]
+}
+
+js_library("cups_add_printer_dialog_util") {
+ deps = [
+ "//ui/webui/resources/js:cr",
]
}
js_library("cups_edit_printer_dialog") {
deps = [
":cups_set_manufacturer_model_behavior",
+ "//ui/webui/resources/cr_elements:cr_scrollable_behavior",
]
}
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
index ce81da6f79c..b0c64325fdc 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
@@ -1,11 +1,13 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
<link rel="import" href="../i18n_setup.html">
+<link rel="import" href="cups_add_printer_dialog_elements.html">
<link rel="import" href="cups_add_printer_dialog_util.html">
<link rel="import" href="cups_printer_shared_css.html">
<link rel="import" href="cups_printers_browser_proxy.html">
@@ -28,9 +30,9 @@
#searchSpinner paper-spinner-lite {
--paper-spinner-stroke-width: 2px;
- -webkit-margin-end: 3px;
- -webkit-margin-start: 20px;
height: 15px;
+ margin-inline-end: 3px;
+ margin-inline-start: 20px;
width: 15px;
}
</style>
@@ -75,7 +77,7 @@
<template>
<style include="cups-printer-shared">
#discoverPrintersButton {
- -webkit-margin-end: 153px;
+ margin-inline-end: 153px;
}
.search-printer-box {
@@ -84,9 +86,9 @@
.search-printer-box paper-spinner-lite {
--paper-spinner-stroke-width: 2px;
- -webkit-margin-end: 3px;
- -webkit-margin-start: 20px;
height: 15px;
+ margin-inline-end: 3px;
+ margin-inline-start: 20px;
width: 15px;
}
@@ -174,16 +176,16 @@
<div slot="dialog-title">$i18n{selectManufacturerAndModelTitle}</div>
<div slot="dialog-body">
<div class="settings-box two-line">
- <drop-down-search-box items="[[manufacturerList]]"
+ <cr-searchable-drop-down items="[[manufacturerList]]"
label="$i18n{printerManufacturer}"
value="{{activePrinter.ppdManufacturer}}">
- </drop-down-search-box>
+ </cr-searchable-drop-down>
</div>
<div class="settings-box two-line">
- <drop-down-search-box items="[[modelList]]"
+ <cr-searchable-drop-down items="[[modelList]]"
label="$i18n{printerModel}"
value="{{activePrinter.ppdModel}}">
- </drop-down-search-box>
+ </cr-searchable-drop-down>
</div>
<div class="settings-box two-line last">
<cr-input class="browse-file-input" readonly value="[[newUserPPD_]]"
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
index fc6d7f1ad8a..c882c08b391 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
@@ -193,49 +193,13 @@ Polymer({
},
/**
- * This function uses regular expressions to determine whether the provided
- * printer address is valid. Address can be either an ipv4/6 address or a
- * hostname followed by an optional port.
- * NOTE: The regular expression for hostnames will allow hostnames that are
- * over 255 characters.
- * @param {String} name
- * @param {String} address
+ * @param {string} name
+ * @param {string} address
* @return {boolean} Whether the add printer button is enabled.
* @private
*/
canAddPrinter_: function(name, address) {
- if (!name || !address)
- return false;
-
- const hostnamePrefix = '([a-z\\d]|[a-z\\d][a-z\\d\\-]{0,61}[a-z\\d])';
-
- // Matches an arbitrary number of 'prefix patterns' which are separated by a
- // dot.
- const hostnameSuffix = `(\\.${hostnamePrefix})*`;
-
- // Matches an optional port at the end of the address.
- const portNumber = '(:\\d+)?';
-
- const ipv6Full = '(([a-f\\d]){1,4}(:(:)?([a-f\\d]){1,4}){1,7})';
-
- // Special cases for addresses using a shorthand notation.
- const ipv6Prefix = '(::([a-f\\d]){1,4})';
- const ipv6Suffix = '(([a-f\\d]){1,4}::)';
- const ipv6Combined = `(${ipv6Full}|${ipv6Prefix}|${ipv6Suffix})`;
- const ipv6WithPort = `(\\[${ipv6Combined}\\]${portNumber})`;
-
- // Matches valid hostnames and ipv4 addresses.
- const hostnameRegex =
- new RegExp(`^${hostnamePrefix}${hostnameSuffix}${portNumber}$`, 'i');
-
- // Matches valid ipv6 addresses.
- const ipv6AddressRegex =
- new RegExp(`^(${ipv6Combined}|${ipv6WithPort})$`, 'i');
-
- const invalidIpv6Regex = new RegExp('.*::.*::.*');
-
- return hostnameRegex.test(address) ||
- (ipv6AddressRegex.test(address) && !invalidIpv6Regex.test(address));
+ return settings.printing.isNameAndAddressValid(name, address);
},
});
@@ -271,7 +235,8 @@ Polymer({
* @private
*/
canAddPrinter_: function(ppdManufacturer, ppdModel, printerPPDPath) {
- return !!((ppdManufacturer && ppdModel) || printerPPDPath);
+ return settings.printing.isPPDInfoValid(
+ ppdManufacturer, ppdModel, printerPPDPath);
},
});
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html
new file mode 100644
index 00000000000..695ce6d9ec2
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.html
@@ -0,0 +1,58 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="cups_printer_shared_css.html">
+<link rel="import" href="cups_printers_browser_proxy.html">
+
+<dom-module id="add-printer-list">
+ <template>
+ <style include="cups-printer-shared">
+ .list-item {
+ padding: 0 20px;
+ }
+ </style>
+ <div>
+ <array-selector id="arraySelector" items="[[printers]]"
+ selected="{{selectedPrinter}}">
+ </array-selector>
+ <template is="dom-repeat" items="[[printers]]">
+ <button class="list-item" on-click="onSelect_">
+ [[item.printerName]]
+ </button>
+ </template>
+ </div>
+ </template>
+</dom-module>
+
+<dom-module id="add-printer-dialog">
+ <template>
+ <style include="settings-shared">
+ #dialog {
+ --cr-dialog-body-container: {
+ /* Force a bottom border regardless of scroll state. */
+ border-bottom: 1px solid var(--paper-grey-300) !important;
+ };
+ }
+ #dialog [slot=body] {
+ height: 350px;
+ padding-inline-end: 0;
+ padding-inline-start: 0;
+ }
+ </style>
+
+ <cr-dialog id="dialog" close-text="$i18n{close}">
+ <div slot="title">
+ <slot name="dialog-title"></slot>
+ </div>
+ <div slot="body">
+ <slot name="dialog-body"></slot>
+ </div>
+ <div slot="button-container">
+ <slot name="dialog-buttons"></slot>
+ </div>
+ </cr-dialog>
+ </template>
+ <script src="cups_add_printer_dialog_elements.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.js b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.js
new file mode 100644
index 00000000000..d27c65f58a8
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_elements.js
@@ -0,0 +1,44 @@
+// Copyright 2016 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.
+
+/** 'add-printers-list' is the list of discovered printers. */
+Polymer({
+ is: 'add-printer-list',
+
+ properties: {
+ /** @type {!Array<!CupsPrinterInfo>} */
+ printers: {
+ type: Array,
+ notify: true,
+ },
+
+ /** @type {!CupsPrinterInfo} */
+ selectedPrinter: {
+ type: Object,
+ notify: true,
+ },
+ },
+
+ /**
+ * @param {{model:Object}} event
+ * @private
+ */
+ onSelect_: function(event) {
+ this.selectedPrinter = event.model.item;
+ },
+});
+
+/** 'add-printer-dialog' is the template of the Add Printer dialog. */
+Polymer({
+ is: 'add-printer-dialog',
+
+ /** @private */
+ attached: function() {
+ this.$.dialog.showModal();
+ },
+
+ close: function() {
+ this.$.dialog.close();
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html
index e19f575f0ae..c7d68b6bd61 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.html
@@ -1,101 +1,2 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="cups_printer_shared_css.html">
-<link rel="import" href="cups_printers_browser_proxy.html">
-
-<dom-module id="add-printer-list">
- <template>
- <style include="cups-printer-shared">
- .list-item {
- padding: 0 20px;
- }
- </style>
- <div>
- <array-selector id="arraySelector" items="[[printers]]"
- selected="{{selectedPrinter}}">
- </array-selector>
- <template is="dom-repeat" items="[[printers]]">
- <button class="list-item" on-click="onSelect_">
- [[item.printerName]]
- </button>
- </template>
- </div>
- </template>
-</dom-module>
-
-<dom-module id="drop-down-search-box">
- <template>
- <style include="cups-printer-shared">
- cr-input {
- --cr-input-error-display: none;
- }
-
- iron-dropdown,
- cr-input {
- width: 270px;
- }
-
- iron-dropdown {
- height: 270px;
- }
-
- iron-dropdown [slot='dropdown-content'] {
- background-color: white;
- box-shadow: 0 2px 6px var(--paper-grey-500);
- min-width: 128px;
- padding: 8px 0;
- }
- </style>
- <!-- |value| is one-way binding on purpose so that it doesn't change
- immediately as the user types. -->
- <cr-input label="[[label]]" on-click="onClick_" value="[[value]]"
- on-value-changed="onInputValueChanged_" id="search">
- </cr-input>
- <iron-dropdown horizontal-align="left" vertical-align="top"
- vertical-offset="52">
- <div slot="dropdown-content">
- <template is="dom-repeat" items="[[items]]"
- filter="[[filterItems_(searchTerm_)]]">
- <button class="list-item" on-click="onSelect_">[[item]]</button>
- </template>
- </div>
- </iron-dropdown>
- </template>
-</dom-module>
-
-<dom-module id="add-printer-dialog">
- <template>
- <style include="settings-shared">
- #dialog {
- --cr-dialog-body-container: {
- /* Force a bottom border regardless of scroll state. */
- border-bottom: 1px solid var(--paper-grey-300) !important;
- };
- }
- #dialog [slot=body] {
- -webkit-padding-end: 0;
- -webkit-padding-start: 0;
- height: 350px;
- }
- </style>
-
- <cr-dialog id="dialog" close-text="$i18n{close}">
- <div slot="title">
- <slot name="dialog-title"></slot>
- </div>
- <div slot="body" scrollable>
- <slot name="dialog-body"></slot>
- </div>
- <div slot="button-container">
- <slot name="dialog-buttons"></slot>
- </div>
- </cr-dialog>
- </template>
- <script src="cups_add_printer_dialog_util.js"></script>
-</dom-module>
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="cups_add_printer_dialog_util.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js
index 77b61fdcdd3..6cff6ecf1b0 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js
@@ -1,104 +1,71 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// Copyright 2018 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.
-/** 'add-printers-list' is the list of discovered printers. */
-Polymer({
- is: 'add-printer-list',
-
- properties: {
- /** @type {!Array<!CupsPrinterInfo>} */
- printers: {
- type: Array,
- notify: true,
- },
-
- /** @type {!CupsPrinterInfo} */
- selectedPrinter: {
- type: Object,
- notify: true,
- },
- },
+/**
+ * @fileoverview Utility functions that are used in Cups printer setup dialogs.
+ */
+cr.define('settings.printing', function() {
/**
- * @param {{model:Object}} event
- * @private
+ * Returns true if the printer's name and address is valid. This function
+ * uses regular expressions to determine whether the provided printer name
+ * and address are valid. Address can be either an ipv4/6 address or a
+ * hostname followed by an optional port.
+ * NOTE: The regular expression for hostnames will allow hostnames that are
+ * over 255 characters.
+ * @param {string} name
+ * @param {string} address
+ * @return {boolean}
*/
- onSelect_: function(event) {
- this.selectedPrinter = event.model.item;
- },
-});
-
-/** 'drop-down-search-box' implements a search box with suggestions dropdown. */
-Polymer({
- is: 'drop-down-search-box',
-
- properties: {
- /** @type {!Array<string>} */
- items: {
- type: Array,
- },
-
- /** @type {string} */
- value: {
- type: String,
- notify: true,
- },
-
- /** @private {string} */
- searchTerm_: String,
+ function isNameAndAddressValid(name, address) {
+ if (!name || !address)
+ return false;
- label: String,
- },
+ const hostnamePrefix = '([a-z\\d]|[a-z\\d][a-z\\d\\-]{0,61}[a-z\\d])';
- /**
- * @param {!Event} event
- * @private
- */
- onClick_: function(event) {
- this.$$('iron-dropdown').open();
- },
+ // Matches an arbitrary number of 'prefix patterns' which are separated by a
+ // dot.
+ const hostnameSuffix = `(\\.${hostnamePrefix})*`;
- /** @private */
- onInputValueChanged_: function() {
- this.searchTerm_ = this.$.search.value;
- },
+ // Matches an optional port at the end of the address.
+ const portNumber = '(:\\d+)?';
- /**
- * @param {{model:Object}} event
- * @private
- */
- onSelect_: function(event) {
- this.$$('iron-dropdown').close();
+ const ipv6Full = '(([a-f\\d]){1,4}(:(:)?([a-f\\d]){1,4}){1,7})';
- this.value = event.model.item;
- this.searchTerm_ = '';
- },
+ // Special cases for addresses using a shorthand notation.
+ const ipv6Prefix = '(::([a-f\\d]){1,4})';
+ const ipv6Suffix = '(([a-f\\d]){1,4}::)';
+ const ipv6Combined = `(${ipv6Full}|${ipv6Prefix}|${ipv6Suffix})`;
+ const ipv6WithPort = `(\\[${ipv6Combined}\\]${portNumber})`;
- /** @private */
- filterItems_: function(searchTerm) {
- if (!searchTerm)
- return null;
- return function(item) {
- return item.toLowerCase().includes(searchTerm.toLowerCase());
- };
- },
-});
+ // Matches valid hostnames and ipv4 addresses.
+ const hostnameRegex =
+ new RegExp(`^${hostnamePrefix}${hostnameSuffix}${portNumber}$`, 'i');
-/** 'add-printer-dialog' is the template of the Add Printer dialog. */
-Polymer({
- is: 'add-printer-dialog',
+ // Matches valid ipv6 addresses.
+ const ipv6AddressRegex =
+ new RegExp(`^(${ipv6Combined}|${ipv6WithPort})$`, 'i');
- behaviors: [
- CrScrollableBehavior,
- ],
+ const invalidIpv6Regex = new RegExp('.*::.*::.*');
- /** @private */
- attached: function() {
- this.$.dialog.showModal();
- },
+ return hostnameRegex.test(address) ||
+ (ipv6AddressRegex.test(address) && !invalidIpv6Regex.test(address));
+ }
- close: function() {
- this.$.dialog.close();
- },
+ /**
+ * Returns true if the printer's manufacturer and model or ppd path is valid.
+ * @param {string} manufacturer
+ * @param {string} model
+ * @param {string} ppdPath
+ * @return {boolean}
+ */
+ function isPPDInfoValid(manufacturer, model, ppdPath) {
+ return !!((manufacturer && model) || ppdPath);
+ }
+
+ return {
+ isNameAndAddressValid: isNameAndAddressValid,
+ isPPDInfoValid: isPPDInfoValid,
+ };
});
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html b/chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
index 0852b6feeea..c544bcf409d 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
@@ -1,7 +1,10 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="cups_add_printer_dialog_elements.html">
<link rel="import" href="cups_add_printer_dialog_util.html">
<link rel="import" href="cups_printer_shared_css.html">
<link rel="import" href="cups_printers_browser_proxy.html">
@@ -20,7 +23,7 @@
</style>
<add-printer-dialog>
<div slot="dialog-title">$i18n{editPrinterDialogTitle}</div>
- <div slot="dialog-body">
+ <div slot="dialog-body" scrollable>
<div class="settings-box first two-line">
<cr-input class="printer-name-input" autofocus
value="{{activePrinter.printerName}}"
@@ -81,16 +84,16 @@
</cr-input>
</div>
<div class="settings-box two-line">
- <drop-down-search-box items="[[manufacturerList]]"
+ <cr-searchable-drop-down items="[[manufacturerList]]"
label="$i18n{printerManufacturer}"
value="{{activePrinter.ppdManufacturer}}">
- </drop-down-search-box>
+ </cr-searchable-drop-down>
</div>
<div class="settings-box two-line">
- <drop-down-search-box items="[[modelList]]"
+ <cr-searchable-drop-down items="[[modelList]]"
label="$i18n{printerModel}"
value="{{activePrinter.ppdModel}}">
- </drop-down-search-box>
+ </cr-searchable-drop-down>
</div>
<div class="settings-box two-line last">
<cr-input class="browse-file-input" readonly tabindex="-1"
@@ -114,7 +117,8 @@
on-click="onCancelTap_">
$i18n{cancel}
</paper-button>
- <paper-button class="action-button" on-click="onSaveTap_">
+ <paper-button class="action-button" on-click="onSaveTap_"
+ disabled="[[!canSavePrinter_(activePrinter.*)]]">
$i18n{editPrinterButtonText}
</paper-button>
</div>
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js b/chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js
index 7b5543d7715..488afe05f3e 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js
@@ -11,6 +11,7 @@ Polymer({
is: 'settings-cups-edit-printer-dialog',
behaviors: [
+ CrScrollableBehavior,
SetManufacturerModelBehavior,
],
@@ -135,4 +136,17 @@ Polymer({
isNetworkProtocol_: function(protocol) {
return ['ipp', 'ipps', 'http', 'https', 'socket', 'lpd'].includes(protocol);
},
+
+ /**
+ * @return {boolean} Whether the Save button is enabled.
+ * @private
+ */
+ canSavePrinter_: function() {
+ return settings.printing.isNameAndAddressValid(
+ this.activePrinter.printerName,
+ this.activePrinter.printerAddress) &&
+ settings.printing.isPPDInfoValid(
+ this.activePrinter.ppdManufacturer, this.activePrinter.ppdModel,
+ this.activePrinter.printerPPDPath);
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html b/chromium/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html
index 7f1b7d0bc07..8b3f8c47bb3 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html
+++ b/chromium/chrome/browser/resources/settings/printing_page/cups_printer_shared_css.html
@@ -47,7 +47,7 @@
}
[slot='dialog-body'] .settings-box .browse-button {
- -webkit-margin-start: 5px;
+ margin-inline-start: 5px;
}
[slot='dialog-body'] .last {
diff --git a/chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn b/chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn
index d2bb5b5324f..b938576c22c 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn
@@ -37,6 +37,8 @@ js_library("privacy_page") {
"..:page_visibility",
"..:route",
"../controls:settings_toggle_button",
+ "../people_page:signout_dialog",
+ "../people_page:sync_browser_proxy",
"../settings_page:settings_animated_pages",
"../site_settings:constants",
"../site_settings:site_data_details_subpage",
diff --git a/chromium/chrome/browser/resources/settings/privacy_page/personalization_options.html b/chromium/chrome/browser/resources/settings/privacy_page/personalization_options.html
index e50aef02669..843f10eeb1d 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/personalization_options.html
+++ b/chromium/chrome/browser/resources/settings/privacy_page/personalization_options.html
@@ -14,8 +14,8 @@
<style include="settings-shared">
:host(.list-frame) settings-toggle-button,
:host(.list-frame) .settings-box {
- -webkit-padding-end: 0;
- -webkit-padding-start: 0;
+ padding-inline-end: 0;
+ padding-inline-start: 0;
}
:host(.list-frame) settings-toggle-button:first-of-type {
diff --git a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html
index f14f0e74725..aabd6fb0c8b 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -11,6 +11,8 @@
<link rel="import" href="../clear_browsing_data_dialog/clear_browsing_data_dialog.html">
<link rel="import" href="../controls/settings_toggle_button.html">
<link rel="import" href="../lifetime_browser_proxy.html">
+<link rel="import" href="../people_page/sync_browser_proxy.html">
+<link rel="import" href="../people_page/signout_dialog.html">
<link rel="import" href="../route.html">
<link rel="import" href="../settings_page/settings_animated_pages.html">
<link rel="import" href="../settings_page/settings_subpage.html">
@@ -29,6 +31,9 @@
<link rel="import" href="../site_settings/zoom_levels.html">
<link rel="import" href="../site_settings_page/site_settings_page.html">
+<if expr="not chromeos">
+<link rel="import" href="chrome://resources/cr_elements/cr_toast/cr_toast.html">
+</if>
<if expr="use_nss_certs">
<link rel="import" href="chrome://resources/cr_components/certificate_manager/certificate_manager.html">
</if>
@@ -38,6 +43,18 @@
<dom-module id="settings-privacy-page">
<template>
<style include="settings-shared">
+<if expr="not chromeos">
+ #toast {
+ color: white;
+ left: 0;
+ z-index: 1;
+ }
+
+ :host-context([dir='rtl']) #toast {
+ left: auto;
+ right: 0;
+ }
+</if>
</style>
<template is="dom-if" if="[[showClearBrowsingDataDialog_]]" restamp>
<settings-clear-browsing-data-dialog prefs="{{prefs}}"
@@ -66,9 +83,22 @@
<settings-animated-pages id="pages" section="privacy"
focus-config="[[focusConfig_]]">
<neon-animatable route-path="default">
- <div class="settings-box first">
- <p class="privacy-explanation">$i18nRaw{improveBrowsingExperience}</p>
- </div>
+ <template is="dom-if" if="[[!unifiedConsentEnabled_]]">
+ <div class="settings-box first">
+ <p class="privacy-explanation">
+ $i18nRaw{improveBrowsingExperience}
+ </p>
+ </div>
+ </template>
+<if expr="not chromeos">
+ <settings-toggle-button id="signinAllowedToggle"
+ pref="{{prefs.signin.allowed_on_next_startup}}"
+ label="$i18n{signinAllowedTitle}"
+ sub-label="$i18n{signinAllowedDescription}"
+ on-settings-boolean-control-change="onSigninAllowedChange_"
+ no-set-pref>
+ </settings-toggle-button>
+</if><!-- not chromeos -->
<template is="dom-if" if="[[!unifiedConsentEnabled_]]">
<settings-personalization-options prefs="{{prefs}}"
page-visibility="[[pageVisibility]]"
@@ -173,7 +203,7 @@
<template is="dom-if" route-path="/content/all" no-search>
<settings-subpage page-title="$i18n{siteSettingsAllSites}">
- <all-sites></all-sites>
+ <all-sites focus-config="[[focusConfig_]]"></all-sites>
</settings-subpage>
</template>
<template is="dom-if" route-path="/content/automaticDownloads" no-search>
@@ -319,6 +349,15 @@
toggle-on-label="$i18n{siteSettingsSoundAllowRecommended}"
category="{{ContentSettingsTypes.SOUND}}">
</category-default-setting>
+ <settings-toggle-button
+ id="block-autoplay-setting"
+ label="$i18n{siteSettingsBlockAutoplaySetting}"
+ pref="{{blockAutoplayStatus_.pref}}"
+ disabled="[[!blockAutoplayStatus_.enabled]]"
+ hidden="[[!enableBlockAutoplayContentSetting_]]"
+ on-settings-boolean-control-change="onBlockAutoplayToggleChange_"
+ no-set-pref>
+ </settings-toggle-button>
<category-setting-exceptions
category="{{ContentSettingsTypes.SOUND}}"
block-header="$i18n{siteSettingsBlockSound}">
@@ -468,7 +507,10 @@
</template>
<template is="dom-if" route-path="/content/siteDetails" no-search>
<settings-subpage page-title="[[pageTitle]]">
- <site-details page-title="{{pageTitle}}"></site-details>
+ <site-details
+ page-title="{{pageTitle}}"
+ block-autoplay-enabled="[[blockAutoplayStatus_.pref.value]]">
+ </site-details>
</settings-subpage>
</template>
<template is="dom-if" route-path="/cookies/detail" no-search>
@@ -542,6 +584,21 @@
</template>
</template>
</settings-animated-pages>
+
+ <template is="dom-if" if="[[showSignoutDialog_]]" restamp>
+ <settings-signout-dialog sync-status="[[syncStatus]]"
+ on-close="onSignoutDialogClosed_">
+ </settings-signout-dialog>
+ </template>
+
+<if expr="not chromeos">
+ <cr-toast id="toast" open="[[showRestart_]]">
+ <div>$i18n{restartToApplyChanges}</div>
+ <paper-button on-click="onRestartTap_">
+ $i18n{restart}
+ </paper-button>
+ </cr-toast>
+</if>
</template>
<script src="privacy_page.js"></script>
</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js
index bc30d06c27d..a619084323d 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js
+++ b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page.js
@@ -3,6 +3,14 @@
// found in the LICENSE file.
/**
+ * @typedef {{
+ * enabled: boolean,
+ * pref: !chrome.settingsPrivate.PrefObject
+ * }}
+ */
+let BlockAutoplayStatus;
+
+/**
* @fileoverview
* 'settings-privacy-page' is the settings page containing privacy and
* security settings.
@@ -28,6 +36,12 @@ Polymer({
},
/**
+ * The current sync status, supplied by SyncBrowserProxy.
+ * @type {?settings.SyncStatus}
+ */
+ syncStatus: Object,
+
+ /**
* Dictionary defining page visibility.
* @type {!PrivacyPageVisibility}
*/
@@ -67,6 +81,22 @@ Polymer({
},
/** @private */
+ enableBlockAutoplayContentSetting_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('enableBlockAutoplayContentSetting');
+ }
+ },
+
+ /** @private {BlockAutoplayStatus} */
+ blockAutoplayStatus_: {
+ type: Object,
+ value: function() {
+ return /** @type {BlockAutoplayStatus} */ ({});
+ }
+ },
+
+ /** @private */
enableClipboardContentSetting_: {
type: Boolean,
value: function() {
@@ -139,6 +169,14 @@ Polymer({
return loadTimeData.getBoolean('enableEphemeralFlashPermission');
},
},
+
+ // <if expr="not chromeos">
+ /** @private */
+ showRestart_: Boolean,
+ // </if>
+
+ /** @private */
+ showSignoutDialog_: Boolean,
},
listeners: {
@@ -150,6 +188,29 @@ Polymer({
this.ContentSettingsTypes = settings.ContentSettingsTypes;
this.browserProxy_ = settings.PrivacyPageBrowserProxyImpl.getInstance();
+
+ this.onBlockAutoplayStatusChanged_({
+ pref: /** @type {chrome.settingsPrivate.PrefObject} */ ({value: false}),
+ enabled: false
+ });
+
+ this.addWebUIListener(
+ 'onBlockAutoplayStatusChanged',
+ this.onBlockAutoplayStatusChanged_.bind(this));
+
+ settings.SyncBrowserProxyImpl.getInstance().getSyncStatus().then(
+ this.handleSyncStatus_.bind(this));
+ this.addWebUIListener(
+ 'sync-status-changed', this.handleSyncStatus_.bind(this));
+ },
+
+ /**
+ * Handler for when the sync state is pushed from the browser.
+ * @param {?settings.SyncStatus} syncStatus
+ * @private
+ */
+ handleSyncStatus_: function(syncStatus) {
+ this.syncStatus = syncStatus;
},
/** @protected */
@@ -168,6 +229,25 @@ Polymer({
},
/**
+ * Called when the block autoplay status changes.
+ * @param {BlockAutoplayStatus} autoplayStatus
+ * @private
+ */
+ onBlockAutoplayStatusChanged_: function(autoplayStatus) {
+ this.blockAutoplayStatus_ = autoplayStatus;
+ },
+
+ /**
+ * Updates the block autoplay pref when the toggle is changed.
+ * @param {!Event} event
+ * @private
+ */
+ onBlockAutoplayToggleChange_: function(event) {
+ const target = /** @type {!SettingsToggleButtonElement} */ (event.target);
+ this.browserProxy_.setBlockAutoplayEnabled(target.checked);
+ },
+
+ /**
* Handles the change event for the do-not-track toggle. Shows a
* confirmation dialog when enabling the setting.
* @param {!Event} event
@@ -300,5 +380,40 @@ Polymer({
return value ? this.i18n('siteSettingsProtectedContentEnableIdentifiers') :
this.i18n('siteSettingsBlocked');
},
+
+ /** @private */
+ onSigninAllowedChange_: function() {
+ if (this.syncStatus.signedIn && !this.$.signinAllowedToggle.checked) {
+ // Switch the toggle back on and show the signout dialog.
+ this.$.signinAllowedToggle.checked = true;
+ this.showSignoutDialog_ = true;
+ } else {
+ /** @type {!SettingsToggleButtonElement} */ (this.$.signinAllowedToggle)
+ .sendPrefChange();
+ this.showRestart_ = true;
+ }
+ },
+
+ /** @private */
+ onSignoutDialogClosed_: function() {
+ if (/** @type {!SettingsSignoutDialogElement} */ (
+ this.$$('settings-signout-dialog'))
+ .wasConfirmed()) {
+ this.$.signinAllowedToggle.checked = false;
+ /** @type {!SettingsToggleButtonElement} */ (this.$.signinAllowedToggle)
+ .sendPrefChange();
+ this.showRestart_ = true;
+ }
+ this.showSignoutDialog_ = false;
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onRestartTap_: function(e) {
+ e.stopPropagation();
+ settings.LifetimeBrowserProxyImpl.getInstance().restart();
+ },
});
})();
diff --git a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.js b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.js
index 63790dfadb2..c1e7d9fc333 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.js
@@ -33,6 +33,9 @@ cr.define('settings', function() {
/** @param {boolean} enabled */
setSafeBrowsingExtendedReportingEnabled(enabled) {}
+
+ /** @param {boolean} enabled */
+ setBlockAutoplayEnabled(enabled) {}
}
/**
@@ -62,6 +65,11 @@ cr.define('settings', function() {
chrome.send('setSafeBrowsingExtendedReportingEnabled', [enabled]);
}
+ /** @override */
+ setBlockAutoplayEnabled(enabled) {
+ chrome.send('setBlockAutoplayEnabled', [enabled]);
+ }
+
// <if expr="is_win or is_macosx">
/** @override */
showManageSSLCertificates() {
diff --git a/chromium/chrome/browser/resources/settings/route.js b/chromium/chrome/browser/resources/settings/route.js
index 7c19ea2f49f..866453bdfdd 100644
--- a/chromium/chrome/browser/resources/settings/route.js
+++ b/chromium/chrome/browser/resources/settings/route.js
@@ -55,6 +55,7 @@
* NETWORK_DETAIL: (undefined|!settings.Route),
* ON_STARTUP: (undefined|!settings.Route),
* PASSWORDS: (undefined|!settings.Route),
+ * PAYMENTS: (undefined|!settings.Route),
* PEOPLE: (undefined|!settings.Route),
* POINTERS: (undefined|!settings.Route),
* POWER: (undefined|!settings.Route),
@@ -275,6 +276,7 @@ cr.define('settings', function() {
if (autofillHomeEnabled) {
r.AUTOFILL = r.PEOPLE.createChild('/autofill');
r.MANAGE_PASSWORDS = r.PEOPLE.createChild('/passwords');
+ r.PAYMENTS = r.PEOPLE.createChild('/payments');
}
// <if expr="not chromeos">
r.MANAGE_PROFILE = r.PEOPLE.createChild('/manageProfile');
@@ -375,6 +377,7 @@ cr.define('settings', function() {
r.ADVANCED.createSection('/passwordsAndForms', 'passwordsAndForms');
r.AUTOFILL = r.PASSWORDS.createChild('/autofill');
r.MANAGE_PASSWORDS = r.PASSWORDS.createChild('/passwords');
+ r.PAYMENTS = r.PASSWORDS.createChild('/payments');
}
r.LANGUAGES = r.ADVANCED.createSection('/languages', 'languages');
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html b/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html
index 26f24c1a061..b181ac3e909 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html
@@ -24,7 +24,7 @@
}
.favicon-image + span {
- -webkit-margin-end: 8px;
+ margin-inline-end: 8px;
}
</style>
<div class="list-item" focus-row-container>
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html
index 4f058e297eb..413a1e34eea 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html
@@ -32,7 +32,7 @@
#keyword-column > div,
.favicon-image + div {
- -webkit-margin-end: 8px;
+ margin-inline-end: 8px;
}
#url-column {
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry_css.html b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry_css.html
index 46bf166feff..2770ff9ff3f 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry_css.html
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engine_entry_css.html
@@ -2,11 +2,11 @@
<template>
<style>
.favicon-image {
- -webkit-margin-end: 8px;
background-repeat: no-repeat;
background-size: contain;
display: inline-block;
height: 20px;
+ margin-inline-end: 8px;
min-width: 20px;
vertical-align: middle;
}
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html
index 2b6698fe907..6ebb6002de7 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/search_engines_list.html
@@ -38,8 +38,8 @@
}
.icon-placeholder {
- -webkit-margin-end: 0;
- -webkit-margin-start: var(--cr-icon-button-margin-start);
+ margin-inline-end: 0;
+ margin-inline-start: var(--cr-icon-button-margin-start);
width: var(--cr-icon-ripple-size);
}
</style>
diff --git a/chromium/chrome/browser/resources/settings/search_page/search_page.html b/chromium/chrome/browser/resources/settings/search_page/search_page.html
index 34ee2bdf1dc..0fa27b3f0d4 100644
--- a/chromium/chrome/browser/resources/settings/search_page/search_page.html
+++ b/chromium/chrome/browser/resources/settings/search_page/search_page.html
@@ -34,11 +34,11 @@
}
iron-icon {
- -webkit-padding-end: 16px;
+ padding-inline-end: 16px;
}
.indented {
- -webkit-margin-start: var(--settings-indent-width);
+ margin-inline-start: var(--settings-indent-width);
}
</style>
<settings-animated-pages id="pages" section="search"
@@ -47,9 +47,9 @@
<!-- Omnibox search engine -->
<div class="settings-box first block">
<div id="search-wrapper">
- <p id="searchExplanation" class="start">
+ <div id="searchExplanation" class="start">
$i18nRaw{searchExplanation}
- </p>
+ </div>
<template is="dom-if" if="[[isDefaultSearchControlledByPolicy_(
prefs.default_search_provider_data.template_url_data)]]">
<cr-policy-pref-indicator pref="[[
diff --git a/chromium/chrome/browser/resources/settings/search_page/search_page.js b/chromium/chrome/browser/resources/settings/search_page/search_page.js
index 1b229698d03..8a66f1d2b38 100644
--- a/chromium/chrome/browser/resources/settings/search_page/search_page.js
+++ b/chromium/chrome/browser/resources/settings/search_page/search_page.js
@@ -150,7 +150,7 @@ Polymer({
*/
isAssistantTurnedOn_: function(
arcEnabled, valuePropAccepted, assistantFeatureEnabled) {
- return (arcEnabled || assistantFeatureEnabled) && valuePropAccepted;
+ return (arcEnabled && valuePropAccepted) || assistantFeatureEnabled;
},
// </if>
diff --git a/chromium/chrome/browser/resources/settings/search_settings.js b/chromium/chrome/browser/resources/settings/search_settings.js
index 19c3a1e609e..0d068f770e2 100644
--- a/chromium/chrome/browser/resources/settings/search_settings.js
+++ b/chromium/chrome/browser/resources/settings/search_settings.js
@@ -381,13 +381,13 @@ cr.define('settings', function() {
class SearchRequest {
/**
* @param {string} rawQuery
- * @param {!HTMLElement} root
+ * @param {!Element} root
*/
constructor(rawQuery, root) {
/** @private {string} */
this.rawQuery_ = rawQuery;
- /** @private {!HTMLElement} */
+ /** @private {!Element} */
this.root_ = root;
/** @type {?RegExp} */
@@ -516,7 +516,7 @@ cr.define('settings', function() {
class SearchManager {
/**
* @param {string} text The text to search for.
- * @param {!Node} page
+ * @param {!Element} page
* @return {!Promise<!settings.SearchRequest>} A signal indicating that
* searching finished.
*/
@@ -566,11 +566,15 @@ cr.define('settings', function() {
});
}
}
- cr.addSingletonGetter(SearchManagerImpl);
+
+ /** @type {?SearchManager} */
+ let instance = null;
/** @return {!SearchManager} */
function getSearchManager() {
- return SearchManagerImpl.getInstance();
+ if (instance === null)
+ instance = new SearchManagerImpl();
+ return instance;
}
/**
@@ -578,7 +582,7 @@ cr.define('settings', function() {
* @param {!SearchManager} searchManager
*/
function setSearchManagerForTesting(searchManager) {
- SearchManagerImpl.instance_ = searchManager;
+ instance = searchManager;
}
return {
diff --git a/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
index 0e4e060b522..f8f22e9b9c9 100644
--- a/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chromium/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -23,15 +23,15 @@
--cr-selectable-focus: {
outline: auto 5px -webkit-focus-ring-color;
};
- -webkit-margin-end: 2px; /* Margin so selected outline is visible. */
- -webkit-margin-start: 1px;
- -webkit-padding-start: 23px; /* 24px - 1px from margin for outline. */
align-items: center;
color: var(--settings-nav-grey);
display: flex;
font-weight: 500;
+ margin-inline-end: 2px; /* Margin so selected outline is visible. */
+ margin-inline-start: 1px;
min-height: 20px;
padding-bottom: 10px;
+ padding-inline-start: 23px; /* 24px - 1px from margin for outline. */
padding-top: 10px;
}
@@ -41,7 +41,7 @@
iron-icon {
--iron-icon-fill-color: var(--settings-nav-grey);
- -webkit-margin-end: 24px;
+ margin-inline-end: 24px;
pointer-events: none;
vertical-align: top;
}
@@ -51,12 +51,12 @@
}
#advancedButton {
- -webkit-padding-end: 0;
background-color: unset;
border: none;
border-radius: initial;
height: unset;
margin-top: 8px;
+ padding-inline-end: 0;
text-transform: none;
}
@@ -77,7 +77,7 @@
#advancedButton > iron-icon,
#extensionsLink > iron-icon {
@apply --cr-icon-height-width;
- -webkit-margin-end: 14px; /* 16px - 2px from margin for outline. */
+ margin-inline-end: 14px; /* 16px - 2px from margin for outline. */
}
#menuSeparator {
diff --git a/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn b/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn
index d354bfa4fd3..9114c55812a 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn
@@ -46,6 +46,7 @@ js_library("settings_section") {
js_library("settings_subpage") {
deps = [
":settings_subpage_search",
+ "..:find_shortcut_behavior",
"..:route",
"//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted",
"//third_party/polymer/v1_0/components-chromium/neon-animation:neon-animatable-behavior-extracted",
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html b/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
index 655b3faa8a0..10c922d3ff9 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
@@ -4,6 +4,7 @@
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/cr/ui.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
+<link rel="import" href="chrome://resources/html/util.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-from-left-animation.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-from-right-animation.html">
<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-left-animation.html">
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js b/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
index 7492cde177e..1fe497be49b 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
@@ -32,9 +32,9 @@ Polymer({
/**
* A Map specifying which element should be focused when exiting a subpage.
* The key of the map holds a settings.Route path, and the value holds
- * either a query selector that identifies the desired element or a function
- * to be run when a neon-animation-finish event is handled.
- * @type {?Map<string, (string|Function)>}
+ * either a query selector that identifies the desired element, an element
+ * or a function to be run when a neon-animation-finish event is handled.
+ * @type {?Map<string, (string|Element|Function)>}
*/
focusConfig: Object,
},
@@ -88,6 +88,9 @@ Polymer({
if (settings.routes.SITE_SETTINGS_SITE_DATA)
subpagePaths.push(settings.routes.SITE_SETTINGS_SITE_DATA.path);
+ if (settings.routes.SITE_SETTINGS_ALL)
+ subpagePaths.push(settings.routes.SITE_SETTINGS_ALL.path);
+
// <if expr="chromeos">
if (settings.routes.INTERNET_NETWORKS)
subpagePaths.push(settings.routes.INTERNET_NETWORKS.path);
@@ -104,20 +107,23 @@ Polymer({
if (!e.detail.item.matches(query))
return;
- const selectorOrFunction = this.focusConfig.get(this.previousRoute_.path);
- if (selectorOrFunction) {
+ let pathConfig = this.focusConfig.get(this.previousRoute_.path);
+ if (pathConfig) {
+ let handler;
+ if (typeof pathConfig == 'function') {
+ handler = pathConfig;
+ } else {
+ handler = () => {
+ if (typeof pathConfig == 'string')
+ pathConfig = assert(this.querySelector(pathConfig));
+ cr.ui.focusWithoutInk(/** @type {!Element} */ (pathConfig));
+ };
+ }
// neon-animatable has "display: none" until the animation finishes,
// so calling focus() on any of its children has no effect until
// "display:none" is removed. Therefore, don't set focus from within
// the currentRouteChanged callback.
- listenOnce(this, 'neon-animation-finish', () => {
- if (typeof selectorOrFunction == 'function') {
- selectorOrFunction();
- } else {
- const selector = /** @type {string} */ (selectorOrFunction);
- cr.ui.focusWithoutInk(assert(this.querySelector(selector)));
- }
- });
+ listenOnce(this, 'neon-animation-finish', handler);
}
},
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_section.html b/chromium/chrome/browser/resources/settings/settings_page/settings_section.html
index 24bb6386339..7599a515645 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_section.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_section.html
@@ -7,11 +7,11 @@
<template>
<style>
:host {
- -webkit-margin-end: 3px;
- -webkit-margin-start: 3px;
display: flex;
flex-direction: column;
/* Margin so the box-shadow isn't clipped during animations. */
+ margin-inline-end: 3px;
+ margin-inline-start: 3px;
position: relative;
}
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
index e736d4fd182..b940d7f9423 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.html
@@ -7,6 +7,7 @@
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
+<link rel="import" href="../find_shortcut_behavior.html">
<link rel="import" href="../icons.html">
<link rel="import" href="../route.html">
<link rel="import" href="settings_subpage_search.html">
@@ -38,8 +39,8 @@
paper-icon-button-light {
/* Centers the ripple on the icon with appropriate margin on right. */
- -webkit-margin-end: 10px;
- -webkit-margin-start: -10px;
+ margin-inline-end: 10px;
+ margin-inline-start: -10px;
}
paper-spinner-lite {
@@ -54,7 +55,7 @@
settings-subpage-search {
/* Keep normal icon spacing from subpage-title-extra controls. */
- -webkit-margin-start: 16px;
+ margin-inline-start: 16px;
}
</style>
<div class="settings-box first" id="headerLine">
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js
index 32880610425..82fecc6a084 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage.js
@@ -15,6 +15,8 @@ Polymer({
// TODO(michaelpg): phase out NeonAnimatableBehavior.
Polymer.NeonAnimatableBehavior,
Polymer.IronResizableBehavior,
+ settings.FindShortcutBehavior,
+ settings.RouteObserverBehavior,
],
properties: {
@@ -47,6 +49,13 @@ Polymer({
type: Object,
value: null,
},
+
+ /** @private */
+ active_: {
+ type: Boolean,
+ value: false,
+ observer: 'onActiveChanged_',
+ },
},
/** @override */
@@ -71,6 +80,22 @@ Polymer({
this, () => cr.ui.focusWithoutInk(this.$.closeButton));
},
+ /** @protected */
+ currentRouteChanged: function(route) {
+ this.active_ = this.getAttribute('route-path') == route.path;
+ },
+
+ /** @private */
+ onActiveChanged_: function() {
+ if (!this.searchLabel)
+ return;
+
+ if (this.active_)
+ this.becomeActiveFindShortcutListener();
+ else
+ this.removeSelfAsFindShortcutListener();
+ },
+
/**
* Clear the value of the search field.
* @param {!Event} e
@@ -89,4 +114,15 @@ Polymer({
onSearchChanged_: function(e) {
this.searchTerm = e.detail;
},
+
+ // Override settings.FindShortcutBehavior methods.
+ handleFindShortcut: function(modalContextOpen) {
+ if (modalContextOpen)
+ return false;
+ const subpageSearch = this.$$('settings-subpage-search');
+ const searchInput = subpageSearch.getSearchInput();
+ if (searchInput != subpageSearch.shadowRoot.activeElement)
+ searchInput.focus();
+ return true;
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html
index bad6b43ebe5..100316f9b1e 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html
+++ b/chromium/chrome/browser/resources/settings/settings_page/settings_subpage_search.html
@@ -29,29 +29,19 @@
--cr-input-error-display: none;
--cr-input-input: {
background-color: white;
- -webkit-padding-end: 0;
- -webkit-padding-start: 0;
- padding-bottom: 2px;
- padding-top: 2px;
border-bottom: 1px solid var(--google-grey-900);
}
+ --cr-input-padding-end: 0;
+ --cr-input-padding-start: 0;
+ --cr-input-padding-bottom: 2px;
+ --cr-input-padding-top: 2px;
display: inline-block;
vertical-align: middle;
width: 160px; /* Special width for search input. */
}
:host([has-search-text]) cr-input {
- /* Unfortunately we have to duplicate most of this mixin, due to how
- redeclaration overrides the entire mixin, but the only value that
- changes is padding-end. */
- --cr-input-input: {
- background-color: white;
- -webkit-padding-end: 20px;
- -webkit-padding-start: 0;
- padding-bottom: 2px;
- padding-top: 2px;
- border-bottom: 1px solid var(--google-grey-900);
- }
+ --cr-input-padding-end: 20px;
}
#searchInput {
@@ -64,12 +54,11 @@
}
#clearSearchContainer {
- -webkit-margin-end: -4px;
- -webkit-margin-start: 4px;
-
/* A 16px icon that fits on the input line. */
background-size: 16px;
height: 24px;
+ margin-inline-end: -4px;
+ margin-inline-start: 4px;
position: absolute;
right: 0;
width: 24px;
diff --git a/chromium/chrome/browser/resources/settings/settings_resources.grd b/chromium/chrome/browser/resources/settings/settings_resources.grd
index 12684438ba7..abd10caf92b 100644
--- a/chromium/chrome/browser/resources/settings/settings_resources.grd
+++ b/chromium/chrome/browser/resources/settings/settings_resources.grd
@@ -368,7 +368,8 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_JS"
file="clear_browsing_data_dialog/clear_browsing_data_dialog.js"
- type="chrome_html" />
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_HISTORY_DELETION_DIALOG_HTML"
file="clear_browsing_data_dialog/history_deletion_dialog.html"
type="chrome_html" />
@@ -411,6 +412,14 @@
<structure name="IDR_SETTINGS_CONTROLS_DROPDOWN_MENU_JS"
file="controls/settings_dropdown_menu.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_CONTROLS_PASSWORD_PROMPT_DIALOG_JS"
+ file="controls/password_prompt_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_CONTROLS_PASSWORD_PROMPT_DIALOG_HTML"
+ file="controls/password_prompt_dialog.html"
+ type="chrome_html"
+ preprocess="true"
+ allowexternalscript="true" />
<structure name="IDR_SETTINGS_CONTROLS_PREF_CONTROL_BEHAVIOR_HTML"
file="controls/pref_control_behavior.html"
type="chrome_html" />
@@ -567,6 +576,7 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_DOWNLOADS_BROWSER_PROXY_JS"
file="downloads_page/downloads_browser_proxy.js"
+ preprocess="true"
type="chrome_html" />
<structure name="IDR_SETTINGS_DOWNLOADS_PAGE_HTML"
file="downloads_page/downloads_page.html"
@@ -609,8 +619,7 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_FIND_SHORTCUT_BEHAVIOR_JS"
file ="find_shortcut_behavior.js"
- type="chrome_html"
- preprocess="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_POWERWASH_DIALOG_HTML"
file="reset_page/powerwash_dialog.html"
type="chrome_html" />
@@ -761,6 +770,12 @@
<structure name="IDR_SETTINGS_PASSWORDS_EXPORT_DIALOG_JS"
file="passwords_and_forms_page/passwords_export_dialog.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_PAYMENTS_SECTION_HTML"
+ file="passwords_and_forms_page/payments_section.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PAYMENTS_SECTION_JS"
+ file="passwords_and_forms_page/payments_section.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PEOPLE_PAGE_HTML"
file="people_page/people_page.html"
type="chrome_html"
@@ -807,6 +822,14 @@
file="people_page/manage_profile_browser_proxy.js"
type="chrome_html" />
</if>
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_SIGNOUT_DIALOG_HTML"
+ file="people_page/signout_dialog.html"
+ type="chrome_html"
+ preprocess="true" />
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_SIGNOUT_DIALOG_JS"
+ file="people_page/signout_dialog.js"
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_PEOPLE_PAGE_PROFILE_INFO_BROWSER_PROXY_HTML"
file="people_page/profile_info_browser_proxy.html"
type="chrome_html" />
@@ -894,6 +917,12 @@
<structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_JS"
file="printing_page/cups_add_printer_dialog.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_ELEMENTS_HTML"
+ file="printing_page/cups_add_printer_dialog_elements.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_ELEMENTS_JS"
+ file="printing_page/cups_add_printer_dialog_elements.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_UTIL_HTML"
file="printing_page/cups_add_printer_dialog_util.html"
type="chrome_html" />
@@ -998,6 +1027,12 @@
<structure name="IDR_SETTINGS_SITE_LIST_JS"
file="site_settings/site_list.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_SITE_LIST_ENTRY_HTML"
+ file="site_settings/site_list_entry.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SITE_LIST_ENTRY_JS"
+ file="site_settings/site_list_entry.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_SITE_SETTINGS_BEHAVIOR_HTML"
file="site_settings/site_settings_behavior.html"
type="chrome_html" />
@@ -1312,12 +1347,24 @@
<structure name="IDR_SETTINGS_MULTIDEVICE_CONSTANTS_JS"
file="multidevice_page/multidevice_constants.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_BEHAVIOR_HTML"
+ file="multidevice_page/multidevice_feature_behavior.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_BEHAVIOR_JS"
+ file="multidevice_page/multidevice_feature_behavior.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_ITEM_HTML"
file="multidevice_page/multidevice_feature_item.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_ITEM_JS"
file="multidevice_page/multidevice_feature_item.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_TOGGLE_HTML"
+ file="multidevice_page/multidevice_feature_toggle.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_TOGGLE_JS"
+ file="multidevice_page/multidevice_feature_toggle.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_MULTIDEVICE_PAGE_HTML"
file="multidevice_page/multidevice_page.html"
type="chrome_html" />
@@ -1336,18 +1383,18 @@
<structure name="IDR_SETTINGS_MULTIDEVICE_SUBPAGE_JS"
file="multidevice_page/multidevice_subpage.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_MULTIDEVICE_TETHER_ITEM_HTML"
+ file="multidevice_page/multidevice_tether_item.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_MULTIDEVICE_TETHER_ITEM_JS"
+ file="multidevice_page/multidevice_tether_item.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROXY_SECTION_HTML"
file="internet_page/network_proxy_section.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_PROXY_SECTION_JS"
file="internet_page/network_proxy_section.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_LISTENER_BEHAVIOR_HTML"
- file="internet_page/network_listener_behavior.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_LISTENER_BEHAVIOR_JS"
- file="internet_page/network_listener_behavior.js"
- type="chrome_html" />
<structure name="IDR_SETTINGS_NETWORK_SUMMARY_HTML"
file="internet_page/network_summary.html"
type="chrome_html" />
@@ -1416,11 +1463,11 @@
type="chrome_html"
preprocess="true"
allowexternalscript="true" />
- <structure name="IDR_SETTINGS_PEOPLE_PASSWORD_PROMPT_DIALOG_JS"
- file="people_page/password_prompt_dialog.js"
+ <structure name="IDR_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_PROMPT_DIALOG_JS"
+ file="people_page/lock_screen_password_prompt_dialog.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_PASSWORD_PROMPT_DIALOG_HTML"
- file="people_page/password_prompt_dialog.html"
+ <structure name="IDR_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_PROMPT_DIALOG_HTML"
+ file="people_page/lock_screen_password_prompt_dialog.html"
type="chrome_html"
preprocess="true"
allowexternalscript="true" />
@@ -1468,12 +1515,6 @@
<structure name="IDR_SETTINGS_PEOPLE_SETUP_FINGERPRINT_DIALOG_HTML"
file="people_page/setup_fingerprint_dialog.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_FINGERPRINT_PROGRESS_ARC_JS"
- file="people_page/fingerprint_progress_arc.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_FINGERPRINT_PROGRESS_ARC_HTML"
- file="people_page/fingerprint_progress_arc.html"
- type="chrome_html" />
<structure name="IDR_SETTINGS_PEOPLE_FINGERPRINT_BROWSER_PROXY_JS"
file="people_page/fingerprint_browser_proxy.js"
type="chrome_html" />
diff --git a/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd b/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd
index fcd5540c552..46a832e137a 100644
--- a/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd
+++ b/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd
@@ -13,8 +13,10 @@
<release seq="1">
<includes>
<include name="IDR_MD_SETTINGS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MD_SETTINGS_VULCANIZED_P2_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\vulcanized.p2.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
<include name="IDR_MD_SETTINGS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\settings\crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" />
<include name="IDR_MD_SETTINGS_LAZY_LOAD_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MD_SETTINGS_LAZY_LOAD_VULCANIZED_P2_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.vulcanized.p2.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
<include name="IDR_MD_SETTINGS_LAZY_LOAD_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" />
</includes>
</release>
diff --git a/chromium/chrome/browser/resources/settings/settings_shared_css.html b/chromium/chrome/browser/resources/settings/settings_shared_css.html
index 6d0d0090e3b..f78d3de53ca 100644
--- a/chromium/chrome/browser/resources/settings/settings_shared_css.html
+++ b/chromium/chrome/browser/resources/settings/settings_shared_css.html
@@ -38,7 +38,7 @@
}
iron-icon.policy {
- -webkit-margin-end: var(--cr-controlled-by-spacing);
+ margin-inline-end: var(--cr-controlled-by-spacing);
}
iron-list {
@@ -61,7 +61,7 @@
}
.separator + paper-icon-button-light {
- -webkit-margin-start: var(--cr-icon-ripple-margin);
+ margin-inline-start: var(--cr-icon-ripple-margin);
}
neon-animatable {
@@ -76,16 +76,16 @@
/* Special case for buttons inside of toggle-buttons. */
.settings-box settings-toggle-button paper-button:last-of-type {
- -webkit-margin-end: 16px;
+ margin-inline-end: 16px;
}
/* Space out multiple buttons in the same row. */
.settings-box paper-button + paper-button {
- -webkit-margin-start: 16px;
+ margin-inline-start: 16px;
}
span ~ a {
- -webkit-margin-start: 4px;
+ margin-inline-start: 4px;
}
a[href] {
@@ -196,6 +196,12 @@
min-height: var(--settings-row-two-line-min-height);
}
+ /* A row with three lines of text. Often the lower lines will be
+ * .secondary. */
+ .three-line {
+ min-height: var(--settings-row-three-line-min-height);
+ }
+
/* A settings-box is a horizontal row of text or controls within a
* setting section (page or subpage). */
.settings-box {
@@ -241,7 +247,7 @@
/* A settings-box that is embedded in another settings-box (e.g. a control
* that is associated with a toggle button). */
.settings-box.embedded {
- -webkit-padding-start: var(--settings-box-row-indent);
+ padding-inline-start: var(--settings-box-row-indent);
}
/* The lower line of text in a two-line row. */
@@ -260,9 +266,9 @@
/* The middle part (horizontally) of a row. */
.settings-box .middle {
- -webkit-padding-start: 16px;
align-items: center;
flex: auto;
+ padding-inline-start: 16px;
}
.settings-box .middle.two-line,
@@ -296,8 +302,8 @@
iron-list,
.list-item {
--cr-paper-icon-button-margin: {
- -webkit-margin-end: 0;
- -webkit-margin-start: var(--cr-icon-button-margin-start);
+ margin-inline-end: 0;
+ margin-inline-start: var(--cr-icon-button-margin-start);
};
}
@@ -310,7 +316,7 @@
* the other way. An example is near the |sign out| button on the People
* settings. */
.separator {
- -webkit-border-start: var(--settings-separator-line);
+ border-inline-start: var(--settings-separator-line);
flex-shrink: 0;
/* Match paper-button's default height. */
height: 32px;
diff --git a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
index cfe71c9f412..37ebe94a487 100644
--- a/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
+++ b/chromium/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -80,15 +80,6 @@ Polymer({
'refresh-pref': 'onRefreshPref_',
},
- /**
- * Tracks if any cr-dialog is open anywhere in the UI. An assumption is being
- * made that only one cr-dialog is open at a time. If this assumption changes
- * |dialogOpen_| should be replaced with a count of the number of dialogs that
- * are open.
- * @private {boolean}
- */
- dialogOpen_: false,
-
/** @override */
created: function() {
settings.initializeRouteFromUrl();
@@ -157,7 +148,7 @@ Polymer({
loadTimeData.getBoolean('androidAppsVisible');
this.showCrostini_ = loadTimeData.valueExists('showCrostini') &&
loadTimeData.getBoolean('showCrostini');
- this.showMultidevice_ = this.showAndroidApps_ &&
+ this.showMultidevice_ =
loadTimeData.valueExists('enableMultideviceSettings') &&
loadTimeData.getBoolean('enableMultideviceSettings');
this.havePlayStoreApp_ = loadTimeData.valueExists('havePlayStoreApp') &&
@@ -173,15 +164,6 @@ Polymer({
this.addEventListener('hide-container', () => {
this.$.container.style.visibility = 'hidden';
});
-
- this.addEventListener('cr-dialog-open', () => {
- this.dialogOpen_ = true;
- });
-
- this.addEventListener('close', e => {
- if (e.composedPath()[0].nodeName == 'CR-DIALOG')
- this.dialogOpen_ = false;
- });
},
/** @override */
@@ -215,6 +197,8 @@ Polymer({
scrollToTop(e.detail.bottom - this.$.container.clientHeight)
.then(e.detail.callback);
});
+
+ this.becomeActiveFindShortcutListener();
},
/** @override */
@@ -246,12 +230,11 @@ Polymer({
},
// Override settings.FindShortcutBehavior methods.
- canHandleFindShortcut: function() {
- return !this.$.drawer.open && !this.dialogOpen_;
- },
-
- handleFindShortcut: function() {
+ handleFindShortcut: function(modalContextOpen) {
+ if (modalContextOpen)
+ return false;
this.$$('cr-toolbar').getSearchField().showAndFocus();
+ return true;
},
/**
diff --git a/chromium/chrome/browser/resources/settings/settings_vars_css.html b/chromium/chrome/browser/resources/settings/settings_vars_css.html
index e9236860967..174fcfb2167 100644
--- a/chromium/chrome/browser/resources/settings/settings_vars_css.html
+++ b/chromium/chrome/browser/resources/settings/settings_vars_css.html
@@ -22,8 +22,8 @@
--settings-error-color: var(--google-red-700);
--settings-list-frame-padding: {
- -webkit-padding-end: var(--settings-box-row-padding);
- -webkit-padding-start: var(--settings-box-row-indent);
+ padding-inline-end: var(--settings-box-row-padding);
+ padding-inline-start: var(--settings-box-row-indent);
padding-bottom: 0;
padding-top: 0;
}
diff --git a/chromium/chrome/browser/resources/settings/site_settings/BUILD.gn b/chromium/chrome/browser/resources/settings/site_settings/BUILD.gn
index ea34fe26d1b..6fe64dd78ec 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/site_settings/BUILD.gn
@@ -22,6 +22,7 @@ js_type_check("closure_compile") {
":site_details_permission",
":site_entry",
":site_list",
+ ":site_list_entry",
":site_settings_behavior",
":site_settings_prefs_browser_proxy",
":usb_devices",
@@ -154,6 +155,7 @@ js_library("site_data_entry") {
":local_data_browser_proxy",
"..:focus_row_behavior",
"//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:icon",
]
}
@@ -179,6 +181,7 @@ js_library("site_details_permission") {
":site_settings_behavior",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
@@ -203,8 +206,8 @@ js_library("site_entry") {
js_library("site_list") {
deps = [
":constants",
+ ":site_list_entry",
":site_settings_behavior",
- "..:route",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
@@ -215,6 +218,17 @@ js_library("site_list") {
externs_list = [ "$externs_path/settings_private.js" ]
}
+js_library("site_list_entry") {
+ deps = [
+ ":constants",
+ ":site_settings_behavior",
+ "..:focus_row_behavior",
+ "..:route",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_pref_indicator",
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
js_library("site_settings_behavior") {
deps = [
":constants",
@@ -250,6 +264,7 @@ js_library("website_usage_private_api") {
js_library("zoom_levels") {
deps = [
":site_settings_behavior",
+ "//ui/webui/resources/js:list_property_update_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
diff --git a/chromium/chrome/browser/resources/settings/site_settings/all_sites.html b/chromium/chrome/browser/resources/settings/site_settings/all_sites.html
index d08b1bd09ec..6577af68090 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/all_sites.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/all_sites.html
@@ -22,13 +22,13 @@
}
#sortMethod {
- -webkit-margin-start: 1em;
+ margin-inline-start: 1em;
}
/* There is only one top-level heading for All Sites, so remove the
* additional leading padding used for lists. */
.list-frame.without-heading {
- -webkit-padding-start: var(--settings-box-row-padding);
+ padding-inline-start: var(--settings-box-row-padding);
}
</style>
<div id="searchAndSort">
@@ -40,23 +40,28 @@
<label id="sortLabel">$i18n{siteSettingsAllSitesSort}</label>
<select id="sortMethod" class="md-select" aria-labelledby="sortLabel"
on-change="onSortMethodChanged_">
- <!-- TODO(https://crbug.com/835712): Implement remaining two sort
- methods. -->
+ <option value="[[sortMethods_.mostVisited]]">
+ $i18n{siteSettingsAllSitesSortMethodMostVisited}
+ </option>
+ <option value="[[sortMethods_.storage]]">
+ $i18n{siteSettingsAllSitesSortMethodStorage}
+ </option>
<option value="[[sortMethods_.name]]">
$i18n{siteSettingsAllSitesSortMethodName}
</option>
</select>
</div>
</div>
- <div class="list-frame" hidden$="[[siteGroupList.length]]">
+ <div class="list-frame" hidden$="[[siteGroupMap.size]]">
<div class="list-item secondary">$i18n{noSitesAdded}</div>
</div>
<div class="list-frame without-heading" id="listContainer">
<iron-list id="allSitesList"
- items="[[filterPopulatedList_(siteGroupList, searchQuery_)]]"
+ items="[[filterPopulatedList_(siteGroupMap, searchQuery_)]]"
scroll-target="[[subpageScrollTarget]]">
<template>
- <site-entry site-group="[[item]]" list-index="[[index]]"></site-entry>
+ <site-entry site-group="[[item]]" list-index="[[index]]"
+ tabindex$="[[tabIndex]]"></site-entry>
</template>
</iron-list>
</div>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/all_sites.js b/chromium/chrome/browser/resources/settings/site_settings/all_sites.js
index 537bc46b0f3..b424251d1de 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/all_sites.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/all_sites.js
@@ -19,13 +19,14 @@ Polymer({
properties: {
/**
- * Array of sites to display in the widget, grouped into their eTLD+1s.
- * @type {!Array<!SiteGroup>}
+ * Map containing sites to display in the widget, grouped into their
+ * eTLD+1 names.
+ * @type {!Map<string, !SiteGroup>}
*/
- siteGroupList: {
- type: Array,
+ siteGroupMap: {
+ type: Object,
value: function() {
- return [];
+ return new Map();
},
},
@@ -51,30 +52,64 @@ Polymer({
/**
* All possible sort methods.
- * @type {Object}
+ * @type {!{name: string, mostVisited: string, storage: string}}
* @private
*/
sortMethods_: {
type: Object,
- value: function() {
- return {
- name: 'name',
- mostVisited: 'most-visited',
- storage: 'data-stored',
- };
+ value: {
+ name: 'name',
+ mostVisited: 'most-visited',
+ storage: 'data-stored',
},
readOnly: true,
},
+
+ /**
+ * Stores the last selected item in the All Sites list.
+ * @type {?{item: !SiteGroup, index: number}}
+ * @private
+ */
+ selectedItem_: Object,
+
+ /**
+ * Used to determine focus between settings pages.
+ * @type {!Map<string, (string|Function)>}
+ */
+ focusConfig: {
+ type: Object,
+ observer: 'focusConfigChanged_',
+ },
+ },
+
+ /** @private {?settings.LocalDataBrowserProxy} */
+ localDataBrowserProxy_: null,
+
+ /** @override */
+ created: function() {
+ this.localDataBrowserProxy_ =
+ settings.LocalDataBrowserProxyImpl.getInstance();
},
/** @override */
ready: function() {
- this.browserProxy_ =
- settings.SiteSettingsPrefsBrowserProxyImpl.getInstance();
+ this.addWebUIListener(
+ 'onLocalStorageListFetched', this.onLocalStorageListFetched.bind(this));
this.addWebUIListener(
'contentSettingSitePermissionChanged', this.populateList_.bind(this));
this.addEventListener(
- 'site-entry-resized', this.resizeListIfScrollTargetActive_.bind(this));
+ 'site-entry-selected',
+ (/** @type {!{detail: !{item: !SiteGroup, index: number}}} */ e) => {
+ this.selectedItem_ = e.detail;
+ });
+ this.addEventListener('site-entry-storage-updated', () => {
+ this.debounce('site-entry-storage-updated', () => {
+ if (this.sortMethods_ &&
+ this.$.sortMethod.value == this.sortMethods_.storage) {
+ this.onSortMethodChanged_();
+ }
+ }, 500);
+ });
this.populateList_();
},
@@ -99,27 +134,62 @@ Polymer({
if (!contentTypes.includes(settings.ContentSettingsTypes.COOKIES))
contentTypes.push(settings.ContentSettingsTypes.COOKIES);
- this.browserProxy_.getAllSites(contentTypes).then((response) => {
- this.siteGroupList = this.sortSiteGroupList_(response);
+ this.browserProxy.getAllSites(contentTypes).then((response) => {
+ response.forEach(siteGroup => {
+ this.siteGroupMap.set(siteGroup.etldPlus1, siteGroup);
+ });
+ this.forceListUpdate_();
+ });
+ },
+
+ /**
+ * Integrate sites using local storage into the existing sites map, as there
+ * may be overlap between the existing sites.
+ * @param {!Array<!SiteGroup>} list The list of sites using local storage.
+ */
+ onLocalStorageListFetched: function(list) {
+ list.forEach(storageSiteGroup => {
+ if (this.siteGroupMap.has(storageSiteGroup.etldPlus1)) {
+ const siteGroup = this.siteGroupMap.get(storageSiteGroup.etldPlus1);
+ const storageOriginInfoMap = new Map();
+ storageSiteGroup.origins.forEach(
+ originInfo =>
+ storageOriginInfoMap.set(originInfo.origin, originInfo));
+
+ // If there is an overlapping origin, update the original
+ // |originInfo|.
+ siteGroup.origins.forEach(originInfo => {
+ if (!storageOriginInfoMap.has(originInfo.origin))
+ return;
+ Object.apply(originInfo, storageOriginInfoMap.get(originInfo.origin));
+ storageOriginInfoMap.delete(originInfo.origin);
+ });
+ // Otherwise, add it to the list.
+ storageOriginInfoMap.forEach(
+ originInfo => siteGroup.origins.push(originInfo));
+ } else {
+ this.siteGroupMap.set(storageSiteGroup.etldPlus1, storageSiteGroup);
+ }
});
+ this.forceListUpdate_();
},
/**
- * Filters |this.siteGroupList| with the given search query text.
- * @param {!Array<!SiteGroup>} siteGroupList The list of sites to filter.
+ * Filters the all sites list with the given search query text.
+ * @param {!Map<string, !SiteGroup>} siteGroupMap The map of sites to filter.
* @param {string} searchQuery The filter text.
* @return {!Array<!SiteGroup>}
* @private
*/
- filterPopulatedList_: function(siteGroupList, searchQuery) {
- if (searchQuery.length == 0)
- return siteGroupList;
-
- return siteGroupList.filter((siteGroup) => {
- return siteGroup.origins.find(origin => {
- return origin.includes(searchQuery);
- });
- });
+ filterPopulatedList_: function(siteGroupMap, searchQuery) {
+ const result = [];
+ for (const [etldPlus1, siteGroup] of siteGroupMap) {
+ if (siteGroup.origins.find(
+ originInfo => originInfo.origin.includes(searchQuery))) {
+ result.push(siteGroup);
+ }
+ }
+ return this.sortSiteGroupList_(result);
},
/**
@@ -130,11 +200,89 @@ Polymer({
*/
sortSiteGroupList_: function(siteGroupList) {
const sortMethod = this.$.sortMethod.value;
- if (sortMethod == this.sortMethods_.name)
+ if (!this.sortMethods_)
+ return siteGroupList;
+
+ if (sortMethod == this.sortMethods_.mostVisited) {
+ siteGroupList.sort(this.mostVisitedComparator_);
+ } else if (sortMethod == this.sortMethods_.storage) {
+ // Storage is loaded asynchronously, so make sure it's updated for every
+ // item in the list to ensure the sorting is correct.
+ const etldPlus1List = siteGroupList.reduce((list, siteGroup) => {
+ if (siteGroup.origins.length > 1 && siteGroup.etldPlus1.length > 0)
+ list.push(siteGroup.etldPlus1);
+ return list;
+ }, []);
+
+ this.localDataBrowserProxy_.getNumCookiesList(etldPlus1List)
+ .then(numCookiesList => {
+ assert(etldPlus1List.length == numCookiesList.length);
+ numCookiesList.forEach(cookiesPerEtldPlus1 => {
+ this.siteGroupMap.get(cookiesPerEtldPlus1.etldPlus1).numCookies =
+ cookiesPerEtldPlus1.numCookies;
+ });
+
+ // |siteGroupList| by this point should have already been provided
+ // to the iron list, so just sort in-place here and make sure to
+ // re-render the item order.
+ siteGroupList.sort(this.storageComparator_);
+ this.$.allSitesList.fire('iron-resize');
+ });
+ } else if (sortMethod == this.sortMethods_.name) {
siteGroupList.sort(this.nameComparator_);
+ }
return siteGroupList;
},
+ /**
+ * Comparator used to sort SiteGroups by the amount of engagement the user has
+ * with the origins listed inside it. Note only the maximum engagement is used
+ * for each SiteGroup (as opposed to the sum) in order to prevent domains with
+ * higher numbers of origins from always floating to the top of the list.
+ * @param {!SiteGroup} siteGroup1
+ * @param {!SiteGroup} siteGroup2
+ * @private
+ */
+ mostVisitedComparator_: function(siteGroup1, siteGroup2) {
+ const getMaxEngagement = (max, originInfo) => {
+ return (max > originInfo.engagement) ? max : originInfo.engagement;
+ };
+ const score1 = siteGroup1.origins.reduce(getMaxEngagement, 0);
+ const score2 = siteGroup2.origins.reduce(getMaxEngagement, 0);
+ return score2 - score1;
+ },
+
+ /**
+ * Comparator used to sort SiteGroups by the amount of storage they use. Note
+ * this sorts in descending order.
+ * TODO(https://crbug.com/835712): Account for website storage in sorting by
+ * storage used.
+ * @param {!SiteGroup} siteGroup1
+ * @param {!SiteGroup} siteGroup2
+ * @private
+ */
+ storageComparator_: function(siteGroup1, siteGroup2) {
+ const getOverallUsage = siteGroup => {
+ let usage = 0;
+ siteGroup.origins.forEach(originInfo => {
+ usage += originInfo.usage;
+ });
+ return usage;
+ };
+
+ const siteGroup1Size = getOverallUsage(siteGroup1);
+ const siteGroup2Size = getOverallUsage(siteGroup2);
+ // Use the number of cookies as a tie breaker.
+ return siteGroup2Size - siteGroup1Size ||
+ siteGroup2.numCookies - siteGroup1.numCookies;
+ },
+
+ /**
+ * Comparator used to sort SiteGroups by their eTLD+1 name (domain).
+ * @param {!SiteGroup} siteGroup1
+ * @param {!SiteGroup} siteGroup2
+ * @private
+ */
nameComparator_: function(siteGroup1, siteGroup2) {
return siteGroup1.etldPlus1.localeCompare(siteGroup2.etldPlus1);
},
@@ -154,18 +302,52 @@ Polymer({
* @private
*/
onSortMethodChanged_: function() {
- this.siteGroupList = this.sortSiteGroupList_(this.siteGroupList);
+ this.$.allSitesList.items =
+ this.sortSiteGroupList_(this.$.allSitesList.items);
// Force the iron-list to rerender its items, as the order has changed.
this.$.allSitesList.fire('iron-resize');
},
/**
- * Called when a list item changes its size, and thus the positions and sizes
- * of the items in the entire list also need updating.
+ * Forces the all sites list to update its list of items, taking into account
+ * the search query and the sort method, then re-renders it.
+ * @private
+ */
+ forceListUpdate_: function() {
+ this.$.allSitesList.items =
+ this.filterPopulatedList_(this.siteGroupMap, this.searchQuery_);
+ this.$.allSitesList.fire('iron-resize');
+ },
+
+ /**
+ * @param {!Map<string, (string|Function)>} newConfig
+ * @param {?Map<string, (string|Function)>} oldConfig
* @private
*/
- resizeListIfScrollTargetActive_: function() {
- if (settings.getCurrentRoute() == this.subpageRoute)
- this.$.allSitesList.fire('iron-resize');
+ focusConfigChanged_: function(newConfig, oldConfig) {
+ // focusConfig is set only once on the parent, so this observer should only
+ // fire once.
+ assert(!oldConfig);
+
+ if (!settings.routes.SITE_SETTINGS_ALL)
+ return;
+
+ const onNavigatedTo = () => {
+ this.async(() => {
+ if (this.selectedItem_ == null || this.siteGroupMap.size == 0)
+ return;
+
+ // Focus the site-entry to ensure the iron-list renders it, otherwise
+ // the query selector will not be able to find it. Note the index is
+ // used here instead of the item, in case the item was already removed.
+ const index = Math.max(
+ 0, Math.min(this.selectedItem_.index, this.siteGroupMap.size));
+ this.$.allSitesList.focusItem(index);
+ this.selectedItem_ = null;
+ });
+ };
+
+ this.focusConfig.set(
+ settings.routes.SITE_SETTINGS_SITE_DETAILS.path, onNavigatedTo);
},
});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js b/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
index f23a71fe70c..19db72fabf6 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
@@ -33,6 +33,15 @@ let LocalDataItem;
*/
let LocalDataList;
+/**
+ * Number of cookies attached to a given domain / eTLD+1.
+ * @typedef {{
+ * etldPlus1: string,
+ * numCookies: number,
+ * }}
+ */
+let EtldPlus1CookieNumber;
+
cr.define('settings', function() {
/** @interface */
class LocalDataBrowserProxy {
@@ -69,11 +78,20 @@ cr.define('settings', function() {
getCookieDetails(site) {}
/**
- * Gets the number of cookies formatted in a plural string, given a site.
- * @param {string} site The site to count cookies for.
+ * Gets a list containing the number of cookies for each domain (eTLD+1
+ * names) given in |siteList|. This will always return a result array the
+ * same length and in the same order as |siteList|.
+ * @param {!Array<string>} siteList The list of sites to count cookies for.
+ * @return {!Promise<!Array<!EtldPlus1CookieNumber>>}
+ */
+ getNumCookiesList(siteList) {}
+
+ /**
+ * Gets the plural string for a given number of cookies.
+ * @param {number} numCookies The number of cookies.
* @return {!Promise<string>}
*/
- getNumCookiesString(site) {}
+ getNumCookiesString(numCookies) {}
/**
* Reloads all local data.
@@ -120,8 +138,13 @@ cr.define('settings', function() {
}
/** @override */
- getNumCookiesString(site) {
- return cr.sendWithPromise('localData.getNumCookiesString', site);
+ getNumCookiesList(siteList) {
+ return cr.sendWithPromise('localData.getNumCookiesList', siteList);
+ }
+
+ /** @override */
+ getNumCookiesString(numCookies) {
+ return cr.sendWithPromise('localData.getNumCookiesString', numCookies);
}
/** @override */
diff --git a/chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html b/chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html
index 70aa00c55f8..cfea2a1c20e 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/protocol_handlers.html
@@ -18,8 +18,8 @@
}
.column-header {
- -webkit-margin-start: 20px;
margin-bottom: 15px;
+ margin-inline-start: 20px;
margin-top: 15px;
}
</style>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_data.html b/chromium/chrome/browser/resources/settings/site_settings/site_data.html
index 78e9124cba9..4fa8b7af5ac 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_data.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_data.html
@@ -33,7 +33,7 @@
}
#removeShowingSites {
- -webkit-margin-start: auto;
+ margin-inline-start: auto;
}
</style>
<div class="settings-box continuation">
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_data.js b/chromium/chrome/browser/resources/settings/site_settings/site_data.js
index a1caa294965..235ea12a488 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_data.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_data.js
@@ -158,13 +158,7 @@ Polymer({
lastSelectedIndex :
this.sites.length - 1;
const index = indexFromId > -1 ? indexFromId : indexFallback;
- const ironList =
- /** @type {!IronListElement} */ (this.$$('iron-list'));
- ironList.focusItem(index);
- const siteToSelect = this.sites[index].site.replace(/[.]/g, '\\.');
- const button =
- this.$$(`#siteItem_${siteToSelect}`).$$('.subpage-arrow button');
- cr.ui.focusWithoutInk(assert(button));
+ this.focusOnSiteSelectButton_(index);
});
this.focusConfig.set(
settings.routes.SITE_SETTINGS_DATA_DETAILS.path, onNavigatedTo);
@@ -172,6 +166,20 @@ Polymer({
},
/**
+ * @param {number} index
+ * @private
+ */
+ focusOnSiteSelectButton_: function(index) {
+ const ironList =
+ /** @type {!IronListElement} */ (this.$$('iron-list'));
+ ironList.focusItem(index);
+ const siteToSelect = this.sites[index].site.replace(/[.]/g, '\\.');
+ const button =
+ this.$$(`#siteItem_${siteToSelect}`).$$('.subpage-arrow button');
+ cr.ui.focusWithoutInk(assert(button));
+ },
+
+ /**
* Gather all the site data.
* @private
*/
@@ -239,6 +247,10 @@ Polymer({
* @private
*/
onSiteClick_: function(event) {
+ // If any delete button is selected, the focus will be in a bad state when
+ // returning to this page. To avoid this, the site select button is given
+ // focus. See https://crbug.com/872197.
+ this.focusOnSiteSelectButton_(event.model.index);
settings.navigateTo(
settings.routes.SITE_SETTINGS_DATA_DETAILS,
new URLSearchParams('site=' + event.model.item.site));
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_details.html b/chromium/chrome/browser/resources/settings/site_settings/site_details.html
index 5741588cba2..730957b9612 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details.html
@@ -22,15 +22,15 @@
}
#storage {
- -webkit-padding-end: 0;
+ padding-inline-end: 0;
}
/* When 'Usage' is omitted, subheadings are removed. Reduce the start
* padding allowed for lists without headings and add back vertical space
* that would normally be provided by the subheading. */
.list-frame.without-heading {
- -webkit-padding-start: var(--settings-box-row-padding);
margin-top: 12px;
+ padding-inline-start: var(--settings-box-row-padding);
}
div#resetSettingsButton {
@@ -148,7 +148,8 @@
</site-details-permission>
<site-details-permission category="{{ContentSettingsTypes.SOUND}}"
icon="settings:volume-up" id="sound"
- label="$i18n{siteSettingsSound}">
+ label="$i18n{siteSettingsSound}"
+ use-automatic-label="[[blockAutoplayEnabled]]">
</site-details-permission>
<site-details-permission
category="{{ContentSettingsTypes.AUTOMATIC_DOWNLOADS}}"
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_details.js b/chromium/chrome/browser/resources/settings/site_settings/site_details.js
index 155cc28763b..8906a2a47ea 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details.js
@@ -17,6 +17,11 @@ Polymer({
properties: {
/**
+ * Whether unified autoplay blocking is enabled.
+ */
+ blockAutoplayEnabled: Boolean,
+
+ /**
* The origin that this widget is showing details for.
* @private
*/
@@ -72,6 +77,9 @@ Polymer({
this.addWebUIListener(
'prefEnableDrmChanged', this.prefEnableDrmChanged_.bind(this));
// </if>
+
+ // Refresh block autoplay status from the backend.
+ this.browserProxy.fetchBlockAutoplayStatus();
},
/** @override */
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html b/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html
index 3e305be016a..9da49da8d4e 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.html
@@ -3,6 +3,7 @@
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="../settings_vars_css.html">
<link rel="import" href="constants.html">
@@ -53,16 +54,18 @@
<option id="default" value$="[[ContentSetting.DEFAULT]]">
[[defaultSettingString_(
defaultSetting_,
- '$i18nPolymer{siteSettingsActionAskDefault}',
- '$i18nPolymer{siteSettingsActionAllowDefault}',
- '$i18nPolymer{siteSettingsActionBlockDefault}')]]
+ category,
+ useAutomaticLabel)]]
</option>
<option id="allow" value$="[[ContentSetting.ALLOW]]"
hidden$="[[!showAllowedSetting_(category)]]">
$i18n{siteSettingsActionAllow}
</option>
<option id="block" value$="[[ContentSetting.BLOCK]]">
- $i18n{siteSettingsActionBlock}
+ [[blockSettingString_(
+ category,
+ '$i18n{siteSettingsActionBlock}',
+ '$i18n{siteSettingsActionMute}')]]
</option>
<option id="ask" value$="[[ContentSetting.ASK]]"
hidden$="[[!showAskSetting_(category, site.setting,
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js b/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js
index d559c00baae..8802f151211 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_details_permission.js
@@ -10,10 +10,17 @@
Polymer({
is: 'site-details-permission',
- behaviors: [SiteSettingsBehavior, WebUIListenerBehavior],
+ behaviors: [I18nBehavior, SiteSettingsBehavior, WebUIListenerBehavior],
properties: {
/**
+ * If this is a sound content setting, then this controls whether it
+ * should use "Automatic" instead of "Allow" as the default setting
+ * allow label.
+ */
+ useAutomaticLabel: {type: Boolean, value: false},
+
+ /**
* The site that this widget is showing details for.
* @type {RawSiteException}
*/
@@ -99,30 +106,63 @@ Polymer({
},
/**
+ * Returns if we should use the custom labels for the sound type.
+ * @param {!settings.ContentSettingsTypes} category The permission type.
+ * @return {boolean}
+ * @private
+ */
+ useCustomSoundLabels_: function(category) {
+ return category == settings.ContentSettingsTypes.SOUND &&
+ loadTimeData.getBoolean('enableBlockAutoplayContentSetting');
+ },
+
+ /**
* Updates the string used for this permission category's default setting.
* @param {!settings.ContentSetting} defaultSetting Value of the default
* setting for this permission category.
- * @param {string} askString 'Ask' label, e.g. 'Ask (default)'.
- * @param {string} allowString 'Allow' label, e.g. 'Allow (default)'.
- * @param {string} blockString 'Block' label, e.g. 'Blocked (default)'.
+ * @param {!settings.ContentSettingsTypes} category The permission type.
+ * @param {boolean} useAutomaticLabel Whether to use the automatic label
+ * if the default setting value is allow.
* @return {string}
* @private
*/
- defaultSettingString_: function(
- defaultSetting, askString, allowString, blockString) {
+ defaultSettingString_: function(defaultSetting, category, useAutomaticLabel) {
+ if (defaultSetting == undefined || category == undefined ||
+ useAutomaticLabel == undefined) {
+ return '';
+ }
+
if (defaultSetting == settings.ContentSetting.ASK ||
defaultSetting == settings.ContentSetting.IMPORTANT_CONTENT) {
- return askString;
+ return this.i18n('siteSettingsActionAskDefault');
} else if (defaultSetting == settings.ContentSetting.ALLOW) {
- return allowString;
+ if (this.useCustomSoundLabels_(category) && useAutomaticLabel)
+ return this.i18n('siteSettingsActionAutomaticDefault');
+ return this.i18n('siteSettingsActionAllowDefault');
} else if (defaultSetting == settings.ContentSetting.BLOCK) {
- return blockString;
+ if (this.useCustomSoundLabels_(category))
+ return this.i18n('siteSettingsActionMuteDefault');
+ return this.i18n('siteSettingsActionBlockDefault');
}
assertNotReached(
`No string for ${this.category}'s default of ${defaultSetting}`);
},
/**
+ * Updates the string used for this permission category's block setting.
+ * @param {!settings.ContentSettingsTypes} category The permission type.
+ * @param {string} blockString 'Block' label.
+ * @param {string} muteString 'Mute' label.
+ * @return {string}
+ * @private
+ */
+ blockSettingString_: function(category, blockString, muteString) {
+ if (this.useCustomSoundLabels_(category))
+ return muteString;
+ return blockString;
+ },
+
+ /**
* Returns true if there's a string to display that provides more information
* about this permission's setting. Currently, this only gets called when
* |this.site| is updated.
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_entry.html b/chromium/chrome/browser/resources/settings/site_settings/site_entry.html
index 6305a2b4af0..cd3876ef5dd 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_entry.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_entry.html
@@ -26,9 +26,23 @@
display: flex;
}
- #cookies {
+ .second-line {
margin-top: 0.1em;
}
+
+ /* Data units such as "0 KB" should always read left-to-right. */
+ .data-unit {
+ direction: ltr;
+ unicode-bidi: isolate;
+ }
+
+ #collapseChild .data-unit {
+ padding-inline-start: 1ch;
+ }
+
+ .list-frame {
+ padding-inline-end: 0;
+ }
</style>
<div id="collapseParent">
<div class$="settings-box list-item [[getClassForIndex_(listIndex)]]">
@@ -47,8 +61,11 @@
[[scheme_(siteGroup, -1)]]
</span>
</div>
- <div id="cookies" class="secondary" hidden$="[[!cookieString_]]">
- [[cookieString_]]
+ <div class="second-line secondary">
+ <span class="data-unit">[[overallUsageString_]]</span>
+ <span id="cookies" hidden$="[[!siteGroup.numCookies]]">
+ &middot; [[cookieString_]]
+ </span>
</div>
</div>
<paper-icon-button-light id="expandIcon" class="icon-expand-more"
@@ -77,10 +94,11 @@
<template is="dom-repeat" items="[[siteGroup.origins]]">
<div class="settings-box list-item" on-click="onOriginTap_"
actionable>
- <div class="favicon-image" style$="[[computeSiteIcon(item)]]">
+ <div class="favicon-image"
+ style$="[[computeSiteIcon(item.origin)]]">
</div>
<div class="site-representation middle text-elide">
- <span class="url-directionality">
+ <span id="originSiteRepresentation" class="url-directionality">
[[siteRepresentation_(siteGroup, index)]]
</span>
<span class="secondary"
@@ -91,7 +109,13 @@
hidden$="[[!scheme_(siteGroup, index)]]">
[[scheme_(siteGroup, index)]]
</span>
+ <span class="secondary data-unit" hidden$="[[!item.usage]]">
+ [[originUsagesItem_(originUsages_.*, index)]]
+ </span>
</div>
+ <paper-icon-button-light class="subpage-arrow">
+ <button aria-labelledby$="originSiteRepresentation"></button>
+ </paper-icon-button-light>
</div>
</template>
</div>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_entry.js b/chromium/chrome/browser/resources/settings/site_settings/site_entry.js
index e5fc84d167c..2b3e9833329 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_entry.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_entry.js
@@ -32,10 +32,38 @@ Polymer({
* The string to display when there is a non-zero number of cookies.
* @private
*/
- cookieString_: {
- type: String,
- value: '',
+ cookieString_: String,
+
+ /**
+ * The position of this site-entry in its parent list.
+ */
+ listIndex: {
+ type: Number,
+ value: -1,
},
+
+ /**
+ * The string to display showing the overall usage of this site-entry.
+ * @private
+ */
+ overallUsageString_: String,
+
+ /**
+ * An array containing the strings to display showing the individual disk
+ * usage for each origin in |siteGroup|.
+ * @type {!Array<string>}
+ * @private
+ */
+ originUsages_: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
+ },
+
+ listeners: {
+ 'focus': 'onFocus_',
},
/** @private {?settings.LocalDataBrowserProxy} */
@@ -81,7 +109,7 @@ Polymer({
// was computed.
}
originIndex = this.getIndexBoundToOriginList_(siteGroup, originIndex);
- const url = this.toUrl(siteGroup.origins[originIndex]);
+ const url = this.toUrl(siteGroup.origins[originIndex].origin);
return url.host;
},
@@ -97,21 +125,32 @@ Polymer({
if (this.$.collapseChild.opened)
this.toggleCollapsible_();
// Ungrouped site-entries should not show cookies.
- if (this.cookieString_) {
+ if (this.cookieString_)
this.cookieString_ = '';
- this.fire('site-entry-resized');
- }
}
- if (!siteGroup || !this.grouped_(siteGroup))
+ if (!siteGroup)
return;
+ this.calculateUsageInfo_(siteGroup);
- this.localDataBrowserProxy_.getNumCookiesString(this.displayName_)
- .then(string => {
- // If there was no cookie string previously and now there is, or vice
- // versa, the height of this site-entry will have changed.
- if ((this.cookieString_ == '') != (string == ''))
- this.fire('site-entry-resized');
+ if (!this.grouped_(siteGroup))
+ return;
+
+ const siteList = [this.displayName_];
+ this.localDataBrowserProxy_.getNumCookiesList(siteList)
+ .then(numCookiesList => {
+ assert(siteList.length == numCookiesList.length);
+ const numCookies = numCookiesList[0].numCookies;
+ if (siteGroup.numCookies != numCookies)
+ this.fire('site-entry-storage-updated');
+ siteGroup.numCookies = numCookies;
+ this.notifyPath('siteGroup.numCookies');
+
+ return numCookies == 0 ?
+ Promise.resolve('') :
+ this.localDataBrowserProxy_.getNumCookiesString(numCookies);
+ })
+ .then(string => {
this.cookieString_ = string;
});
},
@@ -131,7 +170,7 @@ Polymer({
return '';
originIndex = this.getIndexBoundToOriginList_(siteGroup, originIndex);
- const url = this.toUrl(siteGroup.origins[originIndex]);
+ const url = this.toUrl(siteGroup.origins[originIndex].origin);
const scheme = url.protocol.replace(new RegExp(':*$'), '');
/** @type{string} */ const HTTPS_SCHEME = 'https';
if (scheme == HTTPS_SCHEME)
@@ -149,7 +188,48 @@ Polymer({
getSiteGroupIcon_: function(siteGroup) {
// TODO(https://crbug.com/835712): Implement heuristic for finding a good
// favicon.
- return this.computeSiteIcon(siteGroup.origins[0]);
+ return this.computeSiteIcon(siteGroup.origins[0].origin);
+ },
+
+ /**
+ * Calculates the amount of disk storage used by the given group of origins
+ * and eTLD+1. Also updates the corresponding display strings.
+ * TODO(https://crbug.com/835712): Add website storage as well.
+ * @param {SiteGroup} siteGroup The eTLD+1 group of origins.
+ * @private
+ */
+ calculateUsageInfo_: function(siteGroup) {
+ const getFormattedBytesForSize = (numBytes) => {
+ if (numBytes == 0)
+ return Promise.resolve('0 B');
+ return this.browserProxy.getFormattedBytes(numBytes);
+ };
+
+ let overallUsage = 0;
+ this.originUsages_ = new Array(siteGroup.origins.length);
+ siteGroup.origins.forEach((originInfo, i) => {
+ overallUsage += originInfo.usage;
+ if (this.grouped_(siteGroup)) {
+ getFormattedBytesForSize(originInfo.usage).then((string) => {
+ this.set(`originUsages_.${i}`, string);
+ });
+ }
+ });
+
+ getFormattedBytesForSize(overallUsage).then(string => {
+ this.overallUsageString_ = string;
+ });
+ },
+
+ /**
+ * Array binding for the |originUsages_| array for use in the HTML.
+ * @param {!{base: !Array<string>}} change The change record for the array.
+ * @param {number} index The index of the array item.
+ * @return {string}
+ * @private
+ */
+ originUsagesItem_: function(change, index) {
+ return change.base[index];
},
/**
@@ -159,6 +239,8 @@ Polymer({
* @private
*/
navigateToSiteDetails_: function(origin) {
+ this.fire(
+ 'site-entry-selected', {item: this.siteGroup, index: this.listIndex});
settings.navigateTo(
settings.routes.SITE_SETTINGS_SITE_DETAILS,
new URLSearchParams('site=' + origin));
@@ -170,7 +252,7 @@ Polymer({
* @private
*/
onOriginTap_: function(e) {
- this.navigateToSiteDetails_(this.siteGroup.origins[e.model.index]);
+ this.navigateToSiteDetails_(this.siteGroup.origins[e.model.index].origin);
},
/**
@@ -181,7 +263,7 @@ Polymer({
onSiteEntryTap_: function() {
// Individual origins don't expand - just go straight to Site Details.
if (!this.grouped_(this.siteGroup)) {
- this.navigateToSiteDetails_(this.siteGroup.origins[0]);
+ this.navigateToSiteDetails_(this.siteGroup.origins[0].origin);
return;
}
this.toggleCollapsible_();
@@ -196,7 +278,7 @@ Polymer({
* @private
*/
toggleCollapsible_: function() {
- let collapseChild =
+ const collapseChild =
/** @type {IronCollapseElement} */ (this.$.collapseChild);
collapseChild.toggle();
this.$.toggleButton.setAttribute('aria-expanded', collapseChild.opened);
@@ -238,7 +320,7 @@ Polymer({
onResetSettings_: function(e) {
const contentSettingsTypes = this.getCategoryList();
for (let i = 0; i < this.siteGroup.origins.length; ++i) {
- const origin = this.siteGroup.origins[i];
+ const origin = this.siteGroup.origins[i].origin;
this.browserProxy.setOriginPermissions(
origin, contentSettingsTypes, settings.ContentSetting.DEFAULT);
if (contentSettingsTypes.includes(settings.ContentSettingsTypes.PLUGINS))
@@ -282,4 +364,15 @@ Polymer({
return 'first';
return '';
},
+
+ /**
+ * Focuses the first focusable button in this site-entry.
+ * @private
+ */
+ onFocus_: function() {
+ const button = /** @type Element */
+ (this.root.querySelector('#toggleButton *:not([hidden]) button'));
+ button.focus();
+ this.tabIndex = -1;
+ },
});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_list.html b/chromium/chrome/browser/resources/settings/site_settings/site_list.html
index 10c0cfc9d24..1ba4ce4a4e5 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_list.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_list.html
@@ -3,27 +3,26 @@
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/html/list_property_update_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-tooltip/paper-tooltip.html">
<link rel="import" href="../i18n_setup.html">
-<link rel="import" href="../icons.html">
-<link rel="import" href="../route.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="add_site_dialog.html">
<link rel="import" href="constants.html">
<link rel="import" href="edit_exception_dialog.html">
+<link rel="import" href="site_list_entry.html">
<link rel="import" href="site_settings_behavior.html">
<link rel="import" href="site_settings_prefs_browser_proxy.html">
<dom-module id="site-list">
<template>
<style include="settings-shared">
- .settings-row {
- flex: 1
+ paper-tooltip {
+ --paper-tooltip: var(--cr-tooltip);
}
</style>
<div id="category">
@@ -64,55 +63,21 @@
<div class="list-item secondary">$i18n{noSitesAdded}</div>
</div>
<div class="list-frame menu-content vertical-list" id="listContainer">
- <template is="dom-repeat" items="[[sites]]">
- <div class="list-item">
- <div class="settings-row"
- actionable$="[[enableSiteSettings_]]" on-click="onOriginTap_">
- <div class="favicon-image"
- style$="[[computeSiteIcon(item.origin)]]">
- </div>
- <div class="middle no-min-width">
- <div class="text-elide">
- <span class="url-directionality">[[item.displayName]]</span>
- </div>
-
- <!-- This div must not contain extra whitespace. -->
- <div class="secondary text-elide"
- id="siteDescription">[[computeSiteDescription_(item)]]</div>
- </div>
- <template is="dom-if" if="[[enableSiteSettings_]]">
- <div on-click="onOriginTap_" actionable>
- <paper-icon-button-light class="subpage-arrow">
- <button aria-label$="[[item.displayName]]"
- aria-describedby="siteDescription"></button>
- </paper-icon-button-light>
- </div>
- <div class="separator"></div>
- </template>
- </div>
- <template is="dom-if" if="[[item.controlledBy]]">
- <cr-policy-pref-indicator pref="[[item]]"
- icon-aria-label="[[label]]">
- </cr-policy-pref-indicator>
- </template>
- <paper-icon-button-light id="resetSiteContainer"
- class="icon-delete-gray"
- hidden="[[shouldHideResetButton_(item, readOnlyList)]]">
- <button id="resetSite" on-click="onResetButtonTap_"
- aria-label="$i18n{siteSettingsActionReset}">
- </button>
- </paper-icon-button-light>
- <paper-icon-button-light id="actionMenuButtonContainer"
- class="icon-more-vert"
- hidden="[[shouldHideActionMenu_(item, readOnlyList)]]">
- <button id="actionMenuButton" on-click="onShowActionMenuTap_"
- title="$i18n{moreActions}">
- </button>
- </paper-icon-button-light>
- </div>
- </template>
+ <iron-list items="[[sites]]" preserve-focus risk-selection>
+ <template>
+ <site-list-entry model="[[item]]" read-only-list="[[readOnlyList]]"
+ on-show-action-menu="onShowActionMenu_" tabindex$="[[tabIndex]]"
+ first$="[[!index]]" iron-list-tab-index="[[tabIndex]]"
+ last-focused="{{lastFocused_}}"
+ on-show-tooltip="onShowTooltip_">
+ </site-list-entry>
+ </template>
+ </iron-list>
</div>
</div>
+ <paper-tooltip id="tooltip" manual-mode position="top">
+ [[tooltipText_]]
+ </paper-tooltip>
<template is="dom-if" if="[[showEditExceptionDialog_]]" restamp>
<settings-edit-exception-dialog model="[[actionMenuSite_]]"
on-close="onEditExceptionDialogClosed_">
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_list.js b/chromium/chrome/browser/resources/settings/site_settings/site_list.js
index 1781ec33bb8..578fb2bd8f3 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_list.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_list.js
@@ -8,7 +8,6 @@
* category.
*/
Polymer({
-
is: 'site-list',
behaviors: [
@@ -18,14 +17,6 @@ Polymer({
],
properties: {
- /** @private */
- enableSiteSettings_: {
- type: Boolean,
- value: function() {
- return loadTimeData.getBoolean('enableSiteSettings');
- },
- },
-
/**
* Some content types (like Location) do not allow the user to manually
* edit the exception list from within Settings.
@@ -108,6 +99,12 @@ Polymer({
SESSION_ONLY: 'SessionOnly',
}
},
+
+ /** @private */
+ lastFocused_: Object,
+
+ /** @private */
+ tooltipText_: String,
},
/**
@@ -193,30 +190,6 @@ Polymer({
},
/**
- * @param {!SiteException} exception The content setting exception.
- * @param {boolean} readOnlyList Whether the site exception list is read-only.
- * @return {boolean}
- * @private
- */
- shouldHideResetButton_: function(exception, readOnlyList) {
- return exception.enforcement ==
- chrome.settingsPrivate.Enforcement.ENFORCED ||
- !(readOnlyList || !!exception.embeddingOrigin);
- },
-
- /**
- * @param {!SiteException} exception The content setting exception.
- * @param {boolean} readOnlyList Whether the site exception list is read-only.
- * @return {boolean}
- * @private
- */
- shouldHideActionMenu_: function(exception, readOnlyList) {
- return exception.enforcement ==
- chrome.settingsPrivate.Enforcement.ENFORCED ||
- readOnlyList || !!exception.embeddingOrigin;
- },
-
- /**
* A handler for the Add Site button.
* @private
*/
@@ -232,6 +205,36 @@ Polymer({
},
/**
+ * Need to use common tooltip since the tooltip in the entry is cut off from
+ * the iron-list.
+ * @param {!{detail: {target: HTMLElement, text: string}}} e
+ * @private
+ */
+ onShowTooltip_: function(e) {
+ this.tooltipText_ = e.detail.text;
+ const target = e.detail.target;
+ // paper-tooltip normally determines the target from the |for| property,
+ // which is a selector. Here paper-tooltip is being reused by multiple
+ // potential targets. Since paper-tooltip does not expose a public property
+ // or method to update the target, the private property |_target| is
+ // updated directly.
+ this.$.tooltip._target = target;
+ /** @type {{updatePosition: Function}} */ (this.$.tooltip).updatePosition();
+ const hide = () => {
+ this.$.tooltip.hide();
+ target.removeEventListener('mouseleave', hide);
+ target.removeEventListener('blur', hide);
+ target.removeEventListener('tap', hide);
+ this.$.tooltip.removeEventListener('mouseenter', hide);
+ };
+ target.addEventListener('mouseleave', hide);
+ target.addEventListener('blur', hide);
+ target.addEventListener('tap', hide);
+ this.$.tooltip.addEventListener('mouseenter', hide);
+ this.$.tooltip.show();
+ },
+
+ /**
* Populate the sites list for display.
* @private
*/
@@ -287,29 +290,6 @@ Polymer({
},
/**
- * A handler for selecting a site (by clicking on the origin).
- * @param {!{model: !{item: !SiteException}}} event
- * @private
- */
- onOriginTap_: function(event) {
- if (!this.enableSiteSettings_)
- return;
- settings.navigateTo(
- settings.routes.SITE_SETTINGS_SITE_DETAILS,
- new URLSearchParams('site=' + event.model.item.origin));
- },
-
- /**
- * @param {?SiteException} site
- * @private
- */
- resetPermissionForOrigin_: function(site) {
- assert(site);
- this.browserProxy.resetCategoryPermissionForPattern(
- site.origin, site.embeddingOrigin, this.category, site.incognito);
- },
-
- /**
* @param {!settings.ContentSetting} contentSetting
* @private
*/
@@ -359,51 +339,20 @@ Polymer({
/** @private */
onResetTap_: function() {
- this.resetPermissionForOrigin_(this.actionMenuSite_);
+ const site = this.actionMenuSite_;
+ assert(site);
+ this.browserProxy.resetCategoryPermissionForPattern(
+ site.origin, site.embeddingOrigin, this.category, site.incognito);
this.closeActionMenu_();
},
/**
- * Returns the appropriate site description to display. This can, for example,
- * be blank, an 'embedded on <site>' or 'Current incognito session' (or a
- * mix of the last two).
- * @param {SiteException} item The site exception entry.
- * @return {string} The site description.
- */
- computeSiteDescription_: function(item) {
- let displayName = '';
- if (item.embeddingOrigin) {
- displayName = loadTimeData.getStringF(
- 'embeddedOnHost', this.sanitizePort(item.embeddingOrigin));
- } else if (this.category == settings.ContentSettingsTypes.GEOLOCATION) {
- displayName = loadTimeData.getString('embeddedOnAnyHost');
- }
-
- if (item.incognito) {
- if (displayName.length > 0)
- return loadTimeData.getStringF('embeddedIncognitoSite', displayName);
- return loadTimeData.getString('incognitoSite');
- }
- return displayName;
- },
-
- /**
- * @param {!{model: !{item: !SiteException}}} e
+ * @param {!Event} e
* @private
*/
- onResetButtonTap_: function(e) {
- this.resetPermissionForOrigin_(e.model.item);
- },
-
- /**
- * @param {!{model: !{item: !SiteException}}} e
- * @private
- */
- onShowActionMenuTap_: function(e) {
- this.activeDialogAnchor_ = /** @type {!HTMLElement} */ (
- Polymer.dom(/** @type {!Event} */ (e)).localTarget);
-
- this.actionMenuSite_ = e.model.item;
+ onShowActionMenu_: function(e) {
+ this.activeDialogAnchor_ = /** @type {!HTMLElement} */ (e.detail.anchor);
+ this.actionMenuSite_ = e.detail.model;
/** @type {!CrActionMenuElement} */ (this.$$('cr-action-menu'))
.showAt(this.activeDialogAnchor_);
},
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_list_entry.html b/chromium/chrome/browser/resources/settings/site_settings/site_list_entry.html
new file mode 100644
index 00000000000..448e7d21f53
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_list_entry.html
@@ -0,0 +1,80 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/web-animations.html">
+<link rel="import" href="../focus_row_behavior.html">
+<link rel="import" href="../i18n_setup.html">
+<link rel="import" href="../icons.html">
+<link rel="import" href="../route.html">
+<link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="constants.html">
+<link rel="import" href="site_settings_behavior.html">
+<link rel="import" href="site_settings_prefs_browser_proxy.html">
+
+<dom-module id="site-list-entry">
+ <template>
+ <style include="settings-shared">
+ .settings-row {
+ flex: 1
+ }
+
+ /* Tooltip is hidden since site-list will display a common tooltip. */
+ cr-policy-pref-indicator {
+ --cr-tooltip: {
+ display: none;
+ };
+ }
+ </style>
+ <div class="list-item" focus-row-container>
+ <div class="settings-row"
+ actionable$="[[enableSiteSettings_]]" on-click="onOriginTap_">
+ <div class="favicon-image"
+ style$="[[computeSiteIcon(model.origin)]]">
+ </div>
+ <div class="middle no-min-width">
+ <div class="text-elide">
+ <span class="url-directionality">[[model.displayName]]</span>
+ </div>
+
+ <!-- This div must not contain extra whitespace. -->
+ <div class="secondary text-elide"
+ id="siteDescription">[[siteDescription_]]</div>
+ </div>
+ <template is="dom-if" if="[[enableSiteSettings_]]">
+ <div on-click="onOriginTap_" actionable>
+ <paper-icon-button-light class="subpage-arrow">
+ <button aria-label$="[[model.displayName]]"
+ aria-describedby="siteDescription" focus-row-control
+ focus-type="site-details"></button>
+ </paper-icon-button-light>
+ </div>
+ <div class="separator"></div>
+ </template>
+ </div>
+ <template is="dom-if" if="[[showPolicyPrefIndicator_]]">
+ <cr-policy-pref-indicator pref="[[model]]"
+ icon-aria-label="[[label]]" on-mouseenter="onShowTooltip_"
+ on-focus="onShowTooltip_" focus-row-control focus-type="policy">
+ </cr-policy-pref-indicator>
+ </template>
+ <paper-icon-button-light id="resetSiteContainer"
+ class="icon-delete-gray"
+ hidden="[[shouldHideResetButton_(model, readOnlyList)]]">
+ <button id="resetSite" on-click="onResetButtonTap_"
+ aria-label="$i18n{siteSettingsActionReset}" focus-row-control
+ focus-type="reset"></button>
+ </paper-icon-button-light>
+ <paper-icon-button-light id="actionMenuButtonContainer"
+ class="icon-more-vert"
+ hidden="[[shouldHideActionMenu_(model, readOnlyList)]]">
+ <button id="actionMenuButton" on-click="onShowActionMenuTap_"
+ title="$i18n{moreActions}" focus-row-control focus-type="menu">
+ </button>
+ </paper-icon-button-light>
+ </div>
+ </template>
+ <script src="site_list_entry.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_list_entry.js b/chromium/chrome/browser/resources/settings/site_settings/site_list_entry.js
new file mode 100644
index 00000000000..37168658a56
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_list_entry.js
@@ -0,0 +1,145 @@
+// Copyright 2018 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
+ * 'site-list-entry' shows an Allowed and Blocked site for a given category.
+ */
+Polymer({
+ is: 'site-list-entry',
+
+ behaviors: [
+ SiteSettingsBehavior,
+ FocusRowBehavior,
+ ],
+
+ properties: {
+ /** @private */
+ enableSiteSettings_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.getBoolean('enableSiteSettings');
+ },
+ },
+
+ /**
+ * Some content types (like Location) do not allow the user to manually
+ * edit the exception list from within Settings.
+ * @private
+ */
+ readOnlyList: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * Site to display in the widget.
+ * @type {!SiteException}
+ */
+ model: Object,
+
+ /** @private */
+ siteDescription_: {
+ type: String,
+ computed: 'computeSiteDescription_(model)',
+ },
+
+ /** @private */
+ showPolicyPrefIndicator_: {
+ type: Boolean,
+ computed: 'computeShowPolicyPrefIndicator_(model)',
+ },
+ },
+
+ /** @private */
+ onShowTooltip_: function() {
+ const indicator = assert(this.$$('cr-policy-pref-indicator'));
+ // The tooltip text is used by an paper-tooltip contained inside the
+ // cr-policy-pref-indicator. The text is currently held in a private
+ // property. This text is needed here to send up to the common tooltip
+ // component.
+ const text = indicator.indicatorTooltip_;
+ this.fire('show-tooltip', {target: indicator, text});
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ shouldHideResetButton_: function() {
+ return this.model.enforcement ==
+ chrome.settingsPrivate.Enforcement.ENFORCED ||
+ !(this.readOnlyList || !!this.model.embeddingOrigin);
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ shouldHideActionMenu_: function() {
+ return this.model.enforcement ==
+ chrome.settingsPrivate.Enforcement.ENFORCED ||
+ this.readOnlyList || !!this.model.embeddingOrigin;
+ },
+
+ /**
+ * A handler for selecting a site (by clicking on the origin).
+ * @param {!{model: !{item: !SiteException}}} event
+ * @private
+ */
+ onOriginTap_: function(event) {
+ if (!this.enableSiteSettings_)
+ return;
+ settings.navigateTo(
+ settings.routes.SITE_SETTINGS_SITE_DETAILS,
+ new URLSearchParams('site=' + this.model.origin));
+ },
+
+ /**
+ * Returns the appropriate site description to display. This can, for example,
+ * be blank, an 'embedded on <site>' or 'Current incognito session' (or a
+ * mix of the last two).
+ * @return {string} The site description.
+ */
+ computeSiteDescription_: function() {
+ let displayName = '';
+ if (this.model.embeddingOrigin) {
+ displayName = loadTimeData.getStringF(
+ 'embeddedOnHost', this.sanitizePort(this.model.embeddingOrigin));
+ } else if (this.category == settings.ContentSettingsTypes.GEOLOCATION) {
+ displayName = loadTimeData.getString('embeddedOnAnyHost');
+ }
+
+ if (this.model.incognito) {
+ if (displayName.length > 0)
+ return loadTimeData.getStringF('embeddedIncognitoSite', displayName);
+ return loadTimeData.getString('incognitoSite');
+ }
+ return displayName;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeShowPolicyPrefIndicator_: function() {
+ return this.model.enforcement ==
+ chrome.settingsPrivate.Enforcement.ENFORCED &&
+ !!this.model.controlledBy;
+ },
+
+ /** @private */
+ onResetButtonTap_: function() {
+ this.browserProxy.resetCategoryPermissionForPattern(
+ this.model.origin, this.model.embeddingOrigin, this.model.category,
+ this.model.incognito);
+ },
+
+ /** @private */
+ onShowActionMenuTap_: function() {
+ this.fire(
+ 'show-action-menu',
+ {anchor: this.$.actionMenuButton, model: this.model});
+ },
+});
diff --git a/chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js b/chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
index 9ee9e90fc87..eaad4f24177 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
@@ -19,12 +19,21 @@ const ContentSettingProvider = {
};
/**
+ * Stores origin information.
+ * @typedef {{origin: string,
+ * engagement: number,
+ * usage: number}}
+ */
+let OriginInfo;
+
+/**
* Represents a list of sites, grouped under the same eTLD+1. For example, an
* origin "https://www.example.com" would be grouped together with
* "https://login.example.com" and "http://example.com" under a common eTLD+1 of
* "example.com".
* @typedef {{etldPlus1: string,
- * origins: Array<string>}}
+ * numCookies: number,
+ * origins: Array<OriginInfo>}}
*/
let SiteGroup;
@@ -118,13 +127,21 @@ cr.define('settings', function() {
/**
* Gets a list of sites, grouped by eTLD+1, affected by any of the content
* settings specified by |contentTypes|.
- * @param {string} contentTypes A list of the content types to retrieve
- * sites for.
+ * @param {!Array<!settings.ContentSettingsTypes>} contentTypes A list of
+ * the content types to retrieve sites for.
* @return {!Promise<!Array<!SiteGroup>>}
*/
getAllSites(contentTypes) {}
/**
+ * Converts a given number of bytes into a human-readable format, with data
+ * units.
+ * @param {number} numBytes The number of bytes to convert.
+ * @return {!Promise<string>}
+ */
+ getFormattedBytes(numBytes) {}
+
+ /**
* Gets the exceptions (site list) for a particular category.
* @param {string} contentType The name of the category to query.
* @return {!Promise<!Array<!RawSiteException>>}
@@ -300,6 +317,12 @@ cr.define('settings', function() {
*/
showAndroidManageAppLinks() {}
// </if>
+
+ /**
+ * Fetches the current block autoplay state. Returns the results via
+ * onBlockAutoplayStatusChanged.
+ */
+ fetchBlockAutoplayStatus() {}
}
/**
@@ -322,6 +345,11 @@ cr.define('settings', function() {
}
/** @override */
+ getFormattedBytes(numBytes) {
+ return cr.sendWithPromise('getFormattedBytes', numBytes);
+ }
+
+ /** @override */
getExceptionList(contentType) {
return cr.sendWithPromise('getExceptionList', contentType);
}
@@ -437,6 +465,11 @@ cr.define('settings', function() {
chrome.send('showAndroidManageAppLinks');
}
// </if>
+
+ /** @override */
+ fetchBlockAutoplayStatus() {
+ chrome.send('fetchBlockAutoplayStatus');
+ }
}
// The singleton instance_ is replaced with a test version of this wrapper
diff --git a/chromium/chrome/browser/resources/settings/site_settings/usb_devices.html b/chromium/chrome/browser/resources/settings/site_settings/usb_devices.html
index 178400c6c86..770b302d6f5 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/usb_devices.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/usb_devices.html
@@ -15,8 +15,8 @@
}
.column-header {
- -webkit-margin-start: 20px;
margin-bottom: 15px;
+ margin-inline-start: 20px;
margin-top: 15px;
}
</style>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html b/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html
index 414569dc440..559e7613d7e 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html
+++ b/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.html
@@ -2,8 +2,9 @@
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/html/list_property_update_behavior.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="site_settings_behavior.html">
@@ -17,37 +18,46 @@
}
.zoom-label {
- -webkit-margin-end: 16px;
color: var(--cr-secondary-text-color);
+ margin-inline-end: 16px;
}
#empty {
margin-top: 15px;
}
+
+ .list-item .favicon-image {
+ flex-shrink: 0;
+ }
+
+ .list-item .middle {
+ overflow-x: hidden;
+ text-overflow: ellipsis;
+ }
</style>
<div class="list-frame vertical-list" id="listContainer">
- <template is="dom-repeat" items="[[sites_]]" id="list">
- <div class="list-item">
- <div class="favicon-image"
- style$="[[computeSiteIcon(item.originForFavicon)]]">
- </div>
- <div class="middle">
- <span class="url-directionality">[[item.displayName]]</span>
- </div>
- <div class="zoom-label">[[item.zoom]]</div>
- <div>
+ <iron-list id="list" preserve-focus items="[[sites_]]"
+ class="cr-separators" risk-selection>
+ <template>
+ <div class="list-item" first$="[[!index]]">
+ <div class="favicon-image"
+ style$="[[computeSiteIcon(item.originForFavicon)]]">
+ </div>
+ <div class="middle">
+ <span class="url-directionality">[[item.displayName]]</span>
+ </div>
+ <div class="zoom-label">[[item.zoom]]</div>
<paper-icon-button-light class="icon-clear">
<button on-click="removeZoomLevel_"
- title="$i18n{siteSettingsRemoveZoomLevel}"></button>
+ title="$i18n{siteSettingsRemoveZoomLevel}"
+ tabindex$="[[tabIndex]]"></button>
</paper-icon-button-light>
</div>
- </div>
- </template>
- <template is="dom-if" if="[[!sites_.length]]">
- <div id="empty">
- $i18n{siteSettingsNoZoomedSites}
- </div>
- </template>
+ </template>
+ </iron-list>
+ <div id="empty" hidden$="[[!showNoSites_]]">
+ $i18n{siteSettingsNoZoomedSites}
+ </div>
</div>
</template>
<script src="zoom_levels.js"></script>
diff --git a/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.js b/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.js
index eeeb057da00..1614243c0be 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.js
+++ b/chromium/chrome/browser/resources/settings/site_settings/zoom_levels.js
@@ -11,14 +11,27 @@
Polymer({
is: 'zoom-levels',
- behaviors: [SiteSettingsBehavior, WebUIListenerBehavior],
+ behaviors: [
+ ListPropertyUpdateBehavior,
+ SiteSettingsBehavior,
+ WebUIListenerBehavior,
+ ],
properties: {
/**
* Array of sites that are zoomed in or out.
* @type {!Array<ZoomLevelEntry>}
*/
- sites_: Array,
+ sites_: {
+ type: Array,
+ value: () => [],
+ },
+
+ /** @private */
+ showNoSites_: {
+ type: Boolean,
+ value: false,
+ },
},
/** @override */
@@ -34,7 +47,8 @@ Polymer({
* their zoom levels.
*/
onZoomLevelsChanged_: function(sites) {
- this.sites_ = sites;
+ this.updateList('sites_', item => `${item.origin}_${item.zoom}`, sites);
+ this.showNoSites_ = this.sites_.length == 0;
},
/**
diff --git a/chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn b/chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn
index ea35eff8914..7467e9e011e 100644
--- a/chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn
@@ -20,5 +20,6 @@ js_library("site_settings_page") {
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:web_ui_listener_behavior",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
]
}
diff --git a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
index 92c863fcf9e..b2894017d19 100644
--- a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
+++ b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -1,6 +1,7 @@
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="../icons.html">
@@ -14,7 +15,7 @@
<template>
<style include="settings-shared">
.settings-box iron-icon + .middle {
- -webkit-padding-start: 20px;
+ padding-inline-start: 20px;
}
</style>
<template is="dom-if" if="[[enableSiteSettings_]]">
diff --git a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
index 72f0f5db31e..c6213ed665e 100644
--- a/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
+++ b/chromium/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
@@ -84,7 +84,7 @@ Polymer({
}
},
- /** @type {!Map<string, string>} */
+ /** @type {!Map<string, (string|Function)>} */
focusConfig: {
type: Object,
observer: 'focusConfigChanged_',
@@ -136,8 +136,9 @@ Polymer({
pairs.forEach(pair => {
const route = pair[0];
const id = pair[1];
- this.focusConfig.set(
- route.path, '* /deep/ #' + id + ' .subpage-arrow button');
+ this.focusConfig.set(route.path, () => this.async(() => {
+ cr.ui.focusWithoutInk(assert(this.$$(`#${id} .subpage-arrow button`)));
+ }));
});
},