Home | History | Annotate | Download | only in cookies
      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>
    298