blob: a818f37060fb3679927ea22c194a70d8b43c3f72 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* 'settings-notifications-subpage' contains the settings for notifications
* under Site Settings.
*/
import '/shared/settings/prefs/prefs.js';
import 'chrome://resources/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_hidden_style.css.js';
import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.js';
import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js';
import 'chrome://resources/cr_elements/cr_shared_style.css.js';
import 'chrome://resources/cr_elements/icons.html.js';
import './category_setting_exceptions.js';
import './settings_category_default_radio_group.js';
import './site_settings_shared.css.js';
import '../privacy_icons.html.js';
import '../privacy_page/collapse_radio_button.js';
import '../safety_hub/safety_hub_module.js';
import '../settings_page/settings_subpage.js';
import '../settings_shared.css.js';
import {PrefsMixin} from '/shared/settings/prefs/prefs_mixin.js';
import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {loadTimeData} from '../i18n_setup.js';
import type {MetricsBrowserProxy} from '../metrics_browser_proxy.js';
import {MetricsBrowserProxyImpl, SafetyHubEntryPoint} from '../metrics_browser_proxy.js';
import {routes} from '../route.js';
import type {Route} from '../router.js';
import {RouteObserverMixin, Router} from '../router.js';
import {SafetyHubBrowserProxyImpl, SafetyHubEvent} from '../safety_hub/safety_hub_browser_proxy.js';
import type {NotificationPermission, SafetyHubBrowserProxy} from '../safety_hub/safety_hub_browser_proxy.js';
import {SettingsViewMixin} from '../settings_page/settings_view_mixin.js';
import {ContentSetting, ContentSettingsTypes, SettingsState} from './constants.js';
import {getTemplate} from './notifications_page.html.js';
import type {SiteSettingsPrefsBrowserProxy} from './site_settings_prefs_browser_proxy.js';
import {SiteSettingsPrefsBrowserProxyImpl} from './site_settings_prefs_browser_proxy.js';
const NotificationsPageElementBase = RouteObserverMixin(
SettingsViewMixin(WebUiListenerMixin(PrefsMixin(PolymerElement))));
export class NotificationsPageElement extends NotificationsPageElementBase {
static get is() {
return 'settings-notifications-page';
}
static get template() {
return getTemplate();
}
static get properties() {
return {
searchTerm: {
type: String,
notify: true,
value: '',
},
isGuest_: {
type: Boolean,
value() {
return loadTimeData.getBoolean('isGuest');
},
},
enablePermissionSiteSettingsRadioButton_: {
type: Boolean,
value: () =>
loadTimeData.getBoolean('enablePermissionSiteSettingsRadioButton'),
},
/** Expose the Permissions SettingsState enum to HTML bindings. */
settingsStateEnum_: {
type: Object,
value: SettingsState,
},
/** Expose ContentSettingsTypes enum to HTML bindings. */
contentSettingsTypesEnum_: {
type: Object,
value: ContentSettingsTypes,
},
showNotificationPermissionsReview_: {
type: Boolean,
value: false,
},
/** Expose ContentSetting enum to HTML bindings. */
contentSettingEnum_: {
type: Object,
value: ContentSetting,
},
shouldShowSafetyHub_: {
type: Boolean,
value() {
return !loadTimeData.getBoolean('isGuest');
},
},
isNotificationAllowed_: Boolean,
notificationPermissionsReviewHeader_: String,
notificationPermissionsReviewSubheader_: String,
};
}
declare searchTerm: string;
declare private isGuest_: boolean;
declare private enablePermissionSiteSettingsRadioButton_: boolean;
declare private shouldShowSafetyHub_: boolean;
declare private isNotificationAllowed_: boolean;
declare private showNotificationPermissionsReview_: boolean;
declare private notificationPermissionsReviewHeader_: string;
declare private notificationPermissionsReviewSubheader_: string;
private siteSettingsPrefsBrowserProxy_: SiteSettingsPrefsBrowserProxy =
SiteSettingsPrefsBrowserProxyImpl.getInstance();
private safetyHubBrowserProxy_: SafetyHubBrowserProxy =
SafetyHubBrowserProxyImpl.getInstance();
private metricsBrowserProxy_: MetricsBrowserProxy =
MetricsBrowserProxyImpl.getInstance();
override ready() {
super.ready();
this.updateNotificationState_();
if (this.isGuest_) {
return;
}
this.addWebUiListener(
SafetyHubEvent.NOTIFICATION_PERMISSIONS_MAYBE_CHANGED,
(sites: NotificationPermission[]) =>
this.onReviewNotificationPermissionListChanged_(sites));
this.safetyHubBrowserProxy_.getNotificationPermissionReview().then(
(sites: NotificationPermission[]) =>
this.onReviewNotificationPermissionListChanged_(sites));
}
override currentRouteChanged(newRoute: Route, oldRoute?: Route) {
super.currentRouteChanged(newRoute, oldRoute);
// Only record the metrics when the user navigates to the notification
// settings page that shows the entry point.
if (this.showNotificationPermissionsReview_) {
this.metricsBrowserProxy_.recordSafetyHubEntryPointShown(
SafetyHubEntryPoint.NOTIFICATIONS);
}
}
private async onReviewNotificationPermissionListChanged_(
permissions: NotificationPermission[]) {
// The notification permissions review is shown when there are items to
// review (provided the feature is enabled and should be shown). Once
// visible it remains that way to show completion info, even if the list is
// emptied.
if (this.showNotificationPermissionsReview_) {
return;
}
this.showNotificationPermissionsReview_ =
!this.isGuest_ && permissions.length > 0;
this.notificationPermissionsReviewHeader_ =
await PluralStringProxyImpl.getInstance().getPluralString(
'safetyHubNotificationPermissionsPrimaryLabel', permissions.length);
this.notificationPermissionsReviewSubheader_ =
await PluralStringProxyImpl.getInstance().getPluralString(
'safetyHubNotificationPermissionsSecondaryLabel',
permissions.length);
}
private async updateNotificationState_() {
const [notificationDefaultValue] = await Promise.all([
this.siteSettingsPrefsBrowserProxy_.getDefaultValueForContentType(
ContentSettingsTypes.NOTIFICATIONS),
]);
this.isNotificationAllowed_ =
(notificationDefaultValue.setting === ContentSetting.ASK);
}
private onNotificationTopLevelRadioChanged_(
event: CustomEvent<{value: string}>) {
const radioButtonName = event.detail.value;
switch (radioButtonName) {
case 'notification-block-radio-button':
this.setPrefValue('generated.notification', SettingsState.BLOCK);
this.isNotificationAllowed_ = false;
break;
case 'notification-ask-radio-button':
this.setPrefValue('generated.notification', SettingsState.CPSS);
this.isNotificationAllowed_ = true;
break;
}
}
private onNotificationTopLevelRadioChanged2_(
event: CustomEvent<{value: boolean}>) {
const selected = event.detail.value;
if (selected) {
this.setPrefValue('generated.notification', SettingsState.CPSS);
this.isNotificationAllowed_ = true;
} else {
this.setPrefValue('generated.notification', SettingsState.BLOCK);
this.isNotificationAllowed_ = false;
}
}
private onSafetyHubButtonClick_() {
this.metricsBrowserProxy_.recordSafetyHubEntryPointClicked(
SafetyHubEntryPoint.NOTIFICATIONS);
Router.getInstance().navigateTo(routes.SAFETY_HUB);
}
// SettingsViewMixin implementation.
override focusBackButton() {
this.shadowRoot!.querySelector('settings-subpage')!.focusBackButton();
}
}
declare global {
interface HTMLElementTagNameMap {
'settings-notifications-page': NotificationsPageElement;
}
}
customElements.define(NotificationsPageElement.is, NotificationsPageElement);