OLD | NEW |
(Empty) | |
| 1 <html> |
| 2 <head> |
| 3 <style> |
| 4 table { |
| 5 border-collapse:collapse; |
| 6 } |
| 7 |
| 8 td { |
| 9 border: 1px solid black; |
| 10 padding-left: 5px; |
| 11 } |
| 12 |
| 13 td.button { |
| 14 border: none; |
| 15 } |
| 16 |
| 17 td.cookie_count { |
| 18 text-align: right; |
| 19 } |
| 20 |
| 21 </style> |
| 22 |
| 23 <script> |
| 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> |
| 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"> |
| 280 Filter: <input id="filter" type="text" oninput="reloadCookieTable()"> |
| 281 <button onclick="resetFilter()">x</button> |
| 282 </div> |
| 283 <br> |
| 284 <div id="summary_div"> |
| 285 Showing <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> |
OLD | NEW |