blob: b269d9ccbc2d39cd460055ca27773441ba3bbe0d [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371// Copyright (c) 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Tim van der Lippe119690c2020-01-13 12:31:304
Tim van der Lippe0ed1d2b2020-02-04 13:45:135import * as Common from '../common/common.js';
6import * as SDK from '../sdk/sdk.js';
7import * as UI from '../ui/ui.js';
8
Tim van der Lippe119690c2020-01-13 12:31:309/** @type {?BlockedURLsPane} */
10export let _instance = null;
11
Blink Reformat4c46d092018-04-07 15:32:3712/**
13 * @implements {UI.ListWidget.Delegate<SDK.NetworkManager.BlockedPattern>}
14 */
Tim van der Lippe0ed1d2b2020-02-04 13:45:1315export class BlockedURLsPane extends UI.Widget.VBox {
Blink Reformat4c46d092018-04-07 15:32:3716 constructor() {
17 super(true);
18 this.registerRequiredCSS('network/blockedURLsPane.css');
19
Tim van der Lippe119690c2020-01-13 12:31:3020 _instance = this;
Paul Lewis5a922e72020-01-24 11:58:0821 this._manager = self.SDK.multitargetNetworkManager;
Tim van der Lippe0ed1d2b2020-02-04 13:45:1322 this._manager.addEventListener(
23 SDK.NetworkManager.MultitargetNetworkManager.Events.BlockedPatternsChanged, this._update, this);
Blink Reformat4c46d092018-04-07 15:32:3724
Tim van der Lippe0ed1d2b2020-02-04 13:45:1325 this._toolbar = new UI.Toolbar.Toolbar('', this.contentElement);
26 this._enabledCheckbox = new UI.Toolbar.ToolbarCheckbox(
27 Common.UIString.UIString('Enable request blocking'), undefined, this._toggleEnabled.bind(this));
Blink Reformat4c46d092018-04-07 15:32:3728 this._toolbar.appendToolbarItem(this._enabledCheckbox);
29 this._toolbar.appendSeparator();
Tim van der Lippe0ed1d2b2020-02-04 13:45:1330 const addButton = new UI.Toolbar.ToolbarButton(Common.UIString.UIString('Add pattern'), 'largeicon-add');
31 addButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._addButtonClicked, this);
Blink Reformat4c46d092018-04-07 15:32:3732 this._toolbar.appendToolbarItem(addButton);
Tim van der Lippe0ed1d2b2020-02-04 13:45:1333 const clearButton =
34 new UI.Toolbar.ToolbarButton(Common.UIString.UIString('Remove all patterns'), 'largeicon-clear');
35 clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._removeAll, this);
Blink Reformat4c46d092018-04-07 15:32:3736 this._toolbar.appendToolbarItem(clearButton);
37
Tim van der Lippe0ed1d2b2020-02-04 13:45:1338 /** @type {!UI.ListWidget.ListWidget<!SDK.NetworkManager.BlockedPattern>} */
39 this._list = new UI.ListWidget.ListWidget(this);
Blink Reformat4c46d092018-04-07 15:32:3740 this._list.element.classList.add('blocked-urls');
41 this._list.registerRequiredCSS('network/blockedURLsPane.css');
42 this._list.setEmptyPlaceholder(this._createEmptyPlaceholder());
43 this._list.show(this.contentElement);
44
45 /** @type {?UI.ListWidget.Editor<!SDK.NetworkManager.BlockedPattern>} */
46 this._editor = null;
47
48 /** @type {!Map<string, number>} */
49 this._blockedCountForUrl = new Map();
Paul Lewisdaac1062020-03-05 14:37:1050 SDK.SDKModel.TargetManager.instance().addModelListener(
Tim van der Lippe0ed1d2b2020-02-04 13:45:1351 SDK.NetworkManager.NetworkManager, SDK.NetworkManager.Events.RequestFinished, this._onRequestFinished, this);
Blink Reformat4c46d092018-04-07 15:32:3752
Tim van der Lippe0ed1d2b2020-02-04 13:45:1353 this._updateThrottler = new Common.Throttler.Throttler(200);
Blink Reformat4c46d092018-04-07 15:32:3754
55 this._update();
56 }
57
58 /**
59 * @return {!Element}
60 */
61 _createEmptyPlaceholder() {
62 const element = this.contentElement.createChild('div', 'no-blocked-urls');
Tim van der Lippe0ed1d2b2020-02-04 13:45:1363 const addButton = UI.UIUtils.createTextButton(ls`Add pattern`, this._addButtonClicked.bind(this), 'add-button');
Mandy Chen6a711a92019-10-08 22:58:1864 UI.ARIAUtils.setAccessibleName(addButton, ls`Add request blocking pattern`);
Tim van der Lippe0ed1d2b2020-02-04 13:45:1365 element.appendChild(UI.UIUtils.formatLocalized('Requests are not blocked. %s', [addButton]));
Blink Reformat4c46d092018-04-07 15:32:3766 return element;
67 }
68
69 static reset() {
Tim van der Lippe119690c2020-01-13 12:31:3070 if (_instance) {
71 _instance.reset();
Tim van der Lippe1d6e57a2019-09-30 11:55:3472 }
Blink Reformat4c46d092018-04-07 15:32:3773 }
74
75 _addButtonClicked() {
76 this._manager.setBlockingEnabled(true);
77 this._list.addNewItem(0, {url: '', enabled: true});
78 }
79
80 /**
81 * @override
82 * @param {!SDK.NetworkManager.BlockedPattern} pattern
83 * @param {boolean} editable
84 * @return {!Element}
85 */
86 renderItem(pattern, editable) {
87 const count = this._blockedRequestsCount(pattern.url);
88 const element = createElementWithClass('div', 'blocked-url');
89 const checkbox = element.createChild('input', 'blocked-url-checkbox');
90 checkbox.type = 'checkbox';
91 checkbox.checked = pattern.enabled;
92 checkbox.disabled = !this._manager.blockingEnabled();
93 element.createChild('div', 'blocked-url-label').textContent = pattern.url;
Tim van der Lippe0ed1d2b2020-02-04 13:45:1394 element.createChild('div', 'blocked-url-count').textContent = Common.UIString.UIString('%d blocked', count);
Blink Reformat4c46d092018-04-07 15:32:3795 element.addEventListener('click', event => this._togglePattern(pattern, event), false);
96 checkbox.addEventListener('click', event => this._togglePattern(pattern, event), false);
97 return element;
98 }
99
100 /**
101 * @param {!SDK.NetworkManager.BlockedPattern} pattern
102 * @param {!Event} event
103 */
104 _togglePattern(pattern, event) {
105 event.consume(true);
106 const patterns = this._manager.blockedPatterns();
107 patterns.splice(patterns.indexOf(pattern), 1, {enabled: !pattern.enabled, url: pattern.url});
108 this._manager.setBlockedPatterns(patterns);
109 }
110
111 _toggleEnabled() {
112 this._manager.setBlockingEnabled(!this._manager.blockingEnabled());
113 this._update();
114 }
115
116 /**
117 * @override
118 * @param {!SDK.NetworkManager.BlockedPattern} pattern
119 * @param {number} index
120 */
121 removeItemRequested(pattern, index) {
122 const patterns = this._manager.blockedPatterns();
123 patterns.splice(index, 1);
124 this._manager.setBlockedPatterns(patterns);
125 }
126
127 /**
128 * @override
129 * @param {!SDK.NetworkManager.BlockedPattern} pattern
130 * @return {!UI.ListWidget.Editor}
131 */
132 beginEdit(pattern) {
133 this._editor = this._createEditor();
134 this._editor.control('url').value = pattern.url;
135 return this._editor;
136 }
137
138 /**
139 * @override
140 * @param {!SDK.NetworkManager.BlockedPattern} item
141 * @param {!UI.ListWidget.Editor} editor
142 * @param {boolean} isNew
143 */
144 commitEdit(item, editor, isNew) {
145 const url = editor.control('url').value;
146 const patterns = this._manager.blockedPatterns();
Tim van der Lippe1d6e57a2019-09-30 11:55:34147 if (isNew) {
Blink Reformat4c46d092018-04-07 15:32:37148 patterns.push({enabled: true, url: url});
Tim van der Lippe1d6e57a2019-09-30 11:55:34149 } else {
Blink Reformat4c46d092018-04-07 15:32:37150 patterns.splice(patterns.indexOf(item), 1, {enabled: true, url: url});
Tim van der Lippe1d6e57a2019-09-30 11:55:34151 }
Blink Reformat4c46d092018-04-07 15:32:37152
153 this._manager.setBlockedPatterns(patterns);
154 }
155
156 /**
157 * @return {!UI.ListWidget.Editor<!SDK.NetworkManager.BlockedPattern>}
158 */
159 _createEditor() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34160 if (this._editor) {
Blink Reformat4c46d092018-04-07 15:32:37161 return this._editor;
Tim van der Lippe1d6e57a2019-09-30 11:55:34162 }
Blink Reformat4c46d092018-04-07 15:32:37163
164 const editor = new UI.ListWidget.Editor();
165 const content = editor.contentElement();
166 const titles = content.createChild('div', 'blocked-url-edit-row');
167 titles.createChild('div').textContent =
Tim van der Lippe0ed1d2b2020-02-04 13:45:13168 Common.UIString.UIString('Text pattern to block matching requests; use * for wildcard');
Blink Reformat4c46d092018-04-07 15:32:37169 const fields = content.createChild('div', 'blocked-url-edit-row');
Amanda Bakerca502822019-07-02 00:01:28170 const validator = (item, index, input) => {
Michael Liaoaf4130a2020-01-14 22:13:14171 let valid = true;
172 let errorMessage;
173 if (!input.value) {
174 errorMessage = ls`Pattern input cannot be empty.`;
175 valid = false;
176 } else if (this._manager.blockedPatterns().find(pattern => pattern.url === input.value)) {
177 errorMessage = ls`Pattern already exists.`;
178 valid = false;
179 }
180 return {valid, errorMessage};
Amanda Bakerca502822019-07-02 00:01:28181 };
182 const urlInput = editor.createInput('url', 'text', '', validator);
Blink Reformat4c46d092018-04-07 15:32:37183 fields.createChild('div', 'blocked-url-edit-value').appendChild(urlInput);
184 return editor;
185 }
186
187 _removeAll() {
188 this._manager.setBlockedPatterns([]);
189 }
190
191 /**
192 * @return {!Promise<?>}
193 */
194 _update() {
195 const enabled = this._manager.blockingEnabled();
196 this._list.element.classList.toggle('blocking-disabled', !enabled && !!this._manager.blockedPatterns().length);
197 this._enabledCheckbox.setChecked(enabled);
198 this._list.clear();
Tim van der Lippe1d6e57a2019-09-30 11:55:34199 for (const pattern of this._manager.blockedPatterns()) {
Blink Reformat4c46d092018-04-07 15:32:37200 this._list.appendItem(pattern, true);
Tim van der Lippe1d6e57a2019-09-30 11:55:34201 }
Blink Reformat4c46d092018-04-07 15:32:37202 return Promise.resolve();
203 }
204
205 /**
206 * @param {string} url
207 * @return {number}
208 */
209 _blockedRequestsCount(url) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34210 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:37211 return 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:34212 }
Blink Reformat4c46d092018-04-07 15:32:37213
214 let result = 0;
215 for (const blockedUrl of this._blockedCountForUrl.keys()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34216 if (this._matches(url, blockedUrl)) {
Blink Reformat4c46d092018-04-07 15:32:37217 result += this._blockedCountForUrl.get(blockedUrl);
Tim van der Lippe1d6e57a2019-09-30 11:55:34218 }
Blink Reformat4c46d092018-04-07 15:32:37219 }
220 return result;
221 }
222
223 /**
224 * @param {string} pattern
225 * @param {string} url
226 * @return {boolean}
227 */
228 _matches(pattern, url) {
229 let pos = 0;
230 const parts = pattern.split('*');
231 for (let index = 0; index < parts.length; index++) {
232 const part = parts[index];
Tim van der Lippe1d6e57a2019-09-30 11:55:34233 if (!part.length) {
Blink Reformat4c46d092018-04-07 15:32:37234 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34235 }
Blink Reformat4c46d092018-04-07 15:32:37236 pos = url.indexOf(part, pos);
Tim van der Lippe1d6e57a2019-09-30 11:55:34237 if (pos === -1) {
Blink Reformat4c46d092018-04-07 15:32:37238 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34239 }
Blink Reformat4c46d092018-04-07 15:32:37240 pos += part.length;
241 }
242 return true;
243 }
244
245 reset() {
246 this._blockedCountForUrl.clear();
247 this._updateThrottler.schedule(this._update.bind(this));
248 }
249
250 /**
Tim van der Lippec02a97c2020-02-14 14:39:27251 * @param {!Common.EventTarget.EventTargetEvent} event
Blink Reformat4c46d092018-04-07 15:32:37252 */
253 _onRequestFinished(event) {
Tim van der Lippe0ed1d2b2020-02-04 13:45:13254 const request = /** @type {!SDK.NetworkRequest.NetworkRequest} */ (event.data);
Blink Reformat4c46d092018-04-07 15:32:37255 if (request.wasBlocked()) {
256 const count = this._blockedCountForUrl.get(request.url()) || 0;
257 this._blockedCountForUrl.set(request.url(), count + 1);
258 this._updateThrottler.schedule(this._update.bind(this));
259 }
260 }
Paul Lewis56509652019-12-06 12:51:58261}