blob: a1b2edce749ac70a33a32c41a5037dd5f5f4cfb4 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* 'settings-safety-check-page' is the settings page containing the browser
* safety check.
*/
(function() {
/**
* States of the safety check parent element.
* @enum {number}
*/
const ParentStatus = {
BEFORE: 0,
CHECKING: 1,
AFTER: 2,
};
/**
* UI states a safety check child can be in. Defines the basic UI of the child.
* @enum {number}
*/
const ChildUiStatus = {
RUNNING: 0,
SAFE: 1,
INFO: 2,
WARNING: 3,
};
/**
* @typedef {{
* newState: settings.SafetyCheckUpdatesStatus,
* displayString: string,
* }}
*/
let UpdatesChangedEvent;
/**
* @typedef {{
* newState: settings.SafetyCheckPasswordsStatus,
* displayString: string,
* buttonString: string,
* }}
*/
let PasswordsChangedEvent;
/**
* @typedef {{
* newState: settings.SafetyCheckSafeBrowsingStatus,
* displayString: string,
* }}
*/
let SafeBrowsingChangedEvent;
/**
* @typedef {{
* newState: settings.SafetyCheckExtensionsStatus,
* displayString: string,
* }}
*/
let ExtensionsChangedEvent;
Polymer({
is: 'settings-safety-check-page',
behaviors: [
WebUIListenerBehavior,
I18nBehavior,
],
properties: {
/**
* Current state of the safety check parent element.
* @private {!ParentStatus}
*/
parentStatus_: {
type: Number,
value: ParentStatus.BEFORE,
},
/**
* Current state of the safety check updates element.
* @private {!settings.SafetyCheckUpdatesStatus}
*/
updatesStatus_: {
type: Number,
value: settings.SafetyCheckUpdatesStatus.CHECKING,
},
/**
* Current state of the safety check passwords element.
* @private {!settings.SafetyCheckPasswordsStatus}
*/
passwordsStatus_: {
type: Number,
value: settings.SafetyCheckPasswordsStatus.CHECKING,
},
/**
* Current state of the safety check safe browsing element.
* @private {!settings.SafetyCheckSafeBrowsingStatus}
*/
safeBrowsingStatus_: {
type: Number,
value: settings.SafetyCheckSafeBrowsingStatus.CHECKING,
},
/**
* Current state of the safety check extensions element.
* @private {!settings.SafetyCheckExtensionsStatus}
*/
extensionsStatus_: {
type: Number,
value: settings.SafetyCheckExtensionsStatus.CHECKING,
},
/**
* UI string to display for the parent status.
* @private
*/
parentDisplayString_: String,
/**
* UI string to display for the updates status.
* @private
*/
updatesDisplayString_: String,
/**
* UI string to display for the passwords status.
* @private
*/
passwordsDisplayString_: String,
/**
* UI string to display for the Safe Browsing status.
* @private
*/
safeBrowsingDisplayString_: String,
/**
* UI string to display for the extensions status.
* @private
*/
extensionsDisplayString_: String,
/**
* UI string to display in the password button.
* @private
*/
passwordsButtonString_: String,
},
/** @private {settings.SafetyCheckBrowserProxy} */
safetyCheckBrowserProxy_: null,
/** @private {?settings.LifetimeBrowserProxy} */
lifetimeBrowserProxy_: null,
/**
* Timer ID for periodic update.
* @private {number}
*/
updateTimerId_: -1,
/** @override */
attached: function() {
this.safetyCheckBrowserProxy_ =
settings.SafetyCheckBrowserProxyImpl.getInstance();
this.lifetimeBrowserProxy_ =
settings.LifetimeBrowserProxyImpl.getInstance();
// Register for safety check status updates.
this.addWebUIListener(
settings.SafetyCheckCallbackConstants.UPDATES_CHANGED,
this.onSafetyCheckUpdatesChanged_.bind(this));
this.addWebUIListener(
settings.SafetyCheckCallbackConstants.PASSWORDS_CHANGED,
this.onSafetyCheckPasswordsChanged_.bind(this));
this.addWebUIListener(
settings.SafetyCheckCallbackConstants.SAFE_BROWSING_CHANGED,
this.onSafetyCheckSafeBrowsingChanged_.bind(this));
this.addWebUIListener(
settings.SafetyCheckCallbackConstants.EXTENSIONS_CHANGED,
this.onSafetyCheckExtensionsChanged_.bind(this));
// Configure default UI.
this.parentDisplayString_ =
this.i18n('safetyCheckParentPrimaryLabelBefore');
},
/**
* Triggers the safety check.
* @private
*/
runSafetyCheck_: function() {
// Update UI.
this.parentDisplayString_ = this.i18n('safetyCheckRunning');
this.parentStatus_ = ParentStatus.CHECKING;
// Reset all children states.
this.updatesStatus_ = settings.SafetyCheckUpdatesStatus.CHECKING;
this.passwordsStatus_ = settings.SafetyCheckPasswordsStatus.CHECKING;
this.safeBrowsingStatus_ = settings.SafetyCheckSafeBrowsingStatus.CHECKING;
this.extensionsStatus_ = settings.SafetyCheckExtensionsStatus.CHECKING;
// Display running-status for safety check elements.
this.updatesDisplayString_ = '';
this.passwordsDisplayString_ = '';
this.safeBrowsingDisplayString_ = '';
this.extensionsDisplayString_ = '';
// Trigger safety check.
this.safetyCheckBrowserProxy_.runSafetyCheck();
// Readout new safety check status via accessibility.
this.fire('iron-announce', {
text: this.i18n('safetyCheckAriaLiveRunning'),
});
},
/** @private */
updateParentFromChildren_: function() {
// If all children elements received updates: update parent element.
if (this.updatesStatus_ != settings.SafetyCheckUpdatesStatus.CHECKING &&
this.passwordsStatus_ != settings.SafetyCheckPasswordsStatus.CHECKING &&
this.safeBrowsingStatus_ !=
settings.SafetyCheckSafeBrowsingStatus.CHECKING &&
this.extensionsStatus_ !=
settings.SafetyCheckExtensionsStatus.CHECKING) {
// Update UI.
this.parentStatus_ = ParentStatus.AFTER;
// Start periodic safety check parent ran string updates.
const timestamp = Date.now();
const update = async () => {
this.parentDisplayString_ =
await this.safetyCheckBrowserProxy_.getParentRanDisplayString(
timestamp);
};
clearInterval(this.updateTimerId_);
this.updateTimerId_ = setInterval(update, 60000);
// Run initial safety check parent ran string update now.
update();
// Readout new safety check status via accessibility.
this.fire('iron-announce', {
text: this.i18n('safetyCheckAriaLiveAfter'),
});
}
},
/**
* @param {!UpdatesChangedEvent} event
* @private
*/
onSafetyCheckUpdatesChanged_: function(event) {
this.updatesStatus_ = event.newState;
this.updatesDisplayString_ = event.displayString;
this.updateParentFromChildren_();
},
/**
* @param {!PasswordsChangedEvent} event
* @private
*/
onSafetyCheckPasswordsChanged_: function(event) {
this.passwordsDisplayString_ = event.displayString;
this.passwordsButtonString_ = event.buttonString;
this.passwordsStatus_ = event.newState;
this.updateParentFromChildren_();
},
/**
* @param {!SafeBrowsingChangedEvent} event
* @private
*/
onSafetyCheckSafeBrowsingChanged_: function(event) {
this.safeBrowsingStatus_ = event.newState;
this.safeBrowsingDisplayString_ = event.displayString;
this.updateParentFromChildren_();
},
/**
* @param {!ExtensionsChangedEvent} event
* @private
*/
onSafetyCheckExtensionsChanged_: function(event) {
this.extensionsDisplayString_ = event.displayString;
this.extensionsStatus_ = event.newState;
this.updateParentFromChildren_();
},
/**
* @private
* @return {boolean}
*/
shouldShowParentButton_: function() {
return this.parentStatus_ == ParentStatus.BEFORE;
},
/**
* @private
* @return {boolean}
*/
shouldShowParentIconButton_: function() {
return this.parentStatus_ == ParentStatus.AFTER;
},
/** @private */
onRunSafetyCheckClick_: function() {
settings.HatsBrowserProxyImpl.getInstance().tryShowSurvey();
this.runSafetyCheck_();
this.focusParent_();
},
/** @private */
focusParent_() {
const parent =
/** @type {!Element} */ (this.$$('#safetyCheckParent'));
parent.focus();
},
/**
* @private
* @return {boolean}
*/
shouldShowChildren_: function() {
return this.parentStatus_ != ParentStatus.BEFORE;
},
/**
* Returns the default icon for a safety check child in the specified state.
* @private
* @param {ChildUiStatus} childUiStatus
* @return {?string}
*/
getChildUiIcon_: function(childUiStatus) {
switch (childUiStatus) {
case ChildUiStatus.RUNNING:
return null;
case ChildUiStatus.SAFE:
return 'cr:check';
case ChildUiStatus.INFO:
return 'cr:info';
case ChildUiStatus.WARNING:
return 'cr:warning';
default:
assertNotReached();
}
},
/**
* Returns the default icon src for animated icons for a safety check child
* in the specified state.
* @private
* @param {ChildUiStatus} childUiStatus
* @return {?string}
*/
getChildUiIconSrc_: function(childUiStatus) {
if (childUiStatus == ChildUiStatus.RUNNING) {
return 'chrome://resources/images/throbber_small.svg';
}
return null;
},
/**
* Returns the default icon class for a safety check child in the specified
* state.
* @private
* @param {ChildUiStatus} childUiStatus
* @return {string}
*/
getChildUiIconClass_: function(childUiStatus) {
switch (childUiStatus) {
case ChildUiStatus.RUNNING:
case ChildUiStatus.SAFE:
return 'icon-blue';
case ChildUiStatus.WARNING:
return 'icon-red';
default:
return '';
}
},
/**
* Returns the default icon aria label for a safety check child in the
* specified state.
* @private
* @param {ChildUiStatus} childUiStatus
* @return {string}
*/
getChildUiIconAriaLabel_: function(childUiStatus) {
switch (childUiStatus) {
case ChildUiStatus.RUNNING:
return this.i18n('safetyCheckIconRunningAriaLabel');
case ChildUiStatus.SAFE:
return this.i18n('safetyCheckIconSafeAriaLabel');
case ChildUiStatus.INFO:
return this.i18n('safetyCheckIconInfoAriaLabel');
case ChildUiStatus.WARNING:
return this.i18n('safetyCheckIconWarningAriaLabel');
default:
assertNotReached();
}
},
/**
* @private
* @return {boolean}
*/
shouldShowUpdatesButton_: function() {
return this.updatesStatus_ == settings.SafetyCheckUpdatesStatus.RELAUNCH;
},
/**
* @private
* @return {boolean}
*/
shouldShowUpdatesManagedIcon_: function() {
return this.updatesStatus_ ==
settings.SafetyCheckUpdatesStatus.DISABLED_BY_ADMIN;
},
/** @private */
onSafetyCheckUpdatesButtonClick_: function() {
this.lifetimeBrowserProxy_.relaunch();
},
/**
* @return {ChildUiStatus}
* @private
*/
getUpdatesUiStatus_: function() {
switch (this.updatesStatus_) {
case settings.SafetyCheckUpdatesStatus.CHECKING:
case settings.SafetyCheckUpdatesStatus.UPDATING:
return ChildUiStatus.RUNNING;
case settings.SafetyCheckUpdatesStatus.UPDATED:
return ChildUiStatus.SAFE;
case settings.SafetyCheckUpdatesStatus.RELAUNCH:
case settings.SafetyCheckUpdatesStatus.DISABLED_BY_ADMIN:
case settings.SafetyCheckUpdatesStatus.FAILED_OFFLINE:
return ChildUiStatus.INFO;
case settings.SafetyCheckUpdatesStatus.FAILED:
return ChildUiStatus.WARNING;
default:
assertNotReached();
}
},
/**
* @private
* @return {?string}
*/
getUpdatesIcon_: function() {
return this.getChildUiIcon_(this.getUpdatesUiStatus_());
},
/**
* @private
* @return {?string}
*/
getUpdatesIconSrc_: function() {
return this.getChildUiIconSrc_(this.getUpdatesUiStatus_());
},
/**
* @private
* @return {string}
*/
getUpdatesIconClass_: function() {
return this.getChildUiIconClass_(this.getUpdatesUiStatus_());
},
/**
* @private
* @return {string}
*/
getUpdatesIconAriaLabel_: function() {
return this.getChildUiIconAriaLabel_(this.getUpdatesUiStatus_());
},
/**
* @private
* @return {boolean}
*/
shouldShowPasswordsButton_: function() {
return this.passwordsStatus_ ==
settings.SafetyCheckPasswordsStatus.COMPROMISED;
},
/**
* @private
* @return {ChildUiStatus}
*/
getPasswordsUiStatus_: function() {
switch (this.passwordsStatus_) {
case settings.SafetyCheckPasswordsStatus.CHECKING:
return ChildUiStatus.RUNNING;
case settings.SafetyCheckPasswordsStatus.SAFE:
return ChildUiStatus.SAFE;
case settings.SafetyCheckPasswordsStatus.COMPROMISED:
return ChildUiStatus.WARNING;
case settings.SafetyCheckPasswordsStatus.OFFLINE:
case settings.SafetyCheckPasswordsStatus.NO_PASSWORDS:
case settings.SafetyCheckPasswordsStatus.SIGNED_OUT:
case settings.SafetyCheckPasswordsStatus.QUOTA_LIMIT:
case settings.SafetyCheckPasswordsStatus.ERROR:
return ChildUiStatus.INFO;
default:
assertNotReached();
}
},
/**
* @private
* @return {?string}
*/
getPasswordsIcon_: function() {
return this.getChildUiIcon_(this.getPasswordsUiStatus_());
},
/**
* @private
* @return {?string}
*/
getPasswordsIconSrc_: function() {
return this.getChildUiIconSrc_(this.getPasswordsUiStatus_());
},
/**
* @private
* @return {string}
*/
getPasswordsIconClass_: function() {
return this.getChildUiIconClass_(this.getPasswordsUiStatus_());
},
/**
* @private
* @return {string}
*/
getPasswordsIconAriaLabel_: function() {
return this.getChildUiIconAriaLabel_(this.getPasswordsUiStatus_());
},
/** @private */
onPasswordsButtonClick_: function() {
settings.Router.getInstance().navigateTo(settings.routes.CHECK_PASSWORDS);
PasswordManagerImpl.getInstance().recordPasswordCheckReferrer(
PasswordManagerProxy.PasswordCheckReferrer.SAFETY_CHECK);
},
/**
* @private
* @return {boolean}
*/
shouldShowSafeBrowsingButton_: function() {
return this.safeBrowsingStatus_ ==
settings.SafetyCheckSafeBrowsingStatus.DISABLED;
},
/**
* @private
* @return {boolean}
*/
shouldShowSafeBrowsingManagedIcon_: function() {
return this.getSafeBrowsingManagedIcon_() != null;
},
/**
* @private
* @return {?string}
*/
getSafeBrowsingManagedIcon_: function() {
switch (this.safeBrowsingStatus_) {
case settings.SafetyCheckSafeBrowsingStatus.DISABLED_BY_ADMIN:
return 'cr20:domain';
case settings.SafetyCheckSafeBrowsingStatus.DISABLED_BY_EXTENSION:
return 'cr:extension';
default:
return null;
}
},
/**
* @private
* @return {ChildUiStatus}
*/
getSafeBrowsingUiStatus_: function() {
switch (this.safeBrowsingStatus_) {
case settings.SafetyCheckSafeBrowsingStatus.CHECKING:
return ChildUiStatus.RUNNING;
case settings.SafetyCheckSafeBrowsingStatus.ENABLED:
return ChildUiStatus.SAFE;
case settings.SafetyCheckSafeBrowsingStatus.DISABLED:
case settings.SafetyCheckSafeBrowsingStatus.DISABLED_BY_ADMIN:
case settings.SafetyCheckSafeBrowsingStatus.DISABLED_BY_EXTENSION:
return ChildUiStatus.INFO;
default:
assertNotReached();
}
},
/**
* @private
* @return {?string}
*/
getSafeBrowsingIcon_: function() {
return this.getChildUiIcon_(this.getSafeBrowsingUiStatus_());
},
/**
* @private
* @return {?string}
*/
getSafeBrowsingIconSrc_: function() {
return this.getChildUiIconSrc_(this.getSafeBrowsingUiStatus_());
},
/**
* @private
* @return {string}
*/
getSafeBrowsingIconClass_: function() {
return this.getChildUiIconClass_(this.getSafeBrowsingUiStatus_());
},
/**
* @private
* @return {string}
*/
getSafeBrowsingIconAriaLabel_: function() {
return this.getChildUiIconAriaLabel_(this.getSafeBrowsingUiStatus_());
},
/** @private */
onSafeBrowsingButtonClick_: function() {
settings.Router.getInstance().navigateTo(settings.routes.SECURITY);
},
/**
* @private
* @return {boolean}
*/
shouldShowExtensionsButton_: function() {
switch (this.extensionsStatus_) {
case settings.SafetyCheckExtensionsStatus.BLOCKLISTED_ALL_DISABLED:
case settings.SafetyCheckExtensionsStatus
.BLOCKLISTED_REENABLED_ALL_BY_USER:
case settings.SafetyCheckExtensionsStatus
.BLOCKLISTED_REENABLED_SOME_BY_USER:
return true;
default:
return false;
}
},
/**
* @private
* @return {boolean}
*/
shouldShowExtensionsManagedIcon_: function() {
return this.extensionsStatus_ ==
settings.SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_ADMIN;
},
/** @private */
onSafetyCheckExtensionsButtonClick_: function() {
settings.OpenWindowProxyImpl.getInstance().openURL('chrome://extensions');
},
/**
* @private
* @return {ChildUiStatus}
*/
getExtensionsUiStatus_: function() {
switch (this.extensionsStatus_) {
case settings.SafetyCheckExtensionsStatus.CHECKING:
return ChildUiStatus.RUNNING;
case settings.SafetyCheckExtensionsStatus.ERROR:
case settings.SafetyCheckExtensionsStatus
.BLOCKLISTED_REENABLED_ALL_BY_ADMIN:
return ChildUiStatus.INFO;
case settings.SafetyCheckExtensionsStatus.NO_BLOCKLISTED_EXTENSIONS:
case settings.SafetyCheckExtensionsStatus.BLOCKLISTED_ALL_DISABLED:
return ChildUiStatus.SAFE;
case settings.SafetyCheckExtensionsStatus
.BLOCKLISTED_REENABLED_ALL_BY_USER:
case settings.SafetyCheckExtensionsStatus
.BLOCKLISTED_REENABLED_SOME_BY_USER:
return ChildUiStatus.WARNING;
default:
assertNotReached();
}
},
/**
* @private
* @return {?string}
*/
getExtensionsIcon_: function() {
return this.getChildUiIcon_(this.getExtensionsUiStatus_());
},
/**
* @private
* @return {?string}
*/
getExtensionsIconSrc_: function() {
return this.getChildUiIconSrc_(this.getExtensionsUiStatus_());
},
/**
* @private
* @return {string}
*/
getExtensionsIconClass_: function() {
return this.getChildUiIconClass_(this.getExtensionsUiStatus_());
},
/**
* @private
* @return {string}
*/
getExtensionsIconAriaLabel_: function() {
return this.getChildUiIconAriaLabel_(this.getExtensionsUiStatus_());
},
/**
* @private
* @return {string}
*/
getExtensionsButtonClass_: function() {
switch (this.extensionsStatus_) {
case settings.SafetyCheckExtensionsStatus
.BLOCKLISTED_REENABLED_ALL_BY_USER:
case settings.SafetyCheckExtensionsStatus
.BLOCKLISTED_REENABLED_SOME_BY_USER:
return 'action-button';
default:
return '';
}
},
});
})();