• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<style>
4table {
5  border-collapse:collapse;
6}
7
8td {
9  border: 1px solid black;
10  padding-left: 5px;
11}
12
13td.button {
14  border: none;
15}
16
17td.cookie_count {
18  text-align: right;
19}
20
21</style>
22
23<script>
24
25if (!chrome.cookies) {
26  chrome.cookies = chrome.experimental.cookies;
27}
28
29// A simple Timer class.
30function Timer() {
31  this.start_ = new Date();
32
33  this.elapsed = function() {
34    return (new Date()) - this.start_;
35  }
36
37  this.reset = function() {
38    this.start_ = new Date();
39  }
40}
41
42// Compares cookies for "key" (name, domain, etc.) equality, but not "value"
43// equality.
44function cookieMatch(c1, c2) {
45  return (c1.name == c2.name) && (c1.domain == c2.domain) &&
46         (c1.hostOnly == c2.hostOnly) && (c1.path == c2.path) &&
47         (c1.secure == c2.secure) && (c1.httpOnly == c2.httpOnly) &&
48         (c1.session == c2.session) && (c1.storeId == c2.storeId);
49}
50
51// Returns an array of sorted keys from an associative array.
52function sortedKeys(array) {
53  var keys = [];
54  for (var i in array) {
55    keys.push(i);
56  }
57  keys.sort();
58  return keys;
59}
60
61// Shorthand for document.querySelector.
62function select(selector) {
63  return document.querySelector(selector);
64}
65
66// An object used for caching data about the browser's cookies, which we update
67// as notifications come in.
68function CookieCache() {
69  this.cookies_ = {};
70
71  this.reset = function() {
72    this.cookies_ = {};
73  }
74
75  this.add = function(cookie) {
76    var domain = cookie.domain;
77    if (!this.cookies_[domain]) {
78      this.cookies_[domain] = [];
79    }
80    this.cookies_[domain].push(cookie);
81  };
82
83  this.remove = function(cookie) {
84    var domain = cookie.domain;
85    if (this.cookies_[domain]) {
86      var i = 0;
87      while (i < this.cookies_[domain].length) {
88        if (cookieMatch(this.cookies_[domain][i], cookie)) {
89          this.cookies_[domain].splice(i, 1);
90        } else {
91          i++;
92        }
93      }
94      if (this.cookies_[domain].length == 0) {
95        delete this.cookies_[domain];
96      }
97    }
98  };
99
100  // Returns a sorted list of cookie domains that match |filter|. If |filter| is
101  //  null, returns all domains.
102  this.getDomains = function(filter) {
103    var result = [];
104    sortedKeys(this.cookies_).forEach(function(domain) {
105      if (!filter || domain.indexOf(filter) != -1) {
106        result.push(domain);
107      }
108    });
109    return result;
110  }
111
112  this.getCookies = function(domain) {
113    return this.cookies_[domain];
114  };
115}
116
117
118var cache = new CookieCache();
119
120
121function removeAllForFilter() {
122  var filter = select("#filter").value;
123  var timer = new Timer();
124  cache.getDomains(filter).forEach(function(domain) {
125    removeCookiesForDomain(domain);
126  });
127}
128
129function removeAll() {
130  var all_cookies = [];
131  cache.getDomains().forEach(function(domain) {
132    cache.getCookies(domain).forEach(function(cookie) {
133      all_cookies.push(cookie);
134    });
135  });
136  cache.reset();
137  var count = all_cookies.length;
138  var timer = new Timer();
139  for (var i = 0; i < count; i++) {
140    removeCookie(all_cookies[i]);
141  }
142  timer.reset();
143  chrome.cookies.getAll({}, function(cookies) {
144    for (var i in cookies) {
145      cache.add(cookies[i]);
146      removeCookie(cookies[i]);
147    }
148  });
149}
150
151function removeCookie(cookie) {
152  var url = "http" + (cookie.secure ? "s" : "") + "://" + cookie.domain +
153            cookie.path;
154  chrome.cookies.remove({"url": url, "name": cookie.name});
155}
156
157function removeCookiesForDomain(domain) {
158 var timer = new Timer();
159 cache.getCookies(domain).forEach(function(cookie) {
160    removeCookie(cookie);
161 });
162}
163
164function resetTable() {
165  var table = select("#cookies");
166  while (table.rows.length > 1) {
167    table.deleteRow(table.rows.length - 1);
168  }
169}
170
171var reload_scheduled = false;
172
173function scheduleReloadCookieTable() {
174  if (!reload_scheduled) {
175    reload_scheduled = true;
176    setTimeout(reloadCookieTable, 250);
177  }
178}
179
180function reloadCookieTable() {
181  reload_scheduled = false;
182
183  var filter = select("#filter").value;
184
185  var domains = cache.getDomains(filter);
186
187  select("#filter_count").innerText = domains.length;
188  select("#total_count").innerText = cache.getDomains().length;
189
190  select("#delete_all_button").innerHTML = "";
191  if (domains.length) {
192    var button = document.createElement("button");
193    button.onclick = removeAllForFilter;
194    button.innerText = "delete all " + domains.length;
195    select("#delete_all_button").appendChild(button);
196  }
197
198  resetTable();
199  var table = select("#cookies");
200
201  domains.forEach(function(domain) {
202    var cookies = cache.getCookies(domain);
203    var row = table.insertRow(-1);
204    row.insertCell(-1).innerText = domain;
205    var cell = row.insertCell(-1);
206    cell.innerText = cookies.length;
207    cell.setAttribute("class", "cookie_count");
208
209    var button = document.createElement("button");
210    button.innerText = "delete";
211    button.onclick = (function(dom){
212      return function() {
213        removeCookiesForDomain(dom);
214      };
215    }(domain));
216    var cell = row.insertCell(-1);
217    cell.appendChild(button);
218    cell.setAttribute("class", "button");
219  });
220}
221
222function focusFilter() {
223  select("#filter").focus();
224}
225
226function resetFilter() {
227  var filter = select("#filter");
228  filter.focus();
229  if (filter.value.length > 0) {
230    filter.value = "";
231    reloadCookieTable();
232  }
233}
234
235var ESCAPE_KEY = 27;
236window.onkeydown = function(event) {
237  if (event.keyCode == ESCAPE_KEY) {
238    resetFilter();
239  }
240}
241
242function listener(info) {
243  cache.remove(info.cookie);
244  if (!info.removed) {
245    cache.add(info.cookie);
246  }
247  scheduleReloadCookieTable();
248}
249
250function startListening() {
251  chrome.cookies.onChanged.addListener(listener);
252}
253
254function stopListening() {
255  chrome.cookies.onChanged.removeListener(listener);
256}
257
258function onload() {
259  focusFilter();
260  var timer = new Timer();
261  chrome.cookies.getAll({}, function(cookies) {
262    startListening();
263    start = new Date();
264    for (var i in cookies) {
265      cache.add(cookies[i]);
266    }
267    timer.reset();
268    reloadCookieTable();
269  });
270}
271
272
273</script>
274</head>
275
276<body onload="onload()" onclick="focusFilter()">
277<h2>Cookies! ... Nom Nom Nom...</h2>
278<button onclick="removeAll()">DELETE ALL!</button>
279<div id="filter_div">
280Filter: <input id="filter" type="text" oninput="reloadCookieTable()">
281<button onclick="resetFilter()">x</button>
282</div>
283<br>
284<div id="summary_div">
285Showing <span id="filter_count"></span> of <span id="total_count"></span> cookie domains.
286<span id="delete_all_button"></span>
287</div>
288<br>
289<table id="cookies">
290<tr class="header">
291<th>Name</th>
292<th>#Cookies</th>
293</tr>
294</table>
295
296</body>
297</html>
298