//@line 39 "/e/fx19rel/WINNT_5.2_Depend/mozilla/browser/components/preferences/cookies.js"

const nsICookie = Components.interfaces.nsICookie;

var gSiteCookiesWindow = {
  _cm               : Components.classes["@mozilla.org/cookiemanager;1"]
                                .getService(Components.interfaces.nsICookieManager),
  _ds               : Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
                                .getService(Components.interfaces.nsIScriptableDateFormat),
  _hosts            : {},
  _hostOrder        : [],
  _tree             : null,
  _bundle           : null,
  _bundleExtra      : null,
  _searchFilterBox	: null,

  init: function ()
  {
    var os = Components.classes["@mozilla.org/observer-service;1"]
                       .getService(Components.interfaces.nsIObserverService);
    os.addObserver(this, "cookie-changed", false);
    os.addObserver(this, "perm-changed", false);
    
    this._bundle = document.getElementById("bundlePreferences");
    this._bundleExtra  = document.getElementById("site-cookie-labels");
    this._tree = document.getElementById("cookiesList");
    this._searchFilterBox = document.getElementById("searchFilter");
    
    this._loadCookies();
    this._tree.treeBoxObject.view = this._view;
    this.sort("rawHost");
    if (this._view.rowCount > 0) 
      this._tree.view.selection.select(0);

    // Add label and access key for clear button, since FF3.1
    // removed these from cookies.dtd
    var clearFilterButton = document.getElementById("clearFilter");
	clearFilterButton.setAttribute("label", this._bundleExtra.getString("clearlabel"));
	clearFilterButton.setAttribute("accesskey", this._bundleExtra.getString("clearaccesskey"));
	
    if ("arguments" in window && window.arguments[0])
    {
    	if (window.arguments[0].filterString)
    	{
        	this.setFilter(window.arguments[0].filterString);  		
    	}
    	if (!window.arguments[0].showSearch)
    	{
    		//alert("Argument showSearch: " + !window.arguments[0].showSearch);
        	this._searchFilterBox.setAttribute("hidden", !window.arguments[0].showSearch); 		
    	}
    	else
    	{
    		document.getElementById("searchFilterLabel").value = gSiteCookiesWindow._bundleExtra.getString("searchbyurl");
    	}
    }
        

      
    this._saveState();
      
    document.getElementById("filter").focus();
  },
  
  uninit: function ()
  {
    var os = Components.classes["@mozilla.org/observer-service;1"]
                       .getService(Components.interfaces.nsIObserverService);
    os.removeObserver(this, "cookie-changed");
    os.removeObserver(this, "perm-changed");
  },
  
  _cookieEquals: function (aCookieA, aCookieB, aStrippedHost)
  {
    return aCookieA.rawHost == aStrippedHost &&
           aCookieA.name == aCookieB.name &&
           aCookieA.path == aCookieB.path;
  },
  
  observe: function (aCookie, aTopic, aData) 
  {
    if (aTopic != "cookie-changed")
      return;
    
    if (aCookie instanceof Components.interfaces.nsICookie) {
      var strippedHost = this._makeStrippedHost(aCookie.host);
      if (aData == "changed")
        this._handleCookieChanged(aCookie, strippedHost);
      else if (aData == "added")
        this._handleCookieAdded(aCookie, strippedHost);
    }
    else if (aData == "cleared") {
      this._hosts = {};
      this._hostOrder = [];
    
      var oldRowCount = this._view._rowCount;
      this._view._rowCount = 0;
      this._tree.treeBoxObject.rowCountChanged(0, -oldRowCount);
      this._view.selection.clearSelection();
    }
    
    // We don't yet handle aData == "deleted" - it's a less common case
    // and is rather complicated as selection tracking is difficult
  },
  
  _handleCookieChanged: function (changedCookie, strippedHost) 
  {
    var rowIndex = 0;
    var cookieItem = null;
    if (!this._view._filtered) {
      for (var i = 0; i < this._hostOrder.length; ++i) { // (var host in this._hosts) {
        ++rowIndex;
        var hostItem = this._hosts[this._hostOrder[i]]; // var hostItem = this._hosts[host];
        if (this._hostOrder[i] == strippedHost) { // host == strippedHost) {
          // Host matches, look for the cookie within this Host collection
          // and update its data
          for (var j = 0; j < hostItem.cookies.length; ++j) {
            ++rowIndex;
            var currCookie = hostItem.cookies[j];
            if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
              currCookie.value    = changedCookie.value;
              currCookie.isSecure = changedCookie.isSecure;
              currCookie.isDomain = changedCookie.isDomain;
              currCookie.expires  = changedCookie.expires;
              cookieItem = currCookie;
              break;
            }
          }
        }
        else if (hostItem.open)
          rowIndex += hostItem.cookies.length;
      }
    }
    else {
      // Just walk the filter list to find the item. It doesn't matter that
      // we don't update the main Host collection when we do this, because
      // when the filter is reset the Host collection is rebuilt anyway.
      for (rowIndex = 0; rowIndex < this._view._filterSet.length; ++rowIndex) {
        currCookie = this._view._filterSet[rowIndex];
        if (this._cookieEquals(currCookie, changedCookie, strippedHost)) {
          currCookie.value    = changedCookie.value;
          currCookie.isSecure = changedCookie.isSecure;
          currCookie.isDomain = changedCookie.isDomain;
          currCookie.expires  = changedCookie.expires;
          cookieItem = currCookie;
          break;
        }
      }
    }
    
    // Make sure the tree display is up to date...
    this._tree.treeBoxObject.invalidateRow(rowIndex);
    // ... and if the cookie is selected, update the displayed metadata too
    if (cookieItem != null && this._view.selection.currentIndex == rowIndex)
      this._updateCookieData(cookieItem);  
  },
  
  _handleCookieAdded: function (changedCookie, strippedHost)
  {
    var rowCountImpact = 0;
    var addedHost = { value: 0 };
    this._addCookie(strippedHost, changedCookie, addedHost);
    if (!this._view._filtered) {
      // The Host collection for this cookie already exists, and it's not open, 
      // so don't increment the rowCountImpact becaues the user is not going to
      // see the additional rows as they're hidden. 
      if (addedHost.value || this._hosts[strippedHost].open)
        ++rowCountImpact;
    }
    else {
      // We're in search mode, and the cookie being added matches
      // the search condition, so add it to the list. 
      var c = this._makeCookieObject(strippedHost, changedCookie);
      if (this._cookieMatchesFilter(c)) {
        this._view._filterSet.push(this._makeCookieObject(strippedHost, changedCookie));
        ++rowCountImpact;
      }
    }
    // Now update the tree display at the end (we could/should re run the sort
    // if any to get the position correct.)
    var oldRowCount = this._rowCount;
    this._view._rowCount += rowCountImpact;
    this._tree.treeBoxObject.rowCountChanged(oldRowCount - 1, rowCountImpact);

    document.getElementById("removeAllCookies").disabled = this._view._filtered;
  },
  
  _view: {
    _filtered   : false,
    _filterSet  : [],
    _filterValue: "",
    _rowCount   : 0,
    _cacheValid : 0,
    _cacheItems : [],
    get rowCount() 
    { 
      return this._rowCount; 
    },
    
    _getItemAtIndex: function (aIndex)
    {
      if (this._filtered)
        return this._filterSet[aIndex];

      var start = 0;
      var count = 0, hostIndex = 0;

      var cacheIndex = Math.min(this._cacheValid, aIndex);
      if (cacheIndex > 0) {
        var cacheItem = this._cacheItems[cacheIndex];
        start = cacheItem['start'];
        count = hostIndex = cacheItem['count'];
      }

      for (var i = start; i < gSiteCookiesWindow._hostOrder.length; ++i) { // var host in gSiteCookiesWindow._hosts) {
        var currHost = gSiteCookiesWindow._hosts[gSiteCookiesWindow._hostOrder[i]]; // gSiteCookiesWindow._hosts[host];
        if (!currHost) continue;
        if (count == aIndex)
          return currHost;
        hostIndex = count;

        var cacheEntry = { 'start' : i, 'count' : count };
        var cacheStart = count;

        if (currHost.open) {
          if (count < aIndex && aIndex <= (count + currHost.cookies.length)) {
            // We are looking for an entry within this host's children, 
            // enumerate them looking for the index. 
            ++count;
            for (var i = 0; i < currHost.cookies.length; ++i) {
              if (count == aIndex) {
                var cookie = currHost.cookies[i];
                cookie.parentIndex = hostIndex;
                return cookie;
              }
              ++count;
            }
          }
          else {
            // A host entry was open, but we weren't looking for an index
            // within that host entry's children, so skip forward over the
            // entry's children. We need to add one to increment for the
            // host value too. 
            count += currHost.cookies.length + 1;
          }
        }
        else
          ++count;

        for (var j = cacheStart; j < count; j++)
          this._cacheItems[j] = cacheEntry;
        this._cacheValid = count - 1;
      }
      return null;
    },

    _removeItemAtIndex: function (aIndex, aCount)
    {
      var removeCount = aCount === undefined ? 1 : aCount;
      if (this._filtered) {
        // remove the cookies from the unfiltered set so that they
        // don't reappear when the filter is changed. See bug 410863.
        for (var i = aIndex; i < aIndex + removeCount; ++i) {
          var item = this._filterSet[i];
          var parent = gSiteCookiesWindow._hosts[item.rawHost];
          for (var j = 0; j < parent.cookies.length; ++j) {
            if (item == parent.cookies[j]) {
              parent.cookies.splice(j, 1);
              break;
            }
          }
        }
        this._filterSet.splice(aIndex, removeCount);
        return;
      }
      
      var item = this._getItemAtIndex(aIndex);
      if (!item) return;
      this._invalidateCache(aIndex - 1);
      if (item.container)
        gSiteCookiesWindow._hosts[item.rawHost] = null;
      else {
        var parent = this._getItemAtIndex(item.parentIndex);
        for (var i = 0; i < parent.cookies.length; ++i) {
          var cookie = parent.cookies[i];
          if (item.rawHost == cookie.rawHost &&
              item.name == cookie.name && item.path == cookie.path)
            parent.cookies.splice(i, removeCount);
        }
      }
    },

    _invalidateCache: function (aIndex)
    {
      this._cacheValid = Math.min(this._cacheValid, aIndex);
    },
    
    getCellText: function (aIndex, aColumn)
    {
      if (!this._filtered) {
        var item = this._getItemAtIndex(aIndex);
        if (!item) 
          return "";
        if (aColumn.id == "domainCol")
          return item.rawHost;
        else if (aColumn.id == "nameCol")
          return item.name;
      }
      else {
        if (aColumn.id == "domainCol")
          return this._filterSet[aIndex].rawHost;
        else if (aColumn.id == "nameCol")
          return this._filterSet[aIndex].name;
      }
      return "";
    },

    _selection: null, 
    get selection () { return this._selection; },
    set selection (val) { this._selection = val; return val; },
    getRowProperties: function (aIndex, aProperties) {},
    getCellProperties: function (aIndex, aColumn, aProperties) {},
    getColumnProperties: function (aColumn, aProperties) {},
    isContainer: function (aIndex)
    {
      if (!this._filtered) {
        var item = this._getItemAtIndex(aIndex);
        if (!item) return false;
        return item.container;
      }
      return false;
    },
    isContainerOpen: function (aIndex) 
    { 
      if (!this._filtered) {
        var item = this._getItemAtIndex(aIndex);
        if (!item) return false;
        return item.open;
      }
      return false;
    },
    isContainerEmpty: function (aIndex) 
    { 
      if (!this._filtered) {
        var item = this._getItemAtIndex(aIndex);
        if (!item) return false;
        return item.cookies.length == 0;
      }
      return false;
    },
    isSeparator: function (aIndex) { return false; },    
    isSorted: function (aIndex) { return false; },    
    canDrop: function (aIndex, aOrientation) { return false; },    
    drop: function (aIndex, aOrientation) {},    
    getParentIndex: function (aIndex) 
    {
      if (!this._filtered) {
        var item = this._getItemAtIndex(aIndex);
        // If an item has no parent index (i.e. it is at the top level) this 
        // function MUST return -1 otherwise we will go into an infinite loop. 
        // Containers are always top level items in the cookies tree, so make 
        // sure to return the appropriate value here.        
        if (!item || item.container) return -1;
        return item.parentIndex;
      }
      return -1;
    },    
    hasNextSibling: function (aParentIndex, aIndex) 
    { 
      if (!this._filtered) {
        // |aParentIndex| appears to be bogus, but we can get the real
        // parent index by getting the entry for |aIndex| and reading the
        // parentIndex field. 
        // The index of the last item in this host collection is the 
        // index of the parent + the size of the host collection, and
        // aIndex has a next sibling if it is less than this value.
        var item = this._getItemAtIndex(aIndex);
        if (item) {
          if (item.container) {
            for (var i = aIndex + 1; i < this.rowCount; ++i) {
              var subsequent = this._getItemAtIndex(i);
              if (subsequent.container) 
                return true;
            }
            return false;
          }
          else {
            var parent = this._getItemAtIndex(item.parentIndex);
            if (parent && parent.container)
              return aIndex < item.parentIndex + parent.cookies.length;
          }
        }
      }
      return aIndex < this.rowCount - 1;
    },
    hasPreviousSibling: function (aIndex)
    {
      if (!this._filtered) {
        var item = this._getItemAtIndex(aIndex);
        if (!item) return false;
        var parent = this._getItemAtIndex(item.parentIndex);
        if (parent && parent.container)
          return aIndex > item.parentIndex + 1;
      }
      return aIndex > 0;
    },
    getLevel: function (aIndex) 
    {
      if (!this._filtered) {
        var item = this._getItemAtIndex(aIndex);
        if (!item) return 0;
        return item.level;
      }
      return 0;
    },
    getImageSrc: function (aIndex, aColumn) {},    
    getProgressMode: function (aIndex, aColumn) {},    
    getCellValue: function (aIndex, aColumn) {},
    setTree: function (aTree) {},    
    toggleOpenState: function (aIndex) 
    {
      if (!this._filtered) {
        var item = this._getItemAtIndex(aIndex);
        if (!item) return;
        this._invalidateCache(aIndex);
        var multiplier = item.open ? -1 : 1;
        var delta = multiplier * item.cookies.length;
        this._rowCount += delta;
        item.open = !item.open;
        gSiteCookiesWindow._tree.treeBoxObject.rowCountChanged(aIndex + 1, delta);
        gSiteCookiesWindow._tree.treeBoxObject.invalidateRow(aIndex);
      }
    },    
    cycleHeader: function (aColumn) {},    
    selectionChanged: function () {},    
    cycleCell: function (aIndex, aColumn) {},    
    isEditable: function (aIndex, aColumn) 
    { 
      return false; 
    },
    isSelectable: function (aIndex, aColumn) 
    { 
      return false; 
    },
    setCellValue: function (aIndex, aColumn, aValue) {},    
    setCellText: function (aIndex, aColumn, aValue) {},    
    performAction: function (aAction) {},  
    performActionOnRow: function (aAction, aIndex) {},    
    performActionOnCell: function (aAction, aindex, aColumn) {}
  },
  
  _makeStrippedHost: function (aHost)
  {
    var formattedHost = aHost.charAt(0) == "." ? aHost.substring(1, aHost.length) : aHost;
    return formattedHost.substring(0, 4) == "www." ? formattedHost.substring(4, formattedHost.length) : formattedHost;
  },
  
  _addCookie: function (aStrippedHost, aCookie, aHostCount)
  {
    if (!(aStrippedHost in this._hosts) || !this._hosts[aStrippedHost]) {
      this._hosts[aStrippedHost] = { cookies   : [], 
                                     rawHost   : aStrippedHost,
                                     level     : 0,
                                     open      : false,
                                     container : true };
      this._hostOrder.push(aStrippedHost);
      ++aHostCount.value;
    }
    
    var c = this._makeCookieObject(aStrippedHost, aCookie);    
    this._hosts[aStrippedHost].cookies.push(c);
  },
  
  _makeCookieObject: function (aStrippedHost, aCookie)
  {
    var host = aCookie.host;
    var formattedHost = host.charAt(0) == "." ? host.substring(1, host.length) : host;
    var c = { name        : aCookie.name,
              value       : aCookie.value,
              isDomain    : aCookie.isDomain,
              host        : aCookie.host,
              rawHost     : aStrippedHost,
              path        : aCookie.path,
              isSecure    : aCookie.isSecure,
              expires     : aCookie.expires,
              level       : 1,
              container   : false };
    return c;
  },
  
  _loadCookies: function () 
  {
    var e = this._cm.enumerator;
    var hostCount = { value: 0 };
    this._hosts = {};
    this._hostOrder = [];
    while (e.hasMoreElements()) {
      var cookie = e.getNext();
      if (cookie && cookie instanceof Components.interfaces.nsICookie) {
        var strippedHost = this._makeStrippedHost(cookie.host);
        this._addCookie(strippedHost, cookie, hostCount);
      }
      else
        break;
    }
    this._view._rowCount = hostCount.value;
  },
  
  formatExpiresString: function (aExpires) 
  {
    if (aExpires) {
      var date = new Date(1000 * aExpires);
      return this._ds.FormatDateTime("", this._ds.dateFormatLong,
                                     this._ds.timeFormatSeconds,
                                     date.getFullYear(),
                                     date.getMonth() + 1,
                                     date.getDate(),
                                     date.getHours(),
                                     date.getMinutes(),
                                     date.getSeconds());
    }
    
    // Due to change in chrome://browser/locale/preferences/preferences.properties
    // from FF 3.5 to 3.6, AtEndOfSession in <= 3.5 is expireAtEndOfSession in 3.6
    var endOfsession = null;
    
    try
    {
    	endOfSession = this._bundle.getString("expireAtEndOfSession");
    }
    catch(e)
    {
    	endOfSession = this._bundle.getString("AtEndOfSession");    	
    }
    
    return endOfSession;
  },
  
  _updateCookieData: function (aItem)
  {
    var seln = this._view.selection;
    var ids = ["name", "value", "host", "path", "isSecure", "expires"];
    var properties;
    
    if (aItem && !aItem.container && seln.count > 0) {
      properties = { name: aItem.name, value: aItem.value, host: aItem.host,
                     path: aItem.path, expires: this.formatExpiresString(aItem.expires),
                     isDomain: aItem.isDomain ? this._bundle.getString("domainColon")
                                              : this._bundle.getString("hostColon"),
                     isSecure: aItem.isSecure ? this._bundle.getString("forSecureOnly")
                                              : this._bundle.getString("forAnyConnection") };
      for (var i = 0; i < ids.length; ++i)
        document.getElementById(ids[i]).disabled = false;
    }
    else {
      var noneSelected = this._bundle.getString("noCookieSelected");
      properties = { name: noneSelected, value: noneSelected, host: noneSelected,
                     path: noneSelected, expires: noneSelected, 
                     isSecure: noneSelected };
      for (i = 0; i < ids.length; ++i)
        document.getElementById(ids[i]).disabled = true;
    }
    for (var property in properties)
      document.getElementById(property).value = properties[property];
  },
  
  onCookieSelected: function () 
  {
    var properties, item;
    var seln = this._tree.view.selection;
    if (!this._view._filtered) 
      item = this._view._getItemAtIndex(seln.currentIndex);
    else
      item = this._view._filterSet[seln.currentIndex];
      
    this._updateCookieData(item);
    
    var rangeCount = seln.getRangeCount();
    var selectedCookieCount = 0;
    for (var i = 0; i < rangeCount; ++i) {
      var min = {}; var max = {};
      seln.getRangeAt(i, min, max);
      for (var j = min.value; j <= max.value; ++j) {
        item = this._view._getItemAtIndex(j);
        if (!item) continue;
        if (item.container && !item.open)
          selectedCookieCount += item.cookies.length;
        else if (!item.container)
          ++selectedCookieCount;
      }
    }
    var item = this._view._getItemAtIndex(seln.currentIndex);
    if (item && seln.count == 1 && item.container && item.open)
      selectedCookieCount += 2;
      
    var stringKey = selectedCookieCount == 1 ? "removeCookie" : "removeCookies";
    document.getElementById("removeCookie").label = this._bundle.getString(stringKey);
    
    document.getElementById("removeAllCookies").disabled = this._view._filtered;
    document.getElementById("removeCookie").disabled = !(seln.count > 0);
  },
  
  deleteCookie: function () 
  { 
//@line 651 "/e/fx19rel/WINNT_5.2_Depend/mozilla/browser/components/preferences/cookies.js"
    var seln = this._view.selection;
    var tbo = this._tree.treeBoxObject;
    
    if (seln.count < 1) return;
    
    var nextSelected = 0;
    var rowCountImpact = 0;
    var deleteItems = [];
    if (!this._view._filtered) {
      var ci = seln.currentIndex;
      nextSelected = ci;
      var invalidateRow = -1;
      var item = this._view._getItemAtIndex(ci);
      if (item.container) {
        rowCountImpact -= (item.open ? item.cookies.length : 0) + 1;
        deleteItems = deleteItems.concat(item.cookies);
        if (!this._view.hasNextSibling(-1, ci)) 
          --nextSelected;
        this._view._removeItemAtIndex(ci);
      }
      else {
        var parent = this._view._getItemAtIndex(item.parentIndex);
        --rowCountImpact;
        if (parent.cookies.length == 1) {
          --rowCountImpact;
          deleteItems.push(item);
          if (!this._view.hasNextSibling(-1, ci))
            --nextSelected;
          if (!this._view.hasNextSibling(-1, item.parentIndex)) 
            --nextSelected;
          this._view._removeItemAtIndex(item.parentIndex);
          invalidateRow = item.parentIndex;
        }
        else {
          deleteItems.push(item);
          if (!this._view.hasNextSibling(-1, ci)) 
            --nextSelected;
          this._view._removeItemAtIndex(ci);
        }
      }
      this._view._rowCount += rowCountImpact;
      tbo.rowCountChanged(ci, rowCountImpact);
      if (invalidateRow != -1)
        tbo.invalidateRow(invalidateRow);
    }
    else {
      var rangeCount = seln.getRangeCount();
      for (var i = 0; i < rangeCount; ++i) {
        var min = {}; var max = {};
        seln.getRangeAt(i, min, max);
        nextSelected = min.value;        
        for (var j = min.value; j <= max.value; ++j) {
          deleteItems.push(this._view._getItemAtIndex(j));
          if (!this._view.hasNextSibling(-1, max.value))
            --nextSelected;
        }
        var delta = max.value - min.value + 1;
        this._view._removeItemAtIndex(min.value, delta);
        rowCountImpact = -1 * delta;
        this._view._rowCount += rowCountImpact;
        tbo.rowCountChanged(min.value, rowCountImpact);
      }
    }
    
    var psvc = Components.classes["@mozilla.org/preferences-service;1"]
                         .getService(Components.interfaces.nsIPrefBranch);
    var blockFutureCookies = false;
    if (psvc.prefHasUserValue("network.cookie.blockFutureCookies"))
      blockFutureCookies = psvc.getBoolPref("network.cookie.blockFutureCookies");
    for (i = 0; i < deleteItems.length; ++i) {
      var item = deleteItems[i];
      this._cm.remove(item.host, item.name, item.path, blockFutureCookies);
    }
    
    if (nextSelected < 0)
      seln.clearSelection();
    else {
      seln.select(nextSelected);
      this._tree.focus();
    }
  },
  
  deleteAllCookies: function ()
  {
    this._cm.removeAll();
    this._tree.focus();
  },
  
  onCookieKeyPress: function (aEvent)
  {
    if (aEvent.keyCode == 46)
      this.deleteCookie();
  },
  
  _lastSortProperty : "",
  _lastSortAscending: false,
  sort: function (aProperty) 
  {
    var ascending = (aProperty == this._lastSortProperty) ? !this._lastSortAscending : true;
    // Sort the Non-Filtered Host Collections
    if (aProperty == "rawHost") {
      function sortByHost(a, b)
      {
        return a.toLowerCase().localeCompare(b.toLowerCase());
      }
      this._hostOrder.sort(sortByHost);
      if (!ascending)
        this._hostOrder.reverse();
    }
        
    function sortByProperty(a, b) 
    {
      return a[aProperty].toLowerCase().localeCompare(b[aProperty].toLowerCase());
    }
    for (var host in this._hosts) {
      var cookies = this._hosts[host].cookies;
      cookies.sort(sortByProperty);
      if (!ascending)
        cookies.reverse();
    }
    // Sort the Filtered List, if in Filtered mode
    if (this._view._filtered) { 
      this._view._filterSet.sort(sortByProperty);
      if (!ascending)
        this._view._filterSet.reverse();
    }

    this._view._invalidateCache(0);
    this._view.selection.clearSelection();
    this._view.selection.select(0);
    this._tree.treeBoxObject.invalidate();
    this._tree.treeBoxObject.ensureRowIsVisible(0);

    this._lastSortAscending = ascending;
    this._lastSortProperty = aProperty;
  },
  
  clearFilter: function ()
  {
    // Revert to single-select in the tree
    this._tree.setAttribute("seltype", "single");
    
    // Clear the Filter and the Tree Display
    document.getElementById("filter").value = "";
    this._view._filtered = false;
    this._view._rowCount = 0;
    this._tree.treeBoxObject.rowCountChanged(0, -this._view._filterSet.length);
    this._view._filterSet = [];

    // Just reload the list to make sure deletions are respected
    this._loadCookies();
    this._tree.treeBoxObject.view = this._view;
    
    // Restore sort order
    var sortby = this._lastSortProperty;
    if (sortby == "") {
      this._lastSortAscending = false;
      this.sort("rawHost");
    }
    else {
      this._lastSortAscending = !this._lastSortAscending;
      this.sort(sortby);
    }

    // Restore open state
    for (var i = 0; i < this._openIndices.length; ++i)
      this._view.toggleOpenState(this._openIndices[i]);
    this._openIndices = [];
    
    // Restore selection
    this._view.selection.clearSelection();
    for (i = 0; i < this._lastSelectedRanges.length; ++i) {
      var range = this._lastSelectedRanges[i];
      this._view.selection.rangedSelect(range.min, range.max, true);
    }
    this._lastSelectedRanges = [];

    document.getElementById("cookiesIntro").value = this._bundle.getString("cookiesAll");
    document.getElementById("clearFilter").disabled = true;
    document.getElementById("filter").focus();
  },
  
  _cookieMatchesFilter: function (aCookie)
  {
    return aCookie.rawHost.indexOf(this._view._filterValue) != -1 ||
           aCookie.name.indexOf(this._view._filterValue) != -1 || 
           aCookie.value.indexOf(this._view._filterValue) != -1;
  },
  
  _cookieHostMatchesFilter: function (aCookie)
  {
    return aCookie.rawHost.indexOf(this._view._filterValue) != -1;
  },
  
  _filterCookies: function (aFilterValue)
  {
    this._view._filterValue = aFilterValue;
    var cookies = [];
    for (var i = 0; i < gSiteCookiesWindow._hostOrder.length; ++i) { //var host in gSiteCookiesWindow._hosts) {
      var currHost = gSiteCookiesWindow._hosts[gSiteCookiesWindow._hostOrder[i]]; // gSiteCookiesWindow._hosts[host];
      if (!currHost) continue;
      for (var j = 0; j < currHost.cookies.length; ++j) {
        var cookie = currHost.cookies[j];
        // Change to only match on host
        if (this._cookieHostMatchesFilter(cookie))
          cookies.push(cookie);
      }
    }
    return cookies;
  },
  
  _lastSelectedRanges: [],
  _openIndices: [],
  _saveState: function ()
  {
    // Save selection
    var seln = this._view.selection;
    this._lastSelectedRanges = [];
    var rangeCount = seln.getRangeCount();
    for (var i = 0; i < rangeCount; ++i) {
      var min = {}; var max = {};
      seln.getRangeAt(i, min, max);
      this._lastSelectedRanges.push({ min: min.value, max: max.value });
    }
  
    // Save open states
    this._openIndices = [];
    for (i = 0; i < this._view.rowCount; ++i) {
      var item = this._view._getItemAtIndex(i);
      if (item && item.container && item.open)
        this._openIndices.push(i);
    }
  },
  
  _filterTimeout: -1,
  onFilterInput: function ()
  {
    if (this._filterTimeout != -1)
      clearTimeout(this._filterTimeout);
   
    function filterCookies()
    {
      var filter = document.getElementById("filter").value;
      if (filter == "") {
        gSiteCookiesWindow.clearFilter();
        return;
      }        
      var view = gSiteCookiesWindow._view;
      view._filterSet = gSiteCookiesWindow._filterCookies(filter);
      if (!view._filtered) {
        // Save Display Info for the Non-Filtered mode when we first
        // enter Filtered mode. 
        gSiteCookiesWindow._saveState();
        view._filtered = true;
      }
      // Move to multi-select in the tree
      gSiteCookiesWindow._tree.setAttribute("seltype", "multiple");
      
      // Clear the display
      var oldCount = view._rowCount;
      view._rowCount = 0;
      gSiteCookiesWindow._tree.treeBoxObject.rowCountChanged(0, -oldCount);
      // Set up the filtered display
      view._rowCount = view._filterSet.length;
      gSiteCookiesWindow._tree.treeBoxObject.rowCountChanged(0, view.rowCount);
      
      // if the view is not empty then select the first item
      if (view.rowCount > 0)
        view.selection.select(0);

      document.getElementById("cookiesIntro").value = gSiteCookiesWindow._bundleExtra.getString("sitelabel") + ' ' + filter;
      document.getElementById("clearFilter").disabled = false;
    }
    window.filterCookies = filterCookies;
    this._filterTimeout = setTimeout("filterCookies();", 500);
  },
  
  onFilterKeyPress: function (aEvent)
  {
    var filter = document.getElementById("filter").value;
    if (aEvent.keyCode == 27 && filter != "") // ESC key
      this.clearFilter();
  },
  
  focusFilterBox: function ()
  { 
    var filter = document.getElementById("filter");
    filter.focus();
    filter.select();
  },

  setFilter: function (aFilterString)
  {
    document.getElementById("filter").value = aFilterString;
    this.onFilterInput();
  }
};

