diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-07-16 11:45:35 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-07-17 08:59:23 +0000 |
commit | 552906b0f222c5d5dd11b9fd73829d510980461a (patch) | |
tree | 3a11e6ed0538a81dd83b20cf3a4783e297f26d91 /chromium/chrome/browser/resources/extensions | |
parent | 1b05827804eaf047779b597718c03e7d38344261 (diff) |
BASELINE: Update Chromium to 83.0.4103.122
Change-Id: Ie3a82f5bb0076eec2a7c6a6162326b4301ee291e
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/chrome/browser/resources/extensions')
49 files changed, 758 insertions, 502 deletions
diff --git a/chromium/chrome/browser/resources/extensions/.eslintrc.js b/chromium/chrome/browser/resources/extensions/.eslintrc.js new file mode 100644 index 00000000000..0b691a4dcc5 --- /dev/null +++ b/chromium/chrome/browser/resources/extensions/.eslintrc.js @@ -0,0 +1,11 @@ +// 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. + +module.exports = { + 'env': { + 'browser': true, + 'es6': true, + }, + 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]}, +}; diff --git a/chromium/chrome/browser/resources/extensions/BUILD.gn b/chromium/chrome/browser/resources/extensions/BUILD.gn index 49c26aa9c38..6b89fa93ad2 100644 --- a/chromium/chrome/browser/resources/extensions/BUILD.gn +++ b/chromium/chrome/browser/resources/extensions/BUILD.gn @@ -29,24 +29,18 @@ if (optimize_webui) { pak_file = extensions_pak_file out_folder = unpak_folder - deps = [ - ":flattened_resources", - ] + deps = [ ":flattened_resources" ] } grit("flattened_resources") { source = "extensions_resources.grd" - # The .grd contains references to generated files. - source_is_generated = true grit_flags = [ "-E", "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), ] - deps = [ - ":polymer3_elements", - ] + deps = [ ":polymer3_elements" ] defines = chrome_grit_defines outputs = [ "grit/extensions_resources.h", @@ -66,7 +60,8 @@ group("closure_compile") { } group("polymer3_elements") { - deps = [ + public_deps = [ + ":checkup_module", ":code_section_module", ":detail_view_module", ":drop_overlay_module", @@ -93,10 +88,16 @@ group("polymer3_elements") { "activity_log:polymer3_elements", ] if (is_chromeos) { - deps += [ ":kiosk_dialog_module" ] + public_deps += [ ":kiosk_dialog_module" ] } } +polymer_modulizer("checkup") { + js_file = "checkup.js" + html_file = "checkup.html" + html_type = "v3-ready" +} + polymer_modulizer("code_section") { js_file = "code_section.js" html_file = "code_section.html" @@ -250,6 +251,7 @@ js_type_check("extensions_module_resources") { ] is_polymer3 = true deps = [ + ":checkup", ":code_section", ":detail_view", ":drag_and_drop_handler", @@ -284,6 +286,12 @@ js_type_check("extensions_module_resources") { } } +js_library("checkup") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + ] +} + js_library("code_section") { deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", @@ -338,16 +346,12 @@ js_library("error_page") { } js_library("host_permissions_toggle_list") { - deps = [ - ":item", - ] + deps = [ ":item" ] externs_list = [ "$externs_path/developer_private.js" ] } js_library("install_warnings_dialog") { - deps = [ - "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", - ] + deps = [ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m" ] externs_list = [ "$externs_path/developer_private.js" ] } @@ -366,18 +370,18 @@ js_library("item") { } js_library("item_behavior") { - deps = [ - "//ui/webui/resources/js:load_time_data.m", - ] + deps = [ "//ui/webui/resources/js:load_time_data.m" ] externs_list = [ "$externs_path/developer_private.js" ] } js_library("item_list") { deps = [ + ":checkup", ":item", "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer", "//ui/webui/resources/cr_elements:cr_container_shadow_behavior.m", "//ui/webui/resources/js:i18n_behavior.m", + "//ui/webui/resources/js:load_time_data.m", ] externs_list = [ "$externs_path/developer_private.js", @@ -412,9 +416,7 @@ js_library("keyboard_shortcuts") { } js_library("kiosk_browser_proxy") { - deps = [ - "//ui/webui/resources/js:cr.m", - ] + deps = [ "//ui/webui/resources/js:cr.m" ] } if (is_chromeos) { @@ -533,7 +535,9 @@ js_library("shortcut_input") { deps = [ ":keyboard_shortcut_delegate", ":shortcut_util", + "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer", "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:i18n_behavior.m", ] externs_list = [ "$externs_path/developer_private.js" ] } diff --git a/chromium/chrome/browser/resources/extensions/activity_log/BUILD.gn b/chromium/chrome/browser/resources/extensions/activity_log/BUILD.gn index d562aa8ca3d..af6d5b02f3d 100644 --- a/chromium/chrome/browser/resources/extensions/activity_log/BUILD.gn +++ b/chromium/chrome/browser/resources/extensions/activity_log/BUILD.gn @@ -36,7 +36,7 @@ polymer_modulizer("activity_log_stream_item") { } group("polymer3_elements") { - deps = [ + public_deps = [ ":activity_log_history_item_module", ":activity_log_history_module", ":activity_log_module", diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log.js index 6bf480f9927..694b67f7864 100644 --- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log.js +++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log.js @@ -97,7 +97,7 @@ Polymer({ * be HISTORY when we navigate to the page. * @private */ - onViewEnterStart_: function() { + onViewEnterStart_() { this.selectedSubpage_ = ActivityLogSubpage.HISTORY; afterNextRender(this, () => focusWithoutInk(this.$.closeButton)); }, @@ -106,7 +106,7 @@ Polymer({ * Set |selectedSubpage_| to NONE to remove the active view from the DOM. * @private */ - onViewExitFinish_: function() { + onViewExitFinish_() { this.selectedSubpage_ = ActivityLogSubpage.NONE; // clear the stream if the user is exiting the activity log page. const activityLogStream = this.$$('activity-log-stream'); @@ -119,7 +119,7 @@ Polymer({ * @private * @return {string} */ - getActivityLogHeading_: function() { + getActivityLogHeading_() { const headingName = this.extensionInfo.isPlaceholder ? this.i18n('missingOrUninstalledExtension') : this.extensionInfo.name; @@ -130,7 +130,7 @@ Polymer({ * @private * @return {boolean} */ - isHistoryTabSelected_: function() { + isHistoryTabSelected_() { return this.selectedSubpage_ === ActivityLogSubpage.HISTORY; }, @@ -138,7 +138,7 @@ Polymer({ * @private * @return {boolean} */ - isStreamTabSelected_: function() { + isStreamTabSelected_() { return this.selectedSubpage_ === ActivityLogSubpage.STREAM; }, @@ -147,7 +147,7 @@ Polymer({ * @param {!ActivityLogSubpage} newTab * @param {!ActivityLogSubpage} oldTab */ - onSelectedSubpageChanged_: function(newTab, oldTab) { + onSelectedSubpageChanged_(newTab, oldTab) { const activityLogStream = this.$$('activity-log-stream'); if (activityLogStream) { if (newTab === ActivityLogSubpage.STREAM) { @@ -165,7 +165,7 @@ Polymer({ }, /** @private */ - onCloseButtonTap_: function() { + onCloseButtonTap_() { if (this.extensionInfo.isPlaceholder) { navigation.navigateTo({page: Page.LIST}); } else { diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history.js index a28281eaa9d..dbd4412f6b2 100644 --- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history.js +++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history.js @@ -179,7 +179,7 @@ function groupActivities(activityData) { */ function sortActivitiesByCallCount(groupedActivities) { return Array.from(groupedActivities.values()).sort((a, b) => { - if (a.count != b.count) { + if (a.count !== b.count) { return b.count - a.count; } if (a.key < b.key) { @@ -252,12 +252,12 @@ Polymer({ * Expose only the promise of dataFetchedResolver_. * @return {!Promise<void>} */ - whenDataFetched: function() { + whenDataFetched() { return this.dataFetchedResolver_.promise; }, /** @override */ - attached: function() { + attached() { this.dataFetchedResolver_ = new PromiseResolver(); this.refreshActivities_(); }, @@ -266,7 +266,7 @@ Polymer({ * @private * @return {boolean} */ - shouldShowEmptyActivityLogMessage_: function() { + shouldShowEmptyActivityLogMessage_() { return this.pageState_ === ActivityLogPageState.LOADED && this.activityData_.length === 0; }, @@ -275,7 +275,7 @@ Polymer({ * @private * @return {boolean} */ - shouldShowLoadingMessage_: function() { + shouldShowLoadingMessage_() { return this.pageState_ === ActivityLogPageState.LOADING; }, @@ -283,20 +283,20 @@ Polymer({ * @private * @return {boolean} */ - shouldShowActivities_: function() { + shouldShowActivities_() { return this.pageState_ === ActivityLogPageState.LOADED && this.activityData_.length > 0; }, /** @private */ - onClearActivitiesClick_: function() { + onClearActivitiesClick_() { this.delegate.deleteActivitiesFromExtension(this.extensionId).then(() => { this.processActivities_([]); }); }, /** @private */ - onMoreActionsClick_: function() { + onMoreActionsClick_() { this.$$('cr-action-menu').showAt(assert(this.$$('cr-icon-button'))); }, @@ -304,7 +304,7 @@ Polymer({ * @private * @param {boolean} expanded */ - expandItems_: function(expanded) { + expandItems_(expanded) { // Do not use .filter here as we need the original index of the item // in |activityData_|. this.activityData_.forEach((item, index) => { @@ -316,17 +316,17 @@ Polymer({ }, /** @private */ - onExpandAllClick_: function() { + onExpandAllClick_() { this.expandItems_(true); }, /** @private */ - onCollapseAllClick_: function() { + onCollapseAllClick_() { this.expandItems_(false); }, /** @private */ - onExportClick_: function() { + onExportClick_() { const fileName = `exported_activity_log_${this.extensionId}.json`; this.delegate.downloadActivities(this.rawActivities_, fileName); }, @@ -335,7 +335,7 @@ Polymer({ * @private * @param {!CustomEvent<!Array<string>>} e */ - deleteItem_: function(e) { + deleteItem_(e) { const activityIds = e.detail; this.delegate.deleteActivitiesById(activityIds).then(() => { // It is possible for multiple activities displayed to have the same @@ -351,7 +351,7 @@ Polymer({ * @param {!Array<!chrome.activityLogPrivate.ExtensionActivity>} * activityData */ - processActivities_: function(activityData) { + processActivities_(activityData) { this.pageState_ = ActivityLogPageState.LOADED; // Sort |activityData| in ascending order based on the activity's @@ -370,7 +370,7 @@ Polymer({ * @private * @return {!Promise<void>} */ - refreshActivities_: function() { + refreshActivities_() { if (this.lastSearch_ === '') { return this.getActivityLog_(); } @@ -382,7 +382,7 @@ Polymer({ * @private * @return {!Promise<void>} */ - getActivityLog_: function() { + getActivityLog_() { this.pageState_ = ActivityLogPageState.LOADING; return this.delegate.getExtensionActivityLog(this.extensionId) .then(result => { @@ -395,7 +395,7 @@ Polymer({ * @param {string} searchTerm * @return {!Promise<void>} */ - getFilteredActivityLog_: function(searchTerm) { + getFilteredActivityLog_(searchTerm) { this.pageState_ = ActivityLogPageState.LOADING; return this.delegate .getFilteredExtensionActivityLog(this.extensionId, searchTerm) @@ -408,7 +408,7 @@ Polymer({ * @private * @param {!CustomEvent<string>} e */ - onSearchChanged_: function(e) { + onSearchChanged_(e) { // Remove all whitespaces from the search term, as API call names and // urls should not contain any whitespace. As of now, only single term // search queries are allowed. diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history_item.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history_item.js index 1ed2d728fcd..94a5ce67fd9 100644 --- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history_item.js +++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history_item.js @@ -57,7 +57,7 @@ Polymer({ * @private * @return {boolean} */ - computeIsExpandable_: function() { + computeIsExpandable_() { return this.data.countsByUrl.size > 0; }, @@ -68,11 +68,11 @@ Polymer({ * @private * @return {!Array<PageUrlItem>} */ - getPageUrls_: function() { + getPageUrls_() { return Array.from(this.data.countsByUrl.entries()) .map(e => ({page: e[0], count: e[1]})) .sort(function(a, b) { - if (a.count != b.count) { + if (a.count !== b.count) { return b.count - a.count; } return a.page < b.page ? -1 : (a.page > b.page ? 1 : 0); @@ -80,14 +80,14 @@ Polymer({ }, /** @private */ - onDeleteTap_: function(e) { + onDeleteTap_(e) { e.stopPropagation(); this.fire( 'delete-activity-log-item', Array.from(this.data.activityIds.values())); }, /** @private */ - onExpandTap_: function() { + onExpandTap_() { if (this.isExpandable_) { this.set('data.expanded', !this.data.expanded); } @@ -99,7 +99,7 @@ Polymer({ * @private * @return {boolean} */ - shouldShowPageUrlCount_: function() { + shouldShowPageUrlCount_() { return this.data.countsByUrl.size > 1; }, }); diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream.js index 7b74faf5714..14a324e01e3 100644 --- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream.js +++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream.js @@ -107,7 +107,7 @@ Polymer({ listenerInstance_: () => {}, /** @override */ - attached: function() { + attached() { // Since this component is not restamped, this will only be called once // in its lifecycle. this.listenerInstance_ = this.extensionActivityListener_.bind(this); @@ -115,15 +115,15 @@ Polymer({ }, /** @private */ - onResizeStream_: function(e) { + onResizeStream_(e) { this.$$('iron-list').notifyResize(); }, - clearStream: function() { + clearStream() { this.splice('activityStream_', 0, this.activityStream_.length); }, - startStream: function() { + startStream() { if (this.isStreamOn_) { return; } @@ -132,7 +132,7 @@ Polymer({ this.delegate.getOnExtensionActivity().addListener(this.listenerInstance_); }, - pauseStream: function() { + pauseStream() { if (!this.isStreamOn_) { return; } @@ -143,7 +143,7 @@ Polymer({ }, /** @private */ - onToggleButtonClick_: function() { + onToggleButtonClick_() { if (this.isStreamOn_) { this.pauseStream(); } else { @@ -155,23 +155,23 @@ Polymer({ * @private * @return {boolean} */ - isStreamEmpty_: function() { - return this.activityStream_.length == 0; + isStreamEmpty_() { + return this.activityStream_.length === 0; }, /** * @private * @return {boolean} */ - isFilteredStreamEmpty_: function() { - return this.filteredActivityStream_.length == 0; + isFilteredStreamEmpty_() { + return this.filteredActivityStream_.length === 0; }, /** * @private * @return {boolean} */ - shouldShowEmptySearchMessage_: function() { + shouldShowEmptySearchMessage_() { return !this.isStreamEmpty_() && this.isFilteredStreamEmpty_(); }, @@ -179,8 +179,8 @@ Polymer({ * @private * @param {!chrome.activityLogPrivate.ExtensionActivity} activity */ - extensionActivityListener_: function(activity) { - if (activity.extensionId != this.extensionId) { + extensionActivityListener_(activity) { + if (activity.extensionId !== this.extensionId) { return; } @@ -196,7 +196,7 @@ Polymer({ * @private * @param {!CustomEvent<string>} e */ - onSearchChanged_: function(e) { + onSearchChanged_(e) { // Remove all whitespaces from the search term, as API call names and // URLs should not contain any whitespace. As of now, only single term // search queries are allowed. @@ -212,7 +212,7 @@ Polymer({ * @private * @return {!Array<!StreamItem>} */ - computeFilteredActivityStream_: function() { + computeFilteredActivityStream_() { if (!this.lastSearch_) { return this.activityStream_.slice(); } diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js index e7025078fbc..82c04c600dd 100644 --- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js +++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js @@ -82,7 +82,7 @@ Polymer({ * @private * @return {boolean} */ - computeIsExpandable_: function() { + computeIsExpandable_() { return this.hasPageUrl_() || this.hasArgs_() || this.hasWebRequestInfo_(); }, @@ -90,7 +90,7 @@ Polymer({ * @private * @return {string} */ - getFormattedTime_: function() { + getFormattedTime_() { // Format the activity's time to HH:MM:SS.mmm format. Use ToLocaleString // for HH:MM:SS and padLeft for milliseconds. const activityDate = new Date(this.data.timestamp); @@ -109,7 +109,7 @@ Polymer({ * @private * @return {boolean} */ - hasPageUrl_: function() { + hasPageUrl_() { return !!this.data.pageUrl; }, @@ -117,7 +117,7 @@ Polymer({ * @private * @return {boolean} */ - hasArgs_: function() { + hasArgs_() { return this.argsList_.length > 0; }, @@ -125,15 +125,15 @@ Polymer({ * @private * @return {boolean} */ - hasWebRequestInfo_: function() { - return !!this.data.webRequestInfo && this.data.webRequestInfo != '{}'; + hasWebRequestInfo_() { + return !!this.data.webRequestInfo && this.data.webRequestInfo !== '{}'; }, /** * @private * @return {!Array<!StreamArgItem>} */ - computeArgsList_: function() { + computeArgsList_() { const parsedArgs = JSON.parse(this.data.args); if (!Array.isArray(parsedArgs)) { return []; @@ -152,7 +152,7 @@ Polymer({ }, /** @private */ - onExpandClick_: function() { + onExpandClick_() { if (this.isExpandable_) { this.set('data.expanded', !this.data.expanded); this.fire('resize-stream'); diff --git a/chromium/chrome/browser/resources/extensions/checkup.html b/chromium/chrome/browser/resources/extensions/checkup.html new file mode 100644 index 00000000000..43fef4133ad --- /dev/null +++ b/chromium/chrome/browser/resources/extensions/checkup.html @@ -0,0 +1,65 @@ +<style include="iron-flex shared-style"> + :host { + --checkup-card-margin: 24px; + --banner-img-height: 115px; + --banner-img-width: 298px; + } + + #card { + background-color: var(--cr-card-background-color); + border-radius: var(--cr-card-border-radius); + box-shadow: var(--cr-card-shadow); + overflow: hidden; + padding: var(--checkup-card-margin); + transition: height var(--drawer-transition); + } + + #banner-img { + background: url(checkup_image.svg); + background-repeat: no-repeat; + display: inline-block; + float: right; + /* Height and width match the dimensions of the banner image. */ + height: var(--banner-img-height); + width: var(--banner-img-width); + } + + #banner-description { + @apply --cr-secondary-text; + flex-basis: var(--extensions-card-width); + text-overflow: ellipsis; + } + + #banner-title { + color: var(--cr-primary-text-color); + font-size: 123%; + } + + /* 932px is the last screen width in which we can fit a banner that spans two + columns and can be calculated by adding 2 card widths of + var(--extensions-card-width) and the column gap var(--grid-gutter) and + maintain padding of 60px on either side of the content on this page + (see content-wrapper in item-list.html).*/ + @media (max-width: 931px) { + #banner-img { + display: block; + float: initial; + margin: 12px auto 0; + } + } + + @media (prefers-color-scheme: dark) { + #banner-img { + background: url(checkup_image_dark.svg); + } + } + +</style> +<div id="card"> + <div id="banner-title" class="cr-title-text">$i18n{checkupTitle}</div> + <div id="banner-img"></div> + <div id="banner-description"> + <p>$i18n{checkupBody1}</p> + <p>$i18n{checkupBody2}</p> + </div> +</div> diff --git a/chromium/chrome/browser/resources/extensions/checkup.js b/chromium/chrome/browser/resources/extensions/checkup.js new file mode 100644 index 00000000000..cb655c10d73 --- /dev/null +++ b/chromium/chrome/browser/resources/extensions/checkup.js @@ -0,0 +1,15 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_components/managed_footnote/managed_footnote.m.js'; +import './shared_style.js'; + +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +Polymer({ + is: 'extensions-checkup', + + _template: html`{__html_template__}`, + +}); diff --git a/chromium/chrome/browser/resources/extensions/code_section.js b/chromium/chrome/browser/resources/extensions/code_section.js index 9a24dd366bb..65c80bd4e0c 100644 --- a/chromium/chrome/browser/resources/extensions/code_section.js +++ b/chromium/chrome/browser/resources/extensions/code_section.js @@ -86,7 +86,7 @@ Polymer({ /** * @private */ - onCodeChanged_: function() { + onCodeChanged_() { if (!this.code || (!this.code.beforeHighlight && !this.code.highlight && !this.code.afterHighlight)) { @@ -114,7 +114,7 @@ Polymer({ .join('\n'); let visibleAfter = linesAfter.slice(0, visibleLineCountAfter).join('\n'); // If the last character is a \n, force it to be rendered. - if (visibleAfter.charAt(visibleAfter.length - 1) == '\n') { + if (visibleAfter.charAt(visibleAfter.length - 1) === '\n') { visibleAfter += ' '; } @@ -142,7 +142,7 @@ Polymer({ * @private */ getLinesNotShownLabel_(lineCount, stringSingular, stringPluralTemplate) { - return lineCount == 1 ? + return lineCount === 1 ? stringSingular : loadTimeData.substituteString(stringPluralTemplate, lineCount); }, @@ -152,7 +152,7 @@ Polymer({ * @param {number} end * @private */ - setLineNumbers_: function(start, end) { + setLineNumbers_(start, end) { let lineNumbers = ''; for (let i = start; i <= end; ++i) { lineNumbers += i + '\n'; @@ -165,7 +165,7 @@ Polymer({ * @param {number} linesBeforeHighlight * @private */ - scrollToHighlight_: function(linesBeforeHighlight) { + scrollToHighlight_(linesBeforeHighlight) { const CSS_LINE_HEIGHT = 20; // Count how many pixels is above the highlighted code. @@ -183,7 +183,7 @@ Polymer({ * @return {string} * @private */ - getAccessibilityHighlightDescription_: function(lineStart, numLines) { + getAccessibilityHighlightDescription_(lineStart, numLines) { if (numLines > 1) { return this.i18n( 'accessibilityErrorMultiLine', lineStart.toString(), @@ -197,7 +197,7 @@ Polymer({ * @private * @return {boolean} */ - computeShowNoCode_: function() { + computeShowNoCode_() { return this.isActive && !this.highlighted_; }, }); diff --git a/chromium/chrome/browser/resources/extensions/detail_view.html b/chromium/chrome/browser/resources/extensions/detail_view.html index 6f63a2a978f..de97fd2ba01 100644 --- a/chromium/chrome/browser/resources/extensions/detail_view.html +++ b/chromium/chrome/browser/resources/extensions/detail_view.html @@ -40,26 +40,22 @@ flex-grow: 1; } - .section { - @apply --cr-section; - } - - .section.block { + .cr-section.block { box-sizing: border-box; display: block; padding-bottom: var(--cr-section-vertical-padding); padding-top: var(--cr-section-vertical-padding); } - .section.continuation { + .cr-section.continuation { border-top: none; } - .section.control-line { + .cr-section.control-line { justify-content: space-between; } - .section:first-child { + .cr-section:first-child { border: none; } @@ -110,7 +106,6 @@ } extensions-toggle-row { - @apply --cr-section; box-sizing: border-box; padding-inline-end: 0; padding-inline-start: 0; @@ -132,7 +127,8 @@ } paper-spinner-lite { - @apply --cr-icon-height-width; + height: var(--cr-icon-size); + width: var(--cr-icon-size); } </style> <div class="page-container" id="container"> @@ -150,7 +146,7 @@ [[data.name]] </span> </div> - <div class="section continuation control-line" id="enable-section"> + <div class="cr-section continuation control-line" id="enable-section"> <span class$="[[computeEnabledStyle_(data.state)]]"> [[computeEnabledText_(data.state, '$i18nPolymer{itemOn}', '$i18nPolymer{itemOff}')]] @@ -161,42 +157,42 @@ icon-class="[[getIndicatorIcon_(data.controlledInfo.type)]]" icon-aria-label="[[data.controlledInfo.type]]"> </cr-tooltip-icon> - <template is="dom-if" if="[[isTerminated_(data.state)]]"> + <template is="dom-if" if="[[showReloadButton_(data.state)]]"> <cr-button id="terminated-reload-button" class="action-button" on-click="onReloadTap_"> $i18n{itemReload} </cr-button> </template> - <cr-toggle id="enable-toggle" + <cr-toggle id="enableToggle" aria-label$="[[appOrExtension( data.type, '$i18nPolymer{appEnabled}', '$i18nPolymer{extensionEnabled}')]]" aria-describedby="name" checked="[[isEnabled_(data.state)]]" - on-change="onEnableChange_" - disabled="[[!isEnableToggleEnabled_(data.*)]]" - hidden$="[[isTerminated_(data.state)]]"> + on-change="onEnableToggleChange_" + disabled$="[[!isEnableToggleEnabled_(data.*)]]" + hidden$="[[!showEnableToggle_(data.*)]]"> </cr-toggle> </div> </div> <div id="warnings" hidden$="[[!hasWarnings_(data.*)]]"> <div id="runtime-warnings" hidden$="[[!data.runtimeWarnings.length]]" - class="section continuation warning control-line"> + class="cr-section continuation warning control-line"> <iron-icon class="warning-icon" icon="cr:error"></iron-icon> <span> <template is="dom-repeat" items="[[data.runtimeWarnings]]"> [[item]] </template> </span> - <template is="dom-if" if="[[!isTerminated_(data.state)]]"> + <template is="dom-if" if="[[!showReloadButton_(data.state)]]"> <cr-button id="warnings-reload-button" class="action-button" on-click="onReloadTap_"> $i18n{itemReload} </cr-button> </template> </div> - <div class="section continuation warning" id="suspicious-warning" + <div class="cr-section continuation warning" id="suspicious-warning" hidden$="[[!data.disableReasons.suspiciousInstall]]"> <iron-icon class="warning-icon" icon="cr:warning"></iron-icon> <span> @@ -206,9 +202,9 @@ </a> </span> </div> - <div class="section continuation warning control-line" + <div class="cr-section continuation warning control-line" id="corrupted-warning" - hidden$="[[!data.disableReasons.corruptInstall]]"> + hidden$="[[!showRepairButton_(data.disableReasons.corruptInstall)]]"> <iron-icon class="warning-icon" icon="cr:warning"></iron-icon> <span>$i18n{itemCorruptInstall}</span> <cr-button id="repair-button" class="action-button" @@ -216,18 +212,18 @@ $i18n{itemRepair} </cr-button> </div> - <div class="section continuation warning" id="blacklisted-warning" + <div class="cr-section continuation warning" id="blacklisted-warning" hidden$="[[!data.blacklistText]]"> <iron-icon class="warning-icon" icon="cr:warning"></iron-icon> <span>[[data.blacklistText]]</span> </div> - <div class="section continuation warning" id="update-required-warning" + <div class="cr-section continuation warning" id="update-required-warning" hidden$="[[!data.disableReasons.updateRequired]]"> <iron-icon class="warning-icon" icon="cr:warning"></iron-icon> <span>$i18n{updateRequiredByPolicy}</span> </div> </div> - <div class="section continuation block"> + <div class="cr-section continuation block"> <div class="section-title" role="heading" aria-level="2"> $i18n{itemDescriptionLabel} </div> @@ -235,13 +231,13 @@ [[getDescription_(data.description, '$i18nPolymer{noDescription}')]] </div> </div> - <div class="section block"> + <div class="cr-section block"> <div class="section-title" role="heading" aria-level="2"> $i18n{itemVersion} </div> <div class="section-content">[[data.version]]</div> </div> - <div class="section block"> + <div class="cr-section block"> <div class="section-title" role="heading" aria-level="2"> $i18n{itemSize} </div> @@ -251,14 +247,14 @@ </paper-spinner-lite> </div> </div> - <div class="section block" id="id-section" hidden$="[[!inDevMode]]"> + <div class="cr-section block" id="id-section" hidden$="[[!inDevMode]]"> <div class="section-title" role="heading" aria-level="2"> $i18n{itemIdHeading} </div> <div class="section-content">[[data.id]]</div> </div> <template is="dom-if" if="[[inDevMode]]"> - <div class="section block" id="inspectable-views"> + <div class="cr-section block" id="inspectable-views"> <div class="section-title" role="heading" aria-level="2"> $i18n{itemInspectViews} </div> @@ -279,7 +275,7 @@ </div> </div> </template> - <div class="section block"> + <div class="cr-section block"> <div class="section-title" role="heading" aria-level="2"> $i18n{itemPermissions} </div> @@ -303,7 +299,7 @@ </ul> </div> </div> - <div class="section block"> + <div class="cr-section block"> <div class="section-title" role="heading" aria-level="2"> $i18n{itemSiteAccess} </div> @@ -332,7 +328,7 @@ </div> <template is="dom-if" if="[[hasDependentExtensions_(data.dependentExtensions.splices)]]"> - <div class="section block"> + <div class="cr-section block"> <div class="section-title" role="heading" aria-level="2"> $i18n{itemDependencies} </div> @@ -352,6 +348,7 @@ data.incognitoAccess.isEnabled, incognitoAvailable)]]"> <extensions-toggle-row id="allow-incognito" checked="[[data.incognitoAccess.isActive]]" + class="hr" on-change="onAllowIncognitoChange_"> <div> <div>$i18n{itemAllowIncognito}</div> @@ -362,6 +359,7 @@ <template is="dom-if" if="[[data.fileAccess.isEnabled]]"> <extensions-toggle-row id="allow-on-file-urls" checked="[[data.fileAccess.isActive]]" + class="hr" on-change="onAllowOnFileUrlsChange_"> <span>$i18n{itemAllowOnFileUrls}</span> </extensions-toggle-row> @@ -369,6 +367,7 @@ <template is="dom-if" if="[[data.errorCollection.isEnabled]]"> <extensions-toggle-row id="collect-errors" checked="[[data.errorCollection.isActive]]" + class="hr" on-change="onCollectErrorsChange_"> <span>$i18n{itemCollectErrors}</span> </extensions-toggle-row> @@ -390,7 +389,7 @@ <cr-link-row class="hr" hidden="[[!data.webStoreUrl.length]]" id="viewInStore" label="$i18n{viewInStore}" on-click="onViewInStoreTap_" external></cr-link-row> - <div class="section block"> + <div class="cr-section block"> <div class="section-title" role="heading" aria-level="2"> $i18n{itemSource} </div> diff --git a/chromium/chrome/browser/resources/extensions/detail_view.js b/chromium/chrome/browser/resources/extensions/detail_view.js index 562c6ba0fb4..eb337947210 100644 --- a/chromium/chrome/browser/resources/extensions/detail_view.js +++ b/chromium/chrome/browser/resources/extensions/detail_view.js @@ -31,7 +31,7 @@ import {afterNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/po import {ItemDelegate} from './item.js'; import {ItemBehavior} from './item_behavior.js'; -import {computeInspectableViewLabel, getItemSource, getItemSourceString, isControlled, isEnabled, userCanChangeEnablement} from './item_util.js'; +import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isControlled, isEnabled, userCanChangeEnablement} from './item_util.js'; import {navigation, Page} from './navigation_helper.js'; Polymer({ @@ -82,7 +82,7 @@ Polymer({ * Focuses the extensions options button. This should be used after the * dialog closes. */ - focusOptionsButton: function() { + focusOptionsButton() { this.$$('#extensions-options').focus(); }, @@ -90,7 +90,7 @@ Polymer({ * Focuses the back button when page is loaded. * @private */ - onViewEnterStart_: function() { + onViewEnterStart_() { const elementToFocus = this.fromActivityLog ? this.$.extensionsActivityLogLink : this.$.closeButton; @@ -99,7 +99,7 @@ Polymer({ }, /** @private */ - onItemIdChanged_: function() { + onItemIdChanged_() { // Clear the size, since this view is reused, such that no obsolete size // is displayed.: this.size_ = ''; @@ -109,7 +109,7 @@ Polymer({ }, /** @private */ - onActivityLogTap_: function() { + onActivityLogTap_() { navigation.navigateTo({page: Page.ACTIVITY_LOG, extensionId: this.data.id}); }, @@ -119,12 +119,12 @@ Polymer({ * @return {string} * @private */ - getDescription_: function(description, fallback) { + getDescription_(description, fallback) { return description || fallback; }, /** @private */ - onCloseButtonTap_: function() { + onCloseButtonTap_() { navigation.navigateTo({page: Page.LIST}); }, @@ -132,7 +132,7 @@ Polymer({ * @return {boolean} * @private */ - isControlled_: function() { + isControlled_() { return isControlled(this.data); }, @@ -140,7 +140,7 @@ Polymer({ * @return {boolean} * @private */ - isEnabled_: function() { + isEnabled_() { return isEnabled(this.data.state); }, @@ -148,24 +148,15 @@ Polymer({ * @return {boolean} * @private */ - isEnableToggleEnabled_: function() { + isEnableToggleEnabled_() { return userCanChangeEnablement(this.data); }, /** - * Returns true if the extension is in the terminated state. * @return {boolean} * @private */ - isTerminated_: function() { - return this.data.state == chrome.developerPrivate.ExtensionState.TERMINATED; - }, - - /** - * @return {boolean} - * @private - */ - hasDependentExtensions_: function() { + hasDependentExtensions_() { return this.data.dependentExtensions.length > 0; }, @@ -173,7 +164,7 @@ Polymer({ * @return {boolean} * @private */ - hasWarnings_: function() { + hasWarnings_() { return this.data.disableReasons.corruptInstall || this.data.disableReasons.suspiciousInstall || this.data.disableReasons.updateRequired || !!this.data.blacklistText || @@ -184,7 +175,7 @@ Polymer({ * @return {string} * @private */ - computeEnabledStyle_: function() { + computeEnabledStyle_() { return this.isEnabled_() ? 'enabled-text' : ''; }, @@ -195,7 +186,7 @@ Polymer({ * @return {string} * @private */ - computeEnabledText_: function(state, onText, offText) { + computeEnabledText_(state, onText, offText) { // TODO(devlin): Get the full spectrum of these strings from bettes. return isEnabled(state) ? onText : offText; }, @@ -205,7 +196,7 @@ Polymer({ * @return {string} * @private */ - computeInspectLabel_: function(view) { + computeInspectLabel_(view) { return computeInspectableViewLabel(view); }, @@ -213,7 +204,7 @@ Polymer({ * @return {boolean} * @private */ - shouldShowOptionsLink_: function() { + shouldShowOptionsLink_() { return !!this.data.optionsPage; }, @@ -221,7 +212,7 @@ Polymer({ * @return {boolean} * @private */ - shouldShowOptionsSection_: function() { + shouldShowOptionsSection_() { return this.data.incognitoAccess.isEnabled || this.data.fileAccess.isEnabled || this.data.errorCollection.isEnabled; }, @@ -230,75 +221,76 @@ Polymer({ * @return {boolean} * @private */ - shouldShowIncognitoOption_: function() { + shouldShowIncognitoOption_() { return this.data.incognitoAccess.isEnabled && this.incognitoAvailable; }, /** @private */ - onEnableChange_: function() { - this.delegate.setItemEnabled(this.data.id, this.$['enable-toggle'].checked); + onEnableToggleChange_() { + this.delegate.setItemEnabled(this.data.id, this.$.enableToggle.checked); + this.$.enableToggle.checked = this.isEnabled_(); }, /** * @param {!{model: !{item: !chrome.developerPrivate.ExtensionView}}} e * @private */ - onInspectTap_: function(e) { + onInspectTap_(e) { this.delegate.inspectItemView(this.data.id, e.model.item); }, /** @private */ - onExtensionOptionsTap_: function() { + onExtensionOptionsTap_() { this.delegate.showItemOptionsPage(this.data); }, /** @private */ - onReloadTap_: function() { + onReloadTap_() { this.delegate.reloadItem(this.data.id).catch(loadError => { this.fire('load-error', loadError); }); }, /** @private */ - onRemoveTap_: function() { + onRemoveTap_() { this.delegate.deleteItem(this.data.id); }, /** @private */ - onRepairTap_: function() { + onRepairTap_() { this.delegate.repairItem(this.data.id); }, /** @private */ - onLoadPathTap_: function() { + onLoadPathTap_() { this.delegate.showInFolder(this.data.id); }, /** @private */ - onAllowIncognitoChange_: function() { + onAllowIncognitoChange_() { this.delegate.setItemAllowedIncognito( this.data.id, this.$$('#allow-incognito').checked); }, /** @private */ - onAllowOnFileUrlsChange_: function() { + onAllowOnFileUrlsChange_() { this.delegate.setItemAllowedOnFileUrls( this.data.id, this.$$('#allow-on-file-urls').checked); }, /** @private */ - onCollectErrorsChange_: function() { + onCollectErrorsChange_() { this.delegate.setItemCollectsErrors( this.data.id, this.$$('#collect-errors').checked); }, /** @private */ - onExtensionWebSiteTap_: function() { + onExtensionWebSiteTap_() { this.delegate.openUrl(this.data.manifestHomePageUrl); }, /** @private */ - onViewInStoreTap_: function() { + onViewInStoreTap_() { this.delegate.openUrl(this.data.webStoreUrl); }, @@ -307,7 +299,7 @@ Polymer({ * @return {string} * @private */ - computeDependentEntry_: function(item) { + computeDependentEntry_(item) { return loadTimeData.getStringF('itemDependentEntry', item.name, item.id); }, @@ -315,7 +307,7 @@ Polymer({ * @return {string} * @private */ - computeSourceString_: function() { + computeSourceString_() { return this.data.locationText || getItemSourceString(getItemSource(this.data)); }, @@ -325,7 +317,7 @@ Polymer({ * @return {string} * @private */ - getIndicatorIcon_: function(type) { + getIndicatorIcon_(type) { switch (type) { case 'POLICY': return 'cr20:domain'; @@ -340,7 +332,7 @@ Polymer({ * @return {boolean} * @private */ - hasPermissions_: function() { + hasPermissions_() { return this.data.permissions.simplePermissions.length > 0 || this.hasRuntimeHostPermissions_(); }, @@ -349,7 +341,7 @@ Polymer({ * @return {boolean} * @private */ - hasRuntimeHostPermissions_: function() { + hasRuntimeHostPermissions_() { return !!this.data.permissions.runtimeHostPermissions; }, @@ -357,7 +349,7 @@ Polymer({ * @return {boolean} * @private */ - showSiteAccessContent_: function() { + showSiteAccessContent_() { return this.showFreeformRuntimeHostPermissions_() || this.showHostPermissionsToggleList_(); }, @@ -366,7 +358,7 @@ Polymer({ * @return {boolean} * @private */ - showFreeformRuntimeHostPermissions_: function() { + showFreeformRuntimeHostPermissions_() { return this.hasRuntimeHostPermissions_() && this.data.permissions.runtimeHostPermissions.hasAllHosts; }, @@ -375,8 +367,39 @@ Polymer({ * @return {boolean} * @private */ - showHostPermissionsToggleList_: function() { + showHostPermissionsToggleList_() { return this.hasRuntimeHostPermissions_() && !this.data.permissions.runtimeHostPermissions.hasAllHosts; }, + + /** + * Returns true if the reload button should be shown. + * @return {boolean} + * @private + */ + showReloadButton_() { + return getEnableControl(this.data) === EnableControl.RELOAD; + }, + + /** + * Returns true if the repair button should be shown. + * @return {boolean} + * @private + */ + showRepairButton_() { + return getEnableControl(this.data) === EnableControl.REPAIR; + }, + + /** + * Returns true if the enable toggle should be shown. + * @return {boolean} + * @private + */ + showEnableToggle_() { + const enableControl = getEnableControl(this.data); + // We still show the toggle even if we also show the repair button in the + // detail view, because the repair button appears just beneath it. + return enableControl === EnableControl.ENABLE_TOGGLE || + enableControl === EnableControl.REPAIR; + }, }); diff --git a/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js b/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js index a6bfab31897..43a5771b715 100644 --- a/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js +++ b/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js @@ -54,7 +54,7 @@ export class DragAndDropHandler { /** @override */ doDrop(e) { this.fireDragEnded_(); - if (e.dataTransfer.files.length != 1) { + if (e.dataTransfer.files.length !== 1) { return; } diff --git a/chromium/chrome/browser/resources/extensions/drop_overlay.js b/chromium/chrome/browser/resources/extensions/drop_overlay.js index 2a627f85c7a..508280eeca4 100644 --- a/chromium/chrome/browser/resources/extensions/drop_overlay.js +++ b/chromium/chrome/browser/resources/extensions/drop_overlay.js @@ -26,7 +26,7 @@ Polymer({ }, /** @override */ - created: function() { + created() { this.hidden = true; const dragTarget = document.documentElement; this.dragWrapperHandler_ = new DragAndDropHandler(true, dragTarget); @@ -49,7 +49,7 @@ Polymer({ * @param {boolean} dragEnabled * @private */ - dragEnabledChanged_: function(dragEnabled) { + dragEnabledChanged_(dragEnabled) { this.dragWrapperHandler_.dragEnabled = dragEnabled; }, }); diff --git a/chromium/chrome/browser/resources/extensions/error_page.html b/chromium/chrome/browser/resources/extensions/error_page.html index 5f67a455dd8..e5cb53d1172 100644 --- a/chromium/chrome/browser/resources/extensions/error_page.html +++ b/chromium/chrome/browser/resources/extensions/error_page.html @@ -6,8 +6,9 @@ iron-icon { --iron-icon-fill-color: var(--google-grey-refresh-700); - @apply --cr-icon-height-width; flex-shrink: 0; + height: var(--cr-icon-size); + width: var(--cr-icon-size); } iron-icon[icon='cr:warning'] { diff --git a/chromium/chrome/browser/resources/extensions/error_page.js b/chromium/chrome/browser/resources/extensions/error_page.js index 1da980e9a85..e922344ae93 100644 --- a/chromium/chrome/browser/resources/extensions/error_page.js +++ b/chromium/chrome/browser/resources/extensions/error_page.js @@ -67,7 +67,7 @@ function getRelativeUrl(url, error) { * @private */ function getErrorSeverityText_(item, log, warn, error) { - if (item.type == chrome.developerPrivate.ErrorType.RUNTIME) { + if (item.type === chrome.developerPrivate.ErrorType.RUNTIME) { switch (item.severity) { case chrome.developerPrivate.ErrorLevel.LOG: return log; @@ -78,7 +78,7 @@ function getErrorSeverityText_(item, log, warn, error) { } assertNotReached(); } - assert(item.type == chrome.developerPrivate.ErrorType.MANIFEST); + assert(item.type === chrome.developerPrivate.ErrorType.MANIFEST); return warn; } @@ -121,7 +121,7 @@ Polymer({ /** @private {?chrome.developerPrivate.StackFrame}*/ selectedStackFrame_: { type: Object, - value: function() { + value() { return null; }, }, @@ -136,12 +136,12 @@ Polymer({ }, /** @override */ - ready: function() { + ready() { FocusOutlineManager.forDocument(document); }, /** @return {!ManifestError|!RuntimeError} */ - getSelectedError: function() { + getSelectedError() { return this.entries_[this.selectedEntry_]; }, @@ -149,7 +149,7 @@ Polymer({ * Focuses the back button when page is loaded. * @private */ - onViewEnterStart_: function() { + onViewEnterStart_() { afterNextRender(this, () => focusWithoutInk(this.$.closeButton)); chrome.metricsPrivate.recordUserAction('Options_ViewExtensionErrors'); }, @@ -160,7 +160,7 @@ Polymer({ * @return {string} * @private */ - getContextUrl_: function(error, unknown) { + getContextUrl_(error, unknown) { return error.contextUrl ? getRelativeUrl(error.contextUrl, error) : unknown; }, @@ -169,7 +169,7 @@ Polymer({ * file source. * @private */ - observeDataChanges_: function() { + observeDataChanges_() { const errors = this.data.manifestErrors.concat(this.data.runtimeErrors); this.entries_ = errors; this.selectedEntry_ = -1; // This also help reset code-section content. @@ -179,12 +179,12 @@ Polymer({ }, /** @private */ - onCloseButtonTap_: function() { + onCloseButtonTap_() { navigation.navigateTo({page: Page.LIST}); }, /** @private */ - onClearAllTap_: function() { + onClearAllTap_() { const ids = this.entries_.map(entry => entry.id); this.delegate.deleteErrors(this.data.id, ids); }, @@ -194,7 +194,7 @@ Polymer({ * @return {string} * @private */ - computeErrorIcon_: function(error) { + computeErrorIcon_(error) { // Do not i18n these strings, they're CSS classes. return getErrorSeverityText_(error, 'info', 'warning', 'error'); }, @@ -204,7 +204,7 @@ Polymer({ * @return {string} * @private */ - computeErrorTypeLabel_: function(error) { + computeErrorTypeLabel_(error) { return getErrorSeverityText_( error, loadTimeData.getString('logLevel'), loadTimeData.getString('warnLevel'), @@ -215,14 +215,14 @@ Polymer({ * @param {!Event} e * @private */ - onDeleteErrorAction_: function(e) { + onDeleteErrorAction_(e) { this.delegate.deleteErrors( this.data.id, [(/** @type {!{model:Object}} */ (e)).model.item.id]); e.stopPropagation(); }, /** private */ - onInDevModeChanged_: function() { + onInDevModeChanged_() { if (!this.inDevMode) { // Wait until next render cycle in case error page is loading. this.async(() => { @@ -235,7 +235,7 @@ Polymer({ * Fetches the source for the selected error and populates the code section. * @private */ - onSelectedErrorChanged_: function() { + onSelectedErrorChanged_() { this.code_ = null; if (this.selectedEntry_ < 0) { @@ -271,8 +271,8 @@ Polymer({ * @return {boolean} * @private */ - computeIsRuntimeError_: function(item) { - return item.type == chrome.developerPrivate.ErrorType.RUNTIME; + computeIsRuntimeError_(item) { + return item.type === chrome.developerPrivate.ErrorType.RUNTIME; }, /** @@ -283,12 +283,12 @@ Polymer({ * @return {string} * @private */ - getStackTraceLabel_: function(frame) { + getStackTraceLabel_(frame) { let description = getRelativeUrl(frame.url, this.getSelectedError()) + ':' + frame.lineNumber; if (frame.functionName) { - const functionName = frame.functionName == '(anonymous function)' ? + const functionName = frame.functionName === '(anonymous function)' ? loadTimeData.getString('anonymousFunction') : frame.functionName; description += ' (' + functionName + ')'; @@ -302,8 +302,8 @@ Polymer({ * @return {string} * @private */ - getStackFrameClass_: function(frame) { - return frame == this.selectedStackFrame_ ? 'selected' : ''; + getStackFrameClass_(frame) { + return frame === this.selectedStackFrame_ ? 'selected' : ''; }, /** @@ -311,8 +311,8 @@ Polymer({ * @return {number} * @private */ - getStackFrameTabIndex_: function(frame) { - return frame == this.selectedStackFrame_ ? 0 : -1; + getStackFrameTabIndex_(frame) { + return frame === this.selectedStackFrame_ ? 0 : -1; }, /** @@ -322,7 +322,7 @@ Polymer({ * @return {boolean} * @private */ - shouldDisplayFrame_: function(url) { + shouldDisplayFrame_(url) { // All our internal scripts are in the 'extensions::' namespace. return !/^extensions::/.test(url); }, @@ -331,7 +331,7 @@ Polymer({ * @param {!chrome.developerPrivate.StackFrame} frame * @private */ - updateSelected_: function(frame) { + updateSelected_(frame) { this.selectedStackFrame_ = assert(frame); const selectedError = this.getSelectedError(); @@ -349,7 +349,7 @@ Polymer({ * @param {!Event} e * @private */ - onStackFrameTap_: function(e) { + onStackFrameTap_(e) { const frame = /** @type {!{model:Object}} */ (e).model.item; this.updateSelected_(frame); }, @@ -358,12 +358,12 @@ Polymer({ * @param {!Event} e * @private */ - onStackKeydown_: function(e) { + onStackKeydown_(e) { let direction = 0; - if (e.key == 'ArrowDown') { + if (e.key === 'ArrowDown') { direction = 1; - } else if (e.key == 'ArrowUp') { + } else if (e.key === 'ArrowUp') { direction = -1; } else { return; @@ -393,14 +393,14 @@ Polymer({ * @return {string} * @private */ - computeErrorClass_: function(index) { - return index == this.selectedEntry_ ? 'selected' : ''; + computeErrorClass_(index) { + return index === this.selectedEntry_ ? 'selected' : ''; }, /** @private */ - iconName_: function(index) { - return index == this.selectedEntry_ ? 'icon-expand-less' : - 'icon-expand-more'; + iconName_(index) { + return index === this.selectedEntry_ ? 'icon-expand-less' : + 'icon-expand-more'; }, /** @@ -409,8 +409,8 @@ Polymer({ * @return {boolean} * @private */ - isOpened_: function(index) { - return index == this.selectedEntry_; + isOpened_(index) { + return index === this.selectedEntry_; }, @@ -419,7 +419,7 @@ Polymer({ * @return {string} The aria-expanded value as a string. * @private */ - isAriaExpanded_: function(index) { + isAriaExpanded_(index) { return this.isOpened_(index).toString(); }, @@ -427,8 +427,8 @@ Polymer({ * @param {!{type: string, code: string, model: !{index: number}}} e * @private */ - onErrorItemAction_: function(e) { - if (e.type == 'keydown' && !((e.code == 'Space' || e.code == 'Enter'))) { + onErrorItemAction_(e) { + if (e.type === 'keydown' && !((e.code === 'Space' || e.code === 'Enter'))) { return; } @@ -436,6 +436,6 @@ Polymer({ // is pressed. e.preventDefault(); this.selectedEntry_ = - this.selectedEntry_ == e.model.index ? -1 : e.model.index; + this.selectedEntry_ === e.model.index ? -1 : e.model.index; }, }); diff --git a/chromium/chrome/browser/resources/extensions/extensions_resources.grd b/chromium/chrome/browser/resources/extensions/extensions_resources.grd index a98ad371e92..81d265b85a7 100644 --- a/chromium/chrome/browser/resources/extensions/extensions_resources.grd +++ b/chromium/chrome/browser/resources/extensions/extensions_resources.grd @@ -30,6 +30,9 @@ <include name="IDR_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_STREAM_ITEM_JS" file="${root_gen_dir}/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js" use_base_dir="false" type ="BINDATA" /> + <include name="IDR_EXTENSIONS_CHECKUP_JS" + file="${root_gen_dir}/chrome/browser/resources/extensions/checkup.js" + use_base_dir="false" type ="BINDATA" /> <include name="IDR_EXTENSIONS_DETAIL_VIEW_JS" file="${root_gen_dir}/chrome/browser/resources/extensions/detail_view.js" use_base_dir="false" type ="BINDATA" /> @@ -38,7 +41,7 @@ use_base_dir="false" type ="BINDATA" /> <include name="IDR_EXTENSIONS_ERROR_PAGE_JS" file="${root_gen_dir}/chrome/browser/resources/extensions/error_page.js" - use_base_dir="false" type ="BINDATA" flattenhtml="true" /> + use_base_dir="false" type ="BINDATA" /> <include name="IDR_EXTENSIONS_KEYBOARD_SHORTCUTS_JS" file="${root_gen_dir}/chrome/browser/resources/extensions/keyboard_shortcuts.js" use_base_dir="false" type ="BINDATA" /> @@ -49,7 +52,7 @@ </if> <include name="IDR_EXTENSIONS_MANAGER_JS" file="${root_gen_dir}/chrome/browser/resources/extensions/manager.js" - use_base_dir="false" type ="BINDATA" flattenhtml="true" /> + preprocess="true" use_base_dir="false" type ="BINDATA" /> <include name="IDR_EXTENSIONS_ICONS_JS" file="${root_gen_dir}/chrome/browser/resources/extensions/icons.js" use_base_dir="false" type ="BINDATA" /> @@ -100,12 +103,11 @@ use_base_dir="false" type ="BINDATA" /> <include name="IDR_EXTENSIONS_TOOLBAR_JS" file="${root_gen_dir}/chrome/browser/resources/extensions/toolbar.js" - use_base_dir="false" type ="BINDATA" flattenhtml="true" /> - <include name="IDR_WEBUI_IMAGES_CHECKUP_IMAGE" - file="checkup_image.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_CHECKUP_IMAGE_DARKMODE" - file="checkup_image_dark.svg" type="BINDATA" - compress="gzip" /> + preprocess="true" use_base_dir="false" type ="BINDATA" /> + <include name="IDR_EXTENSIONS_CHECKUP_IMAGE" + file="checkup_image.svg" type="BINDATA" /> + <include name="IDR_EXTENSIONS_CHECKUP_IMAGE_DARK" + file="checkup_image_dark.svg" type="BINDATA" /> </includes> <structures> <structure name="IDR_EXTENSIONS_ITEM_BEHAVIOR_JS" diff --git a/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd b/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd index d8aec253a44..3ebe27cf553 100644 --- a/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd +++ b/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd @@ -22,6 +22,14 @@ preprocess="true" type="BINDATA" compress="gzip" /> + <include name="IDR_EXTENSIONS_CHECKUP_IMAGE" + file="checkup_image.svg" + type="BINDATA" + compress="gzip" /> + <include name="IDR_EXTENSIONS_CHECKUP_IMAGE_DARK" + file="checkup_image_dark.svg" + type="BINDATA" + compress="gzip" /> </includes> </release> </grit> diff --git a/chromium/chrome/browser/resources/extensions/host_permissions_toggle_list.js b/chromium/chrome/browser/resources/extensions/host_permissions_toggle_list.js index b8a3e492161..9328014b32f 100644 --- a/chromium/chrome/browser/resources/extensions/host_permissions_toggle_list.js +++ b/chromium/chrome/browser/resources/extensions/host_permissions_toggle_list.js @@ -38,8 +38,8 @@ Polymer({ * requested sites. * @private */ - allowedOnAllHosts_: function() { - return this.permissions.hostAccess == + allowedOnAllHosts_() { + return this.permissions.hostAccess === chrome.developerPrivate.HostAccess.ON_ALL_SITES; }, @@ -49,7 +49,7 @@ Polymer({ * @return {!Array<!chrome.developerPrivate.SiteControl>} * @private */ - getSortedHosts_: function() { + getSortedHosts_() { return this.permissions.hosts.sort((a, b) => { if (a.host < b.host) { return -1; @@ -62,7 +62,7 @@ Polymer({ }, /** @private */ - onAllHostsToggleChanged_: function() { + onAllHostsToggleChanged_() { // TODO(devlin): In the case of going from all sites to specific sites, // we'll withhold all sites (i.e., all specific site toggles will move to // unchecked, and the user can check them individually). This is slightly @@ -78,7 +78,7 @@ Polymer({ }, /** @private */ - onHostAccessChanged_: function(e) { + onHostAccessChanged_(e) { const host = e.target.host; const checked = e.target.checked; diff --git a/chromium/chrome/browser/resources/extensions/install_warnings_dialog.js b/chromium/chrome/browser/resources/extensions/install_warnings_dialog.js index b333dca3db5..e599dcfa69c 100644 --- a/chromium/chrome/browser/resources/extensions/install_warnings_dialog.js +++ b/chromium/chrome/browser/resources/extensions/install_warnings_dialog.js @@ -21,12 +21,12 @@ Polymer({ }, /** @override */ - attached: function() { + attached() { this.$.dialog.showModal(); }, /** @private */ - onOkTap_: function() { + onOkTap_() { this.$.dialog.close(); }, }); diff --git a/chromium/chrome/browser/resources/extensions/item.html b/chromium/chrome/browser/resources/extensions/item.html index b70ec925b38..c39e28b1c1c 100644 --- a/chromium/chrome/browser/resources/extensions/item.html +++ b/chromium/chrome/browser/resources/extensions/item.html @@ -34,12 +34,12 @@ } #card { - @apply --cr-card-elevation; background-color: var(--cr-card-background-color); border-radius: var(--cr-card-border-radius); + box-shadow: var(--cr-card-shadow); display: flex; flex-direction: column; - height: 160px; + height: var(--extensions-card-height); /* Duration matches --drawer-transition from toolbar.html. */ transition: height 300ms cubic-bezier(.25, .1, .25, 1); } @@ -132,7 +132,7 @@ .source-icon-wrapper { align-items: center; background: rgb(241, 89, 43); /* Same in light & dark modes. */ - border-radius: 50%; /* 50% border radius == a circle */ + border-radius: 50%; /* 50% border radius === a circle */ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.22), 0 2px 2px 0 rgba(0, 0, 0, 0.12); display: flex; @@ -299,26 +299,28 @@ aria-label="$i18n{itemReload}" aria-describedby="a11yAssociation" on-click="onReloadTap_"></cr-icon-button> </template> - <template is="dom-if" if="[[data.disableReasons.corruptInstall]]"> + <template is="dom-if" + if="[[showRepairButton_(data.disableReasons.corruptInstall)]]"> <cr-button id="repair-button" class="action-button" aria-describedby="a11yAssociation" on-click="onRepairTap_"> $i18n{itemRepair} </cr-button> </template> - <template is="dom-if" if="[[isTerminated_(data.state)]]"> + <template is="dom-if" if="[[showReloadButton_(data.state)]]"> <cr-button id="terminated-reload-button" on-click="onReloadTap_" aria-describedby="a11yAssociation" class="action-button"> $i18n{itemReload} </cr-button> </template> - <cr-toggle id="enable-toggle" + <cr-toggle id="enableToggle" aria-label$="[[appOrExtension( data.type, '$i18nPolymer{appEnabled}', '$i18nPolymer{extensionEnabled}')]]" aria-describedby="a11yAssociation" - checked="[[isEnabled_(data.state)]]" on-change="onEnableChange_" - disabled="[[!isEnableToggleEnabled_(data.*)]]" + checked="[[isEnabled_(data.state)]]" + on-change="onEnableToggleChange_" + disabled$="[[!isEnableToggleEnabled_(data.*)]]" hidden$="[[!showEnableToggle_(data.*)]]"> </cr-toggle> </div> diff --git a/chromium/chrome/browser/resources/extensions/item.js b/chromium/chrome/browser/resources/extensions/item.js index 7973811c58e..e82aecbfbe4 100644 --- a/chromium/chrome/browser/resources/extensions/item.js +++ b/chromium/chrome/browser/resources/extensions/item.js @@ -26,7 +26,7 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {flush, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {ItemBehavior} from './item_behavior.js'; -import {computeInspectableViewLabel, getItemSource, getItemSourceString, isControlled, isEnabled, SourceType, userCanChangeEnablement} from './item_util.js'; +import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isControlled, isEnabled, SourceType, userCanChangeEnablement} from './item_util.js'; import {navigation, Page} from './navigation_helper.js'; /** @interface */ @@ -153,17 +153,17 @@ Polymer({ ], /** @return {!HTMLElement} The "Details" button. */ - getDetailsButton: function() { + getDetailsButton() { return /** @type {!HTMLElement} */ (this.$.detailsButton); }, /** @return {?HTMLElement} The "Errors" button, if it exists. */ - getErrorsButton: function() { + getErrorsButton() { return /** @type {?HTMLElement} */ (this.$$('#errors-button')); }, /** @private string */ - a11yAssociation_: function() { + a11yAssociation_() { // Don't use I18nBehavior.i18n because of additional checks it performs. // Polymer ensures that this string is not stamped into arbitrary HTML. // |this.data.name| can contain any data including html tags. @@ -172,7 +172,7 @@ Polymer({ }, /** @private */ - observeIdVisibility_: function(inDevMode, showingDetails, id) { + observeIdVisibility_(inDevMode, showingDetails, id) { flush(); const idElement = this.$$('#extension-id'); if (idElement) { @@ -185,7 +185,7 @@ Polymer({ * @return {boolean} * @private */ - shouldShowErrorsButton_: function() { + shouldShowErrorsButton_() { // When the error console is disabled (happens when // --disable-error-console command line flag is used or when in the // Stable/Beta channel), |installWarnings| is populated. @@ -200,17 +200,18 @@ Polymer({ }, /** @private */ - onRemoveTap_: function() { + onRemoveTap_() { this.delegate.deleteItem(this.data.id); }, /** @private */ - onEnableChange_: function() { - this.delegate.setItemEnabled(this.data.id, this.$['enable-toggle'].checked); + onEnableToggleChange_() { + this.delegate.setItemEnabled(this.data.id, this.$.enableToggle.checked); + this.$.enableToggle.checked = this.isEnabled_(); }, /** @private */ - onErrorsTap_: function() { + onErrorsTap_() { if (this.data.installWarnings && this.data.installWarnings.length > 0) { this.fire('show-install-warnings', this.data.installWarnings); return; @@ -220,7 +221,7 @@ Polymer({ }, /** @private */ - onDetailsTap_: function() { + onDetailsTap_() { navigation.navigateTo({page: Page.DETAILS, extensionId: this.data.id}); }, @@ -228,17 +229,17 @@ Polymer({ * @param {!{model: !{item: !chrome.developerPrivate.ExtensionView}}} e * @private */ - onInspectTap_: function(e) { + onInspectTap_(e) { this.delegate.inspectItemView(this.data.id, this.data.views[0]); }, /** @private */ - onExtraInspectTap_: function() { + onExtraInspectTap_() { navigation.navigateTo({page: Page.DETAILS, extensionId: this.data.id}); }, /** @private */ - onReloadTap_: function() { + onReloadTap_() { // Don't reload if in the middle of an update. if (this.isReloading_) { return; @@ -266,7 +267,7 @@ Polymer({ }, /** @private */ - onRepairTap_: function() { + onRepairTap_() { this.delegate.repairItem(this.data.id); }, @@ -274,7 +275,7 @@ Polymer({ * @return {boolean} * @private */ - isControlled_: function() { + isControlled_() { return isControlled(this.data); }, @@ -282,7 +283,7 @@ Polymer({ * @return {boolean} * @private */ - isEnabled_: function() { + isEnabled_() { return isEnabled(this.data.state); }, @@ -290,33 +291,43 @@ Polymer({ * @return {boolean} * @private */ - isEnableToggleEnabled_: function() { + isEnableToggleEnabled_() { return userCanChangeEnablement(this.data); }, /** - * Returns true if the enable toggle should be shown. + * Returns true if the reload button should be shown. * @return {boolean} * @private */ - showEnableToggle_: function() { - return !this.isTerminated_() && !this.data.disableReasons.corruptInstall; + showReloadButton_() { + return getEnableControl(this.data) === EnableControl.RELOAD; }, /** - * Returns true if the extension is in the terminated state. + * Returns true if the repair button should be shown. + * @return {boolean} + * @private + */ + showRepairButton_() { + return getEnableControl(this.data) === EnableControl.REPAIR; + }, + + + /** + * Returns true if the enable toggle should be shown. * @return {boolean} * @private */ - isTerminated_: function() { - return this.data.state == chrome.developerPrivate.ExtensionState.TERMINATED; + showEnableToggle_() { + return getEnableControl(this.data) === EnableControl.ENABLE_TOGGLE; }, /** * return {string} * @private */ - computeClasses_: function() { + computeClasses_() { let classes = this.isEnabled_() ? 'enabled' : 'disabled'; if (this.inDevMode) { classes += ' dev-mode'; @@ -328,7 +339,7 @@ Polymer({ * @return {string} * @private */ - computeSourceIndicatorIcon_: function() { + computeSourceIndicatorIcon_() { switch (getItemSource(this.data)) { case SourceType.POLICY: return 'extensions-icons:business'; @@ -349,29 +360,29 @@ Polymer({ * @return {string} * @private */ - computeSourceIndicatorText_: function() { + computeSourceIndicatorText_() { if (this.data.locationText) { return this.data.locationText; } const sourceType = getItemSource(this.data); - return sourceType == SourceType.WEBSTORE ? '' : - getItemSourceString(sourceType); + return sourceType === SourceType.WEBSTORE ? '' : + getItemSourceString(sourceType); }, /** * @return {boolean} * @private */ - computeInspectViewsHidden_: function() { - return !this.data.views || this.data.views.length == 0; + computeInspectViewsHidden_() { + return !this.data.views || this.data.views.length === 0; }, /** * @return {string} * @private */ - computeFirstInspectTitle_: function() { + computeFirstInspectTitle_() { // Note: theoretically, this wouldn't be called without any inspectable // views (because it's in a dom-if="!computeInspectViewsHidden_()"). // However, due to the recycling behavior of iron list, it seems that @@ -386,7 +397,7 @@ Polymer({ * @return {string} * @private */ - computeFirstInspectLabel_: function() { + computeFirstInspectLabel_() { const label = this.computeFirstInspectTitle_(); return label && this.data.views.length > 1 ? label + ',' : label; }, @@ -395,7 +406,7 @@ Polymer({ * @return {boolean} * @private */ - computeExtraViewsHidden_: function() { + computeExtraViewsHidden_() { return this.data.views.length <= 1; }, @@ -403,13 +414,13 @@ Polymer({ * @return {boolean} * @private */ - computeDevReloadButtonHidden_: function() { + computeDevReloadButtonHidden_() { // Only display the reload spinner if the extension is unpacked and // enabled. There's no point in reloading a disabled extension, and we'll // show a crashed reload button if it's terminated. const showIcon = - this.data.location == chrome.developerPrivate.Location.UNPACKED && - this.data.state == chrome.developerPrivate.ExtensionState.ENABLED; + this.data.location === chrome.developerPrivate.Location.UNPACKED && + this.data.state === chrome.developerPrivate.ExtensionState.ENABLED; return !showIcon; }, @@ -417,7 +428,7 @@ Polymer({ * @return {string} * @private */ - computeExtraInspectLabel_: function() { + computeExtraInspectLabel_() { return this.i18n( 'itemInspectViewsExtra', (this.data.views.length - 1).toString()); }, @@ -426,7 +437,7 @@ Polymer({ * @return {boolean} * @private */ - hasWarnings_: function() { + hasWarnings_() { return this.data.disableReasons.corruptInstall || this.data.disableReasons.suspiciousInstall || this.data.runtimeWarnings.length > 0 || !!this.data.blacklistText; @@ -436,7 +447,7 @@ Polymer({ * @return {string} * @private */ - computeWarningsClasses_: function() { + computeWarningsClasses_() { return this.data.blacklistText ? 'severe' : 'mild'; }, }); diff --git a/chromium/chrome/browser/resources/extensions/item_behavior.js b/chromium/chrome/browser/resources/extensions/item_behavior.js index c1e368a4368..984ab93ce0f 100644 --- a/chromium/chrome/browser/resources/extensions/item_behavior.js +++ b/chromium/chrome/browser/resources/extensions/item_behavior.js @@ -12,7 +12,7 @@ export const ItemBehavior = { * @param {string} extensionLabel * @return {string} The app or extension label depending on |type|. */ - appOrExtension: function(type, appLabel, extensionLabel) { + appOrExtension(type, appLabel, extensionLabel) { const ExtensionType = chrome.developerPrivate.ExtensionType; switch (type) { case ExtensionType.HOSTED_APP: diff --git a/chromium/chrome/browser/resources/extensions/item_list.html b/chromium/chrome/browser/resources/extensions/item_list.html index 2ea1c0f87ae..56b2f7b6b8a 100644 --- a/chromium/chrome/browser/resources/extensions/item_list.html +++ b/chromium/chrome/browser/resources/extensions/item_list.html @@ -31,7 +31,6 @@ .items-container { --grid-gutter: 12px; - --max-columns: 3; display: grid; grid-column-gap: var(--grid-gutter); grid-row-gap: var(--grid-gutter); @@ -42,6 +41,12 @@ var(--grid-gutter) * var(--max-columns)); } + #checkup-container { + grid-column: 1 / -1; + /* The checkup card should be at least as tall as an extensions item card.*/ + min-height: var(--extensions-card-height); + } + extensions-item { grid-column-start: auto; grid-row-start: auto; @@ -74,7 +79,7 @@ </style> <div id="container"> <managed-footnote hidden="[[filter]]"></managed-footnote> - <div id="content-wrapper"> + <div id="content-wrapper" style="--max-columns: [[maxColumns_]];"> <div id="no-items" class="empty-list-message" hidden$="[[!shouldShowEmptyItemsMessage_( apps.length, extensions.length)]]"> @@ -88,6 +93,10 @@ <span>$i18n{noSearchResults}</span> </div> <div class="items-container" hidden="[[!shownExtensionsCount_]]"> + <div id="checkup-container" hidden="[[!showCheckup_]]"> + <extensions-checkup id="checkup" slot="view"> + </extensions-checkup> + </div> <!-- Render only a few items first, to improve initial render time, then render the remaining items on a different frame. Value of 3 was chosen by experimentation, and it is a good trade-off between diff --git a/chromium/chrome/browser/resources/extensions/item_list.js b/chromium/chrome/browser/resources/extensions/item_list.js index f24ce184d71..82136e86fa8 100644 --- a/chromium/chrome/browser/resources/extensions/item_list.js +++ b/chromium/chrome/browser/resources/extensions/item_list.js @@ -4,9 +4,11 @@ import 'chrome://resources/cr_components/managed_footnote/managed_footnote.m.js'; import './shared_style.js'; +import './checkup.js'; import {CrContainerShadowBehavior} from 'chrome://resources/cr_elements/cr_container_shadow_behavior.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -46,9 +48,15 @@ Polymer({ }, /** @private */ - shownExtensionsCount_: { + maxColumns_: { type: Number, - value: 0, + value: () => loadTimeData.getBoolean('showCheckup') ? 2 : 3, + }, + + /** @private */ + showCheckup_: { + type: Boolean, + value: () => loadTimeData.getBoolean('showCheckup'), }, /** @private */ @@ -56,13 +64,19 @@ Polymer({ type: Number, value: 0, }, + + /** @private */ + shownExtensionsCount_: { + type: Number, + value: 0, + }, }, /** * @param {string} id * @return {?Element} */ - getDetailsButton: function(id) { + getDetailsButton(id) { const item = this.$$(`#${id}`); return item && item.getDetailsButton(); }, @@ -71,7 +85,7 @@ Polymer({ * @param {string} id * @return {?Element} */ - getErrorsButton: function(id) { + getErrorsButton(id) { const item = this.$$(`#${id}`); return item && item.getErrorsButton(); }, @@ -83,7 +97,7 @@ Polymer({ * return {?Function} * @private */ - computeFilter_: function() { + computeFilter_() { const formattedFilter = this.filter.trim().toLowerCase(); return formattedFilter ? i => i.name.toLowerCase().includes(formattedFilter) : @@ -91,7 +105,7 @@ Polymer({ }, /** @private */ - shouldShowEmptyItemsMessage_: function() { + shouldShowEmptyItemsMessage_() { if (!this.apps || !this.extensions) { return; } @@ -100,20 +114,20 @@ Polymer({ }, /** @private */ - shouldShowEmptySearchMessage_: function() { + shouldShowEmptySearchMessage_() { return !this.shouldShowEmptyItemsMessage_() && this.shownAppsCount_ === 0 && this.shownExtensionsCount_ === 0; }, /** @private */ - onNoExtensionsTap_: function(e) { - if (e.target.tagName == 'A') { + onNoExtensionsTap_(e) { + if (e.target.tagName === 'A') { chrome.metricsPrivate.recordUserAction('Options_GetMoreExtensions'); } }, /** @private */ - announceSearchResults_: function() { + announceSearchResults_() { if (this.computedFilter_) { IronA11yAnnouncer.requestAvailability(); this.async(() => { // Async to allow list to update. @@ -121,7 +135,7 @@ Polymer({ this.fire('iron-announce', { text: this.shouldShowEmptySearchMessage_() ? this.i18n('noSearchResults') : - (total == 1 ? + (total === 1 ? this.i18n('searchResultsSingular', this.filter) : this.i18n( 'searchResultsPlural', total.toString(), this.filter)), diff --git a/chromium/chrome/browser/resources/extensions/item_util.js b/chromium/chrome/browser/resources/extensions/item_util.js index b137f5d8438..a1f91b53f7e 100644 --- a/chromium/chrome/browser/resources/extensions/item_util.js +++ b/chromium/chrome/browser/resources/extensions/item_util.js @@ -18,6 +18,13 @@ export const SourceType = { UNKNOWN: 'unknown', }; +/** @enum {string} */ +export const EnableControl = { + RELOAD: 'RELOAD', + REPAIR: 'REPAIR', + ENABLE_TOGGLE: 'ENABLE_TOGGLE', +}; + /** * Returns true if the extension is enabled, including terminated * extensions. @@ -58,7 +65,8 @@ export function userCanChangeEnablement(item) { // Item is forcefully disabled. if (item.disableReasons.corruptInstall || item.disableReasons.suspiciousInstall || - item.disableReasons.updateRequired) { + item.disableReasons.updateRequired || + item.disableReasons.blockedByPolicy) { return false; } // An item with dependent extensions can't be disabled (it would bork the @@ -67,7 +75,7 @@ export function userCanChangeEnablement(item) { return false; } // Blacklisted can't be enabled, either. - if (item.state == chrome.developerPrivate.ExtensionState.BLACKLISTED) { + if (item.state === chrome.developerPrivate.ExtensionState.BLACKLISTED) { return false; } @@ -80,7 +88,7 @@ export function userCanChangeEnablement(item) { */ export function getItemSource(item) { if (item.controlledInfo && - item.controlledInfo.type == + item.controlledInfo.type === chrome.developerPrivate.ControllerType.POLICY) { return SourceType.POLICY; } @@ -130,17 +138,17 @@ export function computeInspectableViewLabel(view) { // Trim the "chrome-extension://<id>/". const url = new URL(view.url); let label = view.url; - if (url.protocol == 'chrome-extension:') { + if (url.protocol === 'chrome-extension:') { label = url.pathname.substring(1); } - if (label == '_generated_background_page.html') { + if (label === '_generated_background_page.html') { label = loadTimeData.getString('viewBackgroundPage'); } // Add any qualifiers. if (view.incognito) { label += ' ' + loadTimeData.getString('viewIncognito'); } - if (view.renderProcessId == -1) { + if (view.renderProcessId === -1) { label += ' ' + loadTimeData.getString('viewInactive'); } if (view.isIframe) { @@ -149,3 +157,28 @@ export function computeInspectableViewLabel(view) { return label; } + +/** + * Returns true if the extension is in the terminated state. + * @param {!chrome.developerPrivate.ExtensionState} state + * @return {boolean} + * @private + */ +function isTerminated_(state) { + return state === chrome.developerPrivate.ExtensionState.TERMINATED; +} + +/** + * Determines which enable control to display for a given extension. + * @param {!chrome.developerPrivate.ExtensionInfo} data + * @return {EnableControl} + */ +export function getEnableControl(data) { + if (isTerminated_(data.state)) { + return EnableControl.RELOAD; + } + if (data.disableReasons.corruptInstall) { + return EnableControl.REPAIR; + } + return EnableControl.ENABLE_TOGGLE; +} diff --git a/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.html b/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.html index 9c8a8638fb3..832dfb7bd3b 100644 --- a/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.html +++ b/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.html @@ -4,9 +4,9 @@ } .shortcut-card { - @apply --cr-card-elevation; background-color: var(--cr-card-background-color); border-radius: var(--cr-card-border-radius); + box-shadow: var(--cr-card-shadow); color: var(--cr-primary-text-color); margin: 0 auto 16px auto; padding-bottom: 8px; diff --git a/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.js b/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.js index 92d8663ffee..aa9b03bf06a 100644 --- a/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.js +++ b/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.js @@ -44,7 +44,7 @@ Polymer({ }, /** @private */ - onViewEnter_: function() { + onViewEnter_() { chrome.metricsPrivate.recordUserAction('Options_ExtensionCommands'); }, @@ -52,7 +52,7 @@ Polymer({ * @return {!Array<!chrome.developerPrivate.ExtensionInfo>} * @private */ - calculateShownItems_: function() { + calculateShownItems_() { return this.items.filter(function(item) { return item.commands.length > 0; }); @@ -66,7 +66,7 @@ Polymer({ * @return {boolean} * @private */ - hasKeybinding_: function(keybinding) { + hasKeybinding_(keybinding) { return !!keybinding; }, @@ -76,7 +76,7 @@ Polymer({ * @return {boolean} * @private */ - computeScopeDisabled_: function(command) { + computeScopeDisabled_(command) { return command.isExtensionAction || !command.isActive; }, @@ -86,12 +86,12 @@ Polymer({ * @param {string} scope * @return {string} */ - triggerScopeChange_: function(scope) { + triggerScopeChange_(scope) { return scope; }, /** @private */ - onCloseButtonClick_: function() { + onCloseButtonClick_() { this.fire('close'); }, @@ -99,7 +99,7 @@ Polymer({ * @param {!{target: HTMLSelectElement, model: Object}} event * @private */ - onScopeChanged_: function(event) { + onScopeChanged_(event) { this.delegate.updateExtensionCommandScope( event.model.get('item.id'), event.model.get('command.name'), /** @type {chrome.developerPrivate.CommandScope} */ diff --git a/chromium/chrome/browser/resources/extensions/kiosk_dialog.js b/chromium/chrome/browser/resources/extensions/kiosk_dialog.js index 04bc4cb1e9b..1ccf476eb04 100644 --- a/chromium/chrome/browser/resources/extensions/kiosk_dialog.js +++ b/chromium/chrome/browser/resources/extensions/kiosk_dialog.js @@ -52,12 +52,12 @@ Polymer({ kioskBrowserProxy_: null, /** @override */ - ready: function() { + ready() { this.kioskBrowserProxy_ = KioskBrowserProxyImpl.getInstance(); }, /** @override */ - attached: function() { + attached() { this.kioskBrowserProxy_.initializeKioskAppSettings() .then(params => { this.canEditAutoLaunch_ = params.autoLaunchEnabled; @@ -77,7 +77,7 @@ Polymer({ * @param {!KioskAppSettings} settings * @private */ - setSettings_: function(settings) { + setSettings_(settings) { this.apps_ = settings.apps; this.bailoutDisabled_ = settings.disableBailout; this.canEditBailout_ = settings.hasAutoLaunchApp; @@ -87,8 +87,8 @@ Polymer({ * @param {!KioskApp} app * @private */ - updateApp_: function(app) { - const index = this.apps_.findIndex(a => a.id == app.id); + updateApp_(app) { + const index = this.apps_.findIndex(a => a.id === app.id); assert(index < this.apps_.length); this.set('apps_.' + index, app); }, @@ -97,7 +97,7 @@ Polymer({ * @param {string} appId * @private */ - showError_: function(appId) { + showError_(appId) { this.errorAppId_ = appId; }, @@ -106,19 +106,19 @@ Polymer({ * @return {string} * @private */ - getErrorMessage_: function(errorMessage) { + getErrorMessage_(errorMessage) { return this.errorAppId_ + ' ' + errorMessage; }, /** @private */ - onAddAppTap_: function() { + onAddAppTap_() { assert(this.addAppInput_); this.kioskBrowserProxy_.addKioskApp(this.addAppInput_); this.addAppInput_ = null; }, /** @private */ - clearInputInvalid_: function() { + clearInputInvalid_() { this.errorAppId_ = null; }, @@ -126,7 +126,7 @@ Polymer({ * @param {{model: {item: !KioskApp}}} event * @private */ - onAutoLaunchButtonTap_: function(event) { + onAutoLaunchButtonTap_(event) { const app = event.model.item; if (app.autoLaunch) { // If the app is originally set to // auto-launch. @@ -140,7 +140,7 @@ Polymer({ * @param {!Event} event * @private */ - onBailoutChanged_: function(event) { + onBailoutChanged_(event) { event.preventDefault(); if (this.$.bailout.checked) { this.$['confirm-dialog'].showModal(); @@ -151,19 +151,19 @@ Polymer({ }, /** @private */ - onBailoutDialogCancelTap_: function() { + onBailoutDialogCancelTap_() { this.$.bailout.checked = false; this.$['confirm-dialog'].cancel(); }, /** @private */ - onBailoutDialogConfirmTap_: function() { + onBailoutDialogConfirmTap_() { this.kioskBrowserProxy_.setDisableBailoutShortcut(true); this.$['confirm-dialog'].close(); }, /** @private */ - onDoneTap_: function() { + onDoneTap_() { this.$.dialog.close(); }, @@ -171,7 +171,7 @@ Polymer({ * @param {{model: {item: !KioskApp}}} event * @private */ - onDeleteAppTap_: function(event) { + onDeleteAppTap_(event) { this.kioskBrowserProxy_.removeKioskApp(event.model.item.id); }, @@ -182,7 +182,7 @@ Polymer({ * @return {string} * @private */ - getAutoLaunchButtonLabel_: function(autoLaunched, disableStr, enableStr) { + getAutoLaunchButtonLabel_(autoLaunched, disableStr, enableStr) { return autoLaunched ? disableStr : enableStr; }, @@ -190,7 +190,7 @@ Polymer({ * @param {!Event} e * @private */ - stopPropagation_: function(e) { + stopPropagation_(e) { e.stopPropagation(); }, }); diff --git a/chromium/chrome/browser/resources/extensions/load_error.js b/chromium/chrome/browser/resources/extensions/load_error.js index ff678ac6176..ece39918c1a 100644 --- a/chromium/chrome/browser/resources/extensions/load_error.js +++ b/chromium/chrome/browser/resources/extensions/load_error.js @@ -42,16 +42,16 @@ Polymer({ 'observeLoadErrorChanges_(loadError)', ], - show: function() { + show() { /** @type {!CrDialogElement} */ (this.$.dialog).showModal(); }, - close: function() { + close() { /** @type {!CrDialogElement} */ (this.$.dialog).close(); }, /** @private */ - onRetryTap_: function() { + onRetryTap_() { this.retrying_ = true; this.delegate.retryLoadUnpacked(this.loadError.retryGuid) .then( @@ -66,7 +66,7 @@ Polymer({ }, /** @private */ - observeLoadErrorChanges_: function() { + observeLoadErrorChanges_() { assert(this.loadError); const source = this.loadError.source; // CodeSection expects a RequestFileSourceResponse, rather than an diff --git a/chromium/chrome/browser/resources/extensions/manager.html b/chromium/chrome/browser/resources/extensions/manager.html index 87457fba166..7cbf68e59ba 100644 --- a/chromium/chrome/browser/resources/extensions/manager.html +++ b/chromium/chrome/browser/resources/extensions/manager.html @@ -28,6 +28,7 @@ dev-mode-controlled-by-policy="[[devModeControlledByPolicy]]" delegate="[[delegate]]" on-cr-toolbar-menu-tap="onMenuButtonTap_" on-search-changed="onFilterChanged_" + extensions="[[extensions_]]" <if expr="chromeos"> on-kiosk-tap="onKioskTap_" kiosk-enabled="[[kioskEnabled_]]" diff --git a/chromium/chrome/browser/resources/extensions/manager.js b/chromium/chrome/browser/resources/extensions/manager.js index b1df5c6fef5..1b80446a0b7 100644 --- a/chromium/chrome/browser/resources/extensions/manager.js +++ b/chromium/chrome/browser/resources/extensions/manager.js @@ -46,13 +46,13 @@ const compareExtensions = function(a, b) { return x < y ? -1 : (x > y ? 1 : 0); } function compareLocation(x, y) { - if (x.location == y.location) { + if (x.location === y.location) { return 0; } - if (x.location == chrome.developerPrivate.Location.UNPACKED) { + if (x.location === chrome.developerPrivate.Location.UNPACKED) { return -1; } - if (y.location == chrome.developerPrivate.Location.UNPACKED) { + if (y.location === chrome.developerPrivate.Location.UNPACKED) { return 1; } return 0; @@ -76,7 +76,7 @@ Polymer({ /** @type {!Service} */ delegate: { type: Object, - value: function() { + value() { return Service.getInstance(); }, }, @@ -211,7 +211,7 @@ Polymer({ navigationListener_: null, /** @override */ - ready: function() { + ready() { const service = Service.getInstance(); const onProfileStateChanged = profileInfo => { @@ -242,7 +242,7 @@ Polymer({ }, /** @override */ - attached: function() { + attached() { document.documentElement.classList.remove('loading'); document.fonts.load('bold 12px Roboto'); @@ -252,7 +252,7 @@ Polymer({ }, /** @override */ - detached: function() { + detached() { assert(navigation.removeListener( /** @type {number} */ (this.navigationListener_))); this.navigationListener_ = null; @@ -263,7 +263,7 @@ Polymer({ * the user visits chrome://extensions/?id=..., we land on the proper page. * @private */ - initPage_: function() { + initPage_() { this.didInitPage_ = true; this.changePage_(navigation.getCurrentPage()); }, @@ -272,7 +272,7 @@ Polymer({ * @param {!chrome.developerPrivate.EventData} eventData * @private */ - onItemStateChanged_: function(eventData) { + onItemStateChanged_(eventData) { const EventType = chrome.developerPrivate.EventType; switch (eventData.event_type) { case EventType.VIEW_REGISTERED: @@ -301,7 +301,7 @@ Polymer({ const listId = this.getListId_(eventData.extensionInfo); const currentIndex = this[listId].findIndex( - item => item.id == eventData.extensionInfo.id); + item => item.id === eventData.extensionInfo.id); if (currentIndex >= 0) { this.updateItem_(listId, currentIndex, eventData.extensionInfo); @@ -321,7 +321,7 @@ Polymer({ * @param {!CustomEvent<string>} event * @private */ - onFilterChanged_: function(event) { + onFilterChanged_(event) { if (this.currentPage_.page !== Page.LIST) { navigation.navigateTo({page: Page.LIST}); } @@ -329,7 +329,7 @@ Polymer({ }, /** @private */ - onMenuButtonTap_: function() { + onMenuButtonTap_() { this.showDrawer_ = true; this.async(() => { this.$$('#drawer').openDrawer(); @@ -341,7 +341,7 @@ Polymer({ * @return {string} The ID of the list that the item belongs in. * @private */ - getListId_: function(item) { + getListId_(item) { const ExtensionType = chrome.developerPrivate.ExtensionType; switch (item.type) { case ExtensionType.HOSTED_APP: @@ -364,9 +364,9 @@ Polymer({ * @return {number} The index of the item in the list, or -1 if not found. * @private */ - getIndexInList_: function(listId, itemId) { + getIndexInList_(listId, itemId) { return this[listId].findIndex(function(item) { - return item.id == itemId; + return item.id === itemId; }); }, @@ -374,7 +374,7 @@ Polymer({ * @return {?chrome.developerPrivate.ExtensionInfo} * @private */ - getData_: function(id) { + getData_(id) { return this.extensions_[this.getIndexInList_('extensions_', id)] || this.apps_[this.getIndexInList_('apps_', id)]; }, @@ -385,7 +385,7 @@ Polymer({ * @param {!Array<!chrome.developerPrivate.ExtensionInfo>} extensionsAndApps * @private */ - initExtensionsAndApps_: function(extensionsAndApps) { + initExtensionsAndApps_(extensionsAndApps) { extensionsAndApps.sort(compareExtensions); const apps = []; const extensions = []; @@ -405,13 +405,13 @@ Polymer({ * the new element is representing. * @private */ - addItem_: function(listId, item) { + addItem_(listId, item) { // We should never try and add an existing item. - assert(this.getIndexInList_(listId, item.id) == -1); + assert(this.getIndexInList_(listId, item.id) === -1); let insertBeforeChild = this[listId].findIndex(function(listEl) { return compareExtensions(listEl, item) > 0; }); - if (insertBeforeChild == -1) { + if (insertBeforeChild === -1) { insertBeforeChild = this[listId].length; } this.splice(listId, insertBeforeChild, 0, item); @@ -422,7 +422,7 @@ Polymer({ * item to update. * @private */ - updateItem_: function(listId, index, item) { + updateItem_(listId, index, item) { // We should never try and update a non-existent item. assert(index >= 0); this.set([listId, index], item); @@ -432,16 +432,16 @@ Polymer({ // set the item correctly before opening the page. It's a little weird // that the DOM will have stale data, but there's no point in causing the // extra work. - if (this.detailViewItem_ && this.detailViewItem_.id == item.id && - this.currentPage_.page == Page.DETAILS) { + if (this.detailViewItem_ && this.detailViewItem_.id === item.id && + this.currentPage_.page === Page.DETAILS) { this.detailViewItem_ = item; } else if ( - this.errorPageItem_ && this.errorPageItem_.id == item.id && - this.currentPage_.page == Page.ERRORS) { + this.errorPageItem_ && this.errorPageItem_.id === item.id && + this.currentPage_.page === Page.ERRORS) { this.errorPageItem_ = item; } else if ( - this.activityLogItem_ && this.activityLogItem_.id == item.id && - this.currentPage_.page == Page.ACTIVITY_LOG) { + this.activityLogItem_ && this.activityLogItem_.id === item.id && + this.currentPage_.page === Page.ACTIVITY_LOG) { this.activityLogItem_ = item; } }, @@ -450,11 +450,11 @@ Polymer({ * @param {string} itemId The id of item to remove. * @private */ - removeItem_: function(itemId) { + removeItem_(itemId) { // Search for the item to be deleted in |extensions_|. let listId = 'extensions_'; let index = this.getIndexInList_(listId, itemId); - if (index == -1) { + if (index === -1) { // If not in |extensions_| it must be in |apps_|. listId = 'apps_'; index = this.getIndexInList_(listId, itemId); @@ -463,10 +463,10 @@ Polymer({ // We should never try and remove a non-existent item. assert(index >= 0); this.splice(listId, index, 1); - if ((this.currentPage_.page == Page.ACTIVITY_LOG || - this.currentPage_.page == Page.DETAILS || - this.currentPage_.page == Page.ERRORS) && - this.currentPage_.extensionId == itemId) { + if ((this.currentPage_.page === Page.ACTIVITY_LOG || + this.currentPage_.page === Page.DETAILS || + this.currentPage_.page === Page.ERRORS) && + this.currentPage_.extensionId === itemId) { // Leave the details page (the 'list' page is a fine choice). navigation.replaceWith({page: Page.LIST}); } @@ -476,7 +476,7 @@ Polymer({ * @param {!CustomEvent<!chrome.developerPrivate.LoadError>} e * @private */ - onLoadError_: function(e) { + onLoadError_(e) { this.showLoadErrorDialog_ = true; this.async(() => { const dialog = this.$$('#load-error'); @@ -490,7 +490,7 @@ Polymer({ * @param {PageState} newPage * @private */ - changePage_: function(newPage) { + changePage_(newPage) { this.onCloseDrawer_(); const optionsDialog = this.$$('#options-dialog'); @@ -509,7 +509,7 @@ Polymer({ // extension ID is not valid. This enables the use case of seeing an // extension's install-time activities by navigating to an extension's // activity log page, then installing the extension. - if (this.showActivityLog && toPage == Page.ACTIVITY_LOG) { + if (this.showActivityLog && toPage === Page.ACTIVITY_LOG) { activityLogPlaceholder = { id: newPage.extensionId, isPlaceholder: true, @@ -522,11 +522,11 @@ Polymer({ } } - if (toPage == Page.DETAILS) { + if (toPage === Page.DETAILS) { this.detailViewItem_ = assert(data); - } else if (toPage == Page.ERRORS) { + } else if (toPage === Page.ERRORS) { this.errorPageItem_ = assert(data); - } else if (toPage == Page.ACTIVITY_LOG) { + } else if (toPage === Page.ACTIVITY_LOG) { if (!this.showActivityLog) { // Redirect back to the details page if we try to view the // activity log of an extension but the flag is not set. @@ -538,13 +538,13 @@ Polymer({ this.activityLogItem_ = data ? assert(data) : activityLogPlaceholder; } - if (fromPage != toPage) { + if (fromPage !== toPage) { /** @type {CrViewManagerElement} */ (this.$.viewManager) .switchView(/** @type {string} */ (toPage)); } if (newPage.subpage) { - assert(newPage.subpage == Dialog.OPTIONS); + assert(newPage.subpage === Dialog.OPTIONS); assert(newPage.extensionId); this.showOptionsDialog_ = true; this.async(() => { @@ -552,7 +552,7 @@ Polymer({ }); } - document.title = toPage == Page.DETAILS ? + document.title = toPage === Page.DETAILS ? `${loadTimeData.getString('title')} - ${this.detailViewItem_.name}` : loadTimeData.getString('title'); this.currentPage_ = newPage; @@ -563,7 +563,7 @@ Polymer({ * triggered by the dialog's 'close' event. * @private */ - onDrawerClose_: function() { + onDrawerClose_() { this.showDrawer_ = false; }, @@ -571,7 +571,7 @@ Polymer({ * This method animates the closing of the drawer. * @private */ - onCloseDrawer_: function() { + onCloseDrawer_() { const drawer = this.$$('#drawer'); if (drawer && drawer.open) { drawer.close(); @@ -579,18 +579,18 @@ Polymer({ }, /** @private */ - onLoadErrorDialogClose_: function() { + onLoadErrorDialogClose_() { this.showLoadErrorDialog_ = false; }, /** @private */ - onOptionsDialogClose_: function() { + onOptionsDialogClose_() { this.showOptionsDialog_ = false; this.$$('extensions-detail-view').focusOptionsButton(); }, /** @private */ - onViewEnterStart_: function() { + onViewEnterStart_() { this.fromActivityLog_ = false; }, @@ -598,26 +598,26 @@ Polymer({ * @param {!Event} e * @private */ - onViewExitStart_: function(e) { + onViewExitStart_(e) { const viewType = e.composedPath()[0].tagName; - this.fromActivityLog_ = viewType == 'EXTENSIONS-ACTIVITY-LOG'; + this.fromActivityLog_ = viewType === 'EXTENSIONS-ACTIVITY-LOG'; }, /** * @param {!Event} e * @private */ - onViewExitFinish_: function(e) { + onViewExitFinish_(e) { const viewType = e.composedPath()[0].tagName; - if (viewType == 'EXTENSIONS-ITEM-LIST' || - viewType == 'EXTENSIONS-KEYBOARD-SHORTCUTS' || - viewType == 'EXTENSIONS-ACTIVITY-LOG') { + if (viewType === 'EXTENSIONS-ITEM-LIST' || + viewType === 'EXTENSIONS-KEYBOARD-SHORTCUTS' || + viewType === 'EXTENSIONS-ACTIVITY-LOG') { return; } const extensionId = e.composedPath()[0].data.id; const list = this.$$('extensions-item-list'); - const button = viewType == 'EXTENSIONS-DETAIL-VIEW' ? + const button = viewType === 'EXTENSIONS-DETAIL-VIEW' ? list.getDetailsButton(extensionId) : list.getErrorsButton(extensionId); @@ -632,7 +632,7 @@ Polymer({ * @param {!CustomEvent<!Array<string>>} e * @private */ - onShowInstallWarnings_: function(e) { + onShowInstallWarnings_(e) { // Leverage Polymer data bindings instead of just assigning the // installWarnings on the dialog since the dialog hasn't been stamped // in the DOM yet. @@ -641,18 +641,18 @@ Polymer({ }, /** @private */ - onInstallWarningsDialogClose_: function() { + onInstallWarningsDialogClose_() { this.installWarnings_ = null; this.showInstallWarningsDialog_ = false; }, // <if expr="chromeos"> /** @private */ - onKioskTap_: function() { + onKioskTap_() { this.showKioskDialog_ = true; }, - onKioskDialogClose_: function() { + onKioskDialogClose_() { this.showKioskDialog_ = false; }, // </if> diff --git a/chromium/chrome/browser/resources/extensions/navigation_helper.js b/chromium/chrome/browser/resources/extensions/navigation_helper.js index b4bc143d1e7..53de02b2a24 100644 --- a/chromium/chrome/browser/resources/extensions/navigation_helper.js +++ b/chromium/chrome/browser/resources/extensions/navigation_helper.js @@ -36,8 +36,8 @@ export let PageState; * @return {boolean} Whether a and b are equal. */ function isPageStateEqual(a, b) { - return a.page == b.page && a.subpage == b.subpage && - a.extensionId == b.extensionId; + return a.page === b.page && a.subpage === b.subpage && + a.extensionId === b.extensionId; } /** @@ -82,8 +82,8 @@ export class NavigationHelper { * @private */ processRoute_() { - if (this.currentPath_ == '/configureCommands' || - this.currentPath_ == '/shortcuts') { + if (this.currentPath_ === '/configureCommands' || + this.currentPath_ === '/shortcuts') { window.history.replaceState( undefined /* stateObject */, '', '/shortcuts'); } else if (this.currentPath_ !== '/') { @@ -114,7 +114,7 @@ export class NavigationHelper { return {page: Page.ERRORS, extensionId: id}; } - if (this.currentPath_ == '/shortcuts') { + if (this.currentPath_ === '/shortcuts') { return {page: Page.SHORTCUTS}; } @@ -195,7 +195,7 @@ export class NavigationHelper { break; case Page.DETAILS: if (entry.subpage) { - assert(entry.subpage == Dialog.OPTIONS); + assert(entry.subpage === Dialog.OPTIONS); path = '/?options=' + entry.extensionId; } else { path = '/?id=' + entry.extensionId; @@ -211,8 +211,8 @@ export class NavigationHelper { assert(path); const state = {url: path}; const currentPage = this.getCurrentPage(); - const isDialogNavigation = currentPage.page == entry.page && - currentPage.extensionId == entry.extensionId; + const isDialogNavigation = currentPage.page === entry.page && + currentPage.extensionId === entry.extensionId; // Navigating to a dialog doesn't visually change pages; it just opens // a dialog. As such, we replace state rather than pushing a new state // on the stack so that hitting the back button doesn't just toggle the diff --git a/chromium/chrome/browser/resources/extensions/options_dialog.js b/chromium/chrome/browser/resources/extensions/options_dialog.js index ce9aa267217..9f6ca1c5517 100644 --- a/chromium/chrome/browser/resources/extensions/options_dialog.js +++ b/chromium/chrome/browser/resources/extensions/options_dialog.js @@ -15,13 +15,13 @@ import {navigation, Page} from './navigation_helper.js'; * registered yet. */ function whenDocumentReady() { - if (document.readyState == 'complete') { + if (document.readyState === 'complete') { return Promise.resolve(); } return new Promise(function(resolve) { document.addEventListener('readystatechange', function f() { - if (document.readyState == 'complete') { + if (document.readyState === 'complete') { document.removeEventListener('readystatechange', f); resolve(); } @@ -65,7 +65,7 @@ Polymer({ * into account the window width/height. * @private */ - updateDialogSize_: function() { + updateDialogSize_() { const headerHeight = this.$.body.offsetTop; const maxHeight = Math.min(0.9 * window.innerHeight, OptionsDialogMaxHeight); @@ -80,7 +80,7 @@ Polymer({ }, /** @param {chrome.developerPrivate.ExtensionInfo} data */ - show: function(data) { + show(data) { this.data_ = data; whenDocumentReady().then(() => { if (!this.extensionOptions_) { @@ -107,7 +107,7 @@ Polymer({ }, /** @private */ - onClose_: function() { + onClose_() { this.extensionOptions_.onpreferredsizechanged = null; if (this.boundUpdateDialogSize_) { @@ -120,7 +120,7 @@ Polymer({ // still on the details page. We could be on a different page if the // user hit back while the options dialog was visible; in that case, the // new page is already correct. - if (currentPage && currentPage.page == Page.DETAILS) { + if (currentPage && currentPage.page === Page.DETAILS) { // This will update the currentPage_ and the NavigationHelper; since // the active page is already the details page, no main page // transition occurs. diff --git a/chromium/chrome/browser/resources/extensions/pack_dialog.js b/chromium/chrome/browser/resources/extensions/pack_dialog.js index 4791d6ba9eb..1c371fce4b7 100644 --- a/chromium/chrome/browser/resources/extensions/pack_dialog.js +++ b/chromium/chrome/browser/resources/extensions/pack_dialog.js @@ -62,12 +62,12 @@ Polymer({ }, /** @override */ - attached: function() { + attached() { this.$.dialog.showModal(); }, /** @private */ - onRootBrowse_: function() { + onRootBrowse_() { this.delegate.choosePackRootDirectory().then(path => { if (path) { this.set('packDirectory_', path); @@ -76,7 +76,7 @@ Polymer({ }, /** @private */ - onKeyBrowse_: function() { + onKeyBrowse_() { this.delegate.choosePrivateKeyPath().then(path => { if (path) { this.set('keyFile_', path); @@ -85,12 +85,12 @@ Polymer({ }, /** @private */ - onCancelTap_: function() { + onCancelTap_() { this.$.dialog.cancel(); }, /** @private */ - onConfirmTap_: function() { + onConfirmTap_() { this.delegate.packExtension( this.packDirectory_, this.keyFile_, 0, this.onPackResponse_.bind(this)); }, @@ -100,7 +100,7 @@ Polymer({ * response from request to pack an extension. * @private */ - onPackResponse_: function(response) { + onPackResponse_(response) { this.lastResponse_ = response; }, @@ -112,17 +112,17 @@ Polymer({ * @param {!Event} e * @private */ - onAlertClose_: function(e) { + onAlertClose_(e) { e.stopPropagation(); - if (this.lastResponse_.status == + if (this.lastResponse_.status === chrome.developerPrivate.PackStatus.SUCCESS) { this.$.dialog.close(); return; } // This is only possible for a warning dialog. - if (this.$$('extensions-pack-dialog-alert').returnValue == 'success') { + if (this.$$('extensions-pack-dialog-alert').returnValue === 'success') { this.delegate.packExtension( this.lastResponse_.item_path, this.lastResponse_.pem_path, this.lastResponse_.override_flags, this.onPackResponse_.bind(this)); diff --git a/chromium/chrome/browser/resources/extensions/pack_dialog_alert.js b/chromium/chrome/browser/resources/extensions/pack_dialog_alert.js index a39869e2f70..16e149876e8 100644 --- a/chromium/chrome/browser/resources/extensions/pack_dialog_alert.js +++ b/chromium/chrome/browser/resources/extensions/pack_dialog_alert.js @@ -45,7 +45,7 @@ Polymer({ }, /** @override */ - ready: function() { + ready() { // Initialize button label values for initial html binding. this.cancelLabel_ = null; this.confirmLabel_ = null; @@ -71,7 +71,7 @@ Polymer({ }, /** @override */ - attached: function() { + attached() { this.$.dialog.showModal(); }, @@ -79,17 +79,17 @@ Polymer({ * @return {string} * @private */ - getCancelButtonClass_: function() { + getCancelButtonClass_() { return this.confirmLabel_ ? 'cancel-button' : 'action-button'; }, /** @private */ - onCancelTap_: function() { + onCancelTap_() { this.$.dialog.cancel(); }, /** @private */ - onConfirmTap_: function() { + onConfirmTap_() { // The confirm button should only be available in WARNING state. assert(this.model.status === chrome.developerPrivate.PackStatus.WARNING); this.$.dialog.close(); diff --git a/chromium/chrome/browser/resources/extensions/runtime_host_permissions.js b/chromium/chrome/browser/resources/extensions/runtime_host_permissions.js index 1814e423fe8..a2b743b7de0 100644 --- a/chromium/chrome/browser/resources/extensions/runtime_host_permissions.js +++ b/chromium/chrome/browser/resources/extensions/runtime_host_permissions.js @@ -115,12 +115,12 @@ Polymer({ * @param {!Event} event * @private */ - onHostAccessChange_: function(event) { + onHostAccessChange_(event) { const group = /** @type {!HTMLElement} */ (this.$['host-access']); const access = group.selected; - if (access == chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES && - this.permissions.hostAccess != + if (access === chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES && + this.permissions.hostAccess !== chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES) { // If the user is transitioning to the "on specific sites" option, show // the "add host" dialog. This serves two purposes: @@ -141,8 +141,8 @@ Polymer({ * @return {boolean} * @private */ - showSpecificSites_: function() { - return this.permissions.hostAccess == + showSpecificSites_() { + return this.permissions.hostAccess === chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES; }, @@ -151,7 +151,7 @@ Polymer({ * @return {!Array<string>} * @private */ - getRuntimeHosts_: function() { + getRuntimeHosts_() { if (!this.permissions.hosts) { return []; } @@ -168,7 +168,7 @@ Polymer({ * @param {Event} e * @private */ - onAddHostClick_: function(e) { + onAddHostClick_(e) { const target = /** @type {!HTMLElement} */ (e.target); this.doShowHostDialog_(target, null); }, @@ -180,14 +180,14 @@ Polymer({ * edited, or null if this is to add a new entry. * @private */ - doShowHostDialog_: function(anchorElement, currentSite) { + doShowHostDialog_(anchorElement, currentSite) { this.hostDialogAnchorElement_ = anchorElement; this.hostDialogModel_ = currentSite; this.showHostDialog_ = true; }, /** @private */ - onHostDialogClose_: function() { + onHostDialogClose_() { this.hostDialogModel_ = null; this.showHostDialog_ = false; focusWithoutInk(assert(this.hostDialogAnchorElement_, 'Host Anchor')); @@ -196,11 +196,11 @@ Polymer({ }, /** @private */ - onHostDialogCancel_: function() { + onHostDialogCancel_() { // The user canceled the dialog. Set host-access back to the old value, // if the dialog was shown when just transitioning to a new state. if (this.oldHostAccess_) { - assert(this.permissions.hostAccess == this.oldHostAccess_); + assert(this.permissions.hostAccess === this.oldHostAccess_); this.$['host-access'].selected = this.oldHostAccess_; this.oldHostAccess_ = null; } @@ -210,7 +210,7 @@ Polymer({ * @return {boolean} * @private */ - dialogShouldUpdateHostAccess_: function() { + dialogShouldUpdateHostAccess_() { return !!this.oldHostAccess_; }, @@ -221,7 +221,7 @@ Polymer({ * }} e * @private */ - onEditHostClick_: function(e) { + onEditHostClick_(e) { this.actionMenuModel_ = e.model.item; this.actionMenuAnchorElement_ = e.target; const actionMenu = @@ -230,7 +230,7 @@ Polymer({ }, /** @private */ - onActionMenuEditClick_: function() { + onActionMenuEditClick_() { // Cache the site before closing the action menu, since it's cleared. const site = this.actionMenuModel_; @@ -245,21 +245,21 @@ Polymer({ }, /** @private */ - onActionMenuRemoveClick_: function() { + onActionMenuRemoveClick_() { this.delegate.removeRuntimeHostPermission( this.itemId, assert(this.actionMenuModel_, 'Action Menu Model')); this.closeActionMenu_(); }, /** @private */ - closeActionMenu_: function() { + closeActionMenu_() { const menu = this.$.hostActionMenu; assert(menu.open); menu.close(); }, /** @private */ - onActionMenuClose_: function() { + onActionMenuClose_() { this.actionMenuModel_ = null; this.actionMenuAnchorElement_ = null; }, diff --git a/chromium/chrome/browser/resources/extensions/runtime_hosts_dialog.js b/chromium/chrome/browser/resources/extensions/runtime_hosts_dialog.js index bbe15acfcda..35fa8ad87e7 100644 --- a/chromium/chrome/browser/resources/extensions/runtime_hosts_dialog.js +++ b/chromium/chrome/browser/resources/extensions/runtime_hosts_dialog.js @@ -29,8 +29,8 @@ const patternRegExp = new RegExp( '((http|https|\\*)://)?' + // Include subdomains specifier; optional. '(\\*\\.)?' + - // Hostname, required. - '([a-z0-9\\.-]+\\.[a-z0-9]+)' + + // Hostname or localhost, required. + '([a-z0-9\\.-]+\\.[a-z0-9]+|localhost)' + // Port, optional. '(:[0-9]+)?' + // Path, optional but if present must be '/' or '/*'. @@ -95,7 +95,7 @@ Polymer({ }, /** @override */ - attached: function() { + attached() { if (this.currentSite !== null && this.currentSite !== undefined) { this.site_ = this.currentSite; this.validate_(); @@ -104,7 +104,7 @@ Polymer({ }, /** @return {boolean} */ - isOpen: function() { + isOpen() { return this.$.dialog.open; }, @@ -112,10 +112,10 @@ Polymer({ * Validates that the pattern entered is valid. * @private */ - validate_: function() { + validate_() { // If input is empty, disable the action button, but don't show the red // invalid message. - if (this.site_.trim().length == 0) { + if (this.site_.trim().length === 0) { this.inputInvalid_ = false; return; } @@ -128,7 +128,7 @@ Polymer({ * @return {string} * @private */ - computeDialogTitle_: function() { + computeDialogTitle_() { const stringId = this.currentSite === null ? 'runtimeHostsDialogTitle' : 'hostPermissionsEdit'; return loadTimeData.getString(stringId); @@ -138,22 +138,22 @@ Polymer({ * @return {boolean} * @private */ - computeSubmitButtonDisabled_: function() { + computeSubmitButtonDisabled_() { return this.inputInvalid_ || this.site_ === undefined || - this.site_.trim().length == 0; + this.site_.trim().length === 0; }, /** * @return {string} * @private */ - computeSubmitButtonLabel_: function() { + computeSubmitButtonLabel_() { const stringId = this.currentSite === null ? 'add' : 'save'; return loadTimeData.getString(stringId); }, /** @private */ - onCancelTap_: function() { + onCancelTap_() { this.$.dialog.cancel(); }, @@ -162,7 +162,7 @@ Polymer({ * the dialog). * @private */ - onSubmitTap_: function() { + onSubmitTap_() { if (this.currentSite !== null) { this.handleEdit_(); } else { @@ -174,7 +174,7 @@ Polymer({ * Handles adding a new site entry. * @private */ - handleAdd_: function() { + handleAdd_() { assert(!this.currentSite); if (this.updateHostAccess) { @@ -189,14 +189,14 @@ Polymer({ * Handles editing an existing site entry. * @private */ - handleEdit_: function() { + handleEdit_() { assert(this.currentSite); assert( !this.updateHostAccess, 'Editing host permissions should only be possible if the host ' + 'access is already set to specific sites.'); - if (this.currentSite == this.site_) { + if (this.currentSite === this.site_) { // No change in values, so no need to update anything. this.$.dialog.close(); return; @@ -215,7 +215,7 @@ Polymer({ * closes the dialog; otherwise displays the invalid input message. * @private */ - addPermission_: function() { + addPermission_() { const pattern = getPatternFromSite(this.site_); this.delegate.addRuntimeHostPermission(this.itemId, pattern) .then( diff --git a/chromium/chrome/browser/resources/extensions/service.js b/chromium/chrome/browser/resources/extensions/service.js index 0e1e52cb28d..c49c474af07 100644 --- a/chromium/chrome/browser/resources/extensions/service.js +++ b/chromium/chrome/browser/resources/extensions/service.js @@ -117,7 +117,8 @@ export class Service { return new Promise(function(resolve, reject) { chrome.developerPrivate.choosePath(selectType, fileType, function(path) { if (chrome.runtime.lastError && - chrome.runtime.lastError != 'File selection was canceled.') { + chrome.runtime.lastError.message !== + 'File selection was canceled.') { reject(chrome.runtime.lastError); } else { resolve(path || ''); @@ -172,7 +173,7 @@ export class Service { chrome.developerPrivate.loadUnpacked(options, (loadError) => { if (chrome.runtime.lastError && - chrome.runtime.lastError.message != + chrome.runtime.lastError.message !== 'File selection was canceled.') { throw new Error(chrome.runtime.lastError.message); } @@ -190,6 +191,7 @@ export class Service { if (this.isDeleting_) { return; } + chrome.metricsPrivate.recordUserAction('Extensions.RemoveExtensionClick'); this.isDeleting_ = true; chrome.management.uninstall(id, {showConfirmDialog: true}, () => { // The "last error" was almost certainly the user canceling the dialog. @@ -202,6 +204,9 @@ export class Service { /** @override */ setItemEnabled(id, isEnabled) { + chrome.metricsPrivate.recordUserAction( + isEnabled ? 'Extensions.ExtensionEnabled' : + 'Extensions.ExtensionDisabled'); chrome.management.setEnabled(id, isEnabled); } @@ -328,11 +333,34 @@ export class Service { } /** @override */ - updateAllExtensions() { + updateAllExtensions(extensions) { + /** + * Attempt to reload local extensions. If an extension fails to load, the + * user is prompted to try updating the broken extension using loadUnpacked + * and we skip reloading the remaining local extensions. + */ return new Promise((resolve) => { - chrome.developerPrivate.autoUpdate(resolve); - chrome.metricsPrivate.recordUserAction('Options_UpdateExtensions'); - }); + chrome.developerPrivate.autoUpdate(resolve); + chrome.metricsPrivate.recordUserAction('Options_UpdateExtensions'); + }) + .then(() => { + return new Promise((resolve, reject) => { + const loadLocalExtensions = async () => { + for (const extension of extensions) { + if (extension.location === 'UNPACKED') { + try { + await this.reloadItem(extension.id); + } catch (loadError) { + reject(loadError); + break; + } + } + } + resolve('Loaded local extensions.'); + }; + loadLocalExtensions(); + }); + }); } /** @override */ diff --git a/chromium/chrome/browser/resources/extensions/shared_style.html b/chromium/chrome/browser/resources/extensions/shared_style.html index 41ca789f85c..56ad91559c5 100644 --- a/chromium/chrome/browser/resources/extensions/shared_style.html +++ b/chromium/chrome/browser/resources/extensions/shared_style.html @@ -41,8 +41,8 @@ } .page-content { - @apply --cr-card-elevation; background-color: var(--cr-card-background-color); + box-shadow: var(--cr-card-shadow); box-sizing: border-box; margin: auto; min-height: 100%; diff --git a/chromium/chrome/browser/resources/extensions/shared_vars.html b/chromium/chrome/browser/resources/extensions/shared_vars.html index b826b8a16d0..8c210336b03 100644 --- a/chromium/chrome/browser/resources/extensions/shared_vars.html +++ b/chromium/chrome/browser/resources/extensions/shared_vars.html @@ -4,6 +4,7 @@ /* Note: error-color is used for many warnings. There's also an orange-y * warning color in 1 place. */ --error-color: var(--google-red-700); + --extensions-card-height: 160px; --separator-gap: 9px; } diff --git a/chromium/chrome/browser/resources/extensions/shortcut_input.html b/chromium/chrome/browser/resources/extensions/shortcut_input.html index f2c4f4247fb..4658ffbc7e0 100644 --- a/chromium/chrome/browser/resources/extensions/shortcut_input.html +++ b/chromium/chrome/browser/resources/extensions/shortcut_input.html @@ -14,6 +14,11 @@ left: -2px; right: inherit; } + + /* Invisible so the element is still in the tab order. */ + [invisible] { + opacity: 0; + } </style> <div id="main"> <cr-input id="input" placeholder="$i18n{shortcutTypeAShortcut}" @@ -25,7 +30,8 @@ value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]"> <cr-icon-button id="clear" aria-label="$i18nPolymer{clear}" slot="suffix" class="icon-cancel no-overlap" - hidden$="[[computeClearHidden_(capturing_, shortcut)]]" + invisible$="[[computeClearInvisible_(capturing_, shortcut)]]" + hidden$="[[computeClearHidden_(shortcut)]]" on-click="onClearTap_"></cr-icon-button> </cr-input> </div> diff --git a/chromium/chrome/browser/resources/extensions/shortcut_input.js b/chromium/chrome/browser/resources/extensions/shortcut_input.js index 6f56ac6c1aa..cf3ab1a53a5 100644 --- a/chromium/chrome/browser/resources/extensions/shortcut_input.js +++ b/chromium/chrome/browser/resources/extensions/shortcut_input.js @@ -9,6 +9,8 @@ import 'chrome://resources/cr_elements/hidden_style_css.m.js'; import 'chrome://resources/polymer/v3_0/paper-styles/color.js'; import {assert} from 'chrome://resources/js/assert.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {KeyboardShortcutDelegate} from './keyboard_shortcut_delegate.js'; @@ -28,6 +30,8 @@ Polymer({ _template: html`{__html_template__}`, + behaviors: [I18nBehavior], + properties: { /** @type {!KeyboardShortcutDelegate} */ delegate: Object, @@ -67,7 +71,7 @@ Polymer({ }, /** @override */ - ready: function() { + ready() { const node = this.$.input; node.addEventListener('mouseup', this.startCapture_.bind(this)); node.addEventListener('blur', this.endCapture_.bind(this)); @@ -77,7 +81,7 @@ Polymer({ }, /** @private */ - startCapture_: function() { + startCapture_() { if (this.capturing_) { return; } @@ -86,7 +90,7 @@ Polymer({ }, /** @private */ - endCapture_: function() { + endCapture_() { if (!this.capturing_) { return; } @@ -102,12 +106,12 @@ Polymer({ * @param {!Event} e * @private */ - onKeyDown_: function(e) { - if (e.target == this.$.clear) { + onKeyDown_(e) { + if (e.target === this.$.clear) { return; } - if (e.keyCode == Key.Escape) { + if (e.keyCode === Key.Escape) { if (!this.capturing_) { // If we're not currently capturing, allow escape to propagate. return; @@ -118,7 +122,7 @@ Polymer({ e.stopPropagation(); return; } - if (e.keyCode == Key.Tab) { + if (e.keyCode === Key.Tab) { // Allow tab propagation for keyboard navigation. return; } @@ -134,16 +138,16 @@ Polymer({ * @param {!Event} e * @private */ - onKeyUp_: function(e) { + onKeyUp_(e) { // Ignores pressing 'Space' or 'Enter' on the clear button. In 'Enter's // case, the clear button disappears before key-up, so 'Enter's key-up // target becomes the input field, not the clear button, and needs to // be caught explicitly. - if (e.target == this.$.clear || e.key == 'Enter') { + if (e.target === this.$.clear || e.key === 'Enter') { return; } - if (e.keyCode == Key.Escape || e.keyCode == Key.Tab) { + if (e.keyCode === Key.Escape || e.keyCode === Key.Tab) { return; } @@ -158,7 +162,7 @@ Polymer({ * @return {string} UI string. * @private */ - getErrorString_: function( + getErrorString_( error, includeStartModifier, tooManyModifiers, needCharacter) { switch (this.error_) { case ShortcutError.INCLUDE_START_MODIFIER: @@ -168,7 +172,7 @@ Polymer({ case ShortcutError.NEED_CHARACTER: return needCharacter; default: - assert(this.error_ == ShortcutError.NO_ERROR); + assert(this.error_ === ShortcutError.NO_ERROR); return ''; } }, @@ -177,7 +181,7 @@ Polymer({ * @param {!KeyboardEvent} e * @private */ - handleKey_: function(e) { + handleKey_(e) { // While capturing, we prevent all events from bubbling, to prevent // shortcuts lacking the right modifier (F3 for example) from activating // and ending capture prematurely. @@ -204,12 +208,17 @@ Polymer({ this.error_ = ShortcutError.NO_ERROR; + IronA11yAnnouncer.requestAvailability(); + this.fire('iron-announce', { + text: this.i18n('shortcutSet', this.computeText_()), + }); + this.commitPending_(); this.endCapture_(); }, /** @private */ - commitPending_: function() { + commitPending_() { this.shortcut = this.pendingShortcut_; this.delegate.updateExtensionCommandKeybinding( this.item, this.commandName, this.shortcut); @@ -219,32 +228,40 @@ Polymer({ * @return {string} The text to be displayed in the shortcut field. * @private */ - computeText_: function() { + computeText_() { const shortcutString = this.capturing_ ? this.pendingShortcut_ : this.shortcut; return shortcutString.split('+').join(' + '); }, /** + * Invisible when capturing AND we have a shortcut. + * @return {boolean} Whether the clear button is invisible. + * @private + */ + computeClearInvisible_() { + return this.capturing_ && !!this.shortcut; + }, + + /** + * Hidden when no shortcut is set. * @return {boolean} Whether the clear button is hidden. * @private */ - computeClearHidden_: function() { - // We don't want to show the clear button if the input is currently - // capturing a new shortcut or if there is no shortcut to clear. - return this.capturing_ || !this.shortcut; + computeClearHidden_() { + return !this.shortcut; }, /** * @return {boolean} * @private */ - getIsInvalid_: function() { - return this.error_ != ShortcutError.NO_ERROR; + getIsInvalid_() { + return this.error_ !== ShortcutError.NO_ERROR; }, /** @private */ - onClearTap_: function() { + onClearTap_() { assert(this.shortcut); this.pendingShortcut_ = ''; diff --git a/chromium/chrome/browser/resources/extensions/shortcut_util.js b/chromium/chrome/browser/resources/extensions/shortcut_util.js index 0f61a402dab..6c20b5bc693 100644 --- a/chromium/chrome/browser/resources/extensions/shortcut_util.js +++ b/chromium/chrome/browser/resources/extensions/shortcut_util.js @@ -78,11 +78,11 @@ function hasModifier(e, countShiftAsModifier) { * @return {boolean} Whether the key is valid. */ export function isValidKeyCode(keyCode) { - if (keyCode == Key.Escape) { + if (keyCode === Key.Escape) { return false; } for (const k in Key) { - if (Key[k] == keyCode) { + if (Key[k] === keyCode) { return true; } } diff --git a/chromium/chrome/browser/resources/extensions/sidebar.js b/chromium/chrome/browser/resources/extensions/sidebar.js index 5252323fb94..93932a8c7d2 100644 --- a/chromium/chrome/browser/resources/extensions/sidebar.js +++ b/chromium/chrome/browser/resources/extensions/sidebar.js @@ -25,23 +25,23 @@ Polymer({ }, /** @override */ - attached: function() { + attached() { this.$.sectionMenu.select( - navigation.getCurrentPage().page == Page.SHORTCUTS ? 1 : 0); + navigation.getCurrentPage().page === Page.SHORTCUTS ? 1 : 0); }, /** * @param {!Event} e * @private */ - onLinkTap_: function(e) { + onLinkTap_(e) { e.preventDefault(); navigation.navigateTo({page: e.target.dataset.path}); this.fire('close-drawer'); }, /** @private */ - onMoreExtensionsTap_: function() { + onMoreExtensionsTap_() { assert(!this.isSupervised); chrome.metricsPrivate.recordUserAction('Options_GetMoreExtensions'); }, diff --git a/chromium/chrome/browser/resources/extensions/toggle_row.html b/chromium/chrome/browser/resources/extensions/toggle_row.html index 68c0a299250..9752fed0ef8 100644 --- a/chromium/chrome/browser/resources/extensions/toggle_row.html +++ b/chromium/chrome/browser/resources/extensions/toggle_row.html @@ -1,6 +1,6 @@ <style> :host { - flex-direction: column; + display: block; touch-action: none; } diff --git a/chromium/chrome/browser/resources/extensions/toggle_row.js b/chromium/chrome/browser/resources/extensions/toggle_row.js index 43be17b5f42..8973cbeaf99 100644 --- a/chromium/chrome/browser/resources/extensions/toggle_row.js +++ b/chromium/chrome/browser/resources/extensions/toggle_row.js @@ -37,7 +37,7 @@ Polymer({ * @param {!Event} e * @private */ - onNativeClick_: function(e) { + onNativeClick_(e) { // Even though the native checkbox is hidden and can't be actually // cilcked/tapped by the user, because it resides within the <label> the // browser emits an extraneous event when the label is clicked. Stop @@ -51,7 +51,7 @@ Polymer({ * @param {!Event} e * @private */ - onNativeChange_: function(e) { + onNativeChange_(e) { e.stopPropagation(); // Sync value of native checkbox and cr-toggle and |checked|. @@ -65,7 +65,7 @@ Polymer({ * @param {!CustomEvent<boolean>} e * @private */ - onCrToggleChange_: function(e) { + onCrToggleChange_(e) { e.stopPropagation(); // Sync value of native checkbox and cr-toggle. diff --git a/chromium/chrome/browser/resources/extensions/toolbar.js b/chromium/chrome/browser/resources/extensions/toolbar.js index ad6b7eae96c..f67703752bb 100644 --- a/chromium/chrome/browser/resources/extensions/toolbar.js +++ b/chromium/chrome/browser/resources/extensions/toolbar.js @@ -33,9 +33,10 @@ export class ToolbarDelegate { /** * Updates all extensions. + * @param {!Array<!chrome.developerPrivate.ExtensionInfo>} extensions * @return {!Promise} */ - updateAllExtensions() {} + updateAllExtensions(extensions) {} } Polymer({ @@ -44,6 +45,9 @@ Polymer({ _template: html`{__html_template__}`, properties: { + /** @type {!Array<!chrome.developerPrivate.ExtensionInfo>} */ + extensions: Array, + /** @type {ToolbarDelegate} */ delegate: Object, @@ -87,7 +91,7 @@ Polymer({ * @return {boolean} * @private */ - shouldDisableDevMode_: function() { + shouldDisableDevMode_() { return this.devModeControlledByPolicy || this.isSupervised; }, @@ -95,7 +99,7 @@ Polymer({ * @return {string} * @private */ - getTooltipText_: function() { + getTooltipText_() { return this.i18n( this.isSupervised ? 'controlledSettingChildRestriction' : 'controlledSettingPolicy'); @@ -105,7 +109,7 @@ Polymer({ * @return {string} * @private */ - getIcon_: function() { + getIcon_() { return this.isSupervised ? 'cr20:kite' : 'cr20:domain'; }, @@ -113,7 +117,7 @@ Polymer({ * @param {!CustomEvent<boolean>} e * @private */ - onDevModeToggleChange_: function(e) { + onDevModeToggleChange_(e) { this.delegate.setProfileInDevMode(e.detail); chrome.metricsPrivate.recordUserAction( 'Options_ToggleDeveloperMode_' + (e.detail ? 'Enabled' : 'Disabled')); @@ -124,7 +128,7 @@ Polymer({ * @param {boolean} previous * @private */ - onInDevModeChanged_: function(current, previous) { + onInDevModeChanged_(current, previous) { const drawer = this.$.devDrawer; if (this.inDevMode) { if (drawer.hidden) { @@ -134,7 +138,7 @@ Polymer({ /** @suppress {suspiciousCode} */ drawer.offsetTop; } } else { - if (previous == undefined) { + if (previous === undefined) { drawer.hidden = true; return; } @@ -149,7 +153,7 @@ Polymer({ }, /** @private */ - onLoadUnpackedTap_: function() { + onLoadUnpackedTap_() { this.delegate.loadUnpacked().catch(loadError => { this.fire('load-error', loadError); }); @@ -157,26 +161,26 @@ Polymer({ }, /** @private */ - onPackTap_: function() { + onPackTap_() { chrome.metricsPrivate.recordUserAction('Options_PackExtension'); this.showPackDialog_ = true; }, /** @private */ - onPackDialogClose_: function() { + onPackDialogClose_() { this.showPackDialog_ = false; this.$.packExtensions.focus(); }, // <if expr="chromeos"> /** @private */ - onKioskTap_: function() { + onKioskTap_() { this.fire('kiosk-tap'); }, // </if> /** @private */ - onUpdateNowTap_: function() { + onUpdateNowTap_() { // If already updating, do not initiate another update. if (this.isUpdating_) { return; @@ -188,16 +192,18 @@ Polymer({ // Keep the toast open indefinitely. toastManager.duration = 0; toastManager.show(this.i18n('toolbarUpdatingToast')); - this.delegate.updateAllExtensions().then( - () => { - toastManager.hide(); - toastManager.duration = 3000; - toastManager.show(this.i18n('toolbarUpdateDone')); - this.isUpdating_ = false; - }, - () => { - toastManager.hide(); - this.isUpdating_ = false; - }); + this.delegate.updateAllExtensions(this.extensions) + .then( + () => { + toastManager.hide(); + toastManager.duration = 3000; + toastManager.show(this.i18n('toolbarUpdateDone')); + this.isUpdating_ = false; + }, + loadError => { + this.fire('load-error', loadError); + toastManager.hide(); + this.isUpdating_ = false; + }); }, }); |