Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(728)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/components_lazy/CookiesTable.js

Issue 2567873002: DevTools: Add ability to add and edit cookies (Closed)
Patch Set: Add front-end validation. Add `startEditingNextEditableColumnOfDataGridNode` method to DataGrid. Fi… Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Joseph Pecoraro 3 * Copyright (C) 2009 Joseph Pecoraro
4 * Copyright (C) 2010 Google Inc. All rights reserved. 4 * Copyright (C) 2010 Google Inc. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 9 *
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 this._refreshCallback = refreshCallback; 44 this._refreshCallback = refreshCallback;
45 45
46 var columns = /** @type {!Array<!UI.DataGrid.ColumnDescriptor>} */ ([ 46 var columns = /** @type {!Array<!UI.DataGrid.ColumnDescriptor>} */ ([
47 { 47 {
48 id: 'name', 48 id: 'name',
49 title: Common.UIString('Name'), 49 title: Common.UIString('Name'),
50 sortable: true, 50 sortable: true,
51 disclosure: expandable, 51 disclosure: expandable,
52 sort: UI.DataGrid.Order.Ascending, 52 sort: UI.DataGrid.Order.Ascending,
53 longText: true, 53 longText: true,
54 weight: 24 54 weight: 24,
55 editable: true
55 }, 56 },
56 {id: 'value', title: Common.UIString('Value'), sortable: true, longText: t rue, weight: 34}, 57 {id: 'value', title: Common.UIString('Value'), sortable: true, longText: t rue, weight: 34, editable: true},
57 {id: 'domain', title: Common.UIString('Domain'), sortable: true, weight: 7 }, 58 {id: 'domain', title: Common.UIString('Domain'), sortable: true, weight: 7 , editable: true},
58 {id: 'path', title: Common.UIString('Path'), sortable: true, weight: 7}, 59 {id: 'path', title: Common.UIString('Path'), sortable: true, weight: 7, ed itable: true},
59 {id: 'expires', title: Common.UIString('Expires / Max-Age'), sortable: tru e, weight: 7}, 60 {id: 'expires', title: Common.UIString('Expires / Max-Age'), sortable: tru e, weight: 7, editable: true},
60 {id: 'size', title: Common.UIString('Size'), sortable: true, align: UI.Dat aGrid.Align.Right, weight: 7}, 61 {id: 'size', title: Common.UIString('Size'), sortable: true, align: UI.Dat aGrid.Align.Right, weight: 7},
61 {id: 'httpOnly', title: Common.UIString('HTTP'), sortable: true, align: UI .DataGrid.Align.Center, weight: 7}, 62 {id: 'httpOnly', title: Common.UIString('HTTP'), sortable: true, align: UI .DataGrid.Align.Center, weight: 7},
62 {id: 'secure', title: Common.UIString('Secure'), sortable: true, align: UI .DataGrid.Align.Center, weight: 7}, { 63 {id: 'secure', title: Common.UIString('Secure'), sortable: true, align: UI .DataGrid.Align.Center, weight: 7}, {
63 id: 'sameSite', 64 id: 'sameSite',
64 title: Common.UIString('SameSite'), 65 title: Common.UIString('SameSite'),
65 sortable: true, 66 sortable: true,
66 align: UI.DataGrid.Align.Center, 67 align: UI.DataGrid.Align.Center,
67 weight: 7 68 weight: 7
68 } 69 }
69 ]); 70 ]);
70 71
71 if (readOnly) { 72 if (readOnly) {
72 this._dataGrid = new UI.DataGrid(columns); 73 this._dataGrid = new UI.DataGrid(columns);
73 } else { 74 } else {
74 this._dataGrid = new UI.DataGrid(columns, undefined, this._onDeleteCookie. bind(this), refreshCallback); 75 this._dataGrid = new UI.DataGrid(columns, this._onUpdateCookie.bind(this), this._onDeleteCookie.bind(this), refreshCallback);
75 this._dataGrid.setRowContextMenuCallback(this._onRowContextMenu.bind(this) ); 76 this._dataGrid.setRowContextMenuCallback(this._onRowContextMenu.bind(this) );
76 } 77 }
77 78
78 this._dataGrid.setName('cookiesTable'); 79 this._dataGrid.setName('cookiesTable');
79 this._dataGrid.addEventListener(UI.DataGrid.Events.SortingChanged, this._reb uildTable, this); 80 this._dataGrid.addEventListener(UI.DataGrid.Events.SortingChanged, this._reb uildTable, this);
80 81
81 if (selectedCallback) 82 if (selectedCallback)
82 this._dataGrid.addEventListener(UI.DataGrid.Events.SelectedNode, selectedC allback, this); 83 this._dataGrid.addEventListener(UI.DataGrid.Events.SelectedNode, selectedC allback, this);
83 84
84 this._nextSelectedCookie = /** @type {?SDK.Cookie} */ (null); 85 this._nextSelectedCookie = /** @type {?SDK.Cookie} */ (null);
86 this._lastEditedColumnId = /** @type {?string} */ (null);
85 87
86 this._dataGrid.asWidget().show(this.element); 88 this._dataGrid.asWidget().show(this.element);
87 this._data = []; 89 this._data = [];
88 } 90 }
89 91
90 /** 92 /**
91 * @param {?string} domain 93 * @param {?string} domain
92 */ 94 */
93 _clearAndRefresh(domain) { 95 _clearAndRefresh(domain) {
94 this.clear(domain); 96 this.clear(domain);
95 this._refresh(); 97 this._refresh();
96 } 98 }
97 99
98 /** 100 /**
99 * @param {!UI.ContextMenu} contextMenu 101 * @param {!UI.ContextMenu} contextMenu
100 * @param {!UI.DataGridNode} node 102 * @param {!UI.DataGridNode} node
101 */ 103 */
102 _onRowContextMenu(contextMenu, node) { 104 _onRowContextMenu(contextMenu, node) {
103 if (node === this._dataGrid.creationNode) 105 if (node.isCreationNode)
104 return; 106 return;
105 var domain = node.cookie.domain(); 107
108 const cookie = node.cookie;
109 const checkmark = '\u2713';
110 contextMenu.appendCheckboxItem(
111 Common.UIString('Secure flag'),
112 this._setCookieFlag.bind(this, node, 'secure', cookie.secure() ? '' : chec kmark),
113 cookie.secure(),
114 false
115 );
116 contextMenu.appendCheckboxItem(
117 Common.UIString('HttpOnly flag'),
118 this._setCookieFlag.bind(this, node, 'httpOnly', cookie.httpOnly() ? '' : checkmark),
119 cookie.httpOnly(),
120 false
121 );
122
123 var sameSiteSubmenu = contextMenu.appendSubMenuItem(Common.UIString('SameSit e flag'));
124 sameSiteSubmenu.appendCheckboxItem(
125 Common.UIString('<empty>'),
126 this._setCookieFlag.bind(this, node, 'sameSite', ''),
127 !cookie.sameSite(),
128 false
129 );
130 sameSiteSubmenu.appendCheckboxItem(
131 Protocol.Network.CookieSameSite.Lax,
132 this._setCookieFlag.bind(this, node, 'sameSite', Protocol.Network.CookieSa meSite.Lax),
133 cookie.sameSite() === Protocol.Network.CookieSameSite.Lax,
134 false
135 );
136 sameSiteSubmenu.appendCheckboxItem(
137 Protocol.Network.CookieSameSite.Strict,
138 this._setCookieFlag.bind(this, node, 'sameSite', Protocol.Network.CookieSa meSite.Strict),
139 cookie.sameSite() === Protocol.Network.CookieSameSite.Strict,
140 false
141 );
142 contextMenu.appendSeparator();
143
144 var domain = cookie.domain();
106 if (domain) { 145 if (domain) {
107 contextMenu.appendItem( 146 contextMenu.appendItem(
108 Common.UIString.capitalize('Clear ^all from "%s"', domain), this._clea rAndRefresh.bind(this, domain)); 147 Common.UIString.capitalize('Clear ^all from "%s"', domain), this._clea rAndRefresh.bind(this, domain));
109 } 148 }
110 contextMenu.appendItem(Common.UIString.capitalize('Clear ^all'), this._clear AndRefresh.bind(this, null)); 149 contextMenu.appendItem(Common.UIString.capitalize('Clear ^all'), this._clear AndRefresh.bind(this, null));
111 } 150 }
112 151
152 _setCookieFlag(node, flag, value) {
153 node.data[flag] = value;
154 node.refresh();
155 this._saveNode(node);
156 }
157
113 /** 158 /**
114 * @param {!Array.<!SDK.Cookie>} cookies 159 * @param {!Array.<!SDK.Cookie>} cookies
115 */ 160 */
116 setCookies(cookies) { 161 setCookies(cookies) {
117 this.setCookieFolders([{cookies: cookies}]); 162 this.setCookieFolders([{cookies: cookies}]);
118 } 163 }
119 164
120 /** 165 /**
121 * @param {!Array.<!{folderName: ?string, cookies: !Array.<!SDK.Cookie>}>} coo kieFolders 166 * @param {!Array.<!{folderName: ?string, cookies: !Array.<!SDK.Cookie>}>} coo kieFolders
122 */ 167 */
(...skipping 16 matching lines...) Expand all
139 clear(domain) { 184 clear(domain) {
140 for (var i = 0, length = this._data.length; i < length; ++i) { 185 for (var i = 0, length = this._data.length; i < length; ++i) {
141 var cookies = this._data[i].cookies; 186 var cookies = this._data[i].cookies;
142 for (var j = 0, cookieCount = cookies.length; j < cookieCount; ++j) { 187 for (var j = 0, cookieCount = cookies.length; j < cookieCount; ++j) {
143 if (!domain || cookies[j].domain() === domain) 188 if (!domain || cookies[j].domain() === domain)
144 cookies[j].remove(); 189 cookies[j].remove();
145 } 190 }
146 } 191 }
147 } 192 }
148 193
194 /**
195 * @override
196 */
197 willHide() {
198 this._lastEditedColumnId = null;
199 }
200
149 _rebuildTable() { 201 _rebuildTable() {
150 var selectedCookie = this._nextSelectedCookie || this.selectedCookie(); 202 var selectedCookie = this._nextSelectedCookie || this.selectedCookie();
203 var lastEditedColumnId = this._lastEditedColumnId;
151 this._nextSelectedCookie = null; 204 this._nextSelectedCookie = null;
205 this._lastEditedColumnId = null;
152 this._dataGrid.rootNode().removeChildren(); 206 this._dataGrid.rootNode().removeChildren();
153 for (var i = 0; i < this._data.length; ++i) { 207 for (var i = 0; i < this._data.length; ++i) {
154 var item = this._data[i]; 208 var item = this._data[i];
155 if (item.folderName) { 209 if (item.folderName) {
156 var groupData = { 210 var groupData = {
157 name: item.folderName, 211 name: item.folderName,
158 value: '', 212 value: '',
159 domain: '', 213 domain: '',
160 path: '', 214 path: '',
161 expires: '', 215 expires: '',
162 size: this._totalSize(item.cookies), 216 size: this._totalSize(item.cookies),
163 httpOnly: '', 217 httpOnly: '',
164 secure: '', 218 secure: '',
165 sameSite: '' 219 sameSite: ''
166 }; 220 };
167 var groupNode = new UI.DataGridNode(groupData); 221 var groupNode = new UI.DataGridNode(groupData);
168 groupNode.selectable = true; 222 groupNode.selectable = true;
169 this._dataGrid.rootNode().appendChild(groupNode); 223 this._dataGrid.rootNode().appendChild(groupNode);
170 groupNode.element().classList.add('row-group'); 224 groupNode.element().classList.add('row-group');
171 this._populateNode(groupNode, item.cookies, selectedCookie); 225 this._populateNode(groupNode, item.cookies, selectedCookie, lastEditedCo lumnId);
172 groupNode.expand(); 226 groupNode.expand();
173 } else { 227 } else {
174 this._populateNode(this._dataGrid.rootNode(), item.cookies, selectedCook ie); 228 this._populateNode(this._dataGrid.rootNode(), item.cookies, selectedCook ie, lastEditedColumnId);
175 } 229 }
176 } 230 }
231
232 this._dataGrid.addCreationNode(false);
phulce 2016/12/12 17:58:40 probably only want to do this if the table is read
177 } 233 }
178 234
179 /** 235 /**
180 * @param {!UI.DataGridNode} parentNode 236 * @param {!UI.DataGridNode} parentNode
181 * @param {?Array.<!SDK.Cookie>} cookies 237 * @param {?Array.<!SDK.Cookie>} cookies
182 * @param {?SDK.Cookie} selectedCookie 238 * @param {?SDK.Cookie} selectedCookie
239 * @param {?string} lastEditedColumnId
183 */ 240 */
184 _populateNode(parentNode, cookies, selectedCookie) { 241 _populateNode(parentNode, cookies, selectedCookie, lastEditedColumnId) {
185 parentNode.removeChildren(); 242 parentNode.removeChildren();
186 if (!cookies) 243 if (!cookies)
187 return; 244 return;
188 245
189 this._sortCookies(cookies); 246 this._sortCookies(cookies);
190 for (var i = 0; i < cookies.length; ++i) { 247 for (var i = 0; i < cookies.length; ++i) {
191 var cookie = cookies[i]; 248 var cookie = cookies[i];
192 var cookieNode = this._createGridNode(cookie); 249 var cookieNode = this._createGridNode(cookie);
193 parentNode.appendChild(cookieNode); 250 parentNode.appendChild(cookieNode);
194 if (selectedCookie && selectedCookie.name() === cookie.name() && selectedC ookie.domain() === cookie.domain() && 251 if (selectedCookie && selectedCookie.name() === cookie.name() && selectedC ookie.domain() === cookie.domain() &&
195 selectedCookie.path() === cookie.path()) 252 selectedCookie.path() === cookie.path()) {
196 cookieNode.select(); 253 cookieNode.select();
254 if (lastEditedColumnId !== null)
255 this._dataGrid.startEditingNextEditableColumnOfDataGridNode(cookieNode , lastEditedColumnId);
256 }
197 } 257 }
198 } 258 }
199 259
200 _totalSize(cookies) { 260 _totalSize(cookies) {
201 var totalSize = 0; 261 var totalSize = 0;
202 for (var i = 0; cookies && i < cookies.length; ++i) 262 for (var i = 0; cookies && i < cookies.length; ++i)
203 totalSize += cookies[i].size(); 263 totalSize += cookies[i].size();
204 return totalSize; 264 return totalSize;
205 } 265 }
206 266
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 361
302 _onDeleteCookie(node) { 362 _onDeleteCookie(node) {
303 var cookie = node.cookie; 363 var cookie = node.cookie;
304 var neighbour = node.traverseNextNode() || node.traversePreviousNode(); 364 var neighbour = node.traverseNextNode() || node.traversePreviousNode();
305 if (neighbour) 365 if (neighbour)
306 this._nextSelectedCookie = neighbour.cookie; 366 this._nextSelectedCookie = neighbour.cookie;
307 cookie.remove(); 367 cookie.remove();
308 this._refresh(); 368 this._refresh();
309 } 369 }
310 370
371 _onUpdateCookie(editingNode, columnIdentifier, oldText, newText) {
372 this._lastEditedColumnId = columnIdentifier;
373 this._setDefaults(editingNode);
374 if (this._isValidCookieData(editingNode.data))
375 this._saveNode(editingNode);
376 else
377 editingNode.unsaved = true;
378 }
379
380 _setDefaults(node) {
381 if (node.data.name === null)
382 node.data.name = '';
383 if (node.data.value === null)
384 node.data.value = '';
385 if (node.data.domain === null) {
386 var target = SDK.targetManager.targets(SDK.Target.Capability.Network)[0];
387 var url = new URL(target.inspectedURL());
phulce 2016/12/12 17:58:40 I don't think it necessarily makes sense to have t
388 node.data.domain = url.hostname;
389 }
390 if (node.data.path === null)
391 node.data.path = '/';
392 if (node.data.expires === null)
393 node.data.expires = '';
phulce 2016/12/12 17:58:40 Why not session? I guess because it auto-updates o
394 }
395
396 _saveNode(node) {
397 var oldCookie = node.cookie;
398 var newCookie = this._createCookieFromData(node.data);
399 if (oldCookie && (newCookie.name() !== oldCookie.name() || newCookie.url() ! == oldCookie.url())) oldCookie.remove();
400 node.cookie = newCookie;
401 newCookie.save((error, success) => {
402 if (success)
403 this._refresh();
404 else
405 node.unsaved = true;
406 });
407 this._nextSelectedCookie = newCookie;
408 }
409
410 _createCookieFromData(data) {
411 var target = SDK.targetManager.targets(SDK.Target.Capability.Network)[0];
412 var cookie = new SDK.Cookie(target, data.name, data.value, null);
413 cookie.addAttribute('domain', data.domain);
414 cookie.addAttribute('path', data.path);
415 if (data.expires) {
phulce 2016/12/12 17:58:40 Don't we need a `&& data.expires !== 'Session'` he
416 var secondsSinceEpoch = Date.parse(data.expires) / 1000;
417 cookie.addAttribute('expires', secondsSinceEpoch || undefined);
418 }
419 if (data.httpOnly)
420 cookie.addAttribute('httpOnly');
421 if (data.secure)
422 cookie.addAttribute('secure');
423 if (data.sameSite)
424 cookie.addAttribute('sameSite', data.sameSite);
425 cookie.setSize(data.name.length + data.value.length);
426 return cookie;
427 }
428
429 _isValidCookieData(data) {
430 return (data.name || data.value) && this._isValidDomain(data.domain) && this ._isValidPath(data.path) && this._isValidDate(data.expires);
431 }
432
433 _isValidDomain(domain) {
434 if (domain === '')
435 return true;
436 var url = null;
437 try {
438 url = new URL('http://' + domain);
439 } catch (e) {
440 return false;
441 }
442 return url.hostname === domain;
443 }
444
445 _isValidPath(path) {
446 var url = null;
447 try {
448 url = new URL('http://example.com' + path);
449 } catch (e) {
450 return false;
451 }
452 return url.pathname === path;
453 }
454
455 _isValidDate(date) {
456 return date === '' || date === Common.UIString('Session') || !isNaN(Date.par se(date));
457 }
458
311 _refresh() { 459 _refresh() {
312 if (this._refreshCallback) 460 if (this._refreshCallback)
313 this._refreshCallback(); 461 this._refreshCallback();
314 } 462 }
315 }; 463 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698