blob: 09a86819b32ddedc354df576b6b402123c69285a [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
import 'chrome://resources/cr_elements/shared_style_css.m.js';
import './strings.m.js';
import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
import {assert} from 'chrome://resources/js/assert_ts.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {SiteSettingsDelegate} from './site_settings_mixin.js';
// A RegExp to roughly match acceptable patterns entered by the user.
// exec'ing() this RegExp will match the following groups:
// 0: Full matched string.
// 1: Scheme + scheme separator (e.g., 'https://').
// 2: Scheme only (e.g., 'https').
// 3: Hostname (e.g., 'example.com').
// 4: Port, including ':' separator (e.g., ':80').
const patternRegExp = new RegExp(
'^' +
// Scheme; optional.
'((http|https|\\*)://)?' +
// Hostname or localhost, required.
'([a-z0-9\\.-]+\\.[a-z0-9]+|localhost)' +
// Port, optional.
'(:[0-9]+)?' +
'$');
export function getSitePermissionsPatternFromSite(site: string): string {
const res = patternRegExp.exec(site)!;
assert(res);
const scheme = res[1] || 'https://';
const host = res[3];
const port = res[4] || '';
return scheme + host + port;
}
export interface SitePermissionsEditDialogElement {
$: {
dialog: CrDialogElement,
submit: CrButtonElement,
};
}
export class SitePermissionsEditDialogElement extends PolymerElement {
static get is() {
return 'site-permissions-edit-dialog';
}
static get template() {
return html`{__html_template__}`;
}
static get properties() {
return {
delegate: Object,
siteSet: String,
/**
* The site that this entry is currently managing. Only non-empty if this
* is for editing an existing entry.
*/
siteToEdit: {
type: String,
value: null,
},
site_: {
type: String,
value: '',
},
/** Whether the currently-entered input is valid. */
inputValid_: {
type: Boolean,
value: true,
},
};
}
delegate: SiteSettingsDelegate;
siteSet: chrome.developerPrivate.UserSiteSet;
siteToEdit: string|null;
private site_: string;
private inputValid_: boolean;
connectedCallback() {
super.connectedCallback();
if (this.siteToEdit !== null) {
this.site_ = this.siteToEdit;
this.validate_();
}
}
/**
* Validates that the pattern entered is valid by testing it against the
* regex. An empty patterh is considered "valid" as the invalid message will
* not be shown, but the input cannot be submitted as the action button will
* be disabled.
*/
private validate_() {
this.inputValid_ =
this.site_.trim().length === 0 || patternRegExp.test(this.site_);
}
private computeDialogTitle_(): string {
return loadTimeData.getString(
this.siteToEdit === null ? 'sitePermissionsAddSiteDialogTitle' :
'sitePermissionsEditSiteDialogTitle');
}
private computeSubmitButtonDisabled_(): boolean {
// If input is empty, disable the action button.
return !this.inputValid_ || this.site_.trim().length === 0;
}
private computeSubmitButtonLabel_(): string {
return loadTimeData.getString(this.siteToEdit === null ? 'add' : 'save');
}
private onCancel_() {
this.$.dialog.cancel();
}
private onSubmit_() {
const pattern = getSitePermissionsPatternFromSite(this.site_);
if (this.siteToEdit !== null) {
this.handleEdit_(pattern);
} else {
this.handleAdd_(pattern);
}
}
private handleEdit_(pattern: string) {
assert(this.siteToEdit);
if (pattern === this.siteToEdit) {
this.$.dialog.close();
return;
}
this.delegate.removeUserSpecifiedSite(this.siteSet, this.siteToEdit)
.then(() => {
this.addUserSpecifiedSite_(pattern);
});
}
private handleAdd_(pattern: string) {
assert(!this.siteToEdit);
this.addUserSpecifiedSite_(pattern);
}
private addUserSpecifiedSite_(pattern: string) {
this.delegate.addUserSpecifiedSite(this.siteSet, pattern)
.then(
() => {
this.$.dialog.close();
},
() => {
this.inputValid_ = false;
});
}
}
declare global {
interface HTMLElementTagNameMap {
'site-permissions-edit-dialog': SitePermissionsEditDialogElement;
}
}
customElements.define(
SitePermissionsEditDialogElement.is, SitePermissionsEditDialogElement);