blob: 587568e4a3e102f8272ab2a76cb354e540e5f5e8 [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.
4/**
5 * @implements {UI.ListWidget.Delegate<SDK.NetworkManager.BlockedPattern>}
6 */
7Network.BlockedURLsPane = class extends UI.VBox {
8 constructor() {
9 super(true);
10 this.registerRequiredCSS('network/blockedURLsPane.css');
11
12 Network.BlockedURLsPane._instance = this;
13 this._manager = SDK.multitargetNetworkManager;
14 this._manager.addEventListener(SDK.MultitargetNetworkManager.Events.BlockedPatternsChanged, this._update, this);
15
16 this._toolbar = new UI.Toolbar('', this.contentElement);
17 this._enabledCheckbox =
18 new UI.ToolbarCheckbox(Common.UIString('Enable request blocking'), undefined, this._toggleEnabled.bind(this));
19 this._toolbar.appendToolbarItem(this._enabledCheckbox);
20 this._toolbar.appendSeparator();
21 const addButton = new UI.ToolbarButton(Common.UIString('Add pattern'), 'largeicon-add');
22 addButton.addEventListener(UI.ToolbarButton.Events.Click, this._addButtonClicked, this);
23 this._toolbar.appendToolbarItem(addButton);
24 const clearButton = new UI.ToolbarButton(Common.UIString('Remove all patterns'), 'largeicon-clear');
25 clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._removeAll, this);
26 this._toolbar.appendToolbarItem(clearButton);
27
28 /** @type {!UI.ListWidget<!SDK.NetworkManager.BlockedPattern>} */
29 this._list = new UI.ListWidget(this);
30 this._list.element.classList.add('blocked-urls');
31 this._list.registerRequiredCSS('network/blockedURLsPane.css');
32 this._list.setEmptyPlaceholder(this._createEmptyPlaceholder());
33 this._list.show(this.contentElement);
34
35 /** @type {?UI.ListWidget.Editor<!SDK.NetworkManager.BlockedPattern>} */
36 this._editor = null;
37
38 /** @type {!Map<string, number>} */
39 this._blockedCountForUrl = new Map();
40 SDK.targetManager.addModelListener(
41 SDK.NetworkManager, SDK.NetworkManager.Events.RequestFinished, this._onRequestFinished, this);
42
43 this._updateThrottler = new Common.Throttler(200);
44
45 this._update();
46 }
47
48 /**
49 * @return {!Element}
50 */
51 _createEmptyPlaceholder() {
52 const element = this.contentElement.createChild('div', 'no-blocked-urls');
Mandy Chena14625d2019-06-14 21:54:3953 const addLink = UI.XLink.create('', ls`Add pattern`);
Blink Reformat4c46d092018-04-07 15:32:3754 addLink.addEventListener('click', this._addButtonClicked.bind(this), false);
Mandy Chena14625d2019-06-14 21:54:3955 element.appendChild(UI.formatLocalized('Requests are not blocked. %s.', [addLink]));
Blink Reformat4c46d092018-04-07 15:32:3756 return element;
57 }
58
59 static reset() {
Tim van der Lippe1d6e57a2019-09-30 11:55:3460 if (Network.BlockedURLsPane._instance) {
Blink Reformat4c46d092018-04-07 15:32:3761 Network.BlockedURLsPane._instance.reset();
Tim van der Lippe1d6e57a2019-09-30 11:55:3462 }
Blink Reformat4c46d092018-04-07 15:32:3763 }
64
65 _addButtonClicked() {
66 this._manager.setBlockingEnabled(true);
67 this._list.addNewItem(0, {url: '', enabled: true});
68 }
69
70 /**
71 * @override
72 * @param {!SDK.NetworkManager.BlockedPattern} pattern
73 * @param {boolean} editable
74 * @return {!Element}
75 */
76 renderItem(pattern, editable) {
77 const count = this._blockedRequestsCount(pattern.url);
78 const element = createElementWithClass('div', 'blocked-url');
79 const checkbox = element.createChild('input', 'blocked-url-checkbox');
80 checkbox.type = 'checkbox';
81 checkbox.checked = pattern.enabled;
82 checkbox.disabled = !this._manager.blockingEnabled();
83 element.createChild('div', 'blocked-url-label').textContent = pattern.url;
84 element.createChild('div', 'blocked-url-count').textContent = Common.UIString('%d blocked', count);
85 element.addEventListener('click', event => this._togglePattern(pattern, event), false);
86 checkbox.addEventListener('click', event => this._togglePattern(pattern, event), false);
87 return element;
88 }
89
90 /**
91 * @param {!SDK.NetworkManager.BlockedPattern} pattern
92 * @param {!Event} event
93 */
94 _togglePattern(pattern, event) {
95 event.consume(true);
96 const patterns = this._manager.blockedPatterns();
97 patterns.splice(patterns.indexOf(pattern), 1, {enabled: !pattern.enabled, url: pattern.url});
98 this._manager.setBlockedPatterns(patterns);
99 }
100
101 _toggleEnabled() {
102 this._manager.setBlockingEnabled(!this._manager.blockingEnabled());
103 this._update();
104 }
105
106 /**
107 * @override
108 * @param {!SDK.NetworkManager.BlockedPattern} pattern
109 * @param {number} index
110 */
111 removeItemRequested(pattern, index) {
112 const patterns = this._manager.blockedPatterns();
113 patterns.splice(index, 1);
114 this._manager.setBlockedPatterns(patterns);
115 }
116
117 /**
118 * @override
119 * @param {!SDK.NetworkManager.BlockedPattern} pattern
120 * @return {!UI.ListWidget.Editor}
121 */
122 beginEdit(pattern) {
123 this._editor = this._createEditor();
124 this._editor.control('url').value = pattern.url;
125 return this._editor;
126 }
127
128 /**
129 * @override
130 * @param {!SDK.NetworkManager.BlockedPattern} item
131 * @param {!UI.ListWidget.Editor} editor
132 * @param {boolean} isNew
133 */
134 commitEdit(item, editor, isNew) {
135 const url = editor.control('url').value;
136 const patterns = this._manager.blockedPatterns();
Tim van der Lippe1d6e57a2019-09-30 11:55:34137 if (isNew) {
Blink Reformat4c46d092018-04-07 15:32:37138 patterns.push({enabled: true, url: url});
Tim van der Lippe1d6e57a2019-09-30 11:55:34139 } else {
Blink Reformat4c46d092018-04-07 15:32:37140 patterns.splice(patterns.indexOf(item), 1, {enabled: true, url: url});
Tim van der Lippe1d6e57a2019-09-30 11:55:34141 }
Blink Reformat4c46d092018-04-07 15:32:37142
143 this._manager.setBlockedPatterns(patterns);
144 }
145
146 /**
147 * @return {!UI.ListWidget.Editor<!SDK.NetworkManager.BlockedPattern>}
148 */
149 _createEditor() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34150 if (this._editor) {
Blink Reformat4c46d092018-04-07 15:32:37151 return this._editor;
Tim van der Lippe1d6e57a2019-09-30 11:55:34152 }
Blink Reformat4c46d092018-04-07 15:32:37153
154 const editor = new UI.ListWidget.Editor();
155 const content = editor.contentElement();
156 const titles = content.createChild('div', 'blocked-url-edit-row');
157 titles.createChild('div').textContent =
158 Common.UIString('Text pattern to block matching requests; use * for wildcard');
159 const fields = content.createChild('div', 'blocked-url-edit-row');
Amanda Bakerca502822019-07-02 00:01:28160 const validator = (item, index, input) => {
161 const valid = !!input.value && !this._manager.blockedPatterns().find(pattern => pattern.url === input.value);
162 return {valid};
163 };
164 const urlInput = editor.createInput('url', 'text', '', validator);
Blink Reformat4c46d092018-04-07 15:32:37165 fields.createChild('div', 'blocked-url-edit-value').appendChild(urlInput);
166 return editor;
167 }
168
169 _removeAll() {
170 this._manager.setBlockedPatterns([]);
171 }
172
173 /**
174 * @return {!Promise<?>}
175 */
176 _update() {
177 const enabled = this._manager.blockingEnabled();
178 this._list.element.classList.toggle('blocking-disabled', !enabled && !!this._manager.blockedPatterns().length);
179 this._enabledCheckbox.setChecked(enabled);
180 this._list.clear();
Tim van der Lippe1d6e57a2019-09-30 11:55:34181 for (const pattern of this._manager.blockedPatterns()) {
Blink Reformat4c46d092018-04-07 15:32:37182 this._list.appendItem(pattern, true);
Tim van der Lippe1d6e57a2019-09-30 11:55:34183 }
Blink Reformat4c46d092018-04-07 15:32:37184 return Promise.resolve();
185 }
186
187 /**
188 * @param {string} url
189 * @return {number}
190 */
191 _blockedRequestsCount(url) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34192 if (!url) {
Blink Reformat4c46d092018-04-07 15:32:37193 return 0;
Tim van der Lippe1d6e57a2019-09-30 11:55:34194 }
Blink Reformat4c46d092018-04-07 15:32:37195
196 let result = 0;
197 for (const blockedUrl of this._blockedCountForUrl.keys()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34198 if (this._matches(url, blockedUrl)) {
Blink Reformat4c46d092018-04-07 15:32:37199 result += this._blockedCountForUrl.get(blockedUrl);
Tim van der Lippe1d6e57a2019-09-30 11:55:34200 }
Blink Reformat4c46d092018-04-07 15:32:37201 }
202 return result;
203 }
204
205 /**
206 * @param {string} pattern
207 * @param {string} url
208 * @return {boolean}
209 */
210 _matches(pattern, url) {
211 let pos = 0;
212 const parts = pattern.split('*');
213 for (let index = 0; index < parts.length; index++) {
214 const part = parts[index];
Tim van der Lippe1d6e57a2019-09-30 11:55:34215 if (!part.length) {
Blink Reformat4c46d092018-04-07 15:32:37216 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34217 }
Blink Reformat4c46d092018-04-07 15:32:37218 pos = url.indexOf(part, pos);
Tim van der Lippe1d6e57a2019-09-30 11:55:34219 if (pos === -1) {
Blink Reformat4c46d092018-04-07 15:32:37220 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34221 }
Blink Reformat4c46d092018-04-07 15:32:37222 pos += part.length;
223 }
224 return true;
225 }
226
227 reset() {
228 this._blockedCountForUrl.clear();
229 this._updateThrottler.schedule(this._update.bind(this));
230 }
231
232 /**
233 * @param {!Common.Event} event
234 */
235 _onRequestFinished(event) {
236 const request = /** @type {!SDK.NetworkRequest} */ (event.data);
237 if (request.wasBlocked()) {
238 const count = this._blockedCountForUrl.get(request.url()) || 0;
239 this._blockedCountForUrl.set(request.url(), count + 1);
240 this._updateThrottler.schedule(this._update.bind(this));
241 }
242 }
243};
244
245/** @type {?Network.BlockedURLsPane} */
246Network.BlockedURLsPane._instance = null;