CookiesTable.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * Copyright (C) 2009 Apple Inc. All rights reserved.
  3. * Copyright (C) 2009 Joseph Pecoraro
  4. * Copyright (C) 2010 Google Inc. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  16. * its contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  20. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /**
  31. * @constructor
  32. * @extends {WebInspector.View}
  33. * @param {boolean} expandable
  34. * @param {function()=} refreshCallback
  35. * @param {function()=} selectedCallback
  36. */
  37. WebInspector.CookiesTable = function(expandable, refreshCallback, selectedCallback)
  38. {
  39. WebInspector.View.call(this);
  40. this.element.className = "fill";
  41. var readOnly = expandable;
  42. this._refreshCallback = refreshCallback;
  43. var columns = [
  44. {id: "name", title: WebInspector.UIString("Name"), sortable: true, disclosure: expandable, sort: WebInspector.DataGrid.Order.Ascending, longText: true, weight: 24},
  45. {id: "value", title: WebInspector.UIString("Value"), sortable: true, longText: true, weight: 34},
  46. {id: "domain", title: WebInspector.UIString("Domain"), sortable: true, weight: 7},
  47. {id: "path", title: WebInspector.UIString("Path"), sortable: true, weight: 7},
  48. {id: "expires", title: WebInspector.UIString("Expires / Max-Age"), sortable: true, weight: 7},
  49. {id: "size", title: WebInspector.UIString("Size"), sortable: true, align: WebInspector.DataGrid.Align.Right, weight: 7},
  50. {id: "httpOnly", title: WebInspector.UIString("HTTP"), sortable: true, align: WebInspector.DataGrid.Align.Center, weight: 7},
  51. {id: "secure", title: WebInspector.UIString("Secure"), sortable: true, align: WebInspector.DataGrid.Align.Center, weight: 7}
  52. ];
  53. if (readOnly)
  54. this._dataGrid = new WebInspector.DataGrid(columns);
  55. else
  56. this._dataGrid = new WebInspector.DataGrid(columns, undefined, this._onDeleteCookie.bind(this), refreshCallback, this._onContextMenu.bind(this));
  57. this._dataGrid.setName("cookiesTable");
  58. this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._rebuildTable, this);
  59. if (selectedCallback)
  60. this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, selectedCallback, this);
  61. this._nextSelectedCookie = /** @type {?WebInspector.Cookie} */ (null);
  62. this._dataGrid.show(this.element);
  63. this._data = [];
  64. }
  65. WebInspector.CookiesTable.prototype = {
  66. /**
  67. * @param {?string} domain
  68. */
  69. _clearAndRefresh: function(domain)
  70. {
  71. this.clear(domain);
  72. this._refresh();
  73. },
  74. /**
  75. * @param {!WebInspector.ContextMenu} contextMenu
  76. * @param {WebInspector.DataGridNode} node
  77. */
  78. _onContextMenu: function(contextMenu, node)
  79. {
  80. if (node === this._dataGrid.creationNode)
  81. return;
  82. var cookie = node.cookie;
  83. var domain = cookie.domain();
  84. if (domain)
  85. contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear all from \"%s\"" : "Clear All from \"%s\"", domain), this._clearAndRefresh.bind(this, domain));
  86. contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear all" : "Clear All"), this._clearAndRefresh.bind(this, null));
  87. },
  88. /**
  89. * @param {!Array.<!WebInspector.Cookie>} cookies
  90. */
  91. setCookies: function(cookies)
  92. {
  93. this.setCookieFolders([{cookies: cookies}]);
  94. },
  95. /**
  96. * @param {!Array.<!{folderName: ?string, cookies: !Array.<!WebInspector.Cookie>}>} cookieFolders
  97. */
  98. setCookieFolders: function(cookieFolders)
  99. {
  100. this._data = cookieFolders;
  101. this._rebuildTable();
  102. },
  103. /**
  104. * @return {?WebInspector.Cookie}
  105. */
  106. selectedCookie: function()
  107. {
  108. var node = this._dataGrid.selectedNode;
  109. return node ? node.cookie : null;
  110. },
  111. /**
  112. * @param {?string=} domain
  113. */
  114. clear: function(domain)
  115. {
  116. for (var i = 0, length = this._data.length; i < length; ++i) {
  117. var cookies = this._data[i].cookies;
  118. for (var j = 0, cookieCount = cookies.length; j < cookieCount; ++j) {
  119. if (!domain || cookies[j].domain() === domain)
  120. cookies[j].remove();
  121. }
  122. }
  123. },
  124. _rebuildTable: function()
  125. {
  126. var selectedCookie = this._nextSelectedCookie || this.selectedCookie();
  127. this._nextSelectedCookie = null;
  128. this._dataGrid.rootNode().removeChildren();
  129. for (var i = 0; i < this._data.length; ++i) {
  130. var item = this._data[i];
  131. if (item.folderName) {
  132. var groupData = {name: item.folderName, value: "", domain: "", path: "", expires: "", size: this._totalSize(item.cookies), httpOnly: "", secure: ""};
  133. var groupNode = new WebInspector.DataGridNode(groupData);
  134. groupNode.selectable = true;
  135. this._dataGrid.rootNode().appendChild(groupNode);
  136. groupNode.element.addStyleClass("row-group");
  137. this._populateNode(groupNode, item.cookies, selectedCookie);
  138. groupNode.expand();
  139. } else
  140. this._populateNode(this._dataGrid.rootNode(), item.cookies, selectedCookie);
  141. }
  142. },
  143. /**
  144. * @param {!WebInspector.DataGridNode} parentNode
  145. * @param {?Array.<!WebInspector.Cookie>} cookies
  146. * @param {?WebInspector.Cookie} selectedCookie
  147. */
  148. _populateNode: function(parentNode, cookies, selectedCookie)
  149. {
  150. parentNode.removeChildren();
  151. if (!cookies)
  152. return;
  153. this._sortCookies(cookies);
  154. for (var i = 0; i < cookies.length; ++i) {
  155. var cookie = cookies[i];
  156. var cookieNode = this._createGridNode(cookie);
  157. parentNode.appendChild(cookieNode);
  158. if (selectedCookie && selectedCookie.name() === cookie.name() && selectedCookie.domain() === cookie.domain() && selectedCookie.path() === cookie.path())
  159. cookieNode.select();
  160. }
  161. },
  162. _totalSize: function(cookies)
  163. {
  164. var totalSize = 0;
  165. for (var i = 0; cookies && i < cookies.length; ++i)
  166. totalSize += cookies[i].size();
  167. return totalSize;
  168. },
  169. /**
  170. * @param {!Array.<!WebInspector.Cookie>} cookies
  171. */
  172. _sortCookies: function(cookies)
  173. {
  174. var sortDirection = this._dataGrid.isSortOrderAscending() ? 1 : -1;
  175. function compareTo(getter, cookie1, cookie2)
  176. {
  177. return sortDirection * (getter.apply(cookie1) + "").compareTo(getter.apply(cookie2) + "")
  178. }
  179. function numberCompare(getter, cookie1, cookie2)
  180. {
  181. return sortDirection * (getter.apply(cookie1) - getter.apply(cookie2));
  182. }
  183. function expiresCompare(cookie1, cookie2)
  184. {
  185. if (cookie1.session() !== cookie2.session())
  186. return sortDirection * (cookie1.session() ? 1 : -1);
  187. if (cookie1.session())
  188. return 0;
  189. if (cookie1.maxAge() && cookie2.maxAge())
  190. return sortDirection * (cookie1.maxAge() - cookie2.maxAge());
  191. if (cookie1.expires() && cookie2.expires())
  192. return sortDirection * (cookie1.expires() - cookie2.expires());
  193. return sortDirection * (cookie1.expires() ? 1 : -1);
  194. }
  195. var comparator;
  196. switch (this._dataGrid.sortColumnIdentifier()) {
  197. case "name": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.name); break;
  198. case "value": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.value); break;
  199. case "domain": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.domain); break;
  200. case "path": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.path); break;
  201. case "expires": comparator = expiresCompare; break;
  202. case "size": comparator = numberCompare.bind(null, WebInspector.Cookie.prototype.size); break;
  203. case "httpOnly": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.httpOnly); break;
  204. case "secure": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.secure); break;
  205. default: compareTo.bind(null, WebInspector.Cookie.prototype.name);
  206. }
  207. cookies.sort(comparator);
  208. },
  209. /**
  210. * @param {!WebInspector.Cookie} cookie
  211. * @return {!WebInspector.DataGridNode}
  212. */
  213. _createGridNode: function(cookie)
  214. {
  215. var data = {};
  216. data.name = cookie.name();
  217. data.value = cookie.value();
  218. if (cookie.type() === WebInspector.Cookie.Type.Request) {
  219. data.domain = WebInspector.UIString("N/A");
  220. data.path = WebInspector.UIString("N/A");
  221. data.expires = WebInspector.UIString("N/A");
  222. } else {
  223. data.domain = cookie.domain() || "";
  224. data.path = cookie.path() || "";
  225. if (cookie.maxAge())
  226. data.expires = Number.secondsToString(parseInt(cookie.maxAge(), 10));
  227. else if (cookie.expires())
  228. data.expires = new Date(cookie.expires()).toGMTString();
  229. else
  230. data.expires = WebInspector.UIString("Session");
  231. }
  232. data.size = cookie.size();
  233. const checkmark = "\u2713";
  234. data.httpOnly = (cookie.httpOnly() ? checkmark : "");
  235. data.secure = (cookie.secure() ? checkmark : "");
  236. var node = new WebInspector.DataGridNode(data);
  237. node.cookie = cookie;
  238. node.selectable = true;
  239. return node;
  240. },
  241. _onDeleteCookie: function(node)
  242. {
  243. var cookie = node.cookie;
  244. var neighbour = node.traverseNextNode() || node.traversePreviousNode();
  245. if (neighbour)
  246. this._nextSelectedCookie = neighbour.cookie;
  247. cookie.remove();
  248. this._refresh();
  249. },
  250. _refresh: function()
  251. {
  252. if (this._refreshCallback)
  253. this._refreshCallback();
  254. },
  255. __proto__: WebInspector.View.prototype
  256. }