1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/preferences/cookies.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,914 @@ 1.4 +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +const nsICookie = Components.interfaces.nsICookie; 1.10 + 1.11 +var gCookiesWindow = { 1.12 + _cm : Components.classes["@mozilla.org/cookiemanager;1"] 1.13 + .getService(Components.interfaces.nsICookieManager), 1.14 + _ds : Components.classes["@mozilla.org/intl/scriptabledateformat;1"] 1.15 + .getService(Components.interfaces.nsIScriptableDateFormat), 1.16 + _hosts : {}, 1.17 + _hostOrder : [], 1.18 + _tree : null, 1.19 + _bundle : null, 1.20 + 1.21 + init: function () { 1.22 + var os = Components.classes["@mozilla.org/observer-service;1"] 1.23 + .getService(Components.interfaces.nsIObserverService); 1.24 + os.addObserver(this, "cookie-changed", false); 1.25 + os.addObserver(this, "perm-changed", false); 1.26 + 1.27 + this._bundle = document.getElementById("bundlePreferences"); 1.28 + this._tree = document.getElementById("cookiesList"); 1.29 + 1.30 + this._populateList(true); 1.31 + 1.32 + document.getElementById("filter").focus(); 1.33 + }, 1.34 + 1.35 + uninit: function () { 1.36 + var os = Components.classes["@mozilla.org/observer-service;1"] 1.37 + .getService(Components.interfaces.nsIObserverService); 1.38 + os.removeObserver(this, "cookie-changed"); 1.39 + os.removeObserver(this, "perm-changed"); 1.40 + }, 1.41 + 1.42 + _populateList: function (aInitialLoad) { 1.43 + this._loadCookies(); 1.44 + this._tree.treeBoxObject.view = this._view; 1.45 + if (aInitialLoad) 1.46 + this.sort("rawHost"); 1.47 + if (this._view.rowCount > 0) 1.48 + this._tree.view.selection.select(0); 1.49 + 1.50 + if (aInitialLoad) { 1.51 + if ("arguments" in window && 1.52 + window.arguments[0] && 1.53 + window.arguments[0].filterString) 1.54 + this.setFilter(window.arguments[0].filterString); 1.55 + } 1.56 + else { 1.57 + if (document.getElementById("filter").value != "") 1.58 + this.filter(); 1.59 + } 1.60 + 1.61 + this._updateRemoveAllButton(); 1.62 + 1.63 + this._saveState(); 1.64 + }, 1.65 + 1.66 + _cookieEquals: function (aCookieA, aCookieB, aStrippedHost) { 1.67 + return aCookieA.rawHost == aStrippedHost && 1.68 + aCookieA.name == aCookieB.name && 1.69 + aCookieA.path == aCookieB.path; 1.70 + }, 1.71 + 1.72 + observe: function (aCookie, aTopic, aData) { 1.73 + if (aTopic != "cookie-changed") 1.74 + return; 1.75 + 1.76 + if (aCookie instanceof Components.interfaces.nsICookie) { 1.77 + var strippedHost = this._makeStrippedHost(aCookie.host); 1.78 + if (aData == "changed") 1.79 + this._handleCookieChanged(aCookie, strippedHost); 1.80 + else if (aData == "added") 1.81 + this._handleCookieAdded(aCookie, strippedHost); 1.82 + } 1.83 + else if (aData == "cleared") { 1.84 + this._hosts = {}; 1.85 + this._hostOrder = []; 1.86 + 1.87 + var oldRowCount = this._view._rowCount; 1.88 + this._view._rowCount = 0; 1.89 + this._tree.treeBoxObject.rowCountChanged(0, -oldRowCount); 1.90 + this._view.selection.clearSelection(); 1.91 + this._updateRemoveAllButton(); 1.92 + } 1.93 + else if (aData == "reload") { 1.94 + // first, clear any existing entries 1.95 + this.observe(aCookie, aTopic, "cleared"); 1.96 + 1.97 + // then, reload the list 1.98 + this._populateList(false); 1.99 + } 1.100 + 1.101 + // We don't yet handle aData == "deleted" - it's a less common case 1.102 + // and is rather complicated as selection tracking is difficult 1.103 + }, 1.104 + 1.105 + _handleCookieChanged: function (changedCookie, strippedHost) { 1.106 + var rowIndex = 0; 1.107 + var cookieItem = null; 1.108 + if (!this._view._filtered) { 1.109 + for (var i = 0; i < this._hostOrder.length; ++i) { // (var host in this._hosts) { 1.110 + ++rowIndex; 1.111 + var hostItem = this._hosts[this._hostOrder[i]]; // var hostItem = this._hosts[host]; 1.112 + if (this._hostOrder[i] == strippedHost) { // host == strippedHost) { 1.113 + // Host matches, look for the cookie within this Host collection 1.114 + // and update its data 1.115 + for (var j = 0; j < hostItem.cookies.length; ++j) { 1.116 + ++rowIndex; 1.117 + var currCookie = hostItem.cookies[j]; 1.118 + if (this._cookieEquals(currCookie, changedCookie, strippedHost)) { 1.119 + currCookie.value = changedCookie.value; 1.120 + currCookie.isSecure = changedCookie.isSecure; 1.121 + currCookie.isDomain = changedCookie.isDomain; 1.122 + currCookie.expires = changedCookie.expires; 1.123 + cookieItem = currCookie; 1.124 + break; 1.125 + } 1.126 + } 1.127 + } 1.128 + else if (hostItem.open) 1.129 + rowIndex += hostItem.cookies.length; 1.130 + } 1.131 + } 1.132 + else { 1.133 + // Just walk the filter list to find the item. It doesn't matter that 1.134 + // we don't update the main Host collection when we do this, because 1.135 + // when the filter is reset the Host collection is rebuilt anyway. 1.136 + for (rowIndex = 0; rowIndex < this._view._filterSet.length; ++rowIndex) { 1.137 + currCookie = this._view._filterSet[rowIndex]; 1.138 + if (this._cookieEquals(currCookie, changedCookie, strippedHost)) { 1.139 + currCookie.value = changedCookie.value; 1.140 + currCookie.isSecure = changedCookie.isSecure; 1.141 + currCookie.isDomain = changedCookie.isDomain; 1.142 + currCookie.expires = changedCookie.expires; 1.143 + cookieItem = currCookie; 1.144 + break; 1.145 + } 1.146 + } 1.147 + } 1.148 + 1.149 + // Make sure the tree display is up to date... 1.150 + this._tree.treeBoxObject.invalidateRow(rowIndex); 1.151 + // ... and if the cookie is selected, update the displayed metadata too 1.152 + if (cookieItem != null && this._view.selection.currentIndex == rowIndex) 1.153 + this._updateCookieData(cookieItem); 1.154 + }, 1.155 + 1.156 + _handleCookieAdded: function (changedCookie, strippedHost) { 1.157 + var rowCountImpact = 0; 1.158 + var addedHost = { value: 0 }; 1.159 + this._addCookie(strippedHost, changedCookie, addedHost); 1.160 + if (!this._view._filtered) { 1.161 + // The Host collection for this cookie already exists, and it's not open, 1.162 + // so don't increment the rowCountImpact becaues the user is not going to 1.163 + // see the additional rows as they're hidden. 1.164 + if (addedHost.value || this._hosts[strippedHost].open) 1.165 + ++rowCountImpact; 1.166 + } 1.167 + else { 1.168 + // We're in search mode, and the cookie being added matches 1.169 + // the search condition, so add it to the list. 1.170 + var c = this._makeCookieObject(strippedHost, changedCookie); 1.171 + if (this._cookieMatchesFilter(c)) { 1.172 + this._view._filterSet.push(this._makeCookieObject(strippedHost, changedCookie)); 1.173 + ++rowCountImpact; 1.174 + } 1.175 + } 1.176 + // Now update the tree display at the end (we could/should re run the sort 1.177 + // if any to get the position correct.) 1.178 + var oldRowCount = this._rowCount; 1.179 + this._view._rowCount += rowCountImpact; 1.180 + this._tree.treeBoxObject.rowCountChanged(oldRowCount - 1, rowCountImpact); 1.181 + 1.182 + this._updateRemoveAllButton(); 1.183 + }, 1.184 + 1.185 + _view: { 1.186 + _filtered : false, 1.187 + _filterSet : [], 1.188 + _filterValue: "", 1.189 + _rowCount : 0, 1.190 + _cacheValid : 0, 1.191 + _cacheItems : [], 1.192 + get rowCount() { 1.193 + return this._rowCount; 1.194 + }, 1.195 + 1.196 + _getItemAtIndex: function (aIndex) { 1.197 + if (this._filtered) 1.198 + return this._filterSet[aIndex]; 1.199 + 1.200 + var start = 0; 1.201 + var count = 0, hostIndex = 0; 1.202 + 1.203 + var cacheIndex = Math.min(this._cacheValid, aIndex); 1.204 + if (cacheIndex > 0) { 1.205 + var cacheItem = this._cacheItems[cacheIndex]; 1.206 + start = cacheItem['start']; 1.207 + count = hostIndex = cacheItem['count']; 1.208 + } 1.209 + 1.210 + for (var i = start; i < gCookiesWindow._hostOrder.length; ++i) { // var host in gCookiesWindow._hosts) { 1.211 + var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host]; 1.212 + if (!currHost) continue; 1.213 + if (count == aIndex) 1.214 + return currHost; 1.215 + hostIndex = count; 1.216 + 1.217 + var cacheEntry = { 'start' : i, 'count' : count }; 1.218 + var cacheStart = count; 1.219 + 1.220 + if (currHost.open) { 1.221 + if (count < aIndex && aIndex <= (count + currHost.cookies.length)) { 1.222 + // We are looking for an entry within this host's children, 1.223 + // enumerate them looking for the index. 1.224 + ++count; 1.225 + for (var i = 0; i < currHost.cookies.length; ++i) { 1.226 + if (count == aIndex) { 1.227 + var cookie = currHost.cookies[i]; 1.228 + cookie.parentIndex = hostIndex; 1.229 + return cookie; 1.230 + } 1.231 + ++count; 1.232 + } 1.233 + } 1.234 + else { 1.235 + // A host entry was open, but we weren't looking for an index 1.236 + // within that host entry's children, so skip forward over the 1.237 + // entry's children. We need to add one to increment for the 1.238 + // host value too. 1.239 + count += currHost.cookies.length + 1; 1.240 + } 1.241 + } 1.242 + else 1.243 + ++count; 1.244 + 1.245 + for (var j = cacheStart; j < count; j++) 1.246 + this._cacheItems[j] = cacheEntry; 1.247 + this._cacheValid = count - 1; 1.248 + } 1.249 + return null; 1.250 + }, 1.251 + 1.252 + _removeItemAtIndex: function (aIndex, aCount) { 1.253 + var removeCount = aCount === undefined ? 1 : aCount; 1.254 + if (this._filtered) { 1.255 + // remove the cookies from the unfiltered set so that they 1.256 + // don't reappear when the filter is changed. See bug 410863. 1.257 + for (var i = aIndex; i < aIndex + removeCount; ++i) { 1.258 + var item = this._filterSet[i]; 1.259 + var parent = gCookiesWindow._hosts[item.rawHost]; 1.260 + for (var j = 0; j < parent.cookies.length; ++j) { 1.261 + if (item == parent.cookies[j]) { 1.262 + parent.cookies.splice(j, 1); 1.263 + break; 1.264 + } 1.265 + } 1.266 + } 1.267 + this._filterSet.splice(aIndex, removeCount); 1.268 + return; 1.269 + } 1.270 + 1.271 + var item = this._getItemAtIndex(aIndex); 1.272 + if (!item) return; 1.273 + this._invalidateCache(aIndex - 1); 1.274 + if (item.container) 1.275 + gCookiesWindow._hosts[item.rawHost] = null; 1.276 + else { 1.277 + var parent = this._getItemAtIndex(item.parentIndex); 1.278 + for (var i = 0; i < parent.cookies.length; ++i) { 1.279 + var cookie = parent.cookies[i]; 1.280 + if (item.rawHost == cookie.rawHost && 1.281 + item.name == cookie.name && item.path == cookie.path) 1.282 + parent.cookies.splice(i, removeCount); 1.283 + } 1.284 + } 1.285 + }, 1.286 + 1.287 + _invalidateCache: function (aIndex) { 1.288 + this._cacheValid = Math.min(this._cacheValid, aIndex); 1.289 + }, 1.290 + 1.291 + getCellText: function (aIndex, aColumn) { 1.292 + if (!this._filtered) { 1.293 + var item = this._getItemAtIndex(aIndex); 1.294 + if (!item) 1.295 + return ""; 1.296 + if (aColumn.id == "domainCol") 1.297 + return item.rawHost; 1.298 + else if (aColumn.id == "nameCol") 1.299 + return item.name; 1.300 + } 1.301 + else { 1.302 + if (aColumn.id == "domainCol") 1.303 + return this._filterSet[aIndex].rawHost; 1.304 + else if (aColumn.id == "nameCol") 1.305 + return this._filterSet[aIndex].name; 1.306 + } 1.307 + return ""; 1.308 + }, 1.309 + 1.310 + _selection: null, 1.311 + get selection () { return this._selection; }, 1.312 + set selection (val) { this._selection = val; return val; }, 1.313 + getRowProperties: function (aIndex) { return ""; }, 1.314 + getCellProperties: function (aIndex, aColumn) { return ""; }, 1.315 + getColumnProperties: function (aColumn) { return ""; }, 1.316 + isContainer: function (aIndex) { 1.317 + if (!this._filtered) { 1.318 + var item = this._getItemAtIndex(aIndex); 1.319 + if (!item) return false; 1.320 + return item.container; 1.321 + } 1.322 + return false; 1.323 + }, 1.324 + isContainerOpen: function (aIndex) { 1.325 + if (!this._filtered) { 1.326 + var item = this._getItemAtIndex(aIndex); 1.327 + if (!item) return false; 1.328 + return item.open; 1.329 + } 1.330 + return false; 1.331 + }, 1.332 + isContainerEmpty: function (aIndex) { 1.333 + if (!this._filtered) { 1.334 + var item = this._getItemAtIndex(aIndex); 1.335 + if (!item) return false; 1.336 + return item.cookies.length == 0; 1.337 + } 1.338 + return false; 1.339 + }, 1.340 + isSeparator: function (aIndex) { return false; }, 1.341 + isSorted: function (aIndex) { return false; }, 1.342 + canDrop: function (aIndex, aOrientation) { return false; }, 1.343 + drop: function (aIndex, aOrientation) {}, 1.344 + getParentIndex: function (aIndex) { 1.345 + if (!this._filtered) { 1.346 + var item = this._getItemAtIndex(aIndex); 1.347 + // If an item has no parent index (i.e. it is at the top level) this 1.348 + // function MUST return -1 otherwise we will go into an infinite loop. 1.349 + // Containers are always top level items in the cookies tree, so make 1.350 + // sure to return the appropriate value here. 1.351 + if (!item || item.container) return -1; 1.352 + return item.parentIndex; 1.353 + } 1.354 + return -1; 1.355 + }, 1.356 + hasNextSibling: function (aParentIndex, aIndex) { 1.357 + if (!this._filtered) { 1.358 + // |aParentIndex| appears to be bogus, but we can get the real 1.359 + // parent index by getting the entry for |aIndex| and reading the 1.360 + // parentIndex field. 1.361 + // The index of the last item in this host collection is the 1.362 + // index of the parent + the size of the host collection, and 1.363 + // aIndex has a next sibling if it is less than this value. 1.364 + var item = this._getItemAtIndex(aIndex); 1.365 + if (item) { 1.366 + if (item.container) { 1.367 + for (var i = aIndex + 1; i < this.rowCount; ++i) { 1.368 + var subsequent = this._getItemAtIndex(i); 1.369 + if (subsequent.container) 1.370 + return true; 1.371 + } 1.372 + return false; 1.373 + } 1.374 + else { 1.375 + var parent = this._getItemAtIndex(item.parentIndex); 1.376 + if (parent && parent.container) 1.377 + return aIndex < item.parentIndex + parent.cookies.length; 1.378 + } 1.379 + } 1.380 + } 1.381 + return aIndex < this.rowCount - 1; 1.382 + }, 1.383 + hasPreviousSibling: function (aIndex) { 1.384 + if (!this._filtered) { 1.385 + var item = this._getItemAtIndex(aIndex); 1.386 + if (!item) return false; 1.387 + var parent = this._getItemAtIndex(item.parentIndex); 1.388 + if (parent && parent.container) 1.389 + return aIndex > item.parentIndex + 1; 1.390 + } 1.391 + return aIndex > 0; 1.392 + }, 1.393 + getLevel: function (aIndex) { 1.394 + if (!this._filtered) { 1.395 + var item = this._getItemAtIndex(aIndex); 1.396 + if (!item) return 0; 1.397 + return item.level; 1.398 + } 1.399 + return 0; 1.400 + }, 1.401 + getImageSrc: function (aIndex, aColumn) {}, 1.402 + getProgressMode: function (aIndex, aColumn) {}, 1.403 + getCellValue: function (aIndex, aColumn) {}, 1.404 + setTree: function (aTree) {}, 1.405 + toggleOpenState: function (aIndex) { 1.406 + if (!this._filtered) { 1.407 + var item = this._getItemAtIndex(aIndex); 1.408 + if (!item) return; 1.409 + this._invalidateCache(aIndex); 1.410 + var multiplier = item.open ? -1 : 1; 1.411 + var delta = multiplier * item.cookies.length; 1.412 + this._rowCount += delta; 1.413 + item.open = !item.open; 1.414 + gCookiesWindow._tree.treeBoxObject.rowCountChanged(aIndex + 1, delta); 1.415 + gCookiesWindow._tree.treeBoxObject.invalidateRow(aIndex); 1.416 + } 1.417 + }, 1.418 + cycleHeader: function (aColumn) {}, 1.419 + selectionChanged: function () {}, 1.420 + cycleCell: function (aIndex, aColumn) {}, 1.421 + isEditable: function (aIndex, aColumn) { 1.422 + return false; 1.423 + }, 1.424 + isSelectable: function (aIndex, aColumn) { 1.425 + return false; 1.426 + }, 1.427 + setCellValue: function (aIndex, aColumn, aValue) {}, 1.428 + setCellText: function (aIndex, aColumn, aValue) {}, 1.429 + performAction: function (aAction) {}, 1.430 + performActionOnRow: function (aAction, aIndex) {}, 1.431 + performActionOnCell: function (aAction, aindex, aColumn) {} 1.432 + }, 1.433 + 1.434 + _makeStrippedHost: function (aHost) { 1.435 + var formattedHost = aHost.charAt(0) == "." ? aHost.substring(1, aHost.length) : aHost; 1.436 + return formattedHost.substring(0, 4) == "www." ? formattedHost.substring(4, formattedHost.length) : formattedHost; 1.437 + }, 1.438 + 1.439 + _addCookie: function (aStrippedHost, aCookie, aHostCount) { 1.440 + if (!(aStrippedHost in this._hosts) || !this._hosts[aStrippedHost]) { 1.441 + this._hosts[aStrippedHost] = { cookies : [], 1.442 + rawHost : aStrippedHost, 1.443 + level : 0, 1.444 + open : false, 1.445 + container : true }; 1.446 + this._hostOrder.push(aStrippedHost); 1.447 + ++aHostCount.value; 1.448 + } 1.449 + 1.450 + var c = this._makeCookieObject(aStrippedHost, aCookie); 1.451 + this._hosts[aStrippedHost].cookies.push(c); 1.452 + }, 1.453 + 1.454 + _makeCookieObject: function (aStrippedHost, aCookie) { 1.455 + var host = aCookie.host; 1.456 + var formattedHost = host.charAt(0) == "." ? host.substring(1, host.length) : host; 1.457 + var c = { name : aCookie.name, 1.458 + value : aCookie.value, 1.459 + isDomain : aCookie.isDomain, 1.460 + host : aCookie.host, 1.461 + rawHost : aStrippedHost, 1.462 + path : aCookie.path, 1.463 + isSecure : aCookie.isSecure, 1.464 + expires : aCookie.expires, 1.465 + level : 1, 1.466 + container : false }; 1.467 + return c; 1.468 + }, 1.469 + 1.470 + _loadCookies: function () { 1.471 + var e = this._cm.enumerator; 1.472 + var hostCount = { value: 0 }; 1.473 + this._hosts = {}; 1.474 + this._hostOrder = []; 1.475 + while (e.hasMoreElements()) { 1.476 + var cookie = e.getNext(); 1.477 + if (cookie && cookie instanceof Components.interfaces.nsICookie) { 1.478 + var strippedHost = this._makeStrippedHost(cookie.host); 1.479 + this._addCookie(strippedHost, cookie, hostCount); 1.480 + } 1.481 + else 1.482 + break; 1.483 + } 1.484 + this._view._rowCount = hostCount.value; 1.485 + }, 1.486 + 1.487 + formatExpiresString: function (aExpires) { 1.488 + if (aExpires) { 1.489 + var date = new Date(1000 * aExpires); 1.490 + return this._ds.FormatDateTime("", this._ds.dateFormatLong, 1.491 + this._ds.timeFormatSeconds, 1.492 + date.getFullYear(), 1.493 + date.getMonth() + 1, 1.494 + date.getDate(), 1.495 + date.getHours(), 1.496 + date.getMinutes(), 1.497 + date.getSeconds()); 1.498 + } 1.499 + return this._bundle.getString("expireAtEndOfSession"); 1.500 + }, 1.501 + 1.502 + _updateCookieData: function (aItem) { 1.503 + var seln = this._view.selection; 1.504 + var ids = ["name", "value", "host", "path", "isSecure", "expires"]; 1.505 + var properties; 1.506 + 1.507 + if (aItem && !aItem.container && seln.count > 0) { 1.508 + properties = { name: aItem.name, value: aItem.value, host: aItem.host, 1.509 + path: aItem.path, expires: this.formatExpiresString(aItem.expires), 1.510 + isDomain: aItem.isDomain ? this._bundle.getString("domainColon") 1.511 + : this._bundle.getString("hostColon"), 1.512 + isSecure: aItem.isSecure ? this._bundle.getString("forSecureOnly") 1.513 + : this._bundle.getString("forAnyConnection") }; 1.514 + for (var i = 0; i < ids.length; ++i) 1.515 + document.getElementById(ids[i]).disabled = false; 1.516 + } 1.517 + else { 1.518 + var noneSelected = this._bundle.getString("noCookieSelected"); 1.519 + properties = { name: noneSelected, value: noneSelected, host: noneSelected, 1.520 + path: noneSelected, expires: noneSelected, 1.521 + isSecure: noneSelected }; 1.522 + for (i = 0; i < ids.length; ++i) 1.523 + document.getElementById(ids[i]).disabled = true; 1.524 + } 1.525 + for (var property in properties) 1.526 + document.getElementById(property).value = properties[property]; 1.527 + }, 1.528 + 1.529 + onCookieSelected: function () { 1.530 + var properties, item; 1.531 + var seln = this._tree.view.selection; 1.532 + if (!this._view._filtered) 1.533 + item = this._view._getItemAtIndex(seln.currentIndex); 1.534 + else 1.535 + item = this._view._filterSet[seln.currentIndex]; 1.536 + 1.537 + this._updateCookieData(item); 1.538 + 1.539 + var rangeCount = seln.getRangeCount(); 1.540 + var selectedCookieCount = 0; 1.541 + for (var i = 0; i < rangeCount; ++i) { 1.542 + var min = {}; var max = {}; 1.543 + seln.getRangeAt(i, min, max); 1.544 + for (var j = min.value; j <= max.value; ++j) { 1.545 + item = this._view._getItemAtIndex(j); 1.546 + if (!item) continue; 1.547 + if (item.container && !item.open) 1.548 + selectedCookieCount += item.cookies.length; 1.549 + else if (!item.container) 1.550 + ++selectedCookieCount; 1.551 + } 1.552 + } 1.553 + var item = this._view._getItemAtIndex(seln.currentIndex); 1.554 + if (item && seln.count == 1 && item.container && item.open) 1.555 + selectedCookieCount += 2; 1.556 + 1.557 + var removeCookie = document.getElementById("removeCookie"); 1.558 + var removeCookies = document.getElementById("removeCookies"); 1.559 + removeCookie.parentNode.selectedPanel = 1.560 + selectedCookieCount == 1 ? removeCookie : removeCookies; 1.561 + 1.562 + removeCookie.disabled = removeCookies.disabled = !(seln.count > 0); 1.563 + }, 1.564 + 1.565 + performDeletion: function gCookiesWindow_performDeletion(deleteItems) { 1.566 + var psvc = Components.classes["@mozilla.org/preferences-service;1"] 1.567 + .getService(Components.interfaces.nsIPrefBranch); 1.568 + var blockFutureCookies = false; 1.569 + if (psvc.prefHasUserValue("network.cookie.blockFutureCookies")) 1.570 + blockFutureCookies = psvc.getBoolPref("network.cookie.blockFutureCookies"); 1.571 + for (var i = 0; i < deleteItems.length; ++i) { 1.572 + var item = deleteItems[i]; 1.573 + this._cm.remove(item.host, item.name, item.path, blockFutureCookies); 1.574 + } 1.575 + }, 1.576 + 1.577 + deleteCookie: function () { 1.578 + // Selection Notes 1.579 + // - Selection always moves to *NEXT* adjacent item unless item 1.580 + // is last child at a given level in which case it moves to *PREVIOUS* 1.581 + // item 1.582 + // 1.583 + // Selection Cases (Somewhat Complicated) 1.584 + // 1.585 + // 1) Single cookie selected, host has single child 1.586 + // v cnn.com 1.587 + // //// cnn.com ///////////// goksdjf@ //// 1.588 + // > atwola.com 1.589 + // 1.590 + // Before SelectedIndex: 1 Before RowCount: 3 1.591 + // After SelectedIndex: 0 After RowCount: 1 1.592 + // 1.593 + // 2) Host selected, host open 1.594 + // v goats.com //////////////////////////// 1.595 + // goats.com sldkkfjl 1.596 + // goat.scom flksj133 1.597 + // > atwola.com 1.598 + // 1.599 + // Before SelectedIndex: 0 Before RowCount: 4 1.600 + // After SelectedIndex: 0 After RowCount: 1 1.601 + // 1.602 + // 3) Host selected, host closed 1.603 + // > goats.com //////////////////////////// 1.604 + // > atwola.com 1.605 + // 1.606 + // Before SelectedIndex: 0 Before RowCount: 2 1.607 + // After SelectedIndex: 0 After RowCount: 1 1.608 + // 1.609 + // 4) Single cookie selected, host has many children 1.610 + // v goats.com 1.611 + // goats.com sldkkfjl 1.612 + // //// goats.com /////////// flksjl33 //// 1.613 + // > atwola.com 1.614 + // 1.615 + // Before SelectedIndex: 2 Before RowCount: 4 1.616 + // After SelectedIndex: 1 After RowCount: 3 1.617 + // 1.618 + // 5) Single cookie selected, host has many children 1.619 + // v goats.com 1.620 + // //// goats.com /////////// flksjl33 //// 1.621 + // goats.com sldkkfjl 1.622 + // > atwola.com 1.623 + // 1.624 + // Before SelectedIndex: 1 Before RowCount: 4 1.625 + // After SelectedIndex: 1 After RowCount: 3 1.626 + var seln = this._view.selection; 1.627 + var tbo = this._tree.treeBoxObject; 1.628 + 1.629 + if (seln.count < 1) return; 1.630 + 1.631 + var nextSelected = 0; 1.632 + var rowCountImpact = 0; 1.633 + var deleteItems = []; 1.634 + if (!this._view._filtered) { 1.635 + var ci = seln.currentIndex; 1.636 + nextSelected = ci; 1.637 + var invalidateRow = -1; 1.638 + var item = this._view._getItemAtIndex(ci); 1.639 + if (item.container) { 1.640 + rowCountImpact -= (item.open ? item.cookies.length : 0) + 1; 1.641 + deleteItems = deleteItems.concat(item.cookies); 1.642 + if (!this._view.hasNextSibling(-1, ci)) 1.643 + --nextSelected; 1.644 + this._view._removeItemAtIndex(ci); 1.645 + } 1.646 + else { 1.647 + var parent = this._view._getItemAtIndex(item.parentIndex); 1.648 + --rowCountImpact; 1.649 + if (parent.cookies.length == 1) { 1.650 + --rowCountImpact; 1.651 + deleteItems.push(item); 1.652 + if (!this._view.hasNextSibling(-1, ci)) 1.653 + --nextSelected; 1.654 + if (!this._view.hasNextSibling(-1, item.parentIndex)) 1.655 + --nextSelected; 1.656 + this._view._removeItemAtIndex(item.parentIndex); 1.657 + invalidateRow = item.parentIndex; 1.658 + } 1.659 + else { 1.660 + deleteItems.push(item); 1.661 + if (!this._view.hasNextSibling(-1, ci)) 1.662 + --nextSelected; 1.663 + this._view._removeItemAtIndex(ci); 1.664 + } 1.665 + } 1.666 + this._view._rowCount += rowCountImpact; 1.667 + tbo.rowCountChanged(ci, rowCountImpact); 1.668 + if (invalidateRow != -1) 1.669 + tbo.invalidateRow(invalidateRow); 1.670 + } 1.671 + else { 1.672 + var rangeCount = seln.getRangeCount(); 1.673 + // Traverse backwards through selections to avoid messing 1.674 + // up the indices when they are deleted. 1.675 + // See bug 388079. 1.676 + for (var i = rangeCount - 1; i >= 0; --i) { 1.677 + var min = {}; var max = {}; 1.678 + seln.getRangeAt(i, min, max); 1.679 + nextSelected = min.value; 1.680 + for (var j = min.value; j <= max.value; ++j) { 1.681 + deleteItems.push(this._view._getItemAtIndex(j)); 1.682 + if (!this._view.hasNextSibling(-1, max.value)) 1.683 + --nextSelected; 1.684 + } 1.685 + var delta = max.value - min.value + 1; 1.686 + this._view._removeItemAtIndex(min.value, delta); 1.687 + rowCountImpact = -1 * delta; 1.688 + this._view._rowCount += rowCountImpact; 1.689 + tbo.rowCountChanged(min.value, rowCountImpact); 1.690 + } 1.691 + } 1.692 + 1.693 + this.performDeletion(deleteItems); 1.694 + 1.695 + if (nextSelected < 0) 1.696 + seln.clearSelection(); 1.697 + else { 1.698 + seln.select(nextSelected); 1.699 + this._tree.focus(); 1.700 + } 1.701 + }, 1.702 + 1.703 + deleteAllCookies: function () { 1.704 + if (this._view._filtered) { 1.705 + var rowCount = this._view.rowCount; 1.706 + var deleteItems = []; 1.707 + for (var index = 0; index < rowCount; index++) { 1.708 + deleteItems.push(this._view._getItemAtIndex(index)); 1.709 + } 1.710 + this._view._removeItemAtIndex(0, rowCount); 1.711 + this._view._rowCount = 0; 1.712 + this._tree.treeBoxObject.rowCountChanged(0, -rowCount); 1.713 + this.performDeletion(deleteItems); 1.714 + } 1.715 + else { 1.716 + this._cm.removeAll(); 1.717 + } 1.718 + this._updateRemoveAllButton(); 1.719 + this.focusFilterBox(); 1.720 + }, 1.721 + 1.722 + onCookieKeyPress: function (aEvent) { 1.723 + if (aEvent.keyCode == 46) 1.724 + this.deleteCookie(); 1.725 + }, 1.726 + 1.727 + _lastSortProperty : "", 1.728 + _lastSortAscending: false, 1.729 + sort: function (aProperty) { 1.730 + var ascending = (aProperty == this._lastSortProperty) ? !this._lastSortAscending : true; 1.731 + // Sort the Non-Filtered Host Collections 1.732 + if (aProperty == "rawHost") { 1.733 + function sortByHost(a, b) { 1.734 + return a.toLowerCase().localeCompare(b.toLowerCase()); 1.735 + } 1.736 + this._hostOrder.sort(sortByHost); 1.737 + if (!ascending) 1.738 + this._hostOrder.reverse(); 1.739 + } 1.740 + 1.741 + function sortByProperty(a, b) { 1.742 + return a[aProperty].toLowerCase().localeCompare(b[aProperty].toLowerCase()); 1.743 + } 1.744 + for (var host in this._hosts) { 1.745 + var cookies = this._hosts[host].cookies; 1.746 + cookies.sort(sortByProperty); 1.747 + if (!ascending) 1.748 + cookies.reverse(); 1.749 + } 1.750 + // Sort the Filtered List, if in Filtered mode 1.751 + if (this._view._filtered) { 1.752 + this._view._filterSet.sort(sortByProperty); 1.753 + if (!ascending) 1.754 + this._view._filterSet.reverse(); 1.755 + } 1.756 + 1.757 + // Adjust the Sort Indicator 1.758 + var domainCol = document.getElementById("domainCol"); 1.759 + var nameCol = document.getElementById("nameCol"); 1.760 + var sortOrderString = ascending ? "ascending" : "descending"; 1.761 + if (aProperty == "rawHost") { 1.762 + domainCol.setAttribute("sortDirection", sortOrderString); 1.763 + nameCol.removeAttribute("sortDirection"); 1.764 + } 1.765 + else { 1.766 + nameCol.setAttribute("sortDirection", sortOrderString); 1.767 + domainCol.removeAttribute("sortDirection"); 1.768 + } 1.769 + 1.770 + this._view._invalidateCache(0); 1.771 + this._view.selection.clearSelection(); 1.772 + this._view.selection.select(0); 1.773 + this._tree.treeBoxObject.invalidate(); 1.774 + this._tree.treeBoxObject.ensureRowIsVisible(0); 1.775 + 1.776 + this._lastSortAscending = ascending; 1.777 + this._lastSortProperty = aProperty; 1.778 + }, 1.779 + 1.780 + clearFilter: function () { 1.781 + // Revert to single-select in the tree 1.782 + this._tree.setAttribute("seltype", "single"); 1.783 + 1.784 + // Clear the Tree Display 1.785 + this._view._filtered = false; 1.786 + this._view._rowCount = 0; 1.787 + this._tree.treeBoxObject.rowCountChanged(0, -this._view._filterSet.length); 1.788 + this._view._filterSet = []; 1.789 + 1.790 + // Just reload the list to make sure deletions are respected 1.791 + this._loadCookies(); 1.792 + this._tree.treeBoxObject.view = this._view; 1.793 + 1.794 + // Restore sort order 1.795 + var sortby = this._lastSortProperty; 1.796 + if (sortby == "") { 1.797 + this._lastSortAscending = false; 1.798 + this.sort("rawHost"); 1.799 + } 1.800 + else { 1.801 + this._lastSortAscending = !this._lastSortAscending; 1.802 + this.sort(sortby); 1.803 + } 1.804 + 1.805 + // Restore open state 1.806 + for (var i = 0; i < this._openIndices.length; ++i) 1.807 + this._view.toggleOpenState(this._openIndices[i]); 1.808 + this._openIndices = []; 1.809 + 1.810 + // Restore selection 1.811 + this._view.selection.clearSelection(); 1.812 + for (i = 0; i < this._lastSelectedRanges.length; ++i) { 1.813 + var range = this._lastSelectedRanges[i]; 1.814 + this._view.selection.rangedSelect(range.min, range.max, true); 1.815 + } 1.816 + this._lastSelectedRanges = []; 1.817 + 1.818 + document.getElementById("cookiesIntro").value = this._bundle.getString("cookiesAll"); 1.819 + this._updateRemoveAllButton(); 1.820 + }, 1.821 + 1.822 + _cookieMatchesFilter: function (aCookie) { 1.823 + return aCookie.rawHost.indexOf(this._view._filterValue) != -1 || 1.824 + aCookie.name.indexOf(this._view._filterValue) != -1 || 1.825 + aCookie.value.indexOf(this._view._filterValue) != -1; 1.826 + }, 1.827 + 1.828 + _filterCookies: function (aFilterValue) { 1.829 + this._view._filterValue = aFilterValue; 1.830 + var cookies = []; 1.831 + for (var i = 0; i < gCookiesWindow._hostOrder.length; ++i) { //var host in gCookiesWindow._hosts) { 1.832 + var currHost = gCookiesWindow._hosts[gCookiesWindow._hostOrder[i]]; // gCookiesWindow._hosts[host]; 1.833 + if (!currHost) continue; 1.834 + for (var j = 0; j < currHost.cookies.length; ++j) { 1.835 + var cookie = currHost.cookies[j]; 1.836 + if (this._cookieMatchesFilter(cookie)) 1.837 + cookies.push(cookie); 1.838 + } 1.839 + } 1.840 + return cookies; 1.841 + }, 1.842 + 1.843 + _lastSelectedRanges: [], 1.844 + _openIndices: [], 1.845 + _saveState: function () { 1.846 + // Save selection 1.847 + var seln = this._view.selection; 1.848 + this._lastSelectedRanges = []; 1.849 + var rangeCount = seln.getRangeCount(); 1.850 + for (var i = 0; i < rangeCount; ++i) { 1.851 + var min = {}; var max = {}; 1.852 + seln.getRangeAt(i, min, max); 1.853 + this._lastSelectedRanges.push({ min: min.value, max: max.value }); 1.854 + } 1.855 + 1.856 + // Save open states 1.857 + this._openIndices = []; 1.858 + for (i = 0; i < this._view.rowCount; ++i) { 1.859 + var item = this._view._getItemAtIndex(i); 1.860 + if (item && item.container && item.open) 1.861 + this._openIndices.push(i); 1.862 + } 1.863 + }, 1.864 + 1.865 + _updateRemoveAllButton: function gCookiesWindow__updateRemoveAllButton() { 1.866 + document.getElementById("removeAllCookies").disabled = this._view._rowCount == 0; 1.867 + }, 1.868 + 1.869 + filter: function () { 1.870 + var filter = document.getElementById("filter").value; 1.871 + if (filter == "") { 1.872 + gCookiesWindow.clearFilter(); 1.873 + return; 1.874 + } 1.875 + var view = gCookiesWindow._view; 1.876 + view._filterSet = gCookiesWindow._filterCookies(filter); 1.877 + if (!view._filtered) { 1.878 + // Save Display Info for the Non-Filtered mode when we first 1.879 + // enter Filtered mode. 1.880 + gCookiesWindow._saveState(); 1.881 + view._filtered = true; 1.882 + } 1.883 + // Move to multi-select in the tree 1.884 + gCookiesWindow._tree.setAttribute("seltype", "multiple"); 1.885 + 1.886 + // Clear the display 1.887 + var oldCount = view._rowCount; 1.888 + view._rowCount = 0; 1.889 + gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, -oldCount); 1.890 + // Set up the filtered display 1.891 + view._rowCount = view._filterSet.length; 1.892 + gCookiesWindow._tree.treeBoxObject.rowCountChanged(0, view.rowCount); 1.893 + 1.894 + // if the view is not empty then select the first item 1.895 + if (view.rowCount > 0) 1.896 + view.selection.select(0); 1.897 + 1.898 + document.getElementById("cookiesIntro").value = gCookiesWindow._bundle.getString("cookiesFiltered"); 1.899 + this._updateRemoveAllButton(); 1.900 + }, 1.901 + 1.902 + setFilter: function (aFilterString) { 1.903 + document.getElementById("filter").value = aFilterString; 1.904 + this.filter(); 1.905 + }, 1.906 + 1.907 + focusFilterBox: function () { 1.908 + var filter = document.getElementById("filter"); 1.909 + filter.focus(); 1.910 + filter.select(); 1.911 + }, 1.912 + 1.913 + onWindowKeyPress: function (aEvent) { 1.914 + if (aEvent.keyCode == KeyEvent.DOM_VK_ESCAPE) 1.915 + window.close(); 1.916 + } 1.917 +};