| // Copyright 2016 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | /** | 
 |  * @fileoverview | 
 |  * 'add-site-dialog' provides a dialog to add exceptions for a given Content | 
 |  * Settings category. | 
 |  */ | 
 | import 'chrome://resources/cr_elements/cr_button/cr_button.js'; | 
 | import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; | 
 | import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; | 
 | import 'chrome://resources/cr_elements/cr_input/cr_input.js'; | 
 | import '../settings_shared.css.js'; | 
 |  | 
 | import type {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js'; | 
 | import type {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; | 
 | import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; | 
 | import type {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js'; | 
 | import {assert} from 'chrome://resources/js/assert.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} from '../metrics_browser_proxy.js'; | 
 |  | 
 | import {getTemplate} from './add_site_dialog.html.js'; | 
 | import {ContentSetting, ContentSettingsTypes, CookiesExceptionType, SITE_EXCEPTION_WILDCARD} from './constants.js'; | 
 | import type {SiteSettingsMixinInterface} from './site_settings_mixin.js'; | 
 | import {SiteSettingsMixin} from './site_settings_mixin.js'; | 
 |  | 
 | export interface AddSiteDialogElement { | 
 |   $: { | 
 |     add: CrButtonElement, | 
 |     dialog: CrDialogElement, | 
 |     incognito: CrCheckboxElement, | 
 |     site: CrInputElement, | 
 |   }; | 
 | } | 
 |  | 
 | const AddSiteDialogElementBase = SiteSettingsMixin(PolymerElement) as unknown as | 
 |     {new (): PolymerElement & SiteSettingsMixinInterface}; | 
 |  | 
 | export class AddSiteDialogElement extends AddSiteDialogElementBase { | 
 |   static get is() { | 
 |     return 'add-site-dialog'; | 
 |   } | 
 |  | 
 |   static get template() { | 
 |     return getTemplate(); | 
 |   } | 
 |  | 
 |   static get properties() { | 
 |     return { | 
 |       /** | 
 |        * Whether this is about an Allow, Block, SessionOnly, or other. | 
 |        */ | 
 |       contentSetting: String, | 
 |  | 
 |       hasIncognito: { | 
 |         type: Boolean, | 
 |         observer: 'hasIncognitoChanged_', | 
 |       }, | 
 |  | 
 |       /** | 
 |        * Controls what kind of patterns the created cookies exception will have | 
 |        * (based on the CookiesExceptionType): | 
 |        * - THIRD_PARTY: Exception that will have primary pattern as wildcard | 
 |        * (third-party cookie exceptions). | 
 |        * - SITE_DATA: Exception that will have secondary pattern as wildcard | 
 |        * (regular exceptions). | 
 |        * - COMBINED: Support both pattern types and have a checkbox to control | 
 |        * the mode. | 
 |        */ | 
 |       cookiesExceptionType: String, | 
 |  | 
 |       /** | 
 |        * The site to add an exception for. | 
 |        */ | 
 |       site_: String, | 
 |  | 
 |       /** | 
 |        * The error message to display when the pattern is invalid. | 
 |        */ | 
 |       errorMessage_: String, | 
 |     }; | 
 |   } | 
 |  | 
 |   declare contentSetting: ContentSetting; | 
 |   declare hasIncognito: boolean; | 
 |   declare cookiesExceptionType: CookiesExceptionType; | 
 |   declare private site_: string; | 
 |   declare private errorMessage_: string; | 
 |   private metricsBrowserProxy_: MetricsBrowserProxy = | 
 |       MetricsBrowserProxyImpl.getInstance(); | 
 |  | 
 |   override connectedCallback() { | 
 |     super.connectedCallback(); | 
 |  | 
 |     assert(this.category); | 
 |     assert(this.contentSetting); | 
 |     assert(typeof this.hasIncognito !== 'undefined'); | 
 |  | 
 |     this.$.dialog.showModal(); | 
 |   } | 
 |  | 
 |   /** | 
 |    * Validates that the pattern entered is valid. | 
 |    */ | 
 |   private validate_() { | 
 |     // If input is empty, disable the action button, but don't show the red | 
 |     // invalid message. | 
 |     if (this.$.site.value.trim() === '') { | 
 |       this.$.site.invalid = false; | 
 |       this.$.add.disabled = true; | 
 |       return; | 
 |     } | 
 |  | 
 |     this.browserProxy.isPatternValidForType(this.site_, this.category) | 
 |         .then(({isValid, reason}) => { | 
 |           this.$.site.invalid = !isValid; | 
 |           this.$.add.disabled = !isValid; | 
 |           this.errorMessage_ = reason || ''; | 
 |         }); | 
 |   } | 
 |  | 
 |   private onCancelClick_() { | 
 |     this.$.dialog.cancel(); | 
 |   } | 
 |  | 
 |   /** | 
 |    * The tap handler for the Add [Site] button (adds the pattern and closes | 
 |    * the dialog). | 
 |    */ | 
 |   private onSubmit_() { | 
 |     assert(!this.$.add.disabled); | 
 |     let primaryPattern = this.site_; | 
 |     let secondaryPattern = SITE_EXCEPTION_WILDCARD; | 
 |  | 
 |     if (this.cookiesExceptionType === CookiesExceptionType.THIRD_PARTY || | 
 |         this.category === ContentSettingsTypes.TRACKING_PROTECTION) { | 
 |       primaryPattern = SITE_EXCEPTION_WILDCARD; | 
 |       secondaryPattern = this.site_; | 
 |     } | 
 |  | 
 |     if (this.showIncognitoSessionOnly_()) { | 
 |       // Record how many users are interacting with the incognito checkbox | 
 |       // when it is available. | 
 |       this.metricsBrowserProxy_.recordBooleanHistogram( | 
 |           'Settings.AddSiteDialog.Incognito', this.$.incognito.checked); | 
 |     } | 
 |  | 
 |     this.browserProxy.setCategoryPermissionForPattern( | 
 |         primaryPattern, secondaryPattern, this.category, this.contentSetting, | 
 |         this.$.incognito.checked); | 
 |  | 
 |     this.$.dialog.close(); | 
 |   } | 
 |  | 
 |   private showIncognitoSessionOnly_() { | 
 |     return this.hasIncognito && !loadTimeData.getBoolean('isGuest') && | 
 |         this.contentSetting !== ContentSetting.SESSION_ONLY; | 
 |   } | 
 |  | 
 |   private hasIncognitoChanged_() { | 
 |     if (!this.hasIncognito) { | 
 |       this.$.incognito.checked = false; | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | declare global { | 
 |   interface HTMLElementTagNameMap { | 
 |     'add-site-dialog': AddSiteDialogElement; | 
 |   } | 
 | } | 
 |  | 
 | customElements.define(AddSiteDialogElement.is, AddSiteDialogElement); |