OLD | NEW |
1 <html> | 1 <html> |
2 <head> | 2 <head> |
3 <style> | 3 <style> |
4 table { | 4 table { |
5 border-collapse:collapse; | 5 border-collapse:collapse; |
6 } | 6 } |
7 | 7 |
8 td { | 8 td { |
9 border: 1px solid black; | 9 border: 1px solid black; |
10 padding-left: 5px; | 10 padding-left: 5px; |
11 } | 11 } |
12 | 12 |
13 td.button { | 13 td.button { |
14 border: none; | 14 border: none; |
15 } | 15 } |
16 | 16 |
17 td.cookie_count { | 17 td.cookie_count { |
18 text-align: right; | 18 text-align: right; |
19 } | 19 } |
20 | 20 |
21 </style> | 21 </style> |
22 | 22 |
23 <script> | 23 <script src="manager.js"></script> |
24 | 24 |
25 if (!chrome.cookies) { | |
26 chrome.cookies = chrome.experimental.cookies; | |
27 } | |
28 | |
29 // A simple Timer class. | |
30 function 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. | |
44 function 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. | |
52 function 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. | |
62 function 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. | |
68 function 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 | |
118 var cache = new CookieCache(); | |
119 | |
120 | |
121 function 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 | |
129 function 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 | |
151 function 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 | |
157 function removeCookiesForDomain(domain) { | |
158 var timer = new Timer(); | |
159 cache.getCookies(domain).forEach(function(cookie) { | |
160 removeCookie(cookie); | |
161 }); | |
162 } | |
163 | |
164 function resetTable() { | |
165 var table = select("#cookies"); | |
166 while (table.rows.length > 1) { | |
167 table.deleteRow(table.rows.length - 1); | |
168 } | |
169 } | |
170 | |
171 var reload_scheduled = false; | |
172 | |
173 function scheduleReloadCookieTable() { | |
174 if (!reload_scheduled) { | |
175 reload_scheduled = true; | |
176 setTimeout(reloadCookieTable, 250); | |
177 } | |
178 } | |
179 | |
180 function 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 | |
222 function focusFilter() { | |
223 select("#filter").focus(); | |
224 } | |
225 | |
226 function resetFilter() { | |
227 var filter = select("#filter"); | |
228 filter.focus(); | |
229 if (filter.value.length > 0) { | |
230 filter.value = ""; | |
231 reloadCookieTable(); | |
232 } | |
233 } | |
234 | |
235 var ESCAPE_KEY = 27; | |
236 window.onkeydown = function(event) { | |
237 if (event.keyCode == ESCAPE_KEY) { | |
238 resetFilter(); | |
239 } | |
240 } | |
241 | |
242 function listener(info) { | |
243 cache.remove(info.cookie); | |
244 if (!info.removed) { | |
245 cache.add(info.cookie); | |
246 } | |
247 scheduleReloadCookieTable(); | |
248 } | |
249 | |
250 function startListening() { | |
251 chrome.cookies.onChanged.addListener(listener); | |
252 } | |
253 | |
254 function stopListening() { | |
255 chrome.cookies.onChanged.removeListener(listener); | |
256 } | |
257 | |
258 function 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> | 25 </head> |
275 | 26 |
276 <body onload="onload()" onclick="focusFilter()"> | 27 <body> |
277 <h2>Cookies! ... Nom Nom Nom...</h2> | 28 <h2>Cookies! ... Nom Nom Nom...</h2> |
278 <button onclick="removeAll()">DELETE ALL!</button> | 29 <button id="remove_button">DELETE ALL!</button> |
279 <div id="filter_div"> | 30 <div id="filter_div"> |
280 Filter: <input id="filter" type="text" oninput="reloadCookieTable()"> | 31 Filter: <input id="filter" type="text"> |
281 <button onclick="resetFilter()">x</button> | 32 <button>x</button> |
282 </div> | 33 </div> |
283 <br> | 34 <br /> |
284 <div id="summary_div"> | 35 <div id="summary_div"> |
285 Showing <span id="filter_count"></span> of <span id="total_count"></span> cookie
domains. | 36 Showing <span id="filter_count"></span> of <span id="total_count"></span> cook
ie domains. |
286 <span id="delete_all_button"></span> | 37 <span id="delete_all_button"></span> |
287 </div> | 38 </div> |
288 <br> | 39 <br /> |
289 <table id="cookies"> | 40 <table id="cookies"> |
290 <tr class="header"> | 41 <tr class="header"> |
291 <th>Name</th> | 42 <th>Name</th> |
292 <th>#Cookies</th> | 43 <th>#Cookies</th> |
293 </tr> | 44 </tr> |
294 </table> | 45 </table> |
295 | 46 |
296 </body> | 47 </body> |
297 </html> | 48 </html> |
OLD | NEW |