blob: 999f606141e66db7bdc764c5946bf7fba482231c [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;
Tim van der Lippecd0bb372020-05-01 13:53:2121 this._manager = SDK.NetworkManager.MultitargetNetworkManager.instance();
22 this._manager.addEventListener(SDK.NetworkManager.MultitargetNetworkManager.Events.BlockedPatternsChanged, () => {
23 this._update();
24 }, this);
Blink Reformat4c46d092018-04-07 15:32:3725
Tim van der Lippe0ed1d2b2020-02-04 13:45:1326 this._toolbar = new UI.Toolbar.Toolbar('', this.contentElement);
27 this._enabledCheckbox = new UI.Toolbar.ToolbarCheckbox(
vidortegfe9ad1e2020-09-29 17:40:1428 Common.UIString.UIString('Enable network request blocking'), undefined, this._toggleEnabled.bind(this));
Blink Reformat4c46d092018-04-07 15:32:3729 this._toolbar.appendToolbarItem(this._enabledCheckbox);
30 this._toolbar.appendSeparator();
Tim van der Lippe0ed1d2b2020-02-04 13:45:1331 const addButton = new UI.Toolbar.ToolbarButton(Common.UIString.UIString('Add pattern'), 'largeicon-add');
32 addButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._addButtonClicked, this);
Blink Reformat4c46d092018-04-07 15:32:3733 this._toolbar.appendToolbarItem(addButton);
Tim van der Lippe0ed1d2b2020-02-04 13:45:1334 const clearButton =
35 new UI.Toolbar.ToolbarButton(Common.UIString.UIString('Remove all patterns'), 'largeicon-clear');
36 clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.Click, this._removeAll, this);
Blink Reformat4c46d092018-04-07 15:32:3737 this._toolbar.appendToolbarItem(clearButton);
38
Tim van der Lippe0ed1d2b2020-02-04 13:45:1339 /** @type {!UI.ListWidget.ListWidget<!SDK.NetworkManager.BlockedPattern>} */
40 this._list = new UI.ListWidget.ListWidget(this);
Blink Reformat4c46d092018-04-07 15:32:3741 this._list.element.classList.add('blocked-urls');
42 this._list.registerRequiredCSS('network/blockedURLsPane.css');
43 this._list.setEmptyPlaceholder(this._createEmptyPlaceholder());
44 this._list.show(this.contentElement);
45
46 /** @type {?UI.ListWidget.Editor<!SDK.NetworkManager.BlockedPattern>} */
47 this._editor = null;
48
49 /** @type {!Map<string, number>} */
50 this._blockedCountForUrl = new Map();
Paul Lewisdaac1062020-03-05 14:37:1051 SDK.SDKModel.TargetManager.instance().addModelListener(
Tim van der Lippe0ed1d2b2020-02-04 13:45:1352 SDK.NetworkManager.NetworkManager, SDK.NetworkManager.Events.RequestFinished, this._onRequestFinished, this);
Blink Reformat4c46d092018-04-07 15:32:3753
Tim van der Lippe0ed1d2b2020-02-04 13:45:1354 this._updateThrottler = new Common.Throttler.Throttler(200);
Blink Reformat4c46d092018-04-07 15:32:3755
56 this._update();
57 }
58
59 /**
60 * @return {!Element}
61 */
62 _createEmptyPlaceholder() {
63 const element = this.contentElement.createChild('div', 'no-blocked-urls');
Tim van der Lippe0ed1d2b2020-02-04 13:45:1364 const addButton = UI.UIUtils.createTextButton(ls`Add pattern`, this._addButtonClicked.bind(this), 'add-button');
vidortegfe9ad1e2020-09-29 17:40:1465 UI.ARIAUtils.setAccessibleName(addButton, ls`Add network request blocking pattern`);
66 element.appendChild(UI.UIUtils.formatLocalized('Network requests are not blocked. %s', [addButton]));
Blink Reformat4c46d092018-04-07 15:32:3767 return element;
68 }
69
70 static reset() {
Tim van der Lippe119690c2020-01-13 12:31:3071 if (_instance) {
72 _instance.reset();
Tim van der Lippe1d6e57a2019-09-30 11:55:3473 }
Blink Reformat4c46d092018-04-07 15:32:3774 }
75
76 _addButtonClicked() {
77 this._manager.setBlockingEnabled(true);
78 this._list.addNewItem(0, {url: '', enabled: true});
79 }
80
81 /**
82 * @override
83 * @param {!SDK.NetworkManager.BlockedPattern} pattern
84 * @param {boolean} editable
85 * @return {!Element}
86 */
87 renderItem(pattern, editable) {
88 const count = this._blockedRequestsCount(pattern.url);
Tim van der Lippef49e2322020-05-01 15:03:0989 const element = document.createElement('div');
90 element.classList.add('blocked-url');
Tim van der Lippe9f1408a2020-09-18 14:22:3291 const checkbox = /** @type {!HTMLInputElement} */ (element.createChild('input', 'blocked-url-checkbox'));
Blink Reformat4c46d092018-04-07 15:32:3792 checkbox.type = 'checkbox';
93 checkbox.checked = pattern.enabled;
94 checkbox.disabled = !this._manager.blockingEnabled();
95 element.createChild('div', 'blocked-url-label').textContent = pattern.url;
Tim van der Lippe0ed1d2b2020-02-04 13:45:1396 element.createChild('div', 'blocked-url-count').textContent = Common.UIString.UIString('%d blocked', count);
Blink Reformat4c46d092018-04-07 15:32:3797 element.addEventListener('click', event => this._togglePattern(pattern, event), false);
98 checkbox.addEventListener('click', event => this._togglePattern(pattern, event), false);
99 return element;
100 }
101
102 /**
103 * @param {!SDK.NetworkManager.BlockedPattern} pattern
104 * @param {!Event} event
105 */
106 _togglePattern(pattern, event) {
107 event.consume(true);
108 const patterns = this._manager.blockedPatterns();
109 patterns.splice(patterns.indexOf(pattern), 1, {enabled: !pattern.enabled, url: pattern.url});
110 this._manager.setBlockedPatterns(patterns);
111 }
112
113 _toggleEnabled() {
114 this._manager.setBlockingEnabled(!this._manager.blockingEnabled());
115 this._update();
116 }
117
118 /**
119 * @override
120 * @param {!SDK.NetworkManager.BlockedPattern} pattern
121 * @param {number} index
122 */
123 removeItemRequested(pattern, index) {
124 const patterns = this._manager.blockedPatterns();
125 patterns.splice(index, 1);
126 this._manager.setBlockedPatterns(patterns);
127 }
128
129 /**
130 * @override
131 * @param {!SDK.NetworkManager.BlockedPattern} pattern
Tim van der Lippe9f1408a2020-09-18 14:22:32132 * @return {!UI.ListWidget.Editor<!SDK.NetworkManager.BlockedPattern>}
Blink Reformat4c46d092018-04-07 15:32:37133 */
134 beginEdit(pattern) {
135 this._editor = this._createEditor();
136 this._editor.control('url').value = pattern.url;
137 return this._editor;
138 }
139
140 /**
141 * @override
142 * @param {!SDK.NetworkManager.BlockedPattern} item
Tim van der Lippe9f1408a2020-09-18 14:22:32143 * @param {!UI.ListWidget.Editor<!SDK.NetworkManager.BlockedPattern>} editor
Blink Reformat4c46d092018-04-07 15:32:37144 * @param {boolean} isNew
145 */
146 commitEdit(item, editor, isNew) {
147 const url = editor.control('url').value;
148 const patterns = this._manager.blockedPatterns();
Tim van der Lippe1d6e57a2019-09-30 11:55:34149 if (isNew) {
Blink Reformat4c46d092018-04-07 15:32:37150 patterns.push({enabled: true, url: url});
Tim van der Lippe1d6e57a2019-09-30 11:55:34151 } else {
Blink Reformat4c46d092018-04-07 15:32:37152 patterns.splice(patterns.indexOf(item), 1, {enabled: true, url: url});
Tim van der Lippe1d6e57a2019-09-30 11:55:34153 }
Blink Reformat4c46d092018-04-07 15:32:37154
155 this._manager.setBlockedPatterns(patterns);
156 }
157
158 /**
159 * @return {!UI.ListWidget.Editor<!SDK.NetworkManager.BlockedPattern>}
160 */
161 _createEditor() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34162 if (this._editor) {
Blink Reformat4c46d092018-04-07 15:32:37163 return this._editor;
Tim van der Lippe1d6e57a2019-09-30 11:55:34164 }
Blink Reformat4c46d092018-04-07 15:32:37165
166 const editor = new UI.ListWidget.Editor();
167 const content = editor.contentElement();
168 const titles = content.createChild('div', 'blocked-url-edit-row');
169 titles.createChild('div').textContent =
Tim van der Lippe0ed1d2b2020-02-04 13:45:13170 Common.UIString.UIString('Text pattern to block matching requests; use * for wildcard');
Blink Reformat4c46d092018-04-07 15:32:37171 const fields = content.createChild('div', 'blocked-url-edit-row');
Tim van der Lippe9f1408a2020-09-18 14:22:32172 /**
173 * @param {!SDK.NetworkManager.BlockedPattern} item
174 * @param {number} index
175 * @param {(!HTMLInputElement|!HTMLSelectElement)} input
176 */
Amanda Bakerca502822019-07-02 00:01:28177 const validator = (item, index, input) => {
Michael Liaoaf4130a2020-01-14 22:13:14178 let valid = true;
179 let errorMessage;
180 if (!input.value) {
181 errorMessage = ls`Pattern input cannot be empty.`;
182 valid = false;
183 } else if (this._manager.blockedPatterns().find(pattern => pattern.url === input.value)) {
184 errorMessage = ls`Pattern already exists.`;
185 valid = false;
186 }
187 return {valid, errorMessage};
Amanda Bakerca502822019-07-02 00:01:28188 };
189 const urlInput = editor.createInput('url', 'text', '', validator);
Blink Reformat4c46d092018-04-07 15:32:37190 fields.createChild('div', 'blocked-url-edit-value').appendChild(urlInput);
191 return editor;
192 }
193
194 _removeAll() {
195 this._manager.setBlockedPatterns([]);
196 }
197
198 /**
Tim van der Lippecd0bb372020-05-01 13:53:21199 * @return {!Promise<void>}
Blink Reformat4c46d092018-04-07 15:32:37200 */
201 _update() {
202 const enabled = this._manager.blockingEnabled();
203 this._list.element.classList.toggle('blocking-disabled', !enabled && !!this._manager.blockedPatterns().length);
204 this._enabledCheckbox.setChecked(enabled);
205 this._list.clear();
Tim van der Lippe1d6e57a2019-09-30 11:55:34206 for (const pattern of this._manager.blockedPatterns()) {
Blink Reformat4c46d092018-04-07 15:32:37207 this._list.appendItem(pattern, true);
Tim van der Lippe1d6e57a2019-09-30 11:55:34208 }
Blink Reformat4c46d092018-04-07 15:32:37209 return Promise.resolve();
210 }
211
212 /**
213 * @param {string} url
214 * @return {number}
215 */
216 _blockedRequestsCount(url) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34217 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:37218 return 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:34219 }
Blink Reformat4c46d092018-04-07 15:32:37220
221 let result = 0;
222 for (const blockedUrl of this._blockedCountForUrl.keys()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34223 if (this._matches(url, blockedUrl)) {
Tim van der Lippe9f1408a2020-09-18 14:22:32224 result += /** @type {number} */ (this._blockedCountForUrl.get(blockedUrl));
Tim van der Lippe1d6e57a2019-09-30 11:55:34225 }
Blink Reformat4c46d092018-04-07 15:32:37226 }
227 return result;
228 }
229
230 /**
231 * @param {string} pattern
232 * @param {string} url
233 * @return {boolean}
234 */
235 _matches(pattern, url) {
236 let pos = 0;
237 const parts = pattern.split('*');
238 for (let index = 0; index < parts.length; index++) {
239 const part = parts[index];
Tim van der Lippe1d6e57a2019-09-30 11:55:34240 if (!part.length) {
Blink Reformat4c46d092018-04-07 15:32:37241 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34242 }
Blink Reformat4c46d092018-04-07 15:32:37243 pos = url.indexOf(part, pos);
Tim van der Lippe1d6e57a2019-09-30 11:55:34244 if (pos === -1) {
Blink Reformat4c46d092018-04-07 15:32:37245 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34246 }
Blink Reformat4c46d092018-04-07 15:32:37247 pos += part.length;
248 }
249 return true;
250 }
251
252 reset() {
253 this._blockedCountForUrl.clear();
254 this._updateThrottler.schedule(this._update.bind(this));
255 }
256
257 /**
Tim van der Lippec02a97c2020-02-14 14:39:27258 * @param {!Common.EventTarget.EventTargetEvent} event
Blink Reformat4c46d092018-04-07 15:32:37259 */
260 _onRequestFinished(event) {
Tim van der Lippe0ed1d2b2020-02-04 13:45:13261 const request = /** @type {!SDK.NetworkRequest.NetworkRequest} */ (event.data);
Blink Reformat4c46d092018-04-07 15:32:37262 if (request.wasBlocked()) {
263 const count = this._blockedCountForUrl.get(request.url()) || 0;
264 this._blockedCountForUrl.set(request.url(), count + 1);
265 this._updateThrottler.schedule(this._update.bind(this));
266 }
267 }
Paul Lewis56509652019-12-06 12:51:58268}