browser/components/preferences/cookies.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 const nsICookie = Components.interfaces.nsICookie;
michael@0 7
michael@0 8 var gCookiesWindow = {
michael@0 9 _cm : Components.classes["@mozilla.org/cookiemanager;1"]
michael@0 10 .getService(Components.interfaces.nsICookieManager),
michael@0 11 _ds : Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
michael@0 12 .getService(Components.interfaces.nsIScriptableDateFormat),
michael@0 13 _hosts : {},
michael@0 14 _hostOrder : [],
michael@0 15 _tree : null,
michael@0 16 _bundle : null,
michael@0 17
michael@0 18 init: function () {
michael@0 19 var os = Components.classes["@mozilla.org/observer-service;1"]
michael@0 20 .getService(Components.interfaces.nsIObserverService);
michael@0 21 os.addObserver(this, "cookie-changed", false);
michael@0 22 os.addObserver(this, "perm-changed", false);
michael@0 23
michael@0 24 this._bundle = document.getElementById("bundlePreferences");
michael@0 25 this._tree = document.getElementById("cookiesList");
michael@0 26
michael@0 27 this._populateList(true);
michael@0 28
michael@0 29 document.getElementById("filter").focus();
michael@0 30 },
michael@0 31
michael@0 32 uninit: function () {
michael@0 33 var os = Components.classes["@mozilla.org/observer-service;1"]
michael@0 34 .getService(Components.interfaces.nsIObserverService);
michael@0 35 os.removeObserver(this, "cookie-changed");
michael@0 36 os.removeObserver(this, "perm-changed");
michael@0 37 },
michael@0 38
michael@0 39 _populateList: function (aInitialLoad) {
michael@0 40 this._loadCookies();
michael@0 41 this._tree.treeBoxObject.view = this._view;
michael@0 42 if (aInitialLoad)
michael@0 43 this.sort("rawHost");
michael@0 44 if (this._view.rowCount > 0)
michael@0 45 this._tree.view.selection.select(0);
michael@0 46
michael@0 47 if (aInitialLoad) {
michael@0 48 if ("arguments" in window &&
michael@0 49 window.arguments[0] &&
michael@0 50 window.arguments[0].filterString)
michael@0 51 this.setFilter(window.arguments[0].filterString);
michael@0 52 }
michael@0 53 else {
michael@0 54 if (document.getElementById("filter").value != "")
michael@0 55 this.filter();
michael@0 56 }
michael@0 57
michael@0 58 this._updateRemoveAllButton();
michael@0 59
michael@0 60 this._saveState();
michael@0 61 },
michael@0 62
michael@0 63 _cookieEquals: function (aCookieA, aCookieB, aStrippedHost) {
michael@0 64 return aCookieA.rawHost == aStrippedHost &&
michael@0 65 aCookieA.name == aCookieB.name &&
michael@0 66 aCookieA.path == aCookieB.path;
michael@0 67 },
michael@0 68
michael@0 69 observe: function (aCookie, aTopic, aData) {
michael@0 70 if (aTopic != "cookie-changed")
michael@0 71 return;
michael@0 72
michael@0 73 if (aCookie instanceof Components.interfaces.nsICookie) {
michael@0 74 var strippedHost = this._makeStrippedHost(aCookie.host);
michael@0 75 if (aData == "changed")
michael@0 76 this._handleCookieChanged(aCookie, strippedHost);
michael@0 77 else if (aData == "added")
michael@0 78 this._handleCookieAdded(aCookie, strippedHost);
michael@0 79 }
michael@0 80 else if (aData == "cleared") {
michael@0 81 this._hosts = {};
michael@0 82 this._hostOrder = [];
michael@0 83
michael@0 84 var oldRowCount = this._view._rowCount;
michael@0 85 this._view._rowCount = 0;
michael@0 86 this._tree.treeBoxObject.rowCountChanged(0, -oldRowCount);
michael@0 87 this._view.selection.clearSelection();
michael@0 88 this._updateRemoveAllButton();
michael@0 89 }
michael@0 90 else if (aData == "reload") {
michael@0 91 // first, clear any existing entries
michael@0 92 this.observe(aCookie, aTopic, "cleared");
michael@0 93
michael@0 94 // then, reload the list
michael@0 95 this._populateList(false);
michael@0 96 }
michael@0 97
michael@0 98 // We don't yet handle aData == "deleted" - it's a less common case
michael@0 99 // and is rather complicated as selection tracking is difficult
michael@0 100 },
michael@0 101
michael@0 102 _handleCookieChanged: function (changedCookie, strippedHost) {
michael@0 103 var rowIndex = 0;
michael@0 104 var cookieItem = null;
michael@0 105 if (!this._view._filtered) {
michael@0 106 for (var i = 0; i < this._hostOrder.length; ++i) { // (var host in this._hosts) {
michael@0 107 ++rowIndex;
michael@0 108 var hostItem = this._hosts[this._hostOrder[i]]; // var hostItem = this._hosts[host];
michael@0 109 if (this._hostOrder[i] == strippedHost) { // host == strippedHost) {
michael@0 110 // Host matches, look for the cookie within this Host collection
michael@0 111 // and update its data
michael@0 112 for (var j = 0; j < hostItem.cookies.length; ++j) {
michael@0 113 ++rowIndex;
michael@0 114 var currCookie = hostItem.cookies[j];
michael@0 115 if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
michael@0 116 currCookie.value = changedCookie.value;
michael@0 117 currCookie.isSecure = changedCookie.isSecure;
michael@0 118 currCookie.isDomain = changedCookie.isDomain;
michael@0 119 currCookie.expires = changedCookie.expires;
michael@0 120 cookieItem = currCookie;
michael@0 121 break;
michael@0 122 }
michael@0 123 }
michael@0 124 }
michael@0 125 else if (hostItem.open)
michael@0 126 rowIndex += hostItem.cookies.length;
michael@0 127 }
michael@0 128 }
michael@0 129 else {
michael@0 130 // Just walk the filter list to find the item. It doesn't matter that
michael@0 131 // we don't update the main Host collection when we do this, because
michael@0 132 // when the filter is reset the Host collection is rebuilt anyway.
michael@0 133 for (rowIndex = 0; rowIndex < this._view._filterSet.length; ++rowIndex) {
michael@0 134 currCookie = this._view._filterSet[rowIndex];
michael@0 135 if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
michael@0 136 currCookie.value = changedCookie.value;
michael@0 137 currCookie.isSecure = changedCookie.isSecure;
michael@0 138 currCookie.isDomain = changedCookie.isDomain;
michael@0 139 currCookie.expires = changedCookie.expires;
michael@0 140 cookieItem = currCookie;
michael@0 141 break;
michael@0 142 }
michael@0 143 }
michael@0 144 }
michael@0 145
michael@0 146 // Make sure the tree display is up to date...
michael@0 147 this._tree.treeBoxObject.invalidateRow(rowIndex);
michael@0 148 // ... and if the cookie is selected, update the displayed metadata too
michael@0 149 if (cookieItem != null && this._view.selection.currentIndex == rowIndex)
michael@0 150 this._updateCookieData(cookieItem);
michael@0 151 },
michael@0 152
michael@0 153 _handleCookieAdded: function (changedCookie, strippedHost) {
michael@0 154 var rowCountImpact = 0;
michael@0 155 var addedHost = { value: 0 };
michael@0 156 this._addCookie(strippedHost, changedCookie, addedHost);
michael@0 157 if (!this._view._filtered) {
michael@0 158 // The Host collection for this cookie already exists, and it's not open,
michael@0 159 // so don't increment the rowCountImpact becaues the user is not going to
michael@0 160 // see the additional rows as they're hidden.
michael@0 161 if (addedHost.value || this._hosts[strippedHost].open)
michael@0 162 ++rowCountImpact;
michael@0 163 }
michael@0 164 else {
michael@0 165 // We're in search mode, and the cookie being added matches
michael@0 166 // the search condition, so add it to the list.
michael@0 167 var c = this._makeCookieObject(strippedHost, changedCookie);
michael@0 168 if (this._cookieMatchesFilter(c)) {
michael@0 169 this._view._filterSet.push(this._makeCookieObject(strippedHost, changedCookie));
michael@0 170 ++rowCountImpact;
michael@0 171 }
michael@0 172 }
michael@0 173 // Now update the tree display at the end (we could/should re run the sort
michael@0 174 // if any to get the position correct.)
michael@0 175 var oldRowCount = this._rowCount;
michael@0 176 this._view._rowCount += rowCountImpact;
michael@0 177 this._tree.treeBoxObject.rowCountChanged(oldRowCount - 1, rowCountImpact);
michael@0 178
michael@0 179 this._updateRemoveAllButton();
michael@0 180 },
michael@0 181
michael@0 182 _view: {
michael@0 183 _filtered : false,
michael@0 184 _filterSet : [],
michael@0 185 _filterValue: "",
michael@0 186 _rowCount : 0,
michael@0 187 _cacheValid : 0,
michael@0 188 _cacheItems : [],
michael@0 189 get rowCount() {
michael@0 190 return this._rowCount;
michael@0 191 },
michael@0 192
michael@0 193 _getItemAtIndex: function (aIndex) {
michael@0 194 if (this._filtered)
michael@0 195 return this._filterSet[aIndex];
michael@0 196
michael@0 197 var start = 0;
michael@0 198 var count = 0, hostIndex = 0;
michael@0 199
michael@0 200 var cacheIndex = Math.min(this._cacheValid, aIndex);
michael@0 201 if (cacheIndex > 0) {
michael@0 202 var cacheItem = this._cacheItems[cacheIndex];
michael@0 203 start = cacheItem['start'];
michael@0 204 count = hostIndex = cacheItem['count'];
michael@0 205 }
michael@0 206
michael@0 207 for (var i = start; i < gCookiesWindow._hostOrder.length; ++i) { // var host in gCookiesWindow._hosts) {
michael@0 208 var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host];
michael@0 209 if (!currHost) continue;
michael@0 210 if (count == aIndex)
michael@0 211 return currHost;
michael@0 212 hostIndex = count;
michael@0 213
michael@0 214 var cacheEntry = { 'start' : i, 'count' : count };
michael@0 215 var cacheStart = count;
michael@0 216
michael@0 217 if (currHost.open) {
michael@0 218 if (count < aIndex && aIndex <= (count + currHost.cookies.length)) {
michael@0 219 // We are looking for an entry within this host's children,
michael@0 220 // enumerate them looking for the index.
michael@0 221 ++count;
michael@0 222 for (var i = 0; i < currHost.cookies.length; ++i) {
michael@0 223 if (count == aIndex) {
michael@0 224 var cookie = currHost.cookies[i];
michael@0 225 cookie.parentIndex = hostIndex;
michael@0 226 return cookie;
michael@0 227 }
michael@0 228 ++count;
michael@0 229 }
michael@0 230 }
michael@0 231 else {
michael@0 232 // A host entry was open, but we weren't looking for an index
michael@0 233 // within that host entry's children, so skip forward over the
michael@0 234 // entry's children. We need to add one to increment for the
michael@0 235 // host value too.
michael@0 236 count += currHost.cookies.length + 1;
michael@0 237 }
michael@0 238 }
michael@0 239 else
michael@0 240 ++count;
michael@0 241
michael@0 242 for (var j = cacheStart; j < count; j++)
michael@0 243 this._cacheItems[j] = cacheEntry;
michael@0 244 this._cacheValid = count - 1;
michael@0 245 }
michael@0 246 return null;
michael@0 247 },
michael@0 248
michael@0 249 _removeItemAtIndex: function (aIndex, aCount) {
michael@0 250 var removeCount = aCount === undefined ? 1 : aCount;
michael@0 251 if (this._filtered) {
michael@0 252 // remove the cookies from the unfiltered set so that they
michael@0 253 // don't reappear when the filter is changed. See bug 410863.
michael@0 254 for (var i = aIndex; i < aIndex + removeCount; ++i) {
michael@0 255 var item = this._filterSet[i];
michael@0 256 var parent = gCookiesWindow._hosts[item.rawHost];
michael@0 257 for (var j = 0; j < parent.cookies.length; ++j) {
michael@0 258 if (item == parent.cookies[j]) {
michael@0 259 parent.cookies.splice(j, 1);
michael@0 260 break;
michael@0 261 }
michael@0 262 }
michael@0 263 }
michael@0 264 this._filterSet.splice(aIndex, removeCount);
michael@0 265 return;
michael@0 266 }
michael@0 267
michael@0 268 var item = this._getItemAtIndex(aIndex);
michael@0 269 if (!item) return;
michael@0 270 this._invalidateCache(aIndex - 1);
michael@0 271 if (item.container)
michael@0 272 gCookiesWindow._hosts[item.rawHost] = null;
michael@0 273 else {
michael@0 274 var parent = this._getItemAtIndex(item.parentIndex);
michael@0 275 for (var i = 0; i < parent.cookies.length; ++i) {
michael@0 276 var cookie = parent.cookies[i];
michael@0 277 if (item.rawHost == cookie.rawHost &&
michael@0 278 item.name == cookie.name && item.path == cookie.path)
michael@0 279 parent.cookies.splice(i, removeCount);
michael@0 280 }
michael@0 281 }
michael@0 282 },
michael@0 283
michael@0 284 _invalidateCache: function (aIndex) {
michael@0 285 this._cacheValid = Math.min(this._cacheValid, aIndex);
michael@0 286 },
michael@0 287
michael@0 288 getCellText: function (aIndex, aColumn) {
michael@0 289 if (!this._filtered) {
michael@0 290 var item = this._getItemAtIndex(aIndex);
michael@0 291 if (!item)
michael@0 292 return "";
michael@0 293 if (aColumn.id == "domainCol")
michael@0 294 return item.rawHost;
michael@0 295 else if (aColumn.id == "nameCol")
michael@0 296 return item.name;
michael@0 297 }
michael@0 298 else {
michael@0 299 if (aColumn.id == "domainCol")
michael@0 300 return this._filterSet[aIndex].rawHost;
michael@0 301 else if (aColumn.id == "nameCol")
michael@0 302 return this._filterSet[aIndex].name;
michael@0 303 }
michael@0 304 return "";
michael@0 305 },
michael@0 306
michael@0 307 _selection: null,
michael@0 308 get selection () { return this._selection; },
michael@0 309 set selection (val) { this._selection = val; return val; },
michael@0 310 getRowProperties: function (aIndex) { return ""; },
michael@0 311 getCellProperties: function (aIndex, aColumn) { return ""; },
michael@0 312 getColumnProperties: function (aColumn) { return ""; },
michael@0 313 isContainer: function (aIndex) {
michael@0 314 if (!this._filtered) {
michael@0 315 var item = this._getItemAtIndex(aIndex);
michael@0 316 if (!item) return false;
michael@0 317 return item.container;
michael@0 318 }
michael@0 319 return false;
michael@0 320 },
michael@0 321 isContainerOpen: function (aIndex) {
michael@0 322 if (!this._filtered) {
michael@0 323 var item = this._getItemAtIndex(aIndex);
michael@0 324 if (!item) return false;
michael@0 325 return item.open;
michael@0 326 }
michael@0 327 return false;
michael@0 328 },
michael@0 329 isContainerEmpty: function (aIndex) {
michael@0 330 if (!this._filtered) {
michael@0 331 var item = this._getItemAtIndex(aIndex);
michael@0 332 if (!item) return false;
michael@0 333 return item.cookies.length == 0;
michael@0 334 }
michael@0 335 return false;
michael@0 336 },
michael@0 337 isSeparator: function (aIndex) { return false; },
michael@0 338 isSorted: function (aIndex) { return false; },
michael@0 339 canDrop: function (aIndex, aOrientation) { return false; },
michael@0 340 drop: function (aIndex, aOrientation) {},
michael@0 341 getParentIndex: function (aIndex) {
michael@0 342 if (!this._filtered) {
michael@0 343 var item = this._getItemAtIndex(aIndex);
michael@0 344 // If an item has no parent index (i.e. it is at the top level) this
michael@0 345 // function MUST return -1 otherwise we will go into an infinite loop.
michael@0 346 // Containers are always top level items in the cookies tree, so make
michael@0 347 // sure to return the appropriate value here.
michael@0 348 if (!item || item.container) return -1;
michael@0 349 return item.parentIndex;
michael@0 350 }
michael@0 351 return -1;
michael@0 352 },
michael@0 353 hasNextSibling: function (aParentIndex, aIndex) {
michael@0 354 if (!this._filtered) {
michael@0 355 // |aParentIndex| appears to be bogus, but we can get the real
michael@0 356 // parent index by getting the entry for |aIndex| and reading the
michael@0 357 // parentIndex field.
michael@0 358 // The index of the last item in this host collection is the
michael@0 359 // index of the parent + the size of the host collection, and
michael@0 360 // aIndex has a next sibling if it is less than this value.
michael@0 361 var item = this._getItemAtIndex(aIndex);
michael@0 362 if (item) {
michael@0 363 if (item.container) {
michael@0 364 for (var i = aIndex + 1; i < this.rowCount; ++i) {
michael@0 365 var subsequent = this._getItemAtIndex(i);
michael@0 366 if (subsequent.container)
michael@0 367 return true;
michael@0 368 }
michael@0 369 return false;
michael@0 370 }
michael@0 371 else {
michael@0 372 var parent = this._getItemAtIndex(item.parentIndex);
michael@0 373 if (parent && parent.container)
michael@0 374 return aIndex < item.parentIndex + parent.cookies.length;
michael@0 375 }
michael@0 376 }
michael@0 377 }
michael@0 378 return aIndex < this.rowCount - 1;
michael@0 379 },
michael@0 380 hasPreviousSibling: function (aIndex) {
michael@0 381 if (!this._filtered) {
michael@0 382 var item = this._getItemAtIndex(aIndex);
michael@0 383 if (!item) return false;
michael@0 384 var parent = this._getItemAtIndex(item.parentIndex);
michael@0 385 if (parent && parent.container)
michael@0 386 return aIndex > item.parentIndex + 1;
michael@0 387 }
michael@0 388 return aIndex > 0;
michael@0 389 },
michael@0 390 getLevel: function (aIndex) {
michael@0 391 if (!this._filtered) {
michael@0 392 var item = this._getItemAtIndex(aIndex);
michael@0 393 if (!item) return 0;
michael@0 394 return item.level;
michael@0 395 }
michael@0 396 return 0;
michael@0 397 },
michael@0 398 getImageSrc: function (aIndex, aColumn) {},
michael@0 399 getProgressMode: function (aIndex, aColumn) {},
michael@0 400 getCellValue: function (aIndex, aColumn) {},
michael@0 401 setTree: function (aTree) {},
michael@0 402 toggleOpenState: function (aIndex) {
michael@0 403 if (!this._filtered) {
michael@0 404 var item = this._getItemAtIndex(aIndex);
michael@0 405 if (!item) return;
michael@0 406 this._invalidateCache(aIndex);
michael@0 407 var multiplier = item.open ? -1 : 1;
michael@0 408 var delta = multiplier * item.cookies.length;
michael@0 409 this._rowCount += delta;
michael@0 410 item.open = !item.open;
michael@0 411 gCookiesWindow._tree.treeBoxObject.rowCountChanged(aIndex + 1, delta);
michael@0 412 gCookiesWindow._tree.treeBoxObject.invalidateRow(aIndex);
michael@0 413 }
michael@0 414 },
michael@0 415 cycleHeader: function (aColumn) {},
michael@0 416 selectionChanged: function () {},
michael@0 417 cycleCell: function (aIndex, aColumn) {},
michael@0 418 isEditable: function (aIndex, aColumn) {
michael@0 419 return false;
michael@0 420 },
michael@0 421 isSelectable: function (aIndex, aColumn) {
michael@0 422 return false;
michael@0 423 },
michael@0 424 setCellValue: function (aIndex, aColumn, aValue) {},
michael@0 425 setCellText: function (aIndex, aColumn, aValue) {},
michael@0 426 performAction: function (aAction) {},
michael@0 427 performActionOnRow: function (aAction, aIndex) {},
michael@0 428 performActionOnCell: function (aAction, aindex, aColumn) {}
michael@0 429 },
michael@0 430
michael@0 431 _makeStrippedHost: function (aHost) {
michael@0 432 var formattedHost = aHost.charAt(0) == "." ? aHost.substring(1, aHost.length) : aHost;
michael@0 433 return formattedHost.substring(0, 4) == "www." ? formattedHost.substring(4, formattedHost.length) : formattedHost;
michael@0 434 },
michael@0 435
michael@0 436 _addCookie: function (aStrippedHost, aCookie, aHostCount) {
michael@0 437 if (!(aStrippedHost in this._hosts) || !this._hosts[aStrippedHost]) {
michael@0 438 this._hosts[aStrippedHost] = { cookies : [],
michael@0 439 rawHost : aStrippedHost,
michael@0 440 level : 0,
michael@0 441 open : false,
michael@0 442 container : true };
michael@0 443 this._hostOrder.push(aStrippedHost);
michael@0 444 ++aHostCount.value;
michael@0 445 }
michael@0 446
michael@0 447 var c = this._makeCookieObject(aStrippedHost, aCookie);
michael@0 448 this._hosts[aStrippedHost].cookies.push(c);
michael@0 449 },
michael@0 450
michael@0 451 _makeCookieObject: function (aStrippedHost, aCookie) {
michael@0 452 var host = aCookie.host;
michael@0 453 var formattedHost = host.charAt(0) == "." ? host.substring(1, host.length) : host;
michael@0 454 var c = { name : aCookie.name,
michael@0 455 value : aCookie.value,
michael@0 456 isDomain : aCookie.isDomain,
michael@0 457 host : aCookie.host,
michael@0 458 rawHost : aStrippedHost,
michael@0 459 path : aCookie.path,
michael@0 460 isSecure : aCookie.isSecure,
michael@0 461 expires : aCookie.expires,
michael@0 462 level : 1,
michael@0 463 container : false };
michael@0 464 return c;
michael@0 465 },
michael@0 466
michael@0 467 _loadCookies: function () {
michael@0 468 var e = this._cm.enumerator;
michael@0 469 var hostCount = { value: 0 };
michael@0 470 this._hosts = {};
michael@0 471 this._hostOrder = [];
michael@0 472 while (e.hasMoreElements()) {
michael@0 473 var cookie = e.getNext();
michael@0 474 if (cookie && cookie instanceof Components.interfaces.nsICookie) {
michael@0 475 var strippedHost = this._makeStrippedHost(cookie.host);
michael@0 476 this._addCookie(strippedHost, cookie, hostCount);
michael@0 477 }
michael@0 478 else
michael@0 479 break;
michael@0 480 }
michael@0 481 this._view._rowCount = hostCount.value;
michael@0 482 },
michael@0 483
michael@0 484 formatExpiresString: function (aExpires) {
michael@0 485 if (aExpires) {
michael@0 486 var date = new Date(1000 * aExpires);
michael@0 487 return this._ds.FormatDateTime("", this._ds.dateFormatLong,
michael@0 488 this._ds.timeFormatSeconds,
michael@0 489 date.getFullYear(),
michael@0 490 date.getMonth() + 1,
michael@0 491 date.getDate(),
michael@0 492 date.getHours(),
michael@0 493 date.getMinutes(),
michael@0 494 date.getSeconds());
michael@0 495 }
michael@0 496 return this._bundle.getString("expireAtEndOfSession");
michael@0 497 },
michael@0 498
michael@0 499 _updateCookieData: function (aItem) {
michael@0 500 var seln = this._view.selection;
michael@0 501 var ids = ["name", "value", "host", "path", "isSecure", "expires"];
michael@0 502 var properties;
michael@0 503
michael@0 504 if (aItem && !aItem.container && seln.count > 0) {
michael@0 505 properties = { name: aItem.name, value: aItem.value, host: aItem.host,
michael@0 506 path: aItem.path, expires: this.formatExpiresString(aItem.expires),
michael@0 507 isDomain: aItem.isDomain ? this._bundle.getString("domainColon")
michael@0 508 : this._bundle.getString("hostColon"),
michael@0 509 isSecure: aItem.isSecure ? this._bundle.getString("forSecureOnly")
michael@0 510 : this._bundle.getString("forAnyConnection") };
michael@0 511 for (var i = 0; i < ids.length; ++i)
michael@0 512 document.getElementById(ids[i]).disabled = false;
michael@0 513 }
michael@0 514 else {
michael@0 515 var noneSelected = this._bundle.getString("noCookieSelected");
michael@0 516 properties = { name: noneSelected, value: noneSelected, host: noneSelected,
michael@0 517 path: noneSelected, expires: noneSelected,
michael@0 518 isSecure: noneSelected };
michael@0 519 for (i = 0; i < ids.length; ++i)
michael@0 520 document.getElementById(ids[i]).disabled = true;
michael@0 521 }
michael@0 522 for (var property in properties)
michael@0 523 document.getElementById(property).value = properties[property];
michael@0 524 },
michael@0 525
michael@0 526 onCookieSelected: function () {
michael@0 527 var properties, item;
michael@0 528 var seln = this._tree.view.selection;
michael@0 529 if (!this._view._filtered)
michael@0 530 item = this._view._getItemAtIndex(seln.currentIndex);
michael@0 531 else
michael@0 532 item = this._view._filterSet[seln.currentIndex];
michael@0 533
michael@0 534 this._updateCookieData(item);
michael@0 535
michael@0 536 var rangeCount = seln.getRangeCount();
michael@0 537 var selectedCookieCount = 0;
michael@0 538 for (var i = 0; i < rangeCount; ++i) {
michael@0 539 var min = {}; var max = {};
michael@0 540 seln.getRangeAt(i, min, max);
michael@0 541 for (var j = min.value; j <= max.value; ++j) {
michael@0 542 item = this._view._getItemAtIndex(j);
michael@0 543 if (!item) continue;
michael@0 544 if (item.container && !item.open)
michael@0 545 selectedCookieCount += item.cookies.length;
michael@0 546 else if (!item.container)
michael@0 547 ++selectedCookieCount;
michael@0 548 }
michael@0 549 }
michael@0 550 var item = this._view._getItemAtIndex(seln.currentIndex);
michael@0 551 if (item && seln.count == 1 && item.container && item.open)
michael@0 552 selectedCookieCount += 2;
michael@0 553
michael@0 554 var removeCookie = document.getElementById("removeCookie");
michael@0 555 var removeCookies = document.getElementById("removeCookies");
michael@0 556 removeCookie.parentNode.selectedPanel =
michael@0 557 selectedCookieCount == 1 ? removeCookie : removeCookies;
michael@0 558
michael@0 559 removeCookie.disabled = removeCookies.disabled = !(seln.count > 0);
michael@0 560 },
michael@0 561
michael@0 562 performDeletion: function gCookiesWindow_performDeletion(deleteItems) {
michael@0 563 var psvc = Components.classes["@mozilla.org/preferences-service;1"]
michael@0 564 .getService(Components.interfaces.nsIPrefBranch);
michael@0 565 var blockFutureCookies = false;
michael@0 566 if (psvc.prefHasUserValue("network.cookie.blockFutureCookies"))
michael@0 567 blockFutureCookies = psvc.getBoolPref("network.cookie.blockFutureCookies");
michael@0 568 for (var i = 0; i < deleteItems.length; ++i) {
michael@0 569 var item = deleteItems[i];
michael@0 570 this._cm.remove(item.host, item.name, item.path, blockFutureCookies);
michael@0 571 }
michael@0 572 },
michael@0 573
michael@0 574 deleteCookie: function () {
michael@0 575 // Selection Notes
michael@0 576 // - Selection always moves to *NEXT* adjacent item unless item
michael@0 577 // is last child at a given level in which case it moves to *PREVIOUS*
michael@0 578 // item
michael@0 579 //
michael@0 580 // Selection Cases (Somewhat Complicated)
michael@0 581 //
michael@0 582 // 1) Single cookie selected, host has single child
michael@0 583 // v cnn.com
michael@0 584 // //// cnn.com ///////////// goksdjf@ ////
michael@0 585 // > atwola.com
michael@0 586 //
michael@0 587 // Before SelectedIndex: 1 Before RowCount: 3
michael@0 588 // After SelectedIndex: 0 After RowCount: 1
michael@0 589 //
michael@0 590 // 2) Host selected, host open
michael@0 591 // v goats.com ////////////////////////////
michael@0 592 // goats.com sldkkfjl
michael@0 593 // goat.scom flksj133
michael@0 594 // > atwola.com
michael@0 595 //
michael@0 596 // Before SelectedIndex: 0 Before RowCount: 4
michael@0 597 // After SelectedIndex: 0 After RowCount: 1
michael@0 598 //
michael@0 599 // 3) Host selected, host closed
michael@0 600 // > goats.com ////////////////////////////
michael@0 601 // > atwola.com
michael@0 602 //
michael@0 603 // Before SelectedIndex: 0 Before RowCount: 2
michael@0 604 // After SelectedIndex: 0 After RowCount: 1
michael@0 605 //
michael@0 606 // 4) Single cookie selected, host has many children
michael@0 607 // v goats.com
michael@0 608 // goats.com sldkkfjl
michael@0 609 // //// goats.com /////////// flksjl33 ////
michael@0 610 // > atwola.com
michael@0 611 //
michael@0 612 // Before SelectedIndex: 2 Before RowCount: 4
michael@0 613 // After SelectedIndex: 1 After RowCount: 3
michael@0 614 //
michael@0 615 // 5) Single cookie selected, host has many children
michael@0 616 // v goats.com
michael@0 617 // //// goats.com /////////// flksjl33 ////
michael@0 618 // goats.com sldkkfjl
michael@0 619 // > atwola.com
michael@0 620 //
michael@0 621 // Before SelectedIndex: 1 Before RowCount: 4
michael@0 622 // After SelectedIndex: 1 After RowCount: 3
michael@0 623 var seln = this._view.selection;
michael@0 624 var tbo = this._tree.treeBoxObject;
michael@0 625
michael@0 626 if (seln.count < 1) return;
michael@0 627
michael@0 628 var nextSelected = 0;
michael@0 629 var rowCountImpact = 0;
michael@0 630 var deleteItems = [];
michael@0 631 if (!this._view._filtered) {
michael@0 632 var ci = seln.currentIndex;
michael@0 633 nextSelected = ci;
michael@0 634 var invalidateRow = -1;
michael@0 635 var item = this._view._getItemAtIndex(ci);
michael@0 636 if (item.container) {
michael@0 637 rowCountImpact -= (item.open ? item.cookies.length : 0) + 1;
michael@0 638 deleteItems = deleteItems.concat(item.cookies);
michael@0 639 if (!this._view.hasNextSibling(-1, ci))
michael@0 640 --nextSelected;
michael@0 641 this._view._removeItemAtIndex(ci);
michael@0 642 }
michael@0 643 else {
michael@0 644 var parent = this._view._getItemAtIndex(item.parentIndex);
michael@0 645 --rowCountImpact;
michael@0 646 if (parent.cookies.length == 1) {
michael@0 647 --rowCountImpact;
michael@0 648 deleteItems.push(item);
michael@0 649 if (!this._view.hasNextSibling(-1, ci))
michael@0 650 --nextSelected;
michael@0 651 if (!this._view.hasNextSibling(-1, item.parentIndex))
michael@0 652 --nextSelected;
michael@0 653 this._view._removeItemAtIndex(item.parentIndex);
michael@0 654 invalidateRow = item.parentIndex;
michael@0 655 }
michael@0 656 else {
michael@0 657 deleteItems.push(item);
michael@0 658 if (!this._view.hasNextSibling(-1, ci))
michael@0 659 --nextSelected;
michael@0 660 this._view._removeItemAtIndex(ci);
michael@0 661 }
michael@0 662 }
michael@0 663 this._view._rowCount += rowCountImpact;
michael@0 664 tbo.rowCountChanged(ci, rowCountImpact);
michael@0 665 if (invalidateRow != -1)
michael@0 666 tbo.invalidateRow(invalidateRow);
michael@0 667 }
michael@0 668 else {
michael@0 669 var rangeCount = seln.getRangeCount();
michael@0 670 // Traverse backwards through selections to avoid messing
michael@0 671 // up the indices when they are deleted.
michael@0 672 // See bug 388079.
michael@0 673 for (var i = rangeCount - 1; i >= 0; --i) {
michael@0 674 var min = {}; var max = {};
michael@0 675 seln.getRangeAt(i, min, max);
michael@0 676 nextSelected = min.value;
michael@0 677 for (var j = min.value; j <= max.value; ++j) {
michael@0 678 deleteItems.push(this._view._getItemAtIndex(j));
michael@0 679 if (!this._view.hasNextSibling(-1, max.value))
michael@0 680 --nextSelected;
michael@0 681 }
michael@0 682 var delta = max.value - min.value + 1;
michael@0 683 this._view._removeItemAtIndex(min.value, delta);
michael@0 684 rowCountImpact = -1 * delta;
michael@0 685 this._view._rowCount += rowCountImpact;
michael@0 686 tbo.rowCountChanged(min.value, rowCountImpact);
michael@0 687 }
michael@0 688 }
michael@0 689
michael@0 690 this.performDeletion(deleteItems);
michael@0 691
michael@0 692 if (nextSelected < 0)
michael@0 693 seln.clearSelection();
michael@0 694 else {
michael@0 695 seln.select(nextSelected);
michael@0 696 this._tree.focus();
michael@0 697 }
michael@0 698 },
michael@0 699
michael@0 700 deleteAllCookies: function () {
michael@0 701 if (this._view._filtered) {
michael@0 702 var rowCount = this._view.rowCount;
michael@0 703 var deleteItems = [];
michael@0 704 for (var index = 0; index < rowCount; index++) {
michael@0 705 deleteItems.push(this._view._getItemAtIndex(index));
michael@0 706 }
michael@0 707 this._view._removeItemAtIndex(0, rowCount);
michael@0 708 this._view._rowCount = 0;
michael@0 709 this._tree.treeBoxObject.rowCountChanged(0, -rowCount);
michael@0 710 this.performDeletion(deleteItems);
michael@0 711 }
michael@0 712 else {
michael@0 713 this._cm.removeAll();
michael@0 714 }
michael@0 715 this._updateRemoveAllButton();
michael@0 716 this.focusFilterBox();
michael@0 717 },
michael@0 718
michael@0 719 onCookieKeyPress: function (aEvent) {
michael@0 720 if (aEvent.keyCode == 46)
michael@0 721 this.deleteCookie();
michael@0 722 },
michael@0 723
michael@0 724 _lastSortProperty : "",
michael@0 725 _lastSortAscending: false,
michael@0 726 sort: function (aProperty) {
michael@0 727 var ascending = (aProperty == this._lastSortProperty) ? !this._lastSortAscending : true;
michael@0 728 // Sort the Non-Filtered Host Collections
michael@0 729 if (aProperty == "rawHost") {
michael@0 730 function sortByHost(a, b) {
michael@0 731 return a.toLowerCase().localeCompare(b.toLowerCase());
michael@0 732 }
michael@0 733 this._hostOrder.sort(sortByHost);
michael@0 734 if (!ascending)
michael@0 735 this._hostOrder.reverse();
michael@0 736 }
michael@0 737
michael@0 738 function sortByProperty(a, b) {
michael@0 739 return a[aProperty].toLowerCase().localeCompare(b[aProperty].toLowerCase());
michael@0 740 }
michael@0 741 for (var host in this._hosts) {
michael@0 742 var cookies = this._hosts[host].cookies;
michael@0 743 cookies.sort(sortByProperty);
michael@0 744 if (!ascending)
michael@0 745 cookies.reverse();
michael@0 746 }
michael@0 747 // Sort the Filtered List, if in Filtered mode
michael@0 748 if (this._view._filtered) {
michael@0 749 this._view._filterSet.sort(sortByProperty);
michael@0 750 if (!ascending)
michael@0 751 this._view._filterSet.reverse();
michael@0 752 }
michael@0 753
michael@0 754 // Adjust the Sort Indicator
michael@0 755 var domainCol = document.getElementById("domainCol");
michael@0 756 var nameCol = document.getElementById("nameCol");
michael@0 757 var sortOrderString = ascending ? "ascending" : "descending";
michael@0 758 if (aProperty == "rawHost") {
michael@0 759 domainCol.setAttribute("sortDirection", sortOrderString);
michael@0 760 nameCol.removeAttribute("sortDirection");
michael@0 761 }
michael@0 762 else {
michael@0 763 nameCol.setAttribute("sortDirection", sortOrderString);
michael@0 764 domainCol.removeAttribute("sortDirection");
michael@0 765 }
michael@0 766
michael@0 767 this._view._invalidateCache(0);
michael@0 768 this._view.selection.clearSelection();
michael@0 769 this._view.selection.select(0);
michael@0 770 this._tree.treeBoxObject.invalidate();
michael@0 771 this._tree.treeBoxObject.ensureRowIsVisible(0);
michael@0 772
michael@0 773 this._lastSortAscending = ascending;
michael@0 774 this._lastSortProperty = aProperty;
michael@0 775 },
michael@0 776
michael@0 777 clearFilter: function () {
michael@0 778 // Revert to single-select in the tree
michael@0 779 this._tree.setAttribute("seltype", "single");
michael@0 780
michael@0 781 // Clear the Tree Display
michael@0 782 this._view._filtered = false;
michael@0 783 this._view._rowCount = 0;
michael@0 784 this._tree.treeBoxObject.rowCountChanged(0, -this._view._filterSet.length);
michael@0 785 this._view._filterSet = [];
michael@0 786
michael@0 787 // Just reload the list to make sure deletions are respected
michael@0 788 this._loadCookies();
michael@0 789 this._tree.treeBoxObject.view = this._view;
michael@0 790
michael@0 791 // Restore sort order
michael@0 792 var sortby = this._lastSortProperty;
michael@0 793 if (sortby == "") {
michael@0 794 this._lastSortAscending = false;
michael@0 795 this.sort("rawHost");
michael@0 796 }
michael@0 797 else {
michael@0 798 this._lastSortAscending = !this._lastSortAscending;
michael@0 799 this.sort(sortby);
michael@0 800 }
michael@0 801
michael@0 802 // Restore open state
michael@0 803 for (var i = 0; i < this._openIndices.length; ++i)
michael@0 804 this._view.toggleOpenState(this._openIndices[i]);
michael@0 805 this._openIndices = [];
michael@0 806
michael@0 807 // Restore selection
michael@0 808 this._view.selection.clearSelection();
michael@0 809 for (i = 0; i < this._lastSelectedRanges.length; ++i) {
michael@0 810 var range = this._lastSelectedRanges[i];
michael@0 811 this._view.selection.rangedSelect(range.min, range.max, true);
michael@0 812 }
michael@0 813 this._lastSelectedRanges = [];
michael@0 814
michael@0 815 document.getElementById("cookiesIntro").value = this._bundle.getString("cookiesAll");
michael@0 816 this._updateRemoveAllButton();
michael@0 817 },
michael@0 818
michael@0 819 _cookieMatchesFilter: function (aCookie) {
michael@0 820 return aCookie.rawHost.indexOf(this._view._filterValue) != -1 ||
michael@0 821 aCookie.name.indexOf(this._view._filterValue) != -1 ||
michael@0 822 aCookie.value.indexOf(this._view._filterValue) != -1;
michael@0 823 },
michael@0 824
michael@0 825 _filterCookies: function (aFilterValue) {
michael@0 826 this._view._filterValue = aFilterValue;
michael@0 827 var cookies = [];
michael@0 828 for (var i = 0; i < gCookiesWindow._hostOrder.length; ++i) { //var host in gCookiesWindow._hosts) {
michael@0 829 var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host];
michael@0 830 if (!currHost) continue;
michael@0 831 for (var j = 0; j < currHost.cookies.length; ++j) {
michael@0 832 var cookie = currHost.cookies[j];
michael@0 833 if (this._cookieMatchesFilter(cookie))
michael@0 834 cookies.push(cookie);
michael@0 835 }
michael@0 836 }
michael@0 837 return cookies;
michael@0 838 },
michael@0 839
michael@0 840 _lastSelectedRanges: [],
michael@0 841 _openIndices: [],
michael@0 842 _saveState: function () {
michael@0 843 // Save selection
michael@0 844 var seln = this._view.selection;
michael@0 845 this._lastSelectedRanges = [];
michael@0 846 var rangeCount = seln.getRangeCount();
michael@0 847 for (var i = 0; i < rangeCount; ++i) {
michael@0 848 var min = {}; var max = {};
michael@0 849 seln.getRangeAt(i, min, max);
michael@0 850 this._lastSelectedRanges.push({ min: min.value, max: max.value });
michael@0 851 }
michael@0 852
michael@0 853 // Save open states
michael@0 854 this._openIndices = [];
michael@0 855 for (i = 0; i < this._view.rowCount; ++i) {
michael@0 856 var item = this._view._getItemAtIndex(i);
michael@0 857 if (item && item.container && item.open)
michael@0 858 this._openIndices.push(i);
michael@0 859 }
michael@0 860 },
michael@0 861
michael@0 862 _updateRemoveAllButton: function gCookiesWindow__updateRemoveAllButton() {
michael@0 863 document.getElementById("removeAllCookies").disabled = this._view._rowCount == 0;
michael@0 864 },
michael@0 865
michael@0 866 filter: function () {
michael@0 867 var filter = document.getElementById("filter").value;
michael@0 868 if (filter == "") {
michael@0 869 gCookiesWindow.clearFilter();
michael@0 870 return;
michael@0 871 }
michael@0 872 var view = gCookiesWindow._view;
michael@0 873 view._filterSet = gCookiesWindow._filterCookies(filter);
michael@0 874 if (!view._filtered) {
michael@0 875 // Save Display Info for the Non-Filtered mode when we first
michael@0 876 // enter Filtered mode.
michael@0 877 gCookiesWindow._saveState();
michael@0 878 view._filtered = true;
michael@0 879 }
michael@0 880 // Move to multi-select in the tree
michael@0 881 gCookiesWindow._tree.setAttribute("seltype", "multiple");
michael@0 882
michael@0 883 // Clear the display
michael@0 884 var oldCount = view._rowCount;
michael@0 885 view._rowCount = 0;
michael@0 886 gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, -oldCount);
michael@0 887 // Set up the filtered display
michael@0 888 view._rowCount = view._filterSet.length;
michael@0 889 gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, view.rowCount);
michael@0 890
michael@0 891 // if the view is not empty then select the first item
michael@0 892 if (view.rowCount > 0)
michael@0 893 view.selection.select(0);
michael@0 894
michael@0 895 document.getElementById("cookiesIntro").value = gCookiesWindow._bundle.getString("cookiesFiltered");
michael@0 896 this._updateRemoveAllButton();
michael@0 897 },
michael@0 898
michael@0 899 setFilter: function (aFilterString) {
michael@0 900 document.getElementById("filter").value = aFilterString;
michael@0 901 this.filter();
michael@0 902 },
michael@0 903
michael@0 904 focusFilterBox: function () {
michael@0 905 var filter = document.getElementById("filter");
michael@0 906 filter.focus();
michael@0 907 filter.select();
michael@0 908 },
michael@0 909
michael@0 910 onWindowKeyPress: function (aEvent) {
michael@0 911 if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE)
michael@0 912 window.close();
michael@0 913 }
michael@0 914 };

mercurial