0

Remove chrome://settings and Safety Check cleanup integrations

Since this feature is being deprecated, start by removing the clean
up triggers in UX.

Bug: 1407233
Change-Id: Ie41e9319c0b20a87ef4ff6dd7a537e4e6706565f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4174588
Reviewed-by: Rainhard Findling <rainhard@chromium.org>
Reviewed-by: Rebekah Potter <rbpotter@chromium.org>
Commit-Queue: Daniel Rubery <drubery@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1095733}
This commit is contained in:
Daniel Rubery
2023-01-23 18:53:08 +00:00
committed by Chromium LUCI CQ
parent 3d8e57f8ac
commit 016f9590a7
39 changed files with 110 additions and 3184 deletions
WATCHLISTS
chrome
app
browser
test

@ -697,7 +697,6 @@
},
'chrome_cleaner': {
'filepath': 'chrome/browser/component_updater/sw_reporter_'\
'|chrome/browser/resources/settings/chrome_cleanup_page/'\
'|chrome/browser/safe_browsing/chrome_cleaner/'\
'|chrome/browser/ui/views/chrome_cleaner_'\
'|chrome/browser/ui/webui/settings/chrome_cleanup_'\

@ -2366,54 +2366,6 @@
<message name="IDS_SETTINGS_SAFETY_CHECK_TOAST_UNDO_BUTTON_LABEL" desc="After the user has modified permissions for a website, a toast popup message is shown with this text next to a description of the action taken. The user can click this text to undo the action. For example, this text would be next to a descriptiton that says 'Allowed notification permissions for example.com'.">
Undo
</message>
<if expr="is_win and _google_chrome">
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_PRIMARY_LABEL" desc="'Unwanted software protection' is an element in safety check that finds harmful software installed on the computer and allows users to remove it.">
Device software
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_BUTTON_ARIA_LABEL" desc="Accessiblity text for the button that allows users to review and remove harmful software found on their computer.">
Review device software
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITHOUT_TIMESTAMP" desc="This text describes that Chrome can check if any known harmful software is installed on the user's computer.">
Chrome can check your computer for harmful software
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_AFTER_SECONDS" desc="This text describes that Chrome did not find any known harmful software installed on the user's computer, and that it checked for harmful softwrae the last time a certain time ago.">
Chrome didn't find harmful software on your computer • Checked just now
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_AFTER_MINUTES" desc="This text describes that Chrome did not find any known harmful software installed on the user's computer, and that it checked for harmful softwrae the last time a certain time ago.">
{NUM_MINS, plural,
=1 {Chrome didn't find harmful software on your computer • Checked 1 minute ago}
other {Chrome didn't find harmful software on your computer • Checked {NUM_MINS} minutes ago}}
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_AFTER_HOURS" desc="This text describes that Chrome did not find any known harmful software installed on the user's computer, and that it checked for harmful softwrae the last time a certain time ago.">
{NUM_HOURS, plural,
=1 {Chrome didn't find harmful software on your computer • Checked 1 hour ago}
other {Chrome didn't find harmful software on your computer • Checked {NUM_HOURS} hours ago}}
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_YESTERDAY" desc="This text describes that Chrome did not find any known harmful software installed on the user's computer, and that it checked for harmful softwrae the last time a certain time ago.">
Chrome didn't find harmful software on your computer • Checked yesterday
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_AFTER_DAYS" desc="This text describes that Chrome did not find any known harmful software installed on the user's computer, and that it checked for harmful softwrae the last time a certain time ago.">
{NUM_DAYS, plural,
=1 {Chrome didn't find harmful software on your computer • Checked 1 day ago}
other {Chrome didn't find harmful software on your computer • Checked {NUM_DAYS} days ago}}
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_INFECTED" desc="This text describes that Chrome found harmful software on the computer.">
Chrome found harmful software on your computer
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_SCANNING" desc="This text describes that Chrome is currently checking the user's device for unwanted software. This takes a couple of minutes.">
Chrome is checking your computer for harmful software...
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_REMOVING" desc="This text describes that Chrome is currently removing unwanted software frrom the user.s device. This takes a couple of minutes.">
Chrome is removing harmful software from your computer...
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_DISABLED_BY_ADMIN" desc="This text describes that Chrome can't check for unwanted software because an administrator disabled the feature.">
<ph name="BEGIN_LINK">&lt;a target="_blank" href="$1"&gt;</ph>Your administrator<ph name="END_LINK">&lt;/a&gt;</ph> has turned off checking for harmful software
</message>
<message name="IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_ERROR" desc="This text describes that Chrome can't check for unwanted software due to an error.">
Something went wrong. Click for more details.
</message>
</if>
<message name="IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_LABEL" desc="In the advanced options tab, the text next to the checkbox that enables prediction of network actions. Actions include browser-initiated DNS prefetching, TCP and SSL preconnection, and prerendering of webpages.">
Preload pages for faster browsing and searching
</message>

@ -256,9 +256,6 @@ build_webui("build") {
if (is_win) {
web_component_files += [
"safety_check_page/safety_check_chrome_cleaner_child.ts",
"chrome_cleanup_page/chrome_cleanup_page.ts",
"chrome_cleanup_page/items_to_remove_list.ts",
"incompatible_applications_page/incompatible_application_item.ts",
"incompatible_applications_page/incompatible_applications_page.ts",
]
@ -370,10 +367,7 @@ build_webui("build") {
}
if (is_win) {
non_web_component_files += [
"chrome_cleanup_page/chrome_cleanup_proxy.ts",
"incompatible_applications_page/incompatible_applications_browser_proxy.ts",
]
non_web_component_files += [ "incompatible_applications_page/incompatible_applications_browser_proxy.ts" ]
}
if (is_win || is_mac) {
non_web_component_files += [ "autofill_page/passkeys_browser_proxy.ts" ]

@ -1,79 +0,0 @@
<style include="cr-shared-style settings-shared iron-flex">
#status-title {
font-weight: 500;
}
#waiting-spinner {
flex-shrink: 0;
height: 2.0em;
width: 2.0em;
}
/* Apply a fixed height to the <svg> tag inside #powered-by-logo.
Used by |chromeCleanupPoweredByHTML|. */
#powered-by-logo > svg {
height: 22px;
}
</style>
<div class="cr-row first">
<div class="flex">
<div id="status-title" role="status" inner-h-t-m-l="[[title_]]"></div>
<div hidden="[[!showExplanation_]]">
<span class="secondary">[[explanation_]]</span>
</div>
</div>
<paper-spinner-lite id="waiting-spinner"
hidden="[[!isWaitingForResult_]]" active="[[isWaitingForResult_]]">
</paper-spinner-lite>
<template is="dom-if" if="[[showActionButton_]]">
<cr-policy-pref-indicator pref="[[prefs.software_reporter.enabled]]">
</cr-policy-pref-indicator>
<div class="separator"></div>
<cr-button id="action-button" class="action-button"
disabled$="[[!cleanupEnabled_]]" on-click="proceed_">
[[actionButtonLabel_]]
</cr-button>
</template>
</div>
<div class="cr-row continuation">
<settings-checkbox hidden="[[!showLogsPermission_]]"
id="chromeCleanupLogsUploadControl"
sub-label="$i18n{chromeCleanupExplanationLogsPermissionPref}"
pref="{{prefs.software_reporter.reporting}}"
disabled$="[[!cleanupEnabled_]]">
</settings-checkbox>
</div>
<cr-expand-button
aria-label="[[showItemsLinkLabel_]]"
class="cr-row"
expanded="{{itemsToRemoveSectionExpanded_}}"
hidden="[[!showItemsToRemove_]]"
id="show-items-button">
[[showItemsLinkLabel_]]
</cr-expand-button>
<iron-collapse id="iron-collapse-items"
opened="[[itemsToRemoveSectionExpanded_]]">
<items-to-remove-list
id="files-to-remove-list"
hidden="[[!hasFilesToShow_]]"
title="$i18n{chromeCleanupDetailsFilesAndPrograms}"
items-to-show="[[
getListEntriesFromFilePaths_(scannerResults_.files)]]">
</items-to-remove-list>
<items-to-remove-list
id="registry-keys-list"
hidden="[[!hasRegistryKeysToShow_]]"
title="$i18n{chromeCleanupDetailsRegistryEntries}"
items-to-show="[[
getListEntriesFromStrings_(scannerResults_.registryKeys)]]">
</items-to-remove-list>
<div class="cr-row continuation">
<div class="secondary">
$i18nRaw{chromeCleanupDetailsExplanation}
</div>
</div>
<div id="powered-by" class="cr-row continuation"
hidden="[[!isPoweredByPartner_]]">
$i18nRaw{chromeCleanupPoweredByHtml}
</div>
</iron-collapse>

@ -1,744 +0,0 @@
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.js';
import 'chrome://resources/cr_elements/policy/cr_policy_pref_indicator.js';
import 'chrome://resources/cr_elements/cr_shared_style.css.js';
import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
import 'chrome://resources/polymer/v3_0/paper-spinner/paper-spinner-lite.js';
import 'chrome://resources/polymer/v3_0/paper-styles/color.js';
import '../controls/controlled_button.js';
import '../controls/settings_checkbox.js';
import '../prefs/prefs.js';
import '../settings_shared.css.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
import {assert} from 'chrome://resources/js/assert_ts.js';
import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {SettingsCheckboxElement} from '../controls/settings_checkbox.js';
import {getTemplate} from './chrome_cleanup_page.html.js';
import {ChromeCleanupProxy, ChromeCleanupProxyImpl} from './chrome_cleanup_proxy.js';
import {ChromeCleanupRemovalListItem} from './items_to_remove_list.js';
/**
* The reason why the controller is in state kIdle.
* Must be kept in sync with ChromeCleanerController::IdleReason.
*/
export enum ChromeCleanupIdleReason {
INITIAL = 'initial',
REPORTER_FOUND_NOTHING = 'reporter_found_nothing',
REPORTER_FAILED = 'reporter_failed',
SCANNING_FOUND_NOTHING = 'scanning_found_nothing',
SCANNING_FAILED = 'scanning_failed',
CONNECTION_LOST = 'connection_lost',
USER_DECLINED_CLEANUP = 'user_declined_cleanup',
CLEANING_FAILED = 'cleaning_failed',
CLEANING_SUCCEEDED = 'cleaning_succeeded',
CLEANER_DOWNLOAD_FAILED = 'cleaner_download_failed',
}
/**
* The possible states for the cleanup card.
*/
enum ChromeCleanerCardState {
SCANNING_OFFERED = 'scanning_offered',
SCANNING = 'scanning',
CLEANUP_OFFERED = 'cleanup_offered',
CLEANING = 'cleaning',
REBOOT_REQUIRED = 'reboot_required',
SCANNING_FOUND_NOTHING = 'scanning_found_nothing',
SCANNING_FAILED = 'scanning_failed',
CLEANUP_SUCCEEDED = 'cleanup_succeeded',
CLEANING_FAILED = 'cleanup_failed',
CLEANER_DOWNLOAD_FAILED = 'cleaner_download_failed',
}
/**
* Boolean properties for a cleanup card state.
*/
enum ChromeCleanupCardFlags {
NONE = 0,
SHOW_LOGS_PERMISSIONS = 1 << 0,
WAITING_FOR_RESULT = 1 << 1,
SHOW_ITEMS_TO_REMOVE = 1 << 2,
}
/**
* Identifies an ongoing scanning/cleanup action.
*/
enum ChromeCleanupOngoingAction {
NONE = 0,
SCANNING = 1,
CLEANING = 2,
}
interface ChromeCleanupCardActionButton {
label: string;
doAction: () => void;
}
interface ChromeCleanupCardComponents {
title: string|null;
explanation: string|null;
actionButton: ChromeCleanupCardActionButton|null;
flags: number;
}
/**
* Represents the file path structure of a base::FilePath.
* dirname ends with a separator.
*/
export interface ChromeCleanupFilePath {
dirname: string;
basename: string;
}
export interface ChromeCleanerScannerResults {
files: ChromeCleanupFilePath[];
registryKeys: string[];
}
/**
* @fileoverview
* 'settings-chrome-cleanup-page' is the settings page containing Chrome
* Cleanup settings.
*
* Example:
*
* <iron-animated-pages>
* <settings-chrome-cleanup-page></settings-chrome-cleanup-page>
* ... other pages ...
* </iron-animated-pages>
*/
export interface SettingsChromeCleanupPageElement {
$: {
chromeCleanupLogsUploadControl: SettingsCheckboxElement,
chromeCleanupShowNotificationControl: SettingsCheckboxElement,
};
}
const SettingsChromeCleanupPageElementBase =
WebUiListenerMixin(I18nMixin(PolymerElement));
export class SettingsChromeCleanupPageElement extends
SettingsChromeCleanupPageElementBase {
static get is() {
return 'settings-chrome-cleanup-page';
}
static get template() {
return getTemplate();
}
static get properties() {
return {
/**
* Preferences state.
*/
prefs: {
type: Object,
notify: true,
},
title_: {
type: String,
value: '',
},
explanation_: {
type: String,
value: '',
},
isWaitingForResult_: {
type: Boolean,
value: '',
},
showActionButton_: {
type: Boolean,
value: false,
},
cleanupEnabled_: {
type: Boolean,
value: true,
},
actionButtonLabel_: {
type: String,
value: '',
},
showExplanation_: {
type: Boolean,
computed: 'computeShowExplanation_(explanation_)',
},
showLogsPermission_: {
type: Boolean,
value: false,
},
showItemsToRemove_: {
type: Boolean,
value: false,
},
itemsToRemoveSectionExpanded_: {
type: Boolean,
value: false,
observer: 'itemsToRemoveSectionExpandedChanged_',
},
showItemsLinkLabel_: {
type: String,
value: '',
},
showingAllFiles_: {
type: Boolean,
value: false,
},
scannerResults_: {
type: Object,
value() {
return {'files': [], 'registryKeys': []};
},
},
hasFilesToShow_: {
type: Boolean,
computed: 'computeHasFilesToShow_(scannerResults_)',
},
hasRegistryKeysToShow_: {
type: Boolean,
computed: 'computeHasRegistryKeysToShow_(scannerResults_)',
},
logsUploadPref_: {
type: Object,
value() {
return {};
},
},
isPoweredByPartner_: {
type: Boolean,
value: false,
},
/**
* Virtual pref that's attached to the notification checkbox.
*/
notificationEnabledPref_: {
type: Object,
value() {
return {
type: chrome.settingsPrivate.PrefType.BOOLEAN,
value: false,
};
},
},
};
}
prefs: {software_reporter: {reporting: chrome.settingsPrivate.PrefObject}};
private title_: TrustedHTML;
private explanation_: string;
private isWaitingForResult_: boolean;
private showActionButton_: boolean;
private cleanupEnabled_: boolean;
private actionButtonLabel_: string;
private showExplanation_: boolean;
private showLogsPermission_: boolean;
private showNotificationPermission_: boolean;
private showItemsToRemove_: boolean;
private itemsToRemoveSectionExpanded_: boolean;
private showItemsLinkLabel_: string;
private showingAllFiles_: boolean;
private scannerResults_: ChromeCleanerScannerResults;
private hasFilesToShow_: boolean;
private hasRegistryKeysToShow_: boolean;
private logsUploadPref_: chrome.settingsPrivate.PrefObject;
private isPoweredByPartner_: boolean;
private notificationEnabledPref_: chrome.settingsPrivate.PrefObject;
private emptyChromeCleanerScannerResults_:
ChromeCleanerScannerResults = {files: [], registryKeys: []};
private browserProxy_: ChromeCleanupProxy =
ChromeCleanupProxyImpl.getInstance();
private doAction_: (() => void)|null = null;
private cardStateToComponentsMap_:
Map<ChromeCleanerCardState, ChromeCleanupCardComponents>|null = null;
private ongoingAction_: ChromeCleanupOngoingAction =
ChromeCleanupOngoingAction.NONE;
private renderScanOfferedByDefault_: boolean;
constructor() {
super();
/**
* If true; the scan offered view is rendered on state idle, regardless of
* the idle reason received from the cleaner controller. The goal is to
* ignore previous interactions (such as completed cleanups) performed on
* other tabs or if this tab is reloaded.
* Set to false whenever there is a transition to a non-idle state while the
* current tab is open.
*/
this.renderScanOfferedByDefault_ = true;
}
override connectedCallback() {
super.connectedCallback();
this.cardStateToComponentsMap_ = this.buildCardStateToComponentsMap_();
this.addWebUiListener(
'chrome-cleanup-on-idle',
(idleReason: string) => this.onIdle_(idleReason));
this.addWebUiListener(
'chrome-cleanup-on-scanning', () => this.onScanning_());
// Note: both reporter running and scanning share the same UI.
this.addWebUiListener(
'chrome-cleanup-on-reporter-running', () => this.onScanning_());
this.addWebUiListener(
'chrome-cleanup-on-infected',
(isPoweredByPartner: boolean,
scannerResults: ChromeCleanerScannerResults) =>
this.onInfected_(isPoweredByPartner, scannerResults));
this.addWebUiListener(
'chrome-cleanup-on-cleaning',
(isPoweredByPartner: boolean,
scannerResults: ChromeCleanerScannerResults) =>
this.onCleaning_(isPoweredByPartner, scannerResults));
this.addWebUiListener(
'chrome-cleanup-on-reboot-required', () => this.onRebootRequired_());
this.addWebUiListener(
'chrome-cleanup-enabled-change',
(enabled: boolean) => this.onCleanupEnabledChange_(enabled));
this.browserProxy_.registerChromeCleanerObserver();
}
/**
* Implements the action for the only visible button in the UI, which can be
* either to start an action such as a cleanup or to restart the computer.
*/
private proceed_() {
this.doAction_!();
}
/**
* Notifies Chrome that the details section was opened or closed.
*/
private itemsToRemoveSectionExpandedChanged_(
newVal: boolean, oldVal: boolean) {
if (!oldVal && newVal) {
this.browserProxy_.notifyShowDetails(this.itemsToRemoveSectionExpanded_);
}
}
private computeShowExplanation_(explanation: string): boolean {
return explanation !== '';
}
/**
* @param scannerResults The cleanup items to be presented to the user.
* @return Whether there are files to show to the user.
*/
private computeHasFilesToShow_(scannerResults: ChromeCleanerScannerResults):
boolean {
return scannerResults.files.length > 0;
}
/**
* @param scannerResults The cleanup items to be presented to the user.
* @return Whether user-initiated cleanups are enabled and there are registry
* keys to show to the user.
*/
private computeHasRegistryKeysToShow_(
scannerResults: ChromeCleanerScannerResults): boolean {
return scannerResults.registryKeys.length > 0;
}
/**
* Listener of event 'chrome-cleanup-on-idle'.
*/
private onIdle_(idleReason: string) {
const lastAction = this.ongoingAction_;
this.ongoingAction_ = ChromeCleanupOngoingAction.NONE;
this.scannerResults_ = this.emptyChromeCleanerScannerResults_;
// Ignore the idle reason and render the scan offered view if no
// interaction happened on this tab.
if (this.renderScanOfferedByDefault_) {
idleReason = ChromeCleanupIdleReason.INITIAL;
}
switch (idleReason) {
case ChromeCleanupIdleReason.INITIAL:
this.renderCleanupCard_(ChromeCleanerCardState.SCANNING_OFFERED);
break;
case ChromeCleanupIdleReason.SCANNING_FOUND_NOTHING:
case ChromeCleanupIdleReason.REPORTER_FOUND_NOTHING:
this.renderCleanupCard_(ChromeCleanerCardState.SCANNING_FOUND_NOTHING);
break;
case ChromeCleanupIdleReason.SCANNING_FAILED:
case ChromeCleanupIdleReason.REPORTER_FAILED:
this.renderCleanupCard_(ChromeCleanerCardState.SCANNING_FAILED);
break;
case ChromeCleanupIdleReason.CONNECTION_LOST:
if (lastAction === ChromeCleanupOngoingAction.SCANNING) {
this.renderCleanupCard_(ChromeCleanerCardState.SCANNING_FAILED);
} else {
assert(lastAction === ChromeCleanupOngoingAction.CLEANING);
this.renderCleanupCard_(ChromeCleanerCardState.CLEANING_FAILED);
}
break;
case ChromeCleanupIdleReason.CLEANING_FAILED:
case ChromeCleanupIdleReason.USER_DECLINED_CLEANUP:
this.renderCleanupCard_(ChromeCleanerCardState.CLEANING_FAILED);
break;
case ChromeCleanupIdleReason.CLEANING_SUCCEEDED:
this.renderCleanupCard_(ChromeCleanerCardState.CLEANUP_SUCCEEDED);
break;
case ChromeCleanupIdleReason.CLEANER_DOWNLOAD_FAILED:
this.renderCleanupCard_(ChromeCleanerCardState.CLEANER_DOWNLOAD_FAILED);
break;
default:
assert(false, `Unknown idle reason: ${idleReason}`);
}
}
/**
* Listener of event 'chrome-cleanup-on-scanning'.
* No UI will be shown in the Settings page on that state, simply hide the
* card and cleanup this element's fields.
*/
private onScanning_() {
this.ongoingAction_ = ChromeCleanupOngoingAction.SCANNING;
this.scannerResults_ = this.emptyChromeCleanerScannerResults_;
this.renderScanOfferedByDefault_ = false;
this.renderCleanupCard_(ChromeCleanerCardState.SCANNING);
}
/**
* Listener of event 'chrome-cleanup-on-infected'.
* Offers a cleanup to the user and enables presenting files to be removed.
* @param isPoweredByPartner If scanning results are provided by a partner's
* engine.
* @param scannerResults The cleanup items to be presented to the user.
*/
private onInfected_(
isPoweredByPartner: boolean,
scannerResults: ChromeCleanerScannerResults) {
this.isPoweredByPartner_ = isPoweredByPartner;
this.ongoingAction_ = ChromeCleanupOngoingAction.NONE;
this.renderScanOfferedByDefault_ = false;
this.scannerResults_ = scannerResults;
this.updateShowItemsLinklabel_();
this.renderCleanupCard_(ChromeCleanerCardState.CLEANUP_OFFERED);
}
/**
* Listener of event 'chrome-cleanup-on-cleaning'.
* Shows a spinner indicating that an on-going action and enables presenting
* files to be removed.
* @param isPoweredByPartner If scanning results are provided by a partner's
* engine.
* @param scannerResults The cleanup items to be presented to the user.
*/
private onCleaning_(
isPoweredByPartner: boolean,
scannerResults: ChromeCleanerScannerResults) {
this.isPoweredByPartner_ = isPoweredByPartner;
this.ongoingAction_ = ChromeCleanupOngoingAction.CLEANING;
this.renderScanOfferedByDefault_ = false;
this.scannerResults_ = scannerResults;
this.updateShowItemsLinklabel_();
this.renderCleanupCard_(ChromeCleanerCardState.CLEANING);
}
/**
* Listener of event 'chrome-cleanup-on-reboot-required'.
* No UI will be shown in the Settings page on that state, so we simply hide
* the card and cleanup this element's fields.
*/
private onRebootRequired_() {
this.ongoingAction_ = ChromeCleanupOngoingAction.NONE;
this.scannerResults_ = this.emptyChromeCleanerScannerResults_;
this.renderScanOfferedByDefault_ = false;
this.renderCleanupCard_(ChromeCleanerCardState.REBOOT_REQUIRED);
}
/**
* Renders the cleanup card given the state and list of files.
* @param state The card state to be rendered.
*/
private renderCleanupCard_(state: ChromeCleanerCardState) {
const components = this.cardStateToComponentsMap_!.get(state);
assert(components);
this.title_ = components.title === null ?
window.trustedTypes!.emptyHTML :
sanitizeInnerHtml(components.title);
this.explanation_ = components.explanation || '';
this.updateActionButton_(components.actionButton);
this.updateCardFlags_(components.flags);
}
/**
* Updates the action button on the cleanup card as the action expected for
* the current state.
* @param actionButton The button to render, or null if no button should be
* shown.
*/
private updateActionButton_(actionButton: ChromeCleanupCardActionButton|
null) {
if (!actionButton) {
this.showActionButton_ = false;
this.actionButtonLabel_ = '';
this.doAction_ = null;
} else {
this.showActionButton_ = true;
this.actionButtonLabel_ = actionButton.label;
this.doAction_ = actionButton.doAction;
}
}
/**
* Updates boolean flags corresponding to optional components to be rendered
* on the card.
* @param flags Flags indicating optional components to be rendered.
*/
private updateCardFlags_(flags: number) {
this.showLogsPermission_ =
(flags & ChromeCleanupCardFlags.SHOW_LOGS_PERMISSIONS) !== 0;
this.isWaitingForResult_ =
(flags & ChromeCleanupCardFlags.WAITING_FOR_RESULT) !== 0;
this.showItemsToRemove_ =
(flags & ChromeCleanupCardFlags.SHOW_ITEMS_TO_REMOVE) !== 0;
// Files to remove list should only be expandable if details are being
// shown, otherwise it will add extra padding at the bottom of the card.
if (!this.showExplanation_ || !this.showItemsToRemove_) {
this.itemsToRemoveSectionExpanded_ = false;
}
}
/**
* @param enabled Whether cleanup is enabled.
*/
private onCleanupEnabledChange_(enabled: boolean) {
this.cleanupEnabled_ = enabled;
}
/**
* Sends an action to the browser proxy to start scanning.
*/
private startScanning_() {
this.browserProxy_.startScanning(
this.$.chromeCleanupLogsUploadControl.checked);
}
/**
* Sends an action to the browser proxy to start the cleanup.
*/
private startCleanup_() {
this.browserProxy_.startCleanup(
this.$.chromeCleanupLogsUploadControl.checked);
}
/**
* Sends an action to the browser proxy to restart the machine.
*/
private restartComputer_() {
this.browserProxy_.restartComputer();
}
/**
* Updates the label for the collapsed detailed view. If user-initiated
* cleanups are enabled, the string is obtained from the browser proxy,
* since it may require a plural version. Otherwise, use the default value
* for |chromeCleanupLinkShowItems|.
*/
private updateShowItemsLinklabel_() {
const setShowItemsLabel = (text: string) => this.showItemsLinkLabel_ = text;
this.browserProxy_
.getItemsToRemovePluralString(
this.scannerResults_.files.length +
this.scannerResults_.registryKeys.length)
.then(setShowItemsLabel);
}
/**
* @return The map of card states to components to be rendered.
*/
private buildCardStateToComponentsMap_():
Map<ChromeCleanerCardState, ChromeCleanupCardComponents> {
/**
* The action buttons to show on the card.
* @enum {ChromeCleanupCardActionButton}
*/
const actionButtons = {
FIND: {
label: this.i18n('chromeCleanupFindButtonLabel'),
doAction: () => this.startScanning_(),
},
REMOVE: {
label: this.i18n('chromeCleanupRemoveButtonLabel'),
doAction: () => this.startCleanup_(),
},
RESTART_COMPUTER: {
label: this.i18n('chromeCleanupRestartButtonLabel'),
doAction: () => this.restartComputer_(),
},
TRY_SCAN_AGAIN: {
label: this.i18n('chromeCleanupTitleTryAgainButtonLabel'),
// TODO(crbug.com/776538): do not run the reporter component again.
// Try downloading the cleaner and scan with it instead.
doAction: () => this.startScanning_(),
},
};
return new Map([
[
ChromeCleanerCardState.CLEANUP_OFFERED,
{
title: this.i18n('chromeCleanupTitleRemove'),
explanation: this.i18n('chromeCleanupExplanationRemove'),
actionButton: actionButtons.REMOVE,
flags: ChromeCleanupCardFlags.SHOW_LOGS_PERMISSIONS |
ChromeCleanupCardFlags.SHOW_ITEMS_TO_REMOVE,
},
],
[
ChromeCleanerCardState.CLEANING,
{
title: this.i18n('chromeCleanupTitleRemoving'),
explanation: this.i18n('chromeCleanupExplanationRemoving'),
actionButton: null,
flags: ChromeCleanupCardFlags.WAITING_FOR_RESULT |
ChromeCleanupCardFlags.SHOW_ITEMS_TO_REMOVE,
},
],
[
ChromeCleanerCardState.REBOOT_REQUIRED,
{
title: this.i18n('chromeCleanupTitleRestart'),
explanation: null,
actionButton: actionButtons.RESTART_COMPUTER,
flags: ChromeCleanupCardFlags.NONE,
},
],
[
ChromeCleanerCardState.CLEANUP_SUCCEEDED,
{
title: this.i18nAdvanced('chromeCleanupTitleRemoved', {tags: ['a']})
.toString(),
explanation: null,
actionButton: null,
flags: ChromeCleanupCardFlags.NONE,
},
],
[
ChromeCleanerCardState.CLEANING_FAILED,
{
title: this.i18n('chromeCleanupTitleErrorCantRemove'),
explanation: this.i18n('chromeCleanupExplanationCleanupError'),
actionButton: null,
flags: ChromeCleanupCardFlags.NONE,
},
],
[
ChromeCleanerCardState.SCANNING_OFFERED,
{
title: this.i18n('chromeCleanupTitleFindAndRemove'),
explanation: this.i18n('chromeCleanupExplanationFindAndRemove'),
actionButton: actionButtons.FIND,
flags: ChromeCleanupCardFlags.SHOW_LOGS_PERMISSIONS,
},
],
[
ChromeCleanerCardState.SCANNING,
{
title: this.i18n('chromeCleanupTitleScanning'),
explanation: null,
actionButton: null,
flags: ChromeCleanupCardFlags.WAITING_FOR_RESULT,
},
],
[
// TODO(crbug.com/776538): Could we offer to reset settings here?
ChromeCleanerCardState.SCANNING_FOUND_NOTHING,
{
title: this.i18n('chromeCleanupTitleNothingFound'),
explanation: null,
actionButton: null,
flags: ChromeCleanupCardFlags.NONE,
},
],
[
ChromeCleanerCardState.SCANNING_FAILED,
{
title: this.i18n('chromeCleanupTitleScanningFailed'),
explanation: this.i18n('chromeCleanupExplanationScanError'),
actionButton: null,
flags: ChromeCleanupCardFlags.NONE,
},
],
[
ChromeCleanerCardState.CLEANER_DOWNLOAD_FAILED,
{
// TODO(crbug.com/776538): distinguish between missing network
// connectivity and cleanups being disabled by the server.
title: this.i18n('chromeCleanupTitleCleanupUnavailable'),
explanation: this.i18n('chromeCleanupExplanationCleanupUnavailable'),
actionButton: actionButtons.TRY_SCAN_AGAIN,
flags: ChromeCleanupCardFlags.NONE,
},
],
]);
}
private getListEntriesFromStrings_(list: string[]):
ChromeCleanupRemovalListItem[] {
return list.map(entry => ({text: entry, highlightSuffix: null}));
}
private getListEntriesFromFilePaths_(paths: ChromeCleanupFilePath[]):
ChromeCleanupRemovalListItem[] {
return paths.map(
path => ({text: path.dirname, highlightSuffix: path.basename}));
}
}
declare global {
interface HTMLElementTagNameMap {
'settings-chrome-cleanup-page': SettingsChromeCleanupPageElement;
}
}
customElements.define(
SettingsChromeCleanupPageElement.is, SettingsChromeCleanupPageElement);

@ -1,96 +0,0 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// clang-format off
import {sendWithPromise} from 'chrome://resources/js/cr.js';
// clang-format on
export interface ChromeCleanupProxy {
/**
* Registers the current ChromeCleanupHandler as an observer of
* ChromeCleanerController events.
*/
registerChromeCleanerObserver(): void;
/**
* Starts scanning the user's computer.
*/
startScanning(logsUploadEnabled: boolean): void;
/**
* Starts a cleanup on the user's computer.
*/
startCleanup(logsUploadEnabled: boolean): void;
/**
* Restarts the user's computer.
*/
restartComputer(): void;
/**
* Notifies Chrome that the state of the details section changed.
*/
notifyShowDetails(enabled: boolean): void;
/**
* Notifies Chrome that the "learn more" link was clicked.
*/
notifyLearnMoreClicked(): void;
/**
* Requests the plural string for the "show more" link in the detailed
* view for either files to delete or registry keys.
*/
getMoreItemsPluralString(numHiddenItems: number): Promise<string>;
/**
* Requests the plural string for the "items to remove" link in the detailed
* view.
*/
getItemsToRemovePluralString(numItems: number): Promise<string>;
}
export class ChromeCleanupProxyImpl implements ChromeCleanupProxy {
registerChromeCleanerObserver() {
chrome.send('registerChromeCleanerObserver');
}
startScanning(logsUploadEnabled: boolean) {
chrome.send('startScanning', [logsUploadEnabled]);
}
startCleanup(logsUploadEnabled: boolean) {
chrome.send('startCleanup', [logsUploadEnabled]);
}
restartComputer() {
chrome.send('restartComputer');
}
notifyShowDetails(enabled: boolean) {
chrome.send('notifyShowDetails', [enabled]);
}
notifyLearnMoreClicked() {
chrome.send('notifyChromeCleanupLearnMoreClicked');
}
getMoreItemsPluralString(numHiddenItems: number) {
return sendWithPromise('getMoreItemsPluralString', numHiddenItems);
}
getItemsToRemovePluralString(numItems: number) {
return sendWithPromise('getItemsToRemovePluralString', numItems);
}
static getInstance(): ChromeCleanupProxy {
return instance || (instance = new ChromeCleanupProxyImpl());
}
static setInstance(obj: ChromeCleanupProxy) {
instance = obj;
}
}
let instance: ChromeCleanupProxy|null = null;

@ -1,55 +0,0 @@
<style include="settings-shared">
:host {
display: block;
margin: 0;
padding: 0 var(--cr-section-padding);
word-break: break-all;
}
#more-items-link {
color: var(--cr-link-color);
cursor: pointer;
}
#remaining-list :first-child {
margin-top: -1em;
}
.highlight-suffix {
font-weight: bold;
}
</style>
<div id="title" class="secondary">[[title]]</div>
<ul class="secondary">
<template is="dom-repeat" items="[[initialItems_]]">
<li class="visible-item">
<span>[[item.text]]</span><!--
--><span class="highlight-suffix"
hidden="[[!hasHighlightSuffix_(item)]]"><!--
-->[[item.highlightSuffix]]
</span>
</li>
</template>
<li id="more-items-link" hidden="[[expanded_]]" on-click="expandList_">
[[moreItemsLinkText_]]
</li>
</ul>
<!-- Remaining items are kept in a separate <ul> element so that screen
readers don't get confused when the list is expanded. If new items are
simply added to the first <ul> element, the first new item (which will
replace the "N more" link), will be skipped by the reader. As a
consequence, visual impaired users will only have a chance to inspect
that item if they move up on the list, which can't be considered an
expected action. -->
<ul id="remaining-list" hidden="[[!expanded_]]" class="secondary">
<template is="dom-repeat" items="[[remainingItems_]]">
<li class$="[[remainingItemsClass_(expanded_)]]">
<span>[[item.text]]</span><!--
--><span class="highlight-suffix"
hidden="[[!hasHighlightSuffix_(item)]]"><!--
-->[[item.highlightSuffix]]
</span>
</li>
</template>
</ul>

@ -1,163 +0,0 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
import 'chrome://resources/polymer/v3_0/paper-styles/color.js';
import '../settings_shared.css.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {ChromeCleanupProxyImpl} from './chrome_cleanup_proxy.js';
import {getTemplate} from './items_to_remove_list.html.js';
/**
* For each line in the item list, the text field will be shown in normal
* style at front of the line. The highlightSuffix will be appended to the end
* of line and emphasized with bold font.
*/
export interface ChromeCleanupRemovalListItem {
text: string;
highlightSuffix: string|null;
}
/**
* The default number of items to show for files, registry keys and extensions
* on the detailed view when user-initiated cleanups are enabled.
*/
export const CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW: number = 4;
/**
* @fileoverview
* 'items-to-remove-list' represents a list of items to
* be removed or changed to be shown on the Chrome Cleanup page.
* TODO(crbug.com/776538): Update the strings to say that some items are only
* changed and not removed.
*
* Example:
*
* <!-- Items list initially shows |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW|
* items. If there are more than
* |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW| items on the list, then a "show
* more" link is shown; tapping on it expands the list. -->
* <items-to-remove-list
* title="Files and programs:"
* items-to-show="[[filesToShow]]">
* </items-to-remove-list>
*/
export class ItemsToRemoveListElement extends PolymerElement {
static get is() {
return 'items-to-remove-list';
}
static get template() {
return getTemplate();
}
static get properties() {
return {
title: {
type: String,
value: '',
},
itemsToShow: {
type: Array,
observer: 'updateVisibleState_',
},
/**
* If true, all items from |itemsToShow| will be presented on the card,
* and the "show more" link will be omitted.
*/
expanded_: {
type: Boolean,
value: false,
},
/**
* The first |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW| items of |itemsToShow|
* if the list is longer than |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW|.
*/
initialItems_: Array,
/**
* The remaining items to be presented that are not included in
* |initialItems_|. Items in this list are only shown to the user if
* |expanded_| is true.
*/
remainingItems_: Array,
/**
* The text for the "show more" link available if not all files are
* visible in the card.
*/
moreItemsLinkText_: {
type: String,
value: '',
},
};
}
override title: string;
itemsToShow: ChromeCleanupRemovalListItem[];
private expanded_: boolean;
private initialItems_: ChromeCleanupRemovalListItem[]|null;
private remainingItems_: ChromeCleanupRemovalListItem[]|null;
private moreItemsLinkText_: string;
private expandList_() {
this.expanded_ = true;
this.moreItemsLinkText_ = '';
}
/**
* Decides which elements will be visible in the card and if the "show more"
* link will be rendered.
*
* 1. If size(itemsToShow) < CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW, then all
* items will be visible.
* 2. Otherwise, exactly |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW - 1| will be
* visible and the "show more" link will be rendered. The list presented
* to the user will contain exactly |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW|
* elements, and the last one will be the "show more" link.
*/
private updateVisibleState_(itemsToShow: ChromeCleanupRemovalListItem[]) {
// Start expanded if there are less than
// |CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW| items to show.
this.expanded_ = itemsToShow.length <= CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW;
if (this.expanded_) {
this.initialItems_ = itemsToShow;
this.remainingItems_ = [];
this.moreItemsLinkText_ = '';
return;
}
this.initialItems_ =
itemsToShow.slice(0, CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW - 1);
this.remainingItems_ =
itemsToShow.slice(CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW - 1);
const browserProxy = ChromeCleanupProxyImpl.getInstance();
browserProxy.getMoreItemsPluralString(this.remainingItems_.length)
.then(linkText => {
this.moreItemsLinkText_ = linkText;
});
}
/**
* Returns the class for the <li> elements that correspond to the items
* hidden in the default view.
*/
private remainingItemsClass_(expanded: boolean): string {
return expanded ? 'visible-item' : 'hidden-item';
}
private hasHighlightSuffix_(item: ChromeCleanupRemovalListItem): boolean {
return item.highlightSuffix !== null;
}
}
customElements.define(ItemsToRemoveListElement.is, ItemsToRemoveListElement);

@ -116,11 +116,6 @@ export {PasswordsSectionElement} from './autofill_page/passwords_section.js';
export {PaymentsManagerImpl, PaymentsManagerProxy} from './autofill_page/payments_manager_proxy.js';
export {SettingsPaymentsSectionElement} from './autofill_page/payments_section.js';
export {SettingsVirtualCardUnenrollDialogElement} from './autofill_page/virtual_card_unenroll_dialog.js';
// <if expr="_google_chrome and is_win">
export {ChromeCleanerScannerResults, ChromeCleanupFilePath, ChromeCleanupIdleReason, SettingsChromeCleanupPageElement} from './chrome_cleanup_page/chrome_cleanup_page.js';
export {ChromeCleanupProxy, ChromeCleanupProxyImpl} from './chrome_cleanup_page/chrome_cleanup_proxy.js';
export {CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW, ItemsToRemoveListElement} from './chrome_cleanup_page/items_to_remove_list.js';
// </if>
export {ClearBrowsingDataBrowserProxy, ClearBrowsingDataBrowserProxyImpl, ClearBrowsingDataResult, UpdateSyncStateEvent} from './clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js';
export {SettingsClearBrowsingDataDialogElement} from './clear_browsing_data_dialog/clear_browsing_data_dialog.js';
export {SettingsHistoryDeletionDialogElement} from './clear_browsing_data_dialog/history_deletion_dialog.js';

@ -56,11 +56,14 @@ export enum SafetyCheckInteractions {
PASSWORDS_MANAGE_COMPROMISED_PASSWORDS = 2,
SAFE_BROWSING_MANAGE = 3,
EXTENSIONS_REVIEW = 4,
// Deprecated in https://crbug.com/1407233.
CHROME_CLEANER_REBOOT = 5,
// Deprecated in https://crbug.com/1407233.
CHROME_CLEANER_REVIEW_INFECTED_STATE = 6,
PASSWORDS_CARET_NAVIGATION = 7,
SAFE_BROWSING_CARET_NAVIGATION = 8,
EXTENSIONS_CARET_NAVIGATION = 9,
// Deprecated in https://crbug.com/1407233.
CHROME_CLEANER_CARET_NAVIGATION = 10,
PASSWORDS_MANAGE_WEAK_PASSWORDS = 11,
// Leave this at the end.

@ -12,30 +12,8 @@
</settings-reset-profile-dialog>
</template>
</cr-lazy-render>
<if expr="_google_chrome and is_win">
<cr-link-row class="hr" id="chromeCleanupSubpageTrigger"
label="$i18n{resetCleanupComputerTrigger}"
on-click="onChromeCleanupTap_"
role-description="$i18n{subpageArrowRoleDescription}"></cr-link-row>
<template is="dom-if" if="[[showIncompatibleApplications_]]" restamp>
<cr-link-row class="hr" id="incompatibleApplicationsSubpageTrigger"
label="$i18n{incompatibleApplicationsResetCardTitle}"
on-click="onIncompatibleApplicationsTap_"
role-description="$i18n{subpageArrowRoleDescription}">
</cr-link-row>
</template>
</if>
</div>
<if expr="_google_chrome and is_win">
<template is="dom-if" route-path="/cleanup">
<settings-subpage id="chromeCleanupSubpage"
associated-control="[[$$('#chromeCleanupSubpageTrigger')]]"
page-title="$i18n{resetCleanupComputerTrigger}"
learn-more-url="$i18n{chromeCleanupLearnMoreUrl}">
<settings-chrome-cleanup-page prefs="{{prefs}}">
</settings-chrome-cleanup-page>
</settings-subpage>
</template>
<template is="dom-if" if="[[showIncompatibleApplications_]]">
<template is="dom-if" route-path="/incompatibleApplications">
<settings-subpage id="incompatibleApplicationsSubpage"

@ -12,7 +12,6 @@ import '../settings_page/settings_animated_pages.js';
import '../settings_shared.css.js';
import './reset_profile_dialog.js';
// <if expr="_google_chrome and is_win">
import '../chrome_cleanup_page/chrome_cleanup_page.js';
import '../incompatible_applications_page/incompatible_applications_page.js';
// </if>

@ -22,7 +22,6 @@ export enum SafetyCheckCallbackConstants {
PASSWORDS_CHANGED = 'safety-check-passwords-status-changed',
SAFE_BROWSING_CHANGED = 'safety-check-safe-browsing-status-changed',
EXTENSIONS_CHANGED = 'safety-check-extensions-status-changed',
CHROME_CLEANER_CHANGED = 'safety-check-chrome-cleaner-status-changed',
}
/**

@ -1,17 +0,0 @@
<template is="dom-if" if="[[showChild_(status_)]]"
restamp>
<settings-safety-check-child
id="safetyCheckChild"
icon-status="[[getIconStatus_(status_)]]"
label="$i18n{safetyCheckChromeCleanerPrimaryLabel}"
sub-label="[[displayString_]]"
button-label="[[getButtonLabel_(status_)]]"
button-aria-label="[[getButtonAriaLabel_(status_)]]"
button-class="[[getButtonClass_(status_)]]"
on-button-click="onButtonClick_"
managed-icon="[[getManagedIcon_(status_)]]"
on-click="onRowClick_"
row-clickable="[[isRowClickable_(status_)]]"
role="presentation">
</settings-safety-check-child>
</template>

@ -1,219 +0,0 @@
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* 'settings-safety-passwords-child' is the settings page containing the
* safety check child showing the password status.
*/
import {assertNotReached} from 'chrome://resources/js/assert_ts.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {ChromeCleanupProxy, ChromeCleanupProxyImpl} from '../chrome_cleanup_page/chrome_cleanup_proxy.js';
import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js';
import {routes} from '../route.js';
import {Router} from '../router.js';
import {SafetyCheckCallbackConstants, SafetyCheckChromeCleanerStatus} from './safety_check_browser_proxy.js';
import {SafetyCheckIconStatus} from './safety_check_child.js';
import {getTemplate} from './safety_check_chrome_cleaner_child.html.js';
interface ChromeCleanerChangedEvent {
newState: SafetyCheckChromeCleanerStatus;
displayString: string;
}
const SettingsSafetyCheckChromeCleanerChildElementBase =
WebUiListenerMixin(I18nMixin(PolymerElement));
export class SettingsSafetyCheckChromeCleanerChildElement extends
SettingsSafetyCheckChromeCleanerChildElementBase {
static get is() {
return 'settings-safety-check-chrome-cleaner-child';
}
static get template() {
return getTemplate();
}
static get properties() {
return {
/**
* Current state of the safety check Chrome cleaner child.
*/
status_: {
type: Number,
value: SafetyCheckChromeCleanerStatus.HIDDEN,
},
/**
* UI string to display for this child, received from the backend.
*/
displayString_: String,
/**
* A set of statuses that the entire row is clickable.
*/
rowClickableStatuses: {
readOnly: true,
type: Object,
value: () => new Set([
SafetyCheckChromeCleanerStatus.SCANNING_FOR_UWS,
SafetyCheckChromeCleanerStatus.REMOVING_UWS,
SafetyCheckChromeCleanerStatus.ERROR,
SafetyCheckChromeCleanerStatus.NO_UWS_FOUND_WITH_TIMESTAMP,
SafetyCheckChromeCleanerStatus.NO_UWS_FOUND_WITHOUT_TIMESTAMP,
]),
},
};
}
private status_: SafetyCheckChromeCleanerStatus;
private displayString_: string;
private rowClickableStatuses: Set<SafetyCheckChromeCleanerStatus>;
private metricsBrowserProxy_: MetricsBrowserProxy =
MetricsBrowserProxyImpl.getInstance();
private chromeCleanupBrowserProxy_: ChromeCleanupProxy =
ChromeCleanupProxyImpl.getInstance();
override connectedCallback() {
super.connectedCallback();
// Register for safety check status updates.
this.addWebUiListener(
SafetyCheckCallbackConstants.CHROME_CLEANER_CHANGED,
this.onSafetyCheckChromeCleanerChanged_.bind(this));
}
private onSafetyCheckChromeCleanerChanged_(event: ChromeCleanerChangedEvent) {
this.status_ = event.newState;
this.displayString_ = event.displayString;
}
private showChild_(): boolean {
return this.status_ !== SafetyCheckChromeCleanerStatus.HIDDEN;
}
private getIconStatus_(): SafetyCheckIconStatus {
switch (this.status_) {
case SafetyCheckChromeCleanerStatus.HIDDEN:
case SafetyCheckChromeCleanerStatus.CHECKING:
case SafetyCheckChromeCleanerStatus.SCANNING_FOR_UWS:
case SafetyCheckChromeCleanerStatus.REMOVING_UWS:
return SafetyCheckIconStatus.RUNNING;
case SafetyCheckChromeCleanerStatus.NO_UWS_FOUND_WITH_TIMESTAMP:
return SafetyCheckIconStatus.SAFE;
case SafetyCheckChromeCleanerStatus.REBOOT_REQUIRED:
case SafetyCheckChromeCleanerStatus.DISABLED_BY_ADMIN:
case SafetyCheckChromeCleanerStatus.ERROR:
case SafetyCheckChromeCleanerStatus.NO_UWS_FOUND_WITHOUT_TIMESTAMP:
return SafetyCheckIconStatus.INFO;
case SafetyCheckChromeCleanerStatus.INFECTED:
return SafetyCheckIconStatus.WARNING;
default:
assertNotReached();
}
}
private getButtonLabel_(): string|null {
switch (this.status_) {
case SafetyCheckChromeCleanerStatus.INFECTED:
return this.i18n('safetyCheckReview');
case SafetyCheckChromeCleanerStatus.REBOOT_REQUIRED:
return this.i18n('chromeCleanupRestartButtonLabel');
default:
return null;
}
}
private getButtonAriaLabel_(): string|null {
switch (this.status_) {
case SafetyCheckChromeCleanerStatus.INFECTED:
return this.i18n('safetyCheckChromeCleanerButtonAriaLabel');
case SafetyCheckChromeCleanerStatus.REBOOT_REQUIRED:
return this.i18n('chromeCleanupRestartButtonLabel');
default:
return null;
}
}
private getButtonClass_(): string {
switch (this.status_) {
case SafetyCheckChromeCleanerStatus.INFECTED:
case SafetyCheckChromeCleanerStatus.REBOOT_REQUIRED:
return 'action-button';
default:
return '';
}
}
private logUserInteraction_(
safetyCheckInteraction: SafetyCheckInteractions, userAction: string) {
// Log user interaction both in user action and histogram.
this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram(
safetyCheckInteraction);
this.metricsBrowserProxy_.recordAction(userAction);
}
private onButtonClick_() {
switch (this.status_) {
case SafetyCheckChromeCleanerStatus.INFECTED:
this.logUserInteraction_(
SafetyCheckInteractions.CHROME_CLEANER_REVIEW_INFECTED_STATE,
'Settings.SafetyCheck.ChromeCleanerReviewInfectedState');
// Navigate to Chrome cleaner UI.
this.navigateToFoilPage_();
break;
case SafetyCheckChromeCleanerStatus.REBOOT_REQUIRED:
this.logUserInteraction_(
SafetyCheckInteractions.CHROME_CLEANER_REBOOT,
'Settings.SafetyCheck.ChromeCleanerReboot');
this.chromeCleanupBrowserProxy_.restartComputer();
break;
default:
// This is a state without an action.
break;
}
}
private getManagedIcon_(): string|null {
switch (this.status_) {
case SafetyCheckChromeCleanerStatus.DISABLED_BY_ADMIN:
return 'cr20:domain';
default:
return null;
}
}
private isRowClickable_(): boolean {
return this.rowClickableStatuses.has(this.status_);
}
private onRowClick_() {
if (this.isRowClickable_()) {
this.logUserInteraction_(
SafetyCheckInteractions.CHROME_CLEANER_CARET_NAVIGATION,
'Settings.SafetyCheck.ChromeCleanerCaretNavigation');
this.navigateToFoilPage_();
}
}
private navigateToFoilPage_() {
Router.getInstance().navigateTo(
routes.CHROME_CLEANUP,
/* dynamicParams= */ undefined, /* removeSearch= */ true);
}
}
declare global {
interface HTMLElementTagNameMap {
'settings-safety-check-chrome-cleaner-child':
SettingsSafetyCheckChromeCleanerChildElement;
}
}
customElements.define(
SettingsSafetyCheckChromeCleanerChildElement.is,
SettingsSafetyCheckChromeCleanerChildElement);

@ -43,10 +43,6 @@
</settings-safety-check-safe-browsing-child>
<settings-safety-check-extensions-child>
</settings-safety-check-extensions-child>
<if expr="_google_chrome and is_win">
<settings-safety-check-chrome-cleaner-child id="chromeCleanerChild">
</settings-safety-check-chrome-cleaner-child>
</if>
</iron-collapse>
<template is="dom-if"
if="[[shouldShowUnusedSitePermissions_(

@ -20,10 +20,6 @@ import './safety_check_extensions_child.js';
import './safety_check_passwords_child.js';
import './safety_check_safe_browsing_child.js';
import './safety_check_updates_child.js';
// <if expr="_google_chrome and is_win">
import './safety_check_chrome_cleaner_child.js';
// </if>
import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';

@ -79,9 +79,6 @@ export {buildRouter, routes} from './route.js';
export {Route, Router, SettingsRoutes} from './router.js';
export {SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckChromeCleanerStatus, SafetyCheckExtensionsStatus, SafetyCheckParentStatus, SafetyCheckPasswordsStatus, SafetyCheckSafeBrowsingStatus, SafetyCheckUpdatesStatus} from './safety_check_page/safety_check_browser_proxy.js';
export {SafetyCheckIconStatus, SettingsSafetyCheckChildElement} from './safety_check_page/safety_check_child.js';
// <if expr="_google_chrome and is_win">
export {SettingsSafetyCheckChromeCleanerChildElement} from './safety_check_page/safety_check_chrome_cleaner_child.js';
// </if>
export {SettingsSafetyCheckExtensionsChildElement} from './safety_check_page/safety_check_extensions_child.js';
export {SettingsSafetyCheckNotificationPermissionsElement} from './safety_check_page/safety_check_notification_permissions.js';
export {SettingsSafetyCheckPageElement} from './safety_check_page/safety_check_page.js';

@ -40,12 +40,6 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/strings/grit/ui_strings.h"
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
#include "base/win/registry.h"
#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h"
#include "components/chrome_cleaner/public/constants/constants.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ui/chromeos/devicetype_utils.h"
#endif
@ -59,10 +53,6 @@ constexpr char kPasswordsEvent[] = "safety-check-passwords-status-changed";
constexpr char kSafeBrowsingEvent[] =
"safety-check-safe-browsing-status-changed";
constexpr char kExtensionsEvent[] = "safety-check-extensions-status-changed";
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
constexpr char kChromeCleanerEvent[] =
"safety-check-chrome-cleaner-status-changed";
#endif
constexpr char kPerformSafetyCheck[] = "performSafetyCheck";
constexpr char kGetParentRanDisplayString[] = "getSafetyCheckRanDisplayString";
constexpr char kNewState[] = "newState";
@ -101,72 +91,6 @@ SafetyCheckHandler::UpdateStatus ConvertToUpdateStatus(
}
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
SafetyCheckHandler::ChromeCleanerStatus ConvertToChromeCleanerStatus(
safe_browsing::ChromeCleanerController::State state,
safe_browsing::ChromeCleanerController::IdleReason idle_reason,
bool is_allowed_by_policy,
bool is_cct_timestamp_known) {
if (!is_allowed_by_policy) {
return SafetyCheckHandler::ChromeCleanerStatus::kDisabledByAdmin;
}
switch (state) {
case safe_browsing::ChromeCleanerController::State::kIdle:
switch (idle_reason) {
case safe_browsing::ChromeCleanerController::IdleReason::kInitial:
case safe_browsing::ChromeCleanerController::IdleReason::
kReporterFoundNothing:
case safe_browsing::ChromeCleanerController::IdleReason::
kScanningFoundNothing:
case safe_browsing::ChromeCleanerController::IdleReason::
kCleaningSucceeded:
return is_cct_timestamp_known
? SafetyCheckHandler::ChromeCleanerStatus::
kNoUwsFoundWithTimestamp
: SafetyCheckHandler::ChromeCleanerStatus::
kNoUwsFoundWithoutTimestamp;
case safe_browsing::ChromeCleanerController::IdleReason::
kReporterFailed:
case safe_browsing::ChromeCleanerController::IdleReason::
kScanningFailed:
case safe_browsing::ChromeCleanerController::IdleReason::
kCleaningFailed:
case safe_browsing::ChromeCleanerController::IdleReason::
kCleanerDownloadFailed:
return SafetyCheckHandler::ChromeCleanerStatus::kError;
case safe_browsing::ChromeCleanerController::IdleReason::
kConnectionLost:
case safe_browsing::ChromeCleanerController::IdleReason::
kUserDeclinedCleanup:
return SafetyCheckHandler::ChromeCleanerStatus::kInfected;
}
case safe_browsing::ChromeCleanerController::State::kReporterRunning:
case safe_browsing::ChromeCleanerController::State::kScanning:
return SafetyCheckHandler::ChromeCleanerStatus::kScanningForUws;
case safe_browsing::ChromeCleanerController::State::kCleaning:
return SafetyCheckHandler::ChromeCleanerStatus::kRemovingUws;
case safe_browsing::ChromeCleanerController::State::kInfected:
return SafetyCheckHandler::ChromeCleanerStatus::kInfected;
case safe_browsing::ChromeCleanerController::State::kRebootRequired:
return SafetyCheckHandler::ChromeCleanerStatus::kRebootRequired;
}
}
SafetyCheckHandler::ChromeCleanerResult fetchChromeCleanerStatus(
std::unique_ptr<TimestampDelegate>& timestamp_delegate) {
SafetyCheckHandler::ChromeCleanerResult result;
result.cct_completion_time =
timestamp_delegate->FetchChromeCleanerScanCompletionTimestamp();
result.status = ConvertToChromeCleanerStatus(
safe_browsing::ChromeCleanerController::GetInstance()->state(),
safe_browsing::ChromeCleanerController::GetInstance()->idle_reason(),
safe_browsing::ChromeCleanerController::GetInstance()
->IsAllowedByPolicy(),
!result.cct_completion_time.is_null());
return result;
}
#endif
bool IsUnmutedCompromisedCredential(
const extensions::api::passwords_private::PasswordUiEntry& entry) {
DCHECK(entry.compromised_info);
@ -196,59 +120,9 @@ base::Time TimestampDelegate::GetSystemTime() {
return base::Time::Now();
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
base::Time TimestampDelegate::FetchChromeCleanerScanCompletionTimestamp() {
// TODO(crbug.com/1139806): The cleaner scan completion timestamp is not
// always written to the registry. As a workaround, it is also written to a
// pref. This ensures that the timestamp is preserved in case Chrome is still
// opened when the scan completes. Remove this workaround once the timestamp
// is written to the registry in all cases.
const base::Time end_time_from_prefs =
g_browser_process->local_state()->GetTime(
prefs::kChromeCleanerScanCompletionTime);
// Read the scan completion timestamp from the registry, if it exists there.
base::win::RegKey reporter_key;
int64_t end_time = 0;
if (reporter_key.Open(HKEY_CURRENT_USER,
chrome_cleaner::kSoftwareRemovalToolRegistryKey,
KEY_QUERY_VALUE | KEY_SET_VALUE) != ERROR_SUCCESS ||
reporter_key.ReadInt64(chrome_cleaner::kEndTimeValueName, &end_time) !=
ERROR_SUCCESS) {
// TODO(crbug.com/1139806): Part of the above workaround. If the registry
// does not contain the timestamp but the pref does, then return the one
// from the pref.
if (!end_time_from_prefs.is_null()) {
return end_time_from_prefs;
}
// Reading failed. Return 'null' time.
return base::Time();
}
// TODO(crbug.com/1139806): Part of the above workaround. If the timestamp in
// prefs is null or older than the one from the registry, then return the one
// from the registry. Otherwise return the one from prefs.
base::Time end_time_from_registry =
base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(end_time));
if (end_time_from_prefs.is_null() ||
end_time_from_prefs < end_time_from_registry) {
return end_time_from_registry;
} else {
return end_time_from_prefs;
}
}
#endif
SafetyCheckHandler::SafetyCheckHandler() = default;
SafetyCheckHandler::~SafetyCheckHandler() {
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// It seems |OnJavascriptDisallowed| is not always called before the
// deconstructor. Remove the CCT observer (no-op if not registered)
// also here to ensure it does not stay registered.
safe_browsing::ChromeCleanerController::GetInstance()->RemoveObserver(this);
#endif
}
SafetyCheckHandler::~SafetyCheckHandler() = default;
void SafetyCheckHandler::SendSafetyCheckStartedWebUiUpdates() {
AllowJavascript();
@ -266,16 +140,6 @@ void SafetyCheckHandler::SendSafetyCheckStartedWebUiUpdates() {
passwords_status_ = PasswordsStatus::kChecking;
safe_browsing_status_ = SafeBrowsingStatus::kChecking;
extensions_status_ = ExtensionsStatus::kChecking;
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// If the Chrome cleaner status results in the child being hidden,
// then also hide it already in the "running" state.
if (fetchChromeCleanerStatus(timestamp_delegate_).status ==
SafetyCheckHandler::ChromeCleanerStatus::kHidden) {
chrome_cleaner_status_ = SafetyCheckHandler::ChromeCleanerStatus::kHidden;
} else {
chrome_cleaner_status_ = SafetyCheckHandler::ChromeCleanerStatus::kChecking;
}
#endif
// Update WebUi.
FireBasicSafetyCheckWebUiListener(kUpdatesEvent,
@ -292,13 +156,6 @@ void SafetyCheckHandler::SendSafetyCheckStartedWebUiUpdates() {
kExtensionsEvent, static_cast<int>(extensions_status_),
GetStringForExtensions(extensions_status_, Blocklisted(0),
ReenabledUser(0), ReenabledAdmin(0)));
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Construct string without timestamp, using "null time" via |base::Time()|.
FireBasicSafetyCheckWebUiListener(
kChromeCleanerEvent, static_cast<int>(chrome_cleaner_status_),
GetStringForChromeCleaner(chrome_cleaner_status_, base::Time(),
base::Time()));
#endif
// Parent update is last as it reveals the children elements.
FireBasicSafetyCheckWebUiListener(kParentEvent,
static_cast<int>(parent_status_),
@ -361,10 +218,6 @@ void SafetyCheckHandler::PerformSafetyCheck() {
}
DCHECK(extension_service_);
CheckExtensions();
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
CheckChromeCleaner();
#endif
}
SafetyCheckHandler::SafetyCheckHandler(
@ -401,21 +254,6 @@ void SafetyCheckHandler::HandleGetParentRanDisplayString(
const base::Value::List& args) {
const base::Value& callback_id = args[0];
// Send updated timestamp-based display strings to all SC children who have
// such strings.
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// String update for Chrome Cleaner.
base::Value::Dict event;
event.Set(kNewState, static_cast<int>(chrome_cleaner_status_));
event.Set(
kDisplayString,
GetStringForChromeCleaner(
chrome_cleaner_status_,
timestamp_delegate_->FetchChromeCleanerScanCompletionTimestamp(),
timestamp_delegate_->GetSystemTime()));
FireWebUIListener(kChromeCleanerEvent, event);
#endif
// String update for the parent.
ResolveJavascriptCallback(
callback_id,
@ -494,27 +332,6 @@ void SafetyCheckHandler::CheckExtensions() {
}
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
void SafetyCheckHandler::CheckChromeCleaner() {
if (safe_browsing::ChromeCleanerController::GetInstance()->HasObserver(
this)) {
// Observer already registered. Just fetch the current CCT status.
OnChromeCleanerCheckResult(fetchChromeCleanerStatus(timestamp_delegate_));
} else {
// Registering the observer immediately triggers a callback with the
// current state.
safe_browsing::ChromeCleanerController::GetInstance()->AddObserver(this);
}
// Log the current status into metrics.
if (chrome_cleaner_status_ != ChromeCleanerStatus::kHidden &&
chrome_cleaner_status_ != ChromeCleanerStatus::kChecking) {
base::UmaHistogramEnumeration("Settings.SafetyCheck.ChromeCleanerResult",
chrome_cleaner_status_);
}
CompleteParentIfChildrenCompleted();
}
#endif
void SafetyCheckHandler::OnUpdateCheckResult(UpdateStatus status) {
update_status_ = status;
if (update_status_ != UpdateStatus::kChecking) {
@ -569,19 +386,6 @@ void SafetyCheckHandler::OnExtensionsCheckResult(
CompleteParentIfChildrenCompleted();
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
void SafetyCheckHandler::OnChromeCleanerCheckResult(
SafetyCheckHandler::ChromeCleanerResult result) {
base::Value::Dict event;
event.Set(kNewState, static_cast<int>(result.status));
event.Set(kDisplayString,
GetStringForChromeCleaner(result.status, result.cct_completion_time,
timestamp_delegate_->GetSystemTime()));
FireWebUIListener(kChromeCleanerEvent, event);
chrome_cleaner_status_ = result.status;
}
#endif
std::u16string SafetyCheckHandler::GetStringForParent(ParentStatus status) {
switch (status) {
case ParentStatus::kBefore:
@ -753,44 +557,6 @@ std::u16string SafetyCheckHandler::GetStringForExtensions(
}
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
std::u16string SafetyCheckHandler::GetStringForChromeCleaner(
ChromeCleanerStatus status,
base::Time cct_completion_time,
base::Time system_time) {
switch (status) {
case ChromeCleanerStatus::kHidden:
case ChromeCleanerStatus::kChecking:
return u"";
case ChromeCleanerStatus::kInfected:
return l10n_util::GetStringUTF16(
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_INFECTED);
case ChromeCleanerStatus::kRebootRequired:
return l10n_util::GetStringUTF16(
IDS_SETTINGS_RESET_CLEANUP_TITLE_RESTART);
case ChromeCleanerStatus::kScanningForUws:
return l10n_util::GetStringUTF16(
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_SCANNING);
case ChromeCleanerStatus::kRemovingUws:
return l10n_util::GetStringUTF16(
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_REMOVING);
case ChromeCleanerStatus::kDisabledByAdmin:
return l10n_util::GetStringFUTF16(
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_DISABLED_BY_ADMIN,
base::ASCIIToUTF16(chrome::kWhoIsMyAdministratorHelpURL));
case ChromeCleanerStatus::kError:
return l10n_util::GetStringUTF16(
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_ERROR);
case ChromeCleanerStatus::kNoUwsFoundWithTimestamp:
return SafetyCheckHandler::GetStringForChromeCleanerRan(
cct_completion_time, system_time);
case ChromeCleanerStatus::kNoUwsFoundWithoutTimestamp:
return l10n_util::GetStringUTF16(
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITHOUT_TIMESTAMP);
}
}
#endif
std::u16string SafetyCheckHandler::GetStringForTimePassed(
base::Time completion_timestamp,
base::Time system_time,
@ -860,24 +626,6 @@ std::u16string SafetyCheckHandler::GetStringForParentRan(
base::Time::Now());
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
std::u16string SafetyCheckHandler::GetStringForChromeCleanerRan(
base::Time cct_completion_time,
base::Time system_time) {
if (cct_completion_time.is_null()) {
return l10n_util::GetStringUTF16(
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITHOUT_TIMESTAMP);
}
return SafetyCheckHandler::GetStringForTimePassed(
cct_completion_time, system_time,
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_AFTER_SECONDS,
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_AFTER_MINUTES,
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_AFTER_HOURS,
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_YESTERDAY,
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_NO_UWS_WITH_TIMESTAMP_AFTER_DAYS);
}
#endif
void SafetyCheckHandler::DetermineIfOfflineOrError(bool connected) {
OnUpdateCheckResult(connected ? UpdateStatus::kFailed
: UpdateStatus::kFailedOffline);
@ -1015,41 +763,6 @@ void SafetyCheckHandler::OnInsecureCredentialsChanged() {
observed_insecure_credentials_manager_.Reset();
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
void SafetyCheckHandler::OnIdle(
safe_browsing::ChromeCleanerController::IdleReason idle_reason) {
OnChromeCleanerCheckResult(fetchChromeCleanerStatus(timestamp_delegate_));
}
void SafetyCheckHandler::OnReporterRunning() {
OnChromeCleanerCheckResult(fetchChromeCleanerStatus(timestamp_delegate_));
}
void SafetyCheckHandler::OnScanning() {
OnChromeCleanerCheckResult(fetchChromeCleanerStatus(timestamp_delegate_));
}
void SafetyCheckHandler::OnInfected(
bool is_powered_by_partner,
const safe_browsing::ChromeCleanerScannerResults& scanner_results) {
OnChromeCleanerCheckResult(fetchChromeCleanerStatus(timestamp_delegate_));
}
void SafetyCheckHandler::OnCleaning(
bool is_powered_by_partner,
const safe_browsing::ChromeCleanerScannerResults& scanner_results) {
OnChromeCleanerCheckResult(fetchChromeCleanerStatus(timestamp_delegate_));
}
void SafetyCheckHandler::OnRebootRequired() {
OnChromeCleanerCheckResult(fetchChromeCleanerStatus(timestamp_delegate_));
}
void SafetyCheckHandler::OnRebootFailed() {
OnChromeCleanerCheckResult(fetchChromeCleanerStatus(timestamp_delegate_));
}
#endif
void SafetyCheckHandler::OnJavascriptAllowed() {}
void SafetyCheckHandler::OnJavascriptDisallowed() {
@ -1069,10 +782,6 @@ void SafetyCheckHandler::OnJavascriptDisallowed() {
// Destroy the version updater to prevent getting a callback and firing a
// WebUI event, which would cause a crash.
version_updater_.reset();
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Remove |this| as an observer for the Chrome cleaner.
safe_browsing::ChromeCleanerController::GetInstance()->RemoveObserver(this);
#endif
}
void SafetyCheckHandler::RegisterMessages() {
@ -1095,11 +804,6 @@ void SafetyCheckHandler::CompleteParentIfChildrenCompleted() {
extensions_status_ == ExtensionsStatus::kChecking) {
return;
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
if (chrome_cleaner_status_ == ChromeCleanerStatus::kChecking) {
return;
}
#endif
// All children checks completed.
parent_status_ = ParentStatus::kAfter;

@ -29,19 +29,11 @@
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h"
#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_scanner_results_win.h"
#endif
// Delegate for accessing external timestamps, overridden for tests.
class TimestampDelegate {
public:
virtual ~TimestampDelegate() = default;
virtual base::Time GetSystemTime();
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
virtual base::Time FetchChromeCleanerScanCompletionTimestamp();
#endif
};
// Settings page UI handler that checks four areas of browser safety:
@ -49,9 +41,6 @@ class TimestampDelegate {
// software.
class SafetyCheckHandler
: public settings::SettingsPageUIHandler,
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
public safe_browsing::ChromeCleanerController::Observer,
#endif
public password_manager::BulkLeakCheckServiceInterface::Observer,
public password_manager::InsecureCredentialsManager::Observer {
public:
@ -134,28 +123,6 @@ class SafetyCheckHandler
std::u16string GetStringForParentRan(base::Time safety_check_completion_time,
base::Time system_time);
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Constructs the string for the Chrome cleaner 'safe' state which depicts
// how long ago its last check ran.
std::u16string GetStringForChromeCleanerRan();
std::u16string GetStringForChromeCleanerRan(base::Time cct_completion_time,
base::Time system_time);
// safe_browsing::ChromeCleanerController::Observer overrides.
void OnIdle(
safe_browsing::ChromeCleanerController::IdleReason idle_reason) override;
void OnReporterRunning() override;
void OnScanning() override;
void OnInfected(bool is_powered_by_partner,
const safe_browsing::ChromeCleanerScannerResults&
scanner_results) override;
void OnCleaning(bool is_powered_by_partner,
const safe_browsing::ChromeCleanerScannerResults&
scanner_results) override;
void OnRebootRequired() override;
void OnRebootFailed() override;
#endif
protected:
SafetyCheckHandler(
std::unique_ptr<safety_check::UpdateCheckHelper> update_helper,
@ -207,11 +174,6 @@ class SafetyCheckHandler
// that case, if any of those were re-enabled.
void CheckExtensions();
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Checks for unwanted software via the Chrome Cleanup Tool. Only on Windows.
void CheckChromeCleaner();
#endif
// Callbacks that get triggered when each check completes.
void OnUpdateCheckResult(UpdateStatus status);
void OnPasswordsCheckResult(PasswordsStatus status,
@ -223,9 +185,6 @@ class SafetyCheckHandler
Blocklisted blocklisted,
ReenabledUser reenabled_user,
ReenabledAdmin reenabled_admin);
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
void OnChromeCleanerCheckResult(ChromeCleanerResult result);
#endif
// Methods for building user-visible strings based on the safety check
// state.
@ -241,11 +200,6 @@ class SafetyCheckHandler
Blocklisted blocklisted,
ReenabledUser reenabled_user,
ReenabledAdmin reenabled_admin);
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
std::u16string GetStringForChromeCleaner(ChromeCleanerStatus status,
base::Time cct_completion_time,
base::Time system_time);
#endif
// A generic error state often includes the offline state. This method is used
// as a callback for |UpdateCheckHelper| to check connectivity.

@ -53,10 +53,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ui/chromeos/devicetype_utils.h"
#endif
@ -71,9 +67,6 @@ constexpr char kUpdates[] = "updates";
constexpr char kPasswords[] = "passwords";
constexpr char kSafeBrowsing[] = "safe-browsing";
constexpr char kExtensions[] = "extensions";
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
constexpr char kChromeCleaner[] = "chrome-cleaner";
#endif
namespace {
using Enabled = base::StrongAlias<class EnabledTag, bool>;
@ -136,13 +129,6 @@ class TestTimestampDelegate : public TimestampDelegate {
return base::Time::FromDoubleT(1609459199).LocalMidnight() -
base::Seconds(1);
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
base::Time FetchChromeCleanerScanCompletionTimestamp() override {
// 2 seconds before midnight Dec 31st 2020.
return base::Time::FromDoubleT(1609459199).LocalMidnight() -
base::Seconds(2);
}
#endif
};
bool TestDestructionVersionUpdater::destructor_invoked_ = false;
@ -304,14 +290,6 @@ class TestSafetyCheckExtensionService : public TestExtensionService {
std::unordered_map<std::string, ExtensionState> state_map_;
};
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
class TestChromeCleanerControllerDelegate
: public safe_browsing::ChromeCleanerControllerDelegate {
public:
bool IsAllowedByPolicy() override { return false; }
};
#endif
} // namespace
class SafetyCheckHandlerTest : public testing::Test {
@ -352,9 +330,6 @@ class SafetyCheckHandlerTest : public testing::Test {
std::unique_ptr<TestingSafetyCheckHandler> safety_check_;
base::HistogramTester histogram_tester_;
base::test::ScopedFeatureList feature_list_;
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
TestChromeCleanerControllerDelegate test_chrome_cleaner_controller_delegate_;
#endif
};
void SafetyCheckHandlerTest::SetUp() {
@ -1425,270 +1400,6 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledSomeByUser) {
SafetyCheckHandler::ExtensionsStatus::kBlocklistedReenabledSomeByUser, 1);
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
class SafetyCheckHandlerChromeCleanerIdleTest
: public SafetyCheckHandlerTest,
public testing::WithParamInterface<
std::tuple<safe_browsing::ChromeCleanerController::IdleReason,
SafetyCheckHandler::ChromeCleanerStatus,
std::u16string>> {
protected:
void SetUp() override {
SafetyCheckHandlerTest::SetUp();
idle_reason_ = testing::get<0>(GetParam());
expected_cct_status_ = testing::get<1>(GetParam());
expected_display_string_ = testing::get<2>(GetParam());
}
safe_browsing::ChromeCleanerController::IdleReason idle_reason_;
SafetyCheckHandler::ChromeCleanerStatus expected_cct_status_;
std::u16string expected_display_string_;
};
TEST_P(SafetyCheckHandlerChromeCleanerIdleTest, CheckChromeCleanerIdleStates) {
safe_browsing::ChromeCleanerControllerImpl::ResetInstanceForTesting();
safe_browsing::ChromeCleanerControllerImpl::GetInstance()->SetIdleForTesting(
idle_reason_);
safety_check_->PerformSafetyCheck();
// Ensure WebUI event is sent.
const base::Value::Dict* event = GetSafetyCheckStatusChangedWithDataIfExists(
kChromeCleaner, static_cast<int>(expected_cct_status_));
ASSERT_TRUE(event);
VerifyDisplayString(event, expected_display_string_);
// Ensure UMA is logged.
if (expected_cct_status_ ==
SafetyCheckHandler::ChromeCleanerStatus::kHidden ||
expected_cct_status_ ==
SafetyCheckHandler::ChromeCleanerStatus::kChecking) {
// Hidden and checking state should not get recorded.
histogram_tester_.ExpectTotalCount(
"Settings.SafetyCheck.ChromeCleanerResult", 0);
} else {
histogram_tester_.ExpectBucketCount(
"Settings.SafetyCheck.ChromeCleanerResult", expected_cct_status_, 1);
}
}
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_Initial,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::IdleReason::kInitial,
SafetyCheckHandler::ChromeCleanerStatus::kNoUwsFoundWithTimestamp,
u"Browser didn't find harmful software on your computer • Checked just "
u"now")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_ReporterFoundNothing,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::IdleReason::
kReporterFoundNothing,
SafetyCheckHandler::ChromeCleanerStatus::kNoUwsFoundWithTimestamp,
u"Browser didn't find harmful software on your computer • Checked just "
u"now")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_ReporterFailed,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::IdleReason::kReporterFailed,
SafetyCheckHandler::ChromeCleanerStatus::kError,
u"Something went wrong. Click for more details.")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_ScanningFoundNothing,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::IdleReason::
kScanningFoundNothing,
SafetyCheckHandler::ChromeCleanerStatus::kNoUwsFoundWithTimestamp,
u"Browser didn't find harmful software on your computer • Checked just "
u"now")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_ScanningFailed,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::IdleReason::kScanningFailed,
SafetyCheckHandler::ChromeCleanerStatus::kError,
u"Something went wrong. Click for more details.")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_ConnectionLost,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::IdleReason::kConnectionLost,
SafetyCheckHandler::ChromeCleanerStatus::kInfected,
u"Browser found harmful software on your computer")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_UserDeclinedCleanup,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(
std::make_tuple(safe_browsing::ChromeCleanerController::IdleReason::
kUserDeclinedCleanup,
SafetyCheckHandler::ChromeCleanerStatus::kInfected,
u"Browser found harmful software on your computer")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_CleaningFailed,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::IdleReason::kCleaningFailed,
SafetyCheckHandler::ChromeCleanerStatus::kError,
u"Something went wrong. Click for more details.")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_CleaningSucceed,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::IdleReason::kCleaningSucceeded,
SafetyCheckHandler::ChromeCleanerStatus::kNoUwsFoundWithTimestamp,
u"Browser didn't find harmful software on your computer • Checked just "
u"now")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_CleanerDownloadFailed,
SafetyCheckHandlerChromeCleanerIdleTest,
::testing::Values(
std::make_tuple(safe_browsing::ChromeCleanerController::IdleReason::
kCleanerDownloadFailed,
SafetyCheckHandler::ChromeCleanerStatus::kError,
u"Something went wrong. Click for more details.")));
class SafetyCheckHandlerChromeCleanerNonIdleTest
: public SafetyCheckHandlerTest,
public testing::WithParamInterface<
std::tuple<safe_browsing::ChromeCleanerController::State,
SafetyCheckHandler::ChromeCleanerStatus,
std::u16string>> {
protected:
void SetUp() override {
SafetyCheckHandlerTest::SetUp();
state_ = testing::get<0>(GetParam());
expected_cct_status_ = testing::get<1>(GetParam());
expected_display_string_ = testing::get<2>(GetParam());
}
safe_browsing::ChromeCleanerController::State state_;
SafetyCheckHandler::ChromeCleanerStatus expected_cct_status_;
std::u16string expected_display_string_;
};
TEST_P(SafetyCheckHandlerChromeCleanerNonIdleTest,
CheckChromeCleanerNonIdleStates) {
safe_browsing::ChromeCleanerControllerImpl::ResetInstanceForTesting();
safe_browsing::ChromeCleanerControllerImpl::GetInstance()->SetStateForTesting(
state_);
safety_check_->PerformSafetyCheck();
const base::Value::Dict* event = GetSafetyCheckStatusChangedWithDataIfExists(
kChromeCleaner, static_cast<int>(expected_cct_status_));
ASSERT_TRUE(event);
VerifyDisplayString(event, expected_display_string_);
// Ensure UMA is logged.
if (expected_cct_status_ ==
SafetyCheckHandler::ChromeCleanerStatus::kHidden ||
expected_cct_status_ ==
SafetyCheckHandler::ChromeCleanerStatus::kChecking) {
// Hidden and checking state should not get recorded.
histogram_tester_.ExpectTotalCount(
"Settings.SafetyCheck.ChromeCleanerResult", 0);
} else {
histogram_tester_.ExpectBucketCount(
"Settings.SafetyCheck.ChromeCleanerResult", expected_cct_status_, 1);
}
}
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_ReporterRunning,
SafetyCheckHandlerChromeCleanerNonIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::State::kReporterRunning,
SafetyCheckHandler::ChromeCleanerStatus::kScanningForUws,
u"Browser is checking your computer for harmful software…")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_Scanning,
SafetyCheckHandlerChromeCleanerNonIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::State::kScanning,
SafetyCheckHandler::ChromeCleanerStatus::kScanningForUws,
u"Browser is checking your computer for harmful software…")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_Cleaning,
SafetyCheckHandlerChromeCleanerNonIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::State::kCleaning,
SafetyCheckHandler::ChromeCleanerStatus::kRemovingUws,
u"Browser is removing harmful software from your computer…")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_Infected,
SafetyCheckHandlerChromeCleanerNonIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::State::kInfected,
SafetyCheckHandler::ChromeCleanerStatus::kInfected,
u"Browser found harmful software on your computer")));
INSTANTIATE_TEST_SUITE_P(
CheckChromeCleaner_RebootRequired,
SafetyCheckHandlerChromeCleanerNonIdleTest,
::testing::Values(std::make_tuple(
safe_browsing::ChromeCleanerController::State::kRebootRequired,
SafetyCheckHandler::ChromeCleanerStatus::kRebootRequired,
u"To finish removing harmful software, restart your computer")));
TEST_F(SafetyCheckHandlerTest, CheckChromeCleaner_DisabledByAdmin) {
safe_browsing::ChromeCleanerControllerImpl::ResetInstanceForTesting();
safe_browsing::ChromeCleanerControllerImpl::GetInstance()
->SetDelegateForTesting(&test_chrome_cleaner_controller_delegate_);
safety_check_->PerformSafetyCheck();
const base::Value::Dict* event = GetSafetyCheckStatusChangedWithDataIfExists(
kChromeCleaner,
static_cast<int>(
SafetyCheckHandler::ChromeCleanerStatus::kDisabledByAdmin));
ASSERT_TRUE(event);
VerifyDisplayString(
event,
"<a target=\"_blank\" "
"href=\"https://support.google.com/chrome?p=your_administrator\">Your "
"administrator</a> has turned off checking for harmful software");
}
TEST_F(SafetyCheckHandlerTest, CheckChromeCleaner_ObserverUpdateLogging) {
safe_browsing::ChromeCleanerControllerImpl::ResetInstanceForTesting();
safe_browsing::ChromeCleanerControllerImpl::GetInstance()->SetIdleForTesting(
safe_browsing::ChromeCleanerController::IdleReason::
kReporterFoundNothing);
// We expect a user triggering a safety check to log the Chrome cleaner
// result.
safety_check_->PerformSafetyCheck();
histogram_tester_.ExpectBucketCount(
"Settings.SafetyCheck.ChromeCleanerResult",
SafetyCheckHandler::ChromeCleanerStatus::kNoUwsFoundWithTimestamp, 1);
// Subsequent Chrome cleaner status updates without the user running safety
// check again should not trigger logging.
safety_check_->OnIdle(safe_browsing::ChromeCleanerController::IdleReason::
kReporterFoundNothing);
safety_check_->OnReporterRunning();
safety_check_->OnScanning();
safety_check_->OnRebootRequired();
safety_check_->OnRebootFailed();
histogram_tester_.ExpectBucketCount(
"Settings.SafetyCheck.ChromeCleanerResult",
SafetyCheckHandler::ChromeCleanerStatus::kNoUwsFoundWithTimestamp, 1);
histogram_tester_.ExpectBucketCount(
"Settings.SafetyCheck.ChromeCleanerResult",
SafetyCheckHandler::ChromeCleanerStatus::kRebootRequired, 0);
histogram_tester_.ExpectBucketCount(
"Settings.SafetyCheck.ChromeCleanerResult",
SafetyCheckHandler::ChromeCleanerStatus::kScanningForUws, 0);
}
#endif
TEST_F(SafetyCheckHandlerTest, CheckParentRanDisplayString) {
// 1 second before midnight Dec 31st 2020, so that -(24h-1s) is still on the
// same day. This test time is hard coded to prevent DST flakiness, see
@ -1721,51 +1432,6 @@ TEST_F(SafetyCheckHandlerTest, CheckParentRanDisplayString) {
}
}
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
TEST_F(SafetyCheckHandlerTest, CheckChromeCleanerRanDisplayString) {
// Test string without timestamp.
base::Time null_time;
std::u16string display_string =
safety_check_->GetStringForChromeCleanerRan(null_time, null_time);
ReplaceBrowserName(&display_string);
EXPECT_EQ(display_string,
u"Browser can check your computer for harmful software");
// Test strings with timestamp.
// 1 second before midnight Dec 31st 2020, so that -(24h-1s) is still on the
// same day. This test time is hard coded to prevent DST flakiness, see
// crbug.com/1066576.
const base::Time system_time =
base::Time::FromDoubleT(1609459199).LocalMidnight() - base::Seconds(1);
// Display strings for given time deltas in seconds.
std::vector<std::tuple<std::u16string, int>> tuples{
std::make_tuple(u"just now", 1),
std::make_tuple(u"just now", 59),
std::make_tuple(u"1 minute ago", 60),
std::make_tuple(u"2 minutes ago", 60 * 2),
std::make_tuple(u"59 minutes ago", 60 * 60 - 1),
std::make_tuple(u"1 hour ago", 60 * 60),
std::make_tuple(u"2 hours ago", 60 * 60 * 2),
std::make_tuple(u"23 hours ago", 60 * 60 * 23),
std::make_tuple(u"yesterday", 60 * 60 * 24),
std::make_tuple(u"yesterday", 60 * 60 * 24 * 2 - 1),
std::make_tuple(u"2 days ago", 60 * 60 * 24 * 2),
std::make_tuple(u"2 days ago", 60 * 60 * 24 * 3 - 1),
std::make_tuple(u"3 days ago", 60 * 60 * 24 * 3),
std::make_tuple(u"3 days ago", 60 * 60 * 24 * 4 - 1)};
// Test that above time deltas produce the corresponding display strings.
for (auto tuple : tuples) {
const base::Time time = system_time - base::Seconds(std::get<1>(tuple));
display_string =
safety_check_->GetStringForChromeCleanerRan(time, system_time);
ReplaceBrowserName(&display_string);
EXPECT_EQ(base::StrCat({u"Browser didn't find harmful software on your "
u"computer • Checked ",
std::get<0>(tuple)}),
display_string);
}
}
#endif
TEST_F(SafetyCheckHandlerTest, CheckSafetyCheckStartedWebUiEvents) {
safety_check_->SendSafetyCheckStartedWebUiUpdates();
@ -1810,13 +1476,6 @@ TEST_F(SafetyCheckHandlerTest, CheckSafetyCheckCompletedWebUiEvents) {
test_leak_service_->set_state_and_notify(
password_manager::BulkLeakCheckService::State::kSignedOut);
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Set the Chrome cleaner mock response.
safe_browsing::ChromeCleanerControllerImpl::ResetInstanceForTesting();
safe_browsing::ChromeCleanerControllerImpl::GetInstance()->SetStateForTesting(
safe_browsing::ChromeCleanerController::State::kInfected);
#endif
// Check that the parent update is sent after all children checks completed.
const base::Value::Dict* event_parent =
GetSafetyCheckStatusChangedWithDataIfExists(
@ -1824,17 +1483,6 @@ TEST_F(SafetyCheckHandlerTest, CheckSafetyCheckCompletedWebUiEvents) {
ASSERT_TRUE(event_parent);
VerifyDisplayString(event_parent, u"Safety check ran a moment ago");
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Subsequent Chrome cleaner status updates without the user running safety
// check again should not trigger further parent element completion events.
safety_check_->OnIdle(safe_browsing::ChromeCleanerController::IdleReason::
kReporterFoundNothing);
safety_check_->OnReporterRunning();
safety_check_->OnScanning();
safety_check_->OnRebootRequired();
safety_check_->OnRebootFailed();
#endif
// Check that there is no new parent completion event.
const base::Value::Dict* event_parent2 =
GetSafetyCheckStatusChangedWithDataIfExists(

@ -646,32 +646,24 @@ void AddIncompatibleApplicationsStrings(content::WebUIDataSource* html_source) {
void AddResetStrings(content::WebUIDataSource* html_source, Profile* profile) {
static constexpr webui::LocalizedString kLocalizedStrings[] = {
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
{"resetPageTitle", IDS_SETTINGS_RESET_AND_CLEANUP},
#else
{"resetPageTitle", IDS_SETTINGS_RESET},
#endif
{"resetTrigger", IDS_SETTINGS_RESET_SETTINGS_TRIGGER},
{"resetPageExplanation", IDS_RESET_PROFILE_SETTINGS_EXPLANATION},
{"resetPageExplanationBulletPoints",
IDS_RESET_PROFILE_SETTINGS_EXPLANATION_IN_BULLET_POINTS},
{"triggeredResetPageExplanation",
IDS_TRIGGERED_RESET_PROFILE_SETTINGS_EXPLANATION},
{"triggeredResetPageTitle", IDS_TRIGGERED_RESET_PROFILE_SETTINGS_TITLE},
{"resetDialogTitle", IDS_SETTINGS_RESET_PROMPT_TITLE},
{"resetDialogCommit", IDS_SETTINGS_RESET},
{"resetPageFeedback", IDS_SETTINGS_RESET_PROFILE_FEEDBACK},
{"resetPageTitle", IDS_SETTINGS_RESET},
{"resetTrigger", IDS_SETTINGS_RESET_SETTINGS_TRIGGER},
{"resetPageExplanation", IDS_RESET_PROFILE_SETTINGS_EXPLANATION},
{"resetPageExplanationBulletPoints",
IDS_RESET_PROFILE_SETTINGS_EXPLANATION_IN_BULLET_POINTS},
{"triggeredResetPageExplanation",
IDS_TRIGGERED_RESET_PROFILE_SETTINGS_EXPLANATION},
{"triggeredResetPageTitle", IDS_TRIGGERED_RESET_PROFILE_SETTINGS_TITLE},
{"resetDialogTitle", IDS_SETTINGS_RESET_PROMPT_TITLE},
{"resetDialogCommit", IDS_SETTINGS_RESET},
{"resetPageFeedback", IDS_SETTINGS_RESET_PROFILE_FEEDBACK},
// Automatic reset banner (now a dialog).
{"resetAutomatedDialogTitle", IDS_SETTINGS_RESET_AUTOMATED_DIALOG_TITLE},
{"resetProfileBannerButton", IDS_SETTINGS_RESET_BANNER_RESET_BUTTON_TEXT},
{"resetProfileBannerDescription", IDS_SETTINGS_RESET_BANNER_TEXT},
{"resetLearnMoreAccessibilityText",
IDS_SETTINGS_RESET_LEARN_MORE_ACCESSIBILITY_TEXT},
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
{"resetCleanupComputerTrigger",
IDS_SETTINGS_RESET_CLEAN_UP_COMPUTER_TRIGGER},
#endif
// Automatic reset banner (now a dialog).
{"resetAutomatedDialogTitle", IDS_SETTINGS_RESET_AUTOMATED_DIALOG_TITLE},
{"resetProfileBannerButton", IDS_SETTINGS_RESET_BANNER_RESET_BUTTON_TEXT},
{"resetProfileBannerDescription", IDS_SETTINGS_RESET_BANNER_TEXT},
{"resetLearnMoreAccessibilityText",
IDS_SETTINGS_RESET_LEARN_MORE_ACCESSIBILITY_TEXT},
};
html_source->AddLocalizedStrings(kLocalizedStrings);
@ -2246,96 +2238,92 @@ void AddPrivacyGuideStrings(content::WebUIDataSource* html_source) {
void AddSafetyCheckStrings(content::WebUIDataSource* html_source) {
static constexpr webui::LocalizedString kLocalizedStrings[] = {
{"safetyCheckSectionTitle", IDS_SETTINGS_SAFETY_CHECK_SECTION_TITLE},
{"safetyCheckParentPrimaryLabelBefore",
IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_BEFORE},
{"safetyCheckRunning", IDS_SETTINGS_SAFETY_CHECK_RUNNING},
{"safetyCheckParentPrimaryLabelAfter",
IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_AFTER},
{"safetyCheckAriaLiveRunning", IDS_SETTINGS_SAFETY_CHECK_ARIA_LIVE_RUNNING},
{"safetyCheckAriaLiveAfter", IDS_SETTINGS_SAFETY_CHECK_ARIA_LIVE_AFTER},
{"safetyCheckParentButton", IDS_SETTINGS_SAFETY_CHECK_PARENT_BUTTON},
{"safetyCheckParentButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_PARENT_BUTTON_ARIA_LABEL},
{"safetyCheckParentRunAgainButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_PARENT_RUN_AGAIN_BUTTON_ARIA_LABEL},
{"safetyCheckIconRunningAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_ICON_RUNNING_ARIA_LABEL},
{"safetyCheckIconSafeAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_ICON_SAFE_ARIA_LABEL},
{"safetyCheckIconInfoAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_ICON_INFO_ARIA_LABEL},
{"safetyCheckIconWarningAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_ICON_WARNING_ARIA_LABEL},
{"safetyCheckReview", IDS_SETTINGS_SAFETY_CHECK_REVIEW},
{"safetyCheckUpdatesPrimaryLabel",
IDS_SETTINGS_SAFETY_CHECK_UPDATES_PRIMARY_LABEL},
{"safetyCheckUpdatesButtonAriaLabel", IDS_UPDATE_RECOMMENDED_DIALOG_TITLE},
{"safetyCheckPasswordsButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_BUTTON_ARIA_LABEL},
{"safetyCheckSafeBrowsingButton",
IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_BUTTON},
{"safetyCheckSafeBrowsingButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_BUTTON_ARIA_LABEL},
{"safetyCheckExtensionsPrimaryLabel",
IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_PRIMARY_LABEL},
{"safetyCheckExtensionsButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BUTTON_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewIgnoredToastLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_IGNORED_TOAST_LABEL},
{"safetyCheckNotificationPermissionReviewBlockedToastLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_BLOCKED_TOAST_LABEL},
{"safetyCheckNotificationPermissionReviewResetToastLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_RESET_TOAST_LABEL},
{"safetyCheckNotificationPermissionReviewDontAllowLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_DONT_ALLOW_LABEL},
{"safetyCheckNotificationPermissionReviewDontAllowAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_DONT_ALLOW_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewIgnoreLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_IGNORE_LABEL},
{"safetyCheckNotificationPermissionReviewIgnoreAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_IGNORE_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewResetLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_RESET_LABEL},
{"safetyCheckNotificationPermissionReviewResetAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_RESET_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewMoreActionsAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_MORE_ACTIONS_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewUndo",
IDS_SETTINGS_SAFETY_CHECK_TOAST_UNDO_BUTTON_LABEL},
{"safetyCheckNotificationPermissionReviewDoneLabel",
IDS_SETTINGS_SAFETY_CHECK_SITE_PERMISSIONS_REVIEW_DONE_LABEL},
{"safetyCheckNotificationPermissionReviewBlockAllLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_BLOCK_ALL_LABEL},
{"safetyCheckUnusedSitePermissionsHeaderAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_HEADER_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSIONS_REVIEW_BUTTON_ARIA_LABEL},
{"safetyCheckUnusedSitePermissionsAllowAgainAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_ALLOW_AGAIN_ARIA_LABEL},
{"safetyCheckUnusedSitePermissionsAllowAgainLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_ALLOW_AGAIN_LABEL},
{"safetyCheckUnusedSitePermissionsDoneLabel",
IDS_SETTINGS_SAFETY_CHECK_SITE_PERMISSIONS_REVIEW_DONE_LABEL},
{"safetyCheckUnusedSitePermissionsGotItLabel", IDS_SETTINGS_GOT_IT},
{"safetyCheckUnusedSitePermissionsRemovedOnePermissionLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_REMOVED_ONE_PERMISSION_LABEL},
{"safetyCheckUnusedSitePermissionsRemovedTwoPermissionsLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_REMOVED_TWO_PERMISSIONS_LABEL},
{"safetyCheckUnusedSitePermissionsRemovedThreePermissionsLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_REMOVED_THREE_PERMISSIONS_LABEL},
{"safetyCheckUnusedSitePermissionsRemovedFourOrMorePermissionsLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_REMOVED_FOUR_OR_MORE_PERMISSIONS_LABEL},
{"safetyCheckUnusedSitePermissionsToastLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_TOAST_LABEL},
{"safetyCheckUnusedSitePermissionsUndoLabel",
IDS_SETTINGS_SAFETY_CHECK_TOAST_UNDO_BUTTON_LABEL},
#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
{"safetyCheckChromeCleanerPrimaryLabel",
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_PRIMARY_LABEL},
{"safetyCheckChromeCleanerButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_BUTTON_ARIA_LABEL},
#endif // BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
{"safetyCheckSectionTitle", IDS_SETTINGS_SAFETY_CHECK_SECTION_TITLE},
{"safetyCheckParentPrimaryLabelBefore",
IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_BEFORE},
{"safetyCheckRunning", IDS_SETTINGS_SAFETY_CHECK_RUNNING},
{"safetyCheckParentPrimaryLabelAfter",
IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_AFTER},
{"safetyCheckAriaLiveRunning",
IDS_SETTINGS_SAFETY_CHECK_ARIA_LIVE_RUNNING},
{"safetyCheckAriaLiveAfter", IDS_SETTINGS_SAFETY_CHECK_ARIA_LIVE_AFTER},
{"safetyCheckParentButton", IDS_SETTINGS_SAFETY_CHECK_PARENT_BUTTON},
{"safetyCheckParentButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_PARENT_BUTTON_ARIA_LABEL},
{"safetyCheckParentRunAgainButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_PARENT_RUN_AGAIN_BUTTON_ARIA_LABEL},
{"safetyCheckIconRunningAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_ICON_RUNNING_ARIA_LABEL},
{"safetyCheckIconSafeAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_ICON_SAFE_ARIA_LABEL},
{"safetyCheckIconInfoAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_ICON_INFO_ARIA_LABEL},
{"safetyCheckIconWarningAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_ICON_WARNING_ARIA_LABEL},
{"safetyCheckReview", IDS_SETTINGS_SAFETY_CHECK_REVIEW},
{"safetyCheckUpdatesPrimaryLabel",
IDS_SETTINGS_SAFETY_CHECK_UPDATES_PRIMARY_LABEL},
{"safetyCheckUpdatesButtonAriaLabel",
IDS_UPDATE_RECOMMENDED_DIALOG_TITLE},
{"safetyCheckPasswordsButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_BUTTON_ARIA_LABEL},
{"safetyCheckSafeBrowsingButton",
IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_BUTTON},
{"safetyCheckSafeBrowsingButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_BUTTON_ARIA_LABEL},
{"safetyCheckExtensionsPrimaryLabel",
IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_PRIMARY_LABEL},
{"safetyCheckExtensionsButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BUTTON_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewIgnoredToastLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_IGNORED_TOAST_LABEL},
{"safetyCheckNotificationPermissionReviewBlockedToastLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_BLOCKED_TOAST_LABEL},
{"safetyCheckNotificationPermissionReviewResetToastLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_RESET_TOAST_LABEL},
{"safetyCheckNotificationPermissionReviewDontAllowLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_DONT_ALLOW_LABEL},
{"safetyCheckNotificationPermissionReviewDontAllowAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_DONT_ALLOW_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewIgnoreLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_IGNORE_LABEL},
{"safetyCheckNotificationPermissionReviewIgnoreAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_IGNORE_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewResetLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_RESET_LABEL},
{"safetyCheckNotificationPermissionReviewResetAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_RESET_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewMoreActionsAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_REVIEW_NOTIFICATION_PERMISSIONS_MORE_ACTIONS_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewUndo",
IDS_SETTINGS_SAFETY_CHECK_TOAST_UNDO_BUTTON_LABEL},
{"safetyCheckNotificationPermissionReviewDoneLabel",
IDS_SETTINGS_SAFETY_CHECK_SITE_PERMISSIONS_REVIEW_DONE_LABEL},
{"safetyCheckNotificationPermissionReviewBlockAllLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSION_REVIEW_BLOCK_ALL_LABEL},
{"safetyCheckUnusedSitePermissionsHeaderAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_HEADER_ARIA_LABEL},
{"safetyCheckNotificationPermissionReviewButtonAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_NOTIFICATION_PERMISSIONS_REVIEW_BUTTON_ARIA_LABEL},
{"safetyCheckUnusedSitePermissionsAllowAgainAriaLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_ALLOW_AGAIN_ARIA_LABEL},
{"safetyCheckUnusedSitePermissionsAllowAgainLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_ALLOW_AGAIN_LABEL},
{"safetyCheckUnusedSitePermissionsDoneLabel",
IDS_SETTINGS_SAFETY_CHECK_SITE_PERMISSIONS_REVIEW_DONE_LABEL},
{"safetyCheckUnusedSitePermissionsGotItLabel", IDS_SETTINGS_GOT_IT},
{"safetyCheckUnusedSitePermissionsRemovedOnePermissionLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_REMOVED_ONE_PERMISSION_LABEL},
{"safetyCheckUnusedSitePermissionsRemovedTwoPermissionsLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_REMOVED_TWO_PERMISSIONS_LABEL},
{"safetyCheckUnusedSitePermissionsRemovedThreePermissionsLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_REMOVED_THREE_PERMISSIONS_LABEL},
{"safetyCheckUnusedSitePermissionsRemovedFourOrMorePermissionsLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_REMOVED_FOUR_OR_MORE_PERMISSIONS_LABEL},
{"safetyCheckUnusedSitePermissionsToastLabel",
IDS_SETTINGS_SAFETY_CHECK_UNUSED_SITE_PERMISSIONS_TOAST_LABEL},
{"safetyCheckUnusedSitePermissionsUndoLabel",
IDS_SETTINGS_SAFETY_CHECK_TOAST_UNDO_BUTTON_LABEL},
};
html_source->AddLocalizedStrings(kLocalizedStrings);
}

@ -183,12 +183,7 @@ build_webui_tests("build") {
}
if (is_win && is_chrome_branded) {
files += [
"chrome_cleanup_page_test.ts",
"incompatible_applications_page_test.ts",
"safety_check_chrome_cleaner_test.ts",
"test_chrome_cleanup_proxy.ts",
]
files += [ "incompatible_applications_page_test.ts" ]
}
ts_path_mappings = [

@ -1,505 +0,0 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// clang-format off
import {webUIListenerCallback} from 'chrome://resources/js/cr.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW, ChromeCleanerScannerResults, ChromeCleanupFilePath, ChromeCleanupIdleReason, ChromeCleanupProxyImpl, ItemsToRemoveListElement, SettingsCheckboxElement, SettingsChromeCleanupPageElement} from 'chrome://settings/lazy_load.js';
import {CrButtonElement} from 'chrome://settings/settings.js';
import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {TestChromeCleanupProxy} from './test_chrome_cleanup_proxy.js';
// clang-format on
let chromeCleanupPage: SettingsChromeCleanupPageElement;
let chromeCleanupProxy: TestChromeCleanupProxy;
const shortFileList: ChromeCleanupFilePath[] = [
{'dirname': 'C:\\', 'basename': 'file 1'},
{'dirname': 'C:\\', 'basename': 'file 2'},
{'dirname': 'C:\\', 'basename': 'file 3'},
];
const exactSizeFileList =
shortFileList.concat([{'dirname': 'C:\\', 'basename': 'file 4'}]);
const longFileList =
exactSizeFileList.concat([{'dirname': 'C:\\', 'basename': 'file 5'}]);
const shortRegistryKeysList = ['key 1', 'key 2'];
const exactSizeRegistryKeysList = ['key 1', 'key 2', 'key 3', 'key 4'];
const longRegistryKeysList =
['key 1', 'key 2', 'key 3', 'key 4', 'key 5', 'key 6'];
const fileLists = [[], shortFileList, exactSizeFileList, longFileList];
const registryKeysLists = [
[],
shortRegistryKeysList,
exactSizeRegistryKeysList,
longRegistryKeysList,
];
const descriptors = ['No', 'Few', 'ExactSize', 'Many'];
const defaultScannerResults: ChromeCleanerScannerResults = {
files: shortFileList,
registryKeys: shortRegistryKeysList,
};
function validateVisibleItemsList(
originalItems: Array<string|ChromeCleanupFilePath>,
visibleItems: ItemsToRemoveListElement) {
let visibleItemsList =
visibleItems.shadowRoot!.querySelectorAll('.visible-item');
const moreItemsLink =
visibleItems.shadowRoot!.querySelector<HTMLElement>('#more-items-link')!;
if (originalItems.length <= CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW) {
assertEquals(visibleItemsList.length, originalItems.length);
assertTrue(moreItemsLink.hidden);
} else {
assertEquals(
visibleItemsList.length, CHROME_CLEANUP_DEFAULT_ITEMS_TO_SHOW - 1);
assertFalse(moreItemsLink.hidden);
// Tapping on the "show more" link should expand the list.
moreItemsLink.click();
flush();
visibleItemsList =
visibleItems.shadowRoot!.querySelectorAll('.visible-item');
assertEquals(visibleItemsList.length, originalItems.length);
assertTrue(moreItemsLink.hidden);
}
}
/**
* @param expectSuffix Whether a highlight suffix should exist.
*/
function validateHighlightSuffix(
originalItems: Array<string|ChromeCleanupFilePath>,
container: ItemsToRemoveListElement, expectSuffix: boolean) {
const itemList =
container.shadowRoot!.querySelectorAll('li:not(#more-items-link)');
assertEquals(originalItems.length, itemList.length);
for (const item of itemList) {
const suffixes = item.querySelectorAll<HTMLElement>('.highlight-suffix');
assertEquals(suffixes.length, 1);
assertEquals(expectSuffix, !suffixes[0]!.hidden);
}
}
/**
* @param files The list of files to be cleaned.
* @param registryKeys The list of registry entries to be cleaned.
*/
async function startCleanupFromInfected(
files: ChromeCleanupFilePath[], registryKeys: string[]) {
const scannerResults: ChromeCleanerScannerResults = {files, registryKeys};
updateReportingEnabledPref(false);
webUIListenerCallback(
'chrome-cleanup-on-infected', true /* isPoweredByPartner */,
scannerResults);
flush();
const showItemsButton =
chromeCleanupPage.shadowRoot!.querySelector<HTMLElement>(
'#show-items-button')!;
assertTrue(!!showItemsButton);
showItemsButton.click();
const filesToRemoveList =
chromeCleanupPage.shadowRoot!.querySelector<ItemsToRemoveListElement>(
'#files-to-remove-list')!;
assertTrue(!!filesToRemoveList);
validateVisibleItemsList(files, filesToRemoveList);
validateHighlightSuffix(files, filesToRemoveList, true /* expectSuffix */);
const registryKeysListContainer =
chromeCleanupPage.shadowRoot!.querySelector<ItemsToRemoveListElement>(
'#registry-keys-list')!;
assertTrue(!!registryKeysListContainer);
if (registryKeys.length > 0) {
assertFalse(registryKeysListContainer.hidden);
assertTrue(!!registryKeysListContainer);
validateVisibleItemsList(registryKeys, registryKeysListContainer);
validateHighlightSuffix(
registryKeys, registryKeysListContainer, false /* expectSuffix */);
} else {
assertTrue(registryKeysListContainer.hidden);
}
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector<CrButtonElement>(
'#action-button');
assertTrue(!!actionButton);
actionButton!.click();
const logsUploadEnabled = await chromeCleanupProxy.whenCalled('startCleanup');
assertFalse(logsUploadEnabled);
webUIListenerCallback(
'chrome-cleanup-on-cleaning', true /* isPoweredByPartner */,
defaultScannerResults);
flush();
const spinner =
chromeCleanupPage.shadowRoot!.querySelector('paper-spinner-lite')!;
assertTrue(spinner.active);
}
/**
* @param newValue The new value to set to
* prefs.software_reporter.reporting.
*/
function updateReportingEnabledPref(newValue: boolean) {
chromeCleanupPage.prefs = {
software_reporter: {
reporting: {
type: chrome.settingsPrivate.PrefType.BOOLEAN,
value: newValue,
key: '',
},
},
};
}
/**
* @param testingScanOffered Whether to test the case where scanning
* is offered to the user.
*/
function testLogsUploading(testingScanOffered: boolean) {
if (testingScanOffered) {
webUIListenerCallback(
'chrome-cleanup-on-infected', true /* isPoweredByPartner */,
defaultScannerResults);
} else {
webUIListenerCallback(
'chrome-cleanup-on-idle', ChromeCleanupIdleReason.INITIAL);
}
flush();
const logsControl =
chromeCleanupPage.shadowRoot!.querySelector<SettingsCheckboxElement>(
'#chromeCleanupLogsUploadControl');
updateReportingEnabledPref(true);
assertTrue(!!logsControl);
assertTrue(logsControl!.checked);
logsControl!.$.checkbox.click();
assertFalse(logsControl!.checked);
assertFalse(chromeCleanupPage.prefs.software_reporter.reporting.value);
logsControl!.$.checkbox.click();
assertTrue(logsControl!.checked);
assertTrue(chromeCleanupPage.prefs.software_reporter.reporting.value);
updateReportingEnabledPref(false);
assertFalse(logsControl!.checked);
}
/**
* @param onInfected Whether to test the case where current state is
* INFECTED, as opposed to CLEANING.
* @param isPoweredByPartner Whether to test the case when scan
* results are provided by a partner.
*/
function testPartnerLogoShown(
onInfected: boolean, isPoweredByPartner: boolean) {
webUIListenerCallback(
onInfected ? 'chrome-cleanup-on-infected' : 'chrome-cleanup-on-cleaning',
isPoweredByPartner, defaultScannerResults);
flush();
const poweredByContainerControl =
chromeCleanupPage.shadowRoot!.querySelector<HTMLElement>('#powered-by');
assertTrue(!!poweredByContainerControl);
assertNotEquals(poweredByContainerControl!.hidden, isPoweredByPartner);
}
suite('ChromeCleanupHandler', function() {
setup(function() {
chromeCleanupProxy = new TestChromeCleanupProxy();
ChromeCleanupProxyImpl.setInstance(chromeCleanupProxy);
document.body.innerHTML = window.trustedTypes!.emptyHTML;
chromeCleanupPage = document.createElement('settings-chrome-cleanup-page');
chromeCleanupPage.prefs = {
software_reporter: {
reporting: {
type: chrome.settingsPrivate.PrefType.BOOLEAN,
value: true,
key: '',
},
},
};
document.body.appendChild(chromeCleanupPage);
});
function scanOfferedOnInitiallyIdle(idleReason: ChromeCleanupIdleReason) {
webUIListenerCallback('chrome-cleanup-on-idle', idleReason);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector('#action-button');
assertTrue(!!actionButton);
}
test('scanOfferedOnInitiallyIdle_ReporterFoundNothing', function() {
scanOfferedOnInitiallyIdle(ChromeCleanupIdleReason.REPORTER_FOUND_NOTHING);
});
test('scanOfferedOnInitiallyIdle_ReporterFailed', function() {
scanOfferedOnInitiallyIdle(ChromeCleanupIdleReason.REPORTER_FAILED);
});
test('scanOfferedOnInitiallyIdle_ScanningFoundNothing', function() {
scanOfferedOnInitiallyIdle(ChromeCleanupIdleReason.SCANNING_FOUND_NOTHING);
});
test('scanOfferedOnInitiallyIdle_ScanningFailed', function() {
scanOfferedOnInitiallyIdle(ChromeCleanupIdleReason.SCANNING_FAILED);
});
test('scanOfferedOnInitiallyIdle_ConnectionLost', function() {
scanOfferedOnInitiallyIdle(ChromeCleanupIdleReason.CONNECTION_LOST);
});
test('scanOfferedOnInitiallyIdle_UserDeclinedCleanup', function() {
scanOfferedOnInitiallyIdle(ChromeCleanupIdleReason.USER_DECLINED_CLEANUP);
});
test('scanOfferedOnInitiallyIdle_CleaningFailed', function() {
scanOfferedOnInitiallyIdle(ChromeCleanupIdleReason.CLEANING_FAILED);
});
test('scanOfferedOnInitiallyIdle_CleaningSucceeded', function() {
scanOfferedOnInitiallyIdle(ChromeCleanupIdleReason.CLEANING_SUCCEEDED);
});
test('scanOfferedOnInitiallyIdle_CleanerDownloadFailed', function() {
scanOfferedOnInitiallyIdle(ChromeCleanupIdleReason.CLEANER_DOWNLOAD_FAILED);
});
test('cleanerDownloadFailure', function() {
webUIListenerCallback('chrome-cleanup-on-reporter-running');
webUIListenerCallback(
'chrome-cleanup-on-idle',
ChromeCleanupIdleReason.CLEANER_DOWNLOAD_FAILED);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector<CrButtonElement>(
'#action-button');
assertTrue(!!actionButton);
actionButton!.click();
return chromeCleanupProxy.whenCalled('startScanning');
});
test('reporterFoundNothing', function() {
webUIListenerCallback('chrome-cleanup-on-reporter-running');
webUIListenerCallback(
'chrome-cleanup-on-idle',
ChromeCleanupIdleReason.REPORTER_FOUND_NOTHING);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector('#action-button');
assertFalse(!!actionButton);
});
test('reporterFoundNothing', function() {
webUIListenerCallback('chrome-cleanup-on-reporter-running');
webUIListenerCallback(
'chrome-cleanup-on-idle',
ChromeCleanupIdleReason.REPORTER_FOUND_NOTHING);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector('#action-button');
assertFalse(!!actionButton);
});
test('startScanFromIdle', async function() {
updateReportingEnabledPref(false);
webUIListenerCallback(
'chrome-cleanup-on-idle', ChromeCleanupIdleReason.INITIAL);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector<CrButtonElement>(
'#action-button');
assertTrue(!!actionButton);
actionButton!.click();
const logsUploadEnabled =
await chromeCleanupProxy.whenCalled('startScanning');
assertFalse(logsUploadEnabled);
webUIListenerCallback('chrome-cleanup-on-scanning', false);
flush();
const spinner =
chromeCleanupPage.shadowRoot!.querySelector('paper-spinner-lite')!;
assertTrue(spinner.active);
});
test('scanFoundNothing', function() {
webUIListenerCallback('chrome-cleanup-on-scanning', false);
webUIListenerCallback(
'chrome-cleanup-on-idle',
ChromeCleanupIdleReason.SCANNING_FOUND_NOTHING);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector('#action-button');
assertFalse(!!actionButton);
});
test('scanFailure', function() {
webUIListenerCallback('chrome-cleanup-on-scanning', false);
webUIListenerCallback(
'chrome-cleanup-on-idle', ChromeCleanupIdleReason.SCANNING_FAILED);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector('#action-button');
assertFalse(!!actionButton);
});
// Test all combinations of item list sizes.
for (let file_index = 0; file_index < fileLists.length; file_index++) {
for (let registry_index = 0; registry_index < registryKeysLists.length;
registry_index++) {
const testName = 'startCleanupFromInfected_' + descriptors[file_index] +
'Files' + descriptors[registry_index] + 'RegistryKeys';
const fileList = fileLists[file_index]!;
const registryKeysList = registryKeysLists[registry_index]!;
test(testName, async function() {
await startCleanupFromInfected(fileList, registryKeysList);
});
}
}
test('rebootFromRebootRequired', function() {
webUIListenerCallback('chrome-cleanup-on-reboot-required');
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector<CrButtonElement>(
'#action-button');
assertTrue(!!actionButton);
actionButton!.click();
return chromeCleanupProxy.whenCalled('restartComputer');
});
test('cleanupFailure', function() {
updateReportingEnabledPref(false);
webUIListenerCallback(
'chrome-cleanup-on-cleaning', true /* isPoweredByPartner */,
defaultScannerResults);
webUIListenerCallback(
'chrome-cleanup-on-idle', ChromeCleanupIdleReason.CLEANING_FAILED);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector('#action-button');
assertFalse(!!actionButton);
});
test('cleanupSuccess', function() {
webUIListenerCallback(
'chrome-cleanup-on-cleaning', true /* isPoweredByPartner */,
defaultScannerResults);
webUIListenerCallback(
'chrome-cleanup-on-idle', ChromeCleanupIdleReason.CLEANING_SUCCEEDED);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector('#action-button');
assertFalse(!!actionButton);
const title = chromeCleanupPage.shadowRoot!.querySelector('#status-title');
assertTrue(!!title);
assertTrue(!!title!.querySelector('a'));
});
test('logsUploadingOnScanOffered', function() {
return testLogsUploading(true /* testingScanOffered */);
});
test('logsUploadingOnInfected', function() {
return testLogsUploading(false /* testingScanOffered */);
});
test('onInfectedResultsProvidedByPartner_True', function() {
return testPartnerLogoShown(
true /* onInfected */, true /* isPoweredByPartner */);
});
test('onInfectedResultsProvidedByPartner_False', function() {
return testPartnerLogoShown(
true /* onInfected */, false /* isPoweredByPartner */);
});
test('onCleaningResultsProvidedByPartner_True', function() {
return testPartnerLogoShown(
false /* onInfected */, true /* isPoweredByPartner */);
});
test('onCleaningResultsProvidedByPartner_False', function() {
return testPartnerLogoShown(
false /* onInfected */, false /* isPoweredByPartner */);
});
test('logsUploadingState_reporterPolicyDisabled', function() {
webUIListenerCallback(
'chrome-cleanup-on-idle', ChromeCleanupIdleReason.INITIAL);
// prefs.software_reporter.enabled is not a real preference as it can't be
// set by the user. ChromeCleanupHandler can notify the JS of changes to the
// policy enforcement.
webUIListenerCallback('chrome-cleanup-enabled-change', false);
flush();
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector<CrButtonElement>(
'#action-button');
assertTrue(!!actionButton);
assertTrue(actionButton!.disabled);
const logsControl =
chromeCleanupPage.shadowRoot!.querySelector<SettingsCheckboxElement>(
'#chromeCleanupLogsUploadControl');
assertTrue(!!logsControl);
assertTrue(logsControl!.disabled);
});
test('logsUploadingState_reporterReportingPolicyDisabled', function() {
webUIListenerCallback(
'chrome-cleanup-on-idle', ChromeCleanupIdleReason.INITIAL);
flush();
chromeCleanupPage.prefs = {
software_reporter: {
reporting: {
type: chrome.settingsPrivate.PrefType.BOOLEAN,
enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
controlledBy: chrome.settingsPrivate.ControlledBy.USER_POLICY,
value: false,
key: '',
},
},
};
const actionButton =
chromeCleanupPage.shadowRoot!.querySelector<CrButtonElement>(
'#action-button');
assertTrue(!!actionButton);
assertFalse(actionButton!.disabled);
const logsControl =
chromeCleanupPage.shadowRoot!.querySelector<SettingsCheckboxElement>(
'#chromeCleanupLogsUploadControl');
assertTrue(!!logsControl);
assertFalse(logsControl!.disabled);
assertTrue(logsControl!.$.checkbox.disabled);
});
});

@ -351,20 +351,6 @@ TEST_F('CrSettingsSafetyCheckPermissionsTest', 'All', function() {
mocha.run();
});
GEN('#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)');
var CrSettingsSafetyCheckChromeCleanerTest =
class extends CrSettingsBrowserTest {
/** @override */
get browsePreload() {
return 'chrome://settings/test_loader.html?module=settings/safety_check_chrome_cleaner_test.js';
}
};
TEST_F('CrSettingsSafetyCheckChromeCleanerTest', 'All', function() {
mocha.run();
});
GEN('#endif');
var CrSettingsSiteListTest = class extends CrSettingsBrowserTest {
/** @override */
get browsePreload() {
@ -983,12 +969,6 @@ GEN('#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)');
].forEach(test => registerTest(...test));
GEN('#endif');
GEN('#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)');
[['ChromeCleanupPage', 'chrome_cleanup_page_test.js'],
['IncompatibleApplicationsPage', 'incompatible_applications_page_test.js'],
].forEach(test => registerTest(...test));
GEN('#endif');
GEN('#if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !BUILDFLAG(IS_CHROMEOS_ASH)');
registerTest('MetricsReporting', 'metrics_reporting_tests.js');
GEN('#endif');

@ -1,291 +0,0 @@
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// clang-format off
import {webUIListenerCallback} from 'chrome://resources/js/cr.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {ChromeCleanupProxyImpl} from 'chrome://settings/lazy_load.js';
import {MetricsBrowserProxyImpl, Router, routes, SafetyCheckCallbackConstants, SafetyCheckChromeCleanerStatus, SafetyCheckIconStatus, SafetyCheckInteractions, SettingsSafetyCheckChromeCleanerChildElement} from 'chrome://settings/settings.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {TestChromeCleanupProxy} from './test_chrome_cleanup_proxy.js';
import {TestMetricsBrowserProxy} from './test_metrics_browser_proxy.js';
// clang-format on
const testDisplayString = 'Test display string';
/**
* Fire a safety check Chrome cleaner event.
*/
function fireSafetyCheckChromeCleanerEvent(
state: SafetyCheckChromeCleanerStatus) {
const event = {
newState: state,
displayString: testDisplayString,
};
webUIListenerCallback(
SafetyCheckCallbackConstants.CHROME_CLEANER_CHANGED, event);
}
interface AssertSafetyCheckChildParams {
page: HTMLElement;
iconStatus: SafetyCheckIconStatus;
label: string;
buttonLabel?: string;
buttonAriaLabel?: string;
buttonClass?: string;
managedIcon?: boolean;
rowClickable?: boolean;
}
/**
* Verify that the safety check child inside the page has been configured as
* specified.
*/
function assertSafetyCheckChild({
page,
iconStatus,
label,
buttonLabel,
buttonAriaLabel,
buttonClass,
managedIcon,
rowClickable,
}: AssertSafetyCheckChildParams) {
const safetyCheckChild =
page.shadowRoot!.querySelector('settings-safety-check-child');
assertTrue(!!safetyCheckChild, 'safetyCheckChild is null');
assertTrue(
safetyCheckChild.iconStatus === iconStatus,
'unexpected iconStatus: ' + safetyCheckChild.iconStatus);
assertTrue(
safetyCheckChild.label === label,
'unexpected label: ' + safetyCheckChild.label);
assertTrue(
safetyCheckChild.subLabel === testDisplayString,
'unexpected subLabel: ' + safetyCheckChild.subLabel);
assertTrue(
!buttonLabel || safetyCheckChild.buttonLabel === buttonLabel,
'unexpected buttonLabel: ' + safetyCheckChild.buttonLabel);
assertTrue(
!buttonAriaLabel || safetyCheckChild.buttonAriaLabel === buttonAriaLabel,
'unexpected buttonAriaLabel: ' + safetyCheckChild.buttonAriaLabel);
assertTrue(
!buttonClass || safetyCheckChild.buttonClass === buttonClass,
'unexpected buttonClass: ' + safetyCheckChild.buttonClass);
assertTrue(
!!managedIcon === !!safetyCheckChild.managedIcon,
'unexpected managedIcon: ' + safetyCheckChild.managedIcon);
assertTrue(
!!rowClickable === !!safetyCheckChild.rowClickable,
'unexpected rowClickable: ' + safetyCheckChild.rowClickable);
}
suite('SafetyCheckChromeCleanerUiTests', function() {
let chromeCleanupBrowserProxy: TestChromeCleanupProxy;
let metricsBrowserProxy: TestMetricsBrowserProxy;
let page: SettingsSafetyCheckChromeCleanerChildElement;
setup(function() {
chromeCleanupBrowserProxy = new TestChromeCleanupProxy();
ChromeCleanupProxyImpl.setInstance(chromeCleanupBrowserProxy);
metricsBrowserProxy = new TestMetricsBrowserProxy();
MetricsBrowserProxyImpl.setInstance(metricsBrowserProxy);
document.body.innerHTML = window.trustedTypes!.emptyHTML;
page = document.createElement('settings-safety-check-chrome-cleaner-child');
document.body.appendChild(page);
flush();
});
teardown(function() {
page.remove();
Router.getInstance().navigateTo(routes.BASIC);
});
async function expectLogging(
safetyCheckInteraction: SafetyCheckInteractions, userAction: string) {
assertEquals(
safetyCheckInteraction,
await metricsBrowserProxy.whenCalled(
'recordSafetyCheckInteractionHistogram'));
assertEquals(
userAction, await metricsBrowserProxy.whenCalled('recordAction'));
}
test('chromeCleanerHiddenUiTest', function() {
fireSafetyCheckChromeCleanerEvent(SafetyCheckChromeCleanerStatus.HIDDEN);
flush();
// There is no Chrome cleaner child in safety check.
assertFalse(
!!page.shadowRoot!.querySelector('settings-safety-check-child'));
});
test('chromeCleanerCheckingUiTest', function() {
fireSafetyCheckChromeCleanerEvent(SafetyCheckChromeCleanerStatus.CHECKING);
flush();
assertSafetyCheckChild({
page: page,
iconStatus: SafetyCheckIconStatus.RUNNING,
label: 'Device software',
});
});
test('chromeCleanerInfectedTest', async function() {
fireSafetyCheckChromeCleanerEvent(SafetyCheckChromeCleanerStatus.INFECTED);
flush();
assertSafetyCheckChild({
page: page,
iconStatus: SafetyCheckIconStatus.WARNING,
label: 'Device software',
buttonLabel: 'Review',
buttonAriaLabel: 'Review device software',
buttonClass: 'action-button',
});
// User clicks the button.
page.shadowRoot!.querySelector('settings-safety-check-child')!.shadowRoot!
.querySelector<HTMLElement>('#button')!.click();
await expectLogging(
SafetyCheckInteractions.CHROME_CLEANER_REVIEW_INFECTED_STATE,
'Settings.SafetyCheck.ChromeCleanerReviewInfectedState');
// Ensure the correct Settings page is shown.
assertEquals(routes.CHROME_CLEANUP, Router.getInstance().getCurrentRoute());
});
test('chromeCleanerRebootRequiredUiTest', async function() {
fireSafetyCheckChromeCleanerEvent(
SafetyCheckChromeCleanerStatus.REBOOT_REQUIRED);
flush();
assertSafetyCheckChild({
page: page,
iconStatus: SafetyCheckIconStatus.INFO,
label: 'Device software',
buttonLabel: 'Restart computer',
buttonAriaLabel: 'Restart computer',
buttonClass: 'action-button',
});
// User clicks the button.
page.shadowRoot!.querySelector('settings-safety-check-child')!.shadowRoot!
.querySelector<HTMLElement>('#button')!.click();
await expectLogging(
SafetyCheckInteractions.CHROME_CLEANER_REBOOT,
'Settings.SafetyCheck.ChromeCleanerReboot');
// Ensure the browser proxy call is done.
return chromeCleanupBrowserProxy.whenCalled('restartComputer');
});
test('chromeCleanerScanningForUwsUiTest', async function() {
fireSafetyCheckChromeCleanerEvent(
SafetyCheckChromeCleanerStatus.SCANNING_FOR_UWS);
flush();
assertSafetyCheckChild({
page: page,
iconStatus: SafetyCheckIconStatus.RUNNING,
label: 'Device software',
rowClickable: true,
});
// User clicks the row.
page.shadowRoot!.querySelector('settings-safety-check-child')!.click();
// Ensure UMA is logged.
await expectLogging(
SafetyCheckInteractions.CHROME_CLEANER_CARET_NAVIGATION,
'Settings.SafetyCheck.ChromeCleanerCaretNavigation');
// Ensure the correct Settings page is shown.
assertEquals(routes.CHROME_CLEANUP, Router.getInstance().getCurrentRoute());
});
test('chromeCleanerRemovingUwsUiTest', async function() {
fireSafetyCheckChromeCleanerEvent(
SafetyCheckChromeCleanerStatus.REMOVING_UWS);
flush();
assertSafetyCheckChild({
page: page,
iconStatus: SafetyCheckIconStatus.RUNNING,
label: 'Device software',
rowClickable: true,
});
// User clicks the row.
page.shadowRoot!.querySelector('settings-safety-check-child')!.click();
// Ensure UMA is logged.
await expectLogging(
SafetyCheckInteractions.CHROME_CLEANER_CARET_NAVIGATION,
'Settings.SafetyCheck.ChromeCleanerCaretNavigation');
// Ensure the correct Settings page is shown.
assertEquals(routes.CHROME_CLEANUP, Router.getInstance().getCurrentRoute());
});
test('chromeCleanerDisabledByAdminUiTest', function() {
fireSafetyCheckChromeCleanerEvent(
SafetyCheckChromeCleanerStatus.DISABLED_BY_ADMIN);
flush();
assertSafetyCheckChild({
page: page,
iconStatus: SafetyCheckIconStatus.INFO,
label: 'Device software',
managedIcon: true,
});
});
test('chromeCleanerErrorUiTest', async function() {
fireSafetyCheckChromeCleanerEvent(SafetyCheckChromeCleanerStatus.ERROR);
flush();
assertSafetyCheckChild({
page: page,
iconStatus: SafetyCheckIconStatus.INFO,
label: 'Device software',
rowClickable: true,
});
// User clicks the row.
page.shadowRoot!.querySelector('settings-safety-check-child')!.click();
// Ensure UMA is logged.
await expectLogging(
SafetyCheckInteractions.CHROME_CLEANER_CARET_NAVIGATION,
'Settings.SafetyCheck.ChromeCleanerCaretNavigation');
// Ensure the correct Settings page is shown.
assertEquals(routes.CHROME_CLEANUP, Router.getInstance().getCurrentRoute());
});
test('chromeCleanerNoUwsFoundWithTimestampUiTest', async function() {
fireSafetyCheckChromeCleanerEvent(
SafetyCheckChromeCleanerStatus.NO_UWS_FOUND_WITH_TIMESTAMP);
flush();
assertSafetyCheckChild({
page: page,
iconStatus: SafetyCheckIconStatus.SAFE,
label: 'Device software',
rowClickable: true,
});
// User clicks the row.
page.shadowRoot!.querySelector('settings-safety-check-child')!.click();
// Ensure UMA is logged.
await expectLogging(
SafetyCheckInteractions.CHROME_CLEANER_CARET_NAVIGATION,
'Settings.SafetyCheck.ChromeCleanerCaretNavigation');
// Ensure the correct Settings page is shown.
assertEquals(routes.CHROME_CLEANUP, Router.getInstance().getCurrentRoute());
});
test('chromeCleanerNoUwsFoundWithoutTimestampUiTest', async function() {
fireSafetyCheckChromeCleanerEvent(
SafetyCheckChromeCleanerStatus.NO_UWS_FOUND_WITHOUT_TIMESTAMP);
flush();
assertSafetyCheckChild({
page: page,
iconStatus: SafetyCheckIconStatus.INFO,
label: 'Device software',
rowClickable: true,
});
// User clicks the row.
page.shadowRoot!.querySelector('settings-safety-check-child')!.click();
// Ensure UMA is logged.
await expectLogging(
SafetyCheckInteractions.CHROME_CLEANER_CARET_NAVIGATION,
'Settings.SafetyCheck.ChromeCleanerCaretNavigation');
// Ensure the correct Settings page is shown.
assertEquals(routes.CHROME_CLEANUP, Router.getInstance().getCurrentRoute());
});
});

@ -5,7 +5,7 @@
// clang-format off
import {webUIListenerCallback} from 'chrome://resources/js/cr.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {HatsBrowserProxyImpl, LifetimeBrowserProxyImpl, MetricsBrowserProxyImpl, OpenWindowProxyImpl, PasswordCheckReferrer, PasswordManagerImpl, Router, routes, SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckChromeCleanerStatus, SafetyCheckExtensionsStatus, SafetyCheckIconStatus, SafetyCheckInteractions, SafetyCheckParentStatus, SafetyCheckPasswordsStatus, SafetyCheckSafeBrowsingStatus, SafetyCheckUpdatesStatus, SettingsSafetyCheckChildElement, SettingsSafetyCheckExtensionsChildElement, SettingsSafetyCheckPageElement, SettingsSafetyCheckPasswordsChildElement, SettingsSafetyCheckSafeBrowsingChildElement ,SettingsSafetyCheckUpdatesChildElement, TrustSafetyInteraction} from 'chrome://settings/settings.js';
import {HatsBrowserProxyImpl, LifetimeBrowserProxyImpl, MetricsBrowserProxyImpl, OpenWindowProxyImpl, PasswordCheckReferrer, PasswordManagerImpl, Router, routes, SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckExtensionsStatus, SafetyCheckIconStatus, SafetyCheckInteractions, SafetyCheckParentStatus, SafetyCheckPasswordsStatus, SafetyCheckSafeBrowsingStatus, SafetyCheckUpdatesStatus, SettingsSafetyCheckChildElement, SettingsSafetyCheckExtensionsChildElement, SettingsSafetyCheckPageElement, SettingsSafetyCheckPasswordsChildElement, SettingsSafetyCheckSafeBrowsingChildElement ,SettingsSafetyCheckUpdatesChildElement, TrustSafetyInteraction} from 'chrome://settings/settings.js';
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
@ -79,19 +79,6 @@ function fireSafetyCheckExtensionsEvent(state: SafetyCheckExtensionsStatus) {
webUIListenerCallback(SafetyCheckCallbackConstants.EXTENSIONS_CHANGED, event);
}
/**
* Fire a safety check Chrome cleaner event.
*/
function fireSafetyCheckChromeCleanerEvent(
state: SafetyCheckChromeCleanerStatus) {
const event = {
newState: state,
displayString: testDisplayString,
};
webUIListenerCallback(
SafetyCheckCallbackConstants.CHROME_CLEANER_CHANGED, event);
}
class TestSafetyCheckBrowserProxy extends TestBrowserProxy implements
SafetyCheckBrowserProxy {
private parentRanDisplayString_ = '';
@ -168,7 +155,6 @@ suite('SafetyCheckPageUiTests', function() {
fireSafetyCheckPasswordsEvent(SafetyCheckPasswordsStatus.CHECKING);
fireSafetyCheckSafeBrowsingEvent(SafetyCheckSafeBrowsingStatus.CHECKING);
fireSafetyCheckExtensionsEvent(SafetyCheckExtensionsStatus.CHECKING);
fireSafetyCheckChromeCleanerEvent(SafetyCheckChromeCleanerStatus.CHECKING);
fireSafetyCheckParentEvent(SafetyCheckParentStatus.CHECKING);
flush();
@ -185,7 +171,6 @@ suite('SafetyCheckPageUiTests', function() {
SafetyCheckSafeBrowsingStatus.ENABLED_STANDARD);
fireSafetyCheckExtensionsEvent(
SafetyCheckExtensionsStatus.NO_BLOCKLISTED_EXTENSIONS);
fireSafetyCheckChromeCleanerEvent(SafetyCheckChromeCleanerStatus.INFECTED);
fireSafetyCheckParentEvent(SafetyCheckParentStatus.AFTER);
flush();

@ -1,56 +0,0 @@
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {ChromeCleanupProxy} from 'chrome://settings/lazy_load.js';
import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
export class TestChromeCleanupProxy extends TestBrowserProxy implements
ChromeCleanupProxy {
constructor() {
super([
'registerChromeCleanerObserver',
'restartComputer',
'startCleanup',
'startScanning',
'notifyShowDetails',
'notifyLearnMoreClicked',
'getMoreItemsPluralString',
'getItemsToRemovePluralString',
]);
}
registerChromeCleanerObserver() {
this.methodCalled('registerChromeCleanerObserver');
}
restartComputer() {
this.methodCalled('restartComputer');
}
startCleanup(logsUploadEnabled: boolean) {
this.methodCalled('startCleanup', logsUploadEnabled);
}
startScanning(logsUploadEnabled: boolean) {
this.methodCalled('startScanning', logsUploadEnabled);
}
notifyShowDetails(enabled: boolean) {
this.methodCalled('notifyShowDetails', enabled);
}
notifyLearnMoreClicked() {
this.methodCalled('notifyLearnMoreClicked');
}
getMoreItemsPluralString(numHiddenItems: number) {
this.methodCalled('getMoreItemsPluralString', numHiddenItems);
return Promise.resolve('');
}
getItemsToRemovePluralString(numItems: number) {
this.methodCalled('getItemsToRemovePluralString', numItems);
return Promise.resolve('');
}
}