blob: 5966f5d426f61ff3c38d476e31b0fa99579b99ab [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371// Copyright (c) 2016 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/**
6 * @implements {SDK.TargetManager.Observer}
7 */
8Resources.ClearStorageView = class extends UI.ThrottledWidget {
9 constructor() {
10 super(true, 1000);
11 const types = Protocol.Storage.StorageType;
12 this._pieColors = new Map([
13 [types.Appcache, 'rgb(110, 161, 226)'], // blue
14 [types.Cache_storage, 'rgb(229, 113, 113)'], // red
15 [types.Cookies, 'rgb(239, 196, 87)'], // yellow
16 [types.Indexeddb, 'rgb(155, 127, 230)'], // purple
17 [types.Local_storage, 'rgb(116, 178, 102)'], // green
18 [types.Service_workers, 'rgb(255, 167, 36)'], // orange
19 [types.Websql, 'rgb(203, 220, 56)'], // lime
20 ]);
21
22 this._reportView = new UI.ReportView(Common.UIString('Clear storage'));
23 this._reportView.registerRequiredCSS('resources/clearStorageView.css');
24 this._reportView.element.classList.add('clear-storage-header');
25 this._reportView.show(this.contentElement);
26 /** @type {?SDK.Target} */
27 this._target = null;
28 /** @type {?string} */
29 this._securityOrigin = null;
30
31 this._settings = new Map();
Tim van der Lippe1d6e57a2019-09-30 11:55:3432 for (const type of Resources.ClearStorageView.AllStorageTypes) {
Blink Reformat4c46d092018-04-07 15:32:3733 this._settings.set(type, Common.settings.createSetting('clear-storage-' + type, true));
Tim van der Lippe1d6e57a2019-09-30 11:55:3434 }
Blink Reformat4c46d092018-04-07 15:32:3735
36 const quota = this._reportView.appendSection(Common.UIString('Usage'));
Joey Arhar53f63452019-05-25 01:00:1337 this._quotaRow = quota.appendSelectableRow();
Harley Li6b1c2da2018-11-29 23:19:3038 const learnMoreRow = quota.appendRow();
39 const learnMore = UI.XLink.create(
40 'https://developers.google.com/web/tools/chrome-devtools/progressive-web-apps#opaque-responses',
41 ls`Learn more`);
42 learnMoreRow.appendChild(learnMore);
Blink Reformat4c46d092018-04-07 15:32:3743 this._quotaUsage = null;
Jeff Fisher76f49422019-05-21 22:42:0144 this._pieChart = new PerfUI.PieChart(
45 {chartName: ls`Storage Usage`, size: 110, formatter: Number.bytesToString, showLegend: true});
Blink Reformat4c46d092018-04-07 15:32:3746 const usageBreakdownRow = quota.appendRow();
47 usageBreakdownRow.classList.add('usage-breakdown-row');
48 usageBreakdownRow.appendChild(this._pieChart.element);
Blink Reformat4c46d092018-04-07 15:32:3749
Harley Li05120a92018-10-31 22:44:2650 const clearButtonSection = this._reportView.appendSection('', 'clear-storage-button').appendRow();
51 this._clearButton = UI.createTextButton(ls`Clear site data`, this._clear.bind(this));
52 clearButtonSection.appendChild(this._clearButton);
53
Blink Reformat4c46d092018-04-07 15:32:3754 const application = this._reportView.appendSection(Common.UIString('Application'));
55 this._appendItem(application, Common.UIString('Unregister service workers'), 'service_workers');
Junyi Xiao3ddd8d12019-05-23 23:15:4456 application.markFieldListAsGroup();
Blink Reformat4c46d092018-04-07 15:32:3757
58 const storage = this._reportView.appendSection(Common.UIString('Storage'));
59 this._appendItem(storage, Common.UIString('Local and session storage'), 'local_storage');
60 this._appendItem(storage, Common.UIString('IndexedDB'), 'indexeddb');
61 this._appendItem(storage, Common.UIString('Web SQL'), 'websql');
62 this._appendItem(storage, Common.UIString('Cookies'), 'cookies');
Junyi Xiao3ddd8d12019-05-23 23:15:4463 storage.markFieldListAsGroup();
Blink Reformat4c46d092018-04-07 15:32:3764
65 const caches = this._reportView.appendSection(Common.UIString('Cache'));
66 this._appendItem(caches, Common.UIString('Cache storage'), 'cache_storage');
67 this._appendItem(caches, Common.UIString('Application cache'), 'appcache');
Junyi Xiao3ddd8d12019-05-23 23:15:4468 caches.markFieldListAsGroup();
Blink Reformat4c46d092018-04-07 15:32:3769
Dmitry Gozman08dbcb62018-11-01 16:15:0570 SDK.targetManager.observeTargets(this);
Blink Reformat4c46d092018-04-07 15:32:3771 }
72
73 /**
74 * @param {!UI.ReportView.Section} section
75 * @param {string} title
76 * @param {string} settingName
77 */
78 _appendItem(section, title, settingName) {
79 const row = section.appendRow();
80 row.appendChild(UI.SettingsUI.createSettingCheckbox(title, this._settings.get(settingName), true));
81 }
82
83 /**
84 * @override
85 * @param {!SDK.Target} target
86 */
87 targetAdded(target) {
Tim van der Lippe1d6e57a2019-09-30 11:55:3488 if (this._target) {
Blink Reformat4c46d092018-04-07 15:32:3789 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:3490 }
Blink Reformat4c46d092018-04-07 15:32:3791 this._target = target;
92 const securityOriginManager = target.model(SDK.SecurityOriginManager);
Harley Liddf2b682019-03-08 22:35:2393 this._updateOrigin(
94 securityOriginManager.mainSecurityOrigin(), securityOriginManager.unreachableMainSecurityOrigin());
Blink Reformat4c46d092018-04-07 15:32:3795 securityOriginManager.addEventListener(
96 SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, this._originChanged, this);
97 }
98
99 /**
100 * @override
101 * @param {!SDK.Target} target
102 */
103 targetRemoved(target) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34104 if (this._target !== target) {
Blink Reformat4c46d092018-04-07 15:32:37105 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34106 }
Blink Reformat4c46d092018-04-07 15:32:37107 const securityOriginManager = target.model(SDK.SecurityOriginManager);
108 securityOriginManager.removeEventListener(
109 SDK.SecurityOriginManager.Events.MainSecurityOriginChanged, this._originChanged, this);
110 }
111
112 /**
113 * @param {!Common.Event} event
114 */
115 _originChanged(event) {
Harley Liddf2b682019-03-08 22:35:23116 const mainOrigin = /** *@type {string} */ (event.data.mainSecurityOrigin);
117 const unreachableMainOrigin = /** @type {string} */ (event.data.unreachableMainSecurityOrigin);
118 this._updateOrigin(mainOrigin, unreachableMainOrigin);
Blink Reformat4c46d092018-04-07 15:32:37119 }
120
121 /**
Harley Liddf2b682019-03-08 22:35:23122 * @param {string} mainOrigin
123 * @param {string} unreachableMainOrigin
Blink Reformat4c46d092018-04-07 15:32:37124 */
Harley Liddf2b682019-03-08 22:35:23125 _updateOrigin(mainOrigin, unreachableMainOrigin) {
126 if (unreachableMainOrigin) {
127 this._securityOrigin = unreachableMainOrigin;
128 this._reportView.setSubtitle(ls`${unreachableMainOrigin} (failed to load)`);
Harley Li922a27b2019-02-01 20:38:39129 } else {
Harley Liddf2b682019-03-08 22:35:23130 this._securityOrigin = mainOrigin;
131 this._reportView.setSubtitle(mainOrigin);
Harley Li922a27b2019-02-01 20:38:39132 }
Harley Liddf2b682019-03-08 22:35:23133
Blink Reformat4c46d092018-04-07 15:32:37134 this.doUpdate();
135 }
136
Sergey Poromov47ac0392019-06-28 09:28:22137 _clear() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34138 if (!this._securityOrigin) {
Blink Reformat4c46d092018-04-07 15:32:37139 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34140 }
Harley Li29038872019-03-27 20:50:04141 const selectedStorageTypes = [];
Blink Reformat4c46d092018-04-07 15:32:37142 for (const type of this._settings.keys()) {
Tim van der Lippe1d6e57a2019-09-30 11:55:34143 if (this._settings.get(type).get()) {
Harley Li29038872019-03-27 20:50:04144 selectedStorageTypes.push(type);
Tim van der Lippe1d6e57a2019-09-30 11:55:34145 }
Blink Reformat4c46d092018-04-07 15:32:37146 }
147
Tim van der Lippe1d6e57a2019-09-30 11:55:34148 if (this._target) {
Sergey Poromov47ac0392019-06-28 09:28:22149 Resources.ClearStorageView.clear(this._target, this._securityOrigin, selectedStorageTypes);
Tim van der Lippe1d6e57a2019-09-30 11:55:34150 }
Sergey Poromov47ac0392019-06-28 09:28:22151
Harley Li29038872019-03-27 20:50:04152 this._clearButton.disabled = true;
153 const label = this._clearButton.textContent;
154 this._clearButton.textContent = Common.UIString('Clearing...');
Sergey Poromov47ac0392019-06-28 09:28:22155 setTimeout(() => {
156 this._clearButton.disabled = false;
157 this._clearButton.textContent = label;
158 }, 500);
Harley Li29038872019-03-27 20:50:04159 }
160
161 /**
162 * @param {!SDK.Target} target
163 * @param {string} securityOrigin
164 * @param {!Array<string>} selectedStorageTypes
165 */
Sergey Poromov47ac0392019-06-28 09:28:22166 static clear(target, securityOrigin, selectedStorageTypes) {
167 target.storageAgent().clearDataForOrigin(securityOrigin, selectedStorageTypes.join(','));
Harley Li29038872019-03-27 20:50:04168
169 const set = new Set(selectedStorageTypes);
Blink Reformat4c46d092018-04-07 15:32:37170 const hasAll = set.has(Protocol.Storage.StorageType.All);
171 if (set.has(Protocol.Storage.StorageType.Cookies) || hasAll) {
Harley Li29038872019-03-27 20:50:04172 const cookieModel = target.model(SDK.CookieModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34173 if (cookieModel) {
Sergey Poromov47ac0392019-06-28 09:28:22174 cookieModel.clear();
Tim van der Lippe1d6e57a2019-09-30 11:55:34175 }
Blink Reformat4c46d092018-04-07 15:32:37176 }
177
178 if (set.has(Protocol.Storage.StorageType.Indexeddb) || hasAll) {
179 for (const target of SDK.targetManager.targets()) {
180 const indexedDBModel = target.model(Resources.IndexedDBModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34181 if (indexedDBModel) {
Sergey Poromov47ac0392019-06-28 09:28:22182 indexedDBModel.clearForOrigin(securityOrigin);
Tim van der Lippe1d6e57a2019-09-30 11:55:34183 }
Blink Reformat4c46d092018-04-07 15:32:37184 }
185 }
186
187 if (set.has(Protocol.Storage.StorageType.Local_storage) || hasAll) {
Harley Li29038872019-03-27 20:50:04188 const storageModel = target.model(Resources.DOMStorageModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34189 if (storageModel) {
Sergey Poromov47ac0392019-06-28 09:28:22190 storageModel.clearForOrigin(securityOrigin);
Tim van der Lippe1d6e57a2019-09-30 11:55:34191 }
Blink Reformat4c46d092018-04-07 15:32:37192 }
193
194 if (set.has(Protocol.Storage.StorageType.Websql) || hasAll) {
Harley Li29038872019-03-27 20:50:04195 const databaseModel = target.model(Resources.DatabaseModel);
Sergey Poromov47ac0392019-06-28 09:28:22196 if (databaseModel) {
197 databaseModel.disable();
198 databaseModel.enable();
199 }
Blink Reformat4c46d092018-04-07 15:32:37200 }
201
202 if (set.has(Protocol.Storage.StorageType.Cache_storage) || hasAll) {
203 const target = SDK.targetManager.mainTarget();
204 const model = target && target.model(SDK.ServiceWorkerCacheModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34205 if (model) {
Sergey Poromov47ac0392019-06-28 09:28:22206 model.clearForOrigin(securityOrigin);
Tim van der Lippe1d6e57a2019-09-30 11:55:34207 }
Blink Reformat4c46d092018-04-07 15:32:37208 }
209
210 if (set.has(Protocol.Storage.StorageType.Appcache) || hasAll) {
Harley Li29038872019-03-27 20:50:04211 const appcacheModel = target.model(Resources.ApplicationCacheModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34212 if (appcacheModel) {
Sergey Poromov47ac0392019-06-28 09:28:22213 appcacheModel.reset();
Tim van der Lippe1d6e57a2019-09-30 11:55:34214 }
Blink Reformat4c46d092018-04-07 15:32:37215 }
Blink Reformat4c46d092018-04-07 15:32:37216 }
217
218 /**
219 * @override
220 * @return {!Promise<?>}
221 */
222 async doUpdate() {
Tim van der Lippe1d6e57a2019-09-30 11:55:34223 if (!this._securityOrigin) {
Blink Reformat4c46d092018-04-07 15:32:37224 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34225 }
Blink Reformat4c46d092018-04-07 15:32:37226
227 const securityOrigin = /** @type {string} */ (this._securityOrigin);
228 const response = await this._target.storageAgent().invoke_getUsageAndQuota({origin: securityOrigin});
229 if (response[Protocol.Error]) {
230 this._quotaRow.textContent = '';
231 this._resetPieChart(0);
232 return;
233 }
234 this._quotaRow.textContent = Common.UIString(
Mathias Bynens7d8cd342019-09-17 13:32:10235 '%s used out of %s storage quota.\xA0', Number.bytesToString(response.usage),
Harley Lid3a65ab2019-03-11 22:36:09236 Number.bytesToString(response.quota));
237 if (response.quota < 125829120) { // 120 MB
238 this._quotaRow.title = ls`Storage quota is limited in Incognito mode`;
239 this._quotaRow.appendChild(UI.Icon.create('smallicon-info'));
240 }
Blink Reformat4c46d092018-04-07 15:32:37241
242 if (!this._quotaUsage || this._quotaUsage !== response.usage) {
243 this._quotaUsage = response.usage;
244 this._resetPieChart(response.usage);
245 for (const usageForType of response.usageBreakdown.sort((a, b) => b.usage - a.usage)) {
246 const value = usageForType.usage;
Tim van der Lippe1d6e57a2019-09-30 11:55:34247 if (!value) {
Blink Reformat4c46d092018-04-07 15:32:37248 continue;
Tim van der Lippe1d6e57a2019-09-30 11:55:34249 }
Blink Reformat4c46d092018-04-07 15:32:37250 const title = this._getStorageTypeName(usageForType.storageType);
251 const color = this._pieColors.get(usageForType.storageType) || '#ccc';
Jeff Fisher76f49422019-05-21 22:42:01252 this._pieChart.addSlice(value, color, title);
Blink Reformat4c46d092018-04-07 15:32:37253 }
254 }
255
256 this._usageUpdatedForTest(response.usage, response.quota, response.usageBreakdown);
257 this.update();
258 }
259
260 /**
261 * @param {number} total
262 */
263 _resetPieChart(total) {
264 this._pieChart.setTotal(total);
Blink Reformat4c46d092018-04-07 15:32:37265 }
266
267 /**
268 * @param {string} type
269 * @return {string}
270 */
271 _getStorageTypeName(type) {
272 switch (type) {
273 case Protocol.Storage.StorageType.File_systems:
274 return Common.UIString('File System');
275 case Protocol.Storage.StorageType.Websql:
276 return Common.UIString('Web SQL');
277 case Protocol.Storage.StorageType.Appcache:
278 return Common.UIString('Application Cache');
279 case Protocol.Storage.StorageType.Indexeddb:
280 return Common.UIString('IndexedDB');
281 case Protocol.Storage.StorageType.Cache_storage:
282 return Common.UIString('Cache Storage');
283 case Protocol.Storage.StorageType.Service_workers:
284 return Common.UIString('Service Workers');
285 default:
286 return Common.UIString('Other');
287 }
288 }
289
290 /**
291 * @param {number} usage
292 * @param {number} quota
293 * @param {!Array<!Protocol.Storage.UsageForType>} usageBreakdown
294 */
295 _usageUpdatedForTest(usage, quota, usageBreakdown) {
296 }
297};
Harley Li29038872019-03-27 20:50:04298
299Resources.ClearStorageView.AllStorageTypes = [
300 Protocol.Storage.StorageType.Appcache, Protocol.Storage.StorageType.Cache_storage,
301 Protocol.Storage.StorageType.Cookies, Protocol.Storage.StorageType.Indexeddb,
302 Protocol.Storage.StorageType.Local_storage, Protocol.Storage.StorageType.Service_workers,
303 Protocol.Storage.StorageType.Websql
304];
305
306/**
307 * @implements {UI.ActionDelegate}
308 */
309Resources.ClearStorageView.ActionDelegate = class {
310 /**
311 * @override
312 * @param {!UI.Context} context
313 * @param {string} actionId
314 * @return {boolean}
315 */
316 handleAction(context, actionId) {
317 switch (actionId) {
318 case 'resources.clear':
319 return this._handleClear();
320 }
321 return false;
322 }
323
324 /**
325 * @return {boolean}
326 */
327 _handleClear() {
328 const target = SDK.targetManager.mainTarget();
Tim van der Lippe1d6e57a2019-09-30 11:55:34329 if (!target) {
Harley Li29038872019-03-27 20:50:04330 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34331 }
Harley Li29038872019-03-27 20:50:04332 const resourceTreeModel = target.model(SDK.ResourceTreeModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34333 if (!resourceTreeModel) {
Harley Li29038872019-03-27 20:50:04334 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34335 }
Harley Li29038872019-03-27 20:50:04336 const securityOrigin = resourceTreeModel.getMainSecurityOrigin();
Tim van der Lippe1d6e57a2019-09-30 11:55:34337 if (!securityOrigin) {
Harley Li29038872019-03-27 20:50:04338 return false;
Tim van der Lippe1d6e57a2019-09-30 11:55:34339 }
Harley Li29038872019-03-27 20:50:04340
341 Resources.ClearStorageView.clear(target, securityOrigin, Resources.ClearStorageView.AllStorageTypes);
342 return true;
343 }
344};