[or-cvs] r15663: Yay! New cookie jar system courtesy of arno. Thanks arno! (in torbutton/trunk/src: . components)
mikeperry at seul.org
mikeperry at seul.org
Sat Jul 5 10:38:44 UTC 2008
Author: mikeperry
Date: 2008-07-05 06:38:42 -0400 (Sat, 05 Jul 2008)
New Revision: 15663
Modified:
torbutton/trunk/src/CHANGELOG
torbutton/trunk/src/components/cookie-jar-selector.js
Log:
Yay! New cookie jar system courtesy of arno. Thanks arno!
Modified: torbutton/trunk/src/CHANGELOG
===================================================================
--- torbutton/trunk/src/CHANGELOG 2008-07-05 08:15:52 UTC (rev 15662)
+++ torbutton/trunk/src/CHANGELOG 2008-07-05 10:38:42 UTC (rev 15663)
@@ -2,10 +2,10 @@
XX Jul 2008
* bugfix: bug 734: Fix exception with clearing history on toggle
* bugfix: bug 735: Fix exception with blocking Non-Tor history writes
- * bugfix: Workaround to get cookie jars functional on FF3 by arno
- * misc: translation updates
+ * bugfix: bug 720: FF3 cookie jar fix submitted by arno
+ * misc: translation updates for French, Farsi, and others
* misc: demote "mapper check" log message to info
- * new: Added ability to not write cookies and cookie jars to disk
+ * new: Option to not write cookies and jars to disk submitted by arno
1.2.0rc4
27 Jun 2008
Modified: torbutton/trunk/src/components/cookie-jar-selector.js
===================================================================
--- torbutton/trunk/src/components/cookie-jar-selector.js 2008-07-05 08:15:52 UTC (rev 15662)
+++ torbutton/trunk/src/components/cookie-jar-selector.js 2008-07-05 10:38:42 UTC (rev 15663)
@@ -22,6 +22,8 @@
this.logger = Components.classes["@torproject.org/torbutton-logger;1"]
.getService(Components.interfaces.nsISupports).wrappedJSObject;
+
+ this.prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
var getProfileFile = function(filename) {
var loc = "ProfD"; // profile directory
@@ -67,95 +69,187 @@
}
};
- var loadCookiesFromFile = function(aFile) {
- var storageService = Cc["@mozilla.org/storage/service;1"]
- .getService(Ci.mozIStorageService);
- try {
- var mDBConn = storageService.openDatabase(aFile);
- } catch(e) {
- this.logger.log(5, "Cookie file open exception: "+e);
- return;
- }
- if (!mDBConn.tableExists("moz_cookies")) { // Should not happen
- this.logger.log(5, "No cookies table!");
- return;
- }
- if (mDBConn.schemaVersion != 2) { // Should not happen
- this.logger.log(5, "Cookies table version mismatch");
- return;
- }
-
- var cookieManager = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
-
- var stmt = mDBConn.createStatement("SELECT id, name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly FROM moz_cookies");
-
- while (stmt.executeStep()) {
- var name = stmt.getUTF8String(1);
- var value = stmt.getUTF8String(2);
- var host = stmt.getUTF8String(3);
- var path = stmt.getUTF8String(4);
- var expiry = stmt.getInt64(5);
- var lastAccessed = stmt.getInt64(6);
- var isSecure = (stmt.getInt32(7) != 0);
- var isHttpOnly = (stmt.getInt32(8) != 0);
- cookieManager.QueryInterface(Ci.nsICookieManager2).add(host, path, name, value, isSecure, isHttpOnly, false, expiry);
- }
- stmt.reset();
- };
-
this.clearCookies = function() {
Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager)
.removeAll();
}
- this.saveCookies = function(name) {
+ // json would be a fine alternative to e4x, but is only available from
+ // gecko1.9
+ //
+ // see http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Processing_XML_with_E4X
+ // and http://developer.mozilla.org/en/docs/E4X
+ // for information about e4x
+ this._cookiesToXml = function(saveSession) {
var cookieManager =
Cc["@mozilla.org/cookiemanager;1"]
.getService(Ci.nsICookieManager);
- cookieManager.QueryInterface(Ci.nsIObserver);
+ var cookiesEnum = cookieManager.enumerator;
+ var cookiesAsXml = new XML('<cookies/>');
+ while (cookiesEnum.hasMoreElements()) {
+ var cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2);
+ var xml = <cookie>{cookie.value}</cookie>;
+ xml. at name = cookie.name;
+ xml. at host = cookie.host;
+ xml. at path = cookie.path;
+ xml. at expiry = cookie.expiry;
+ if (cookie.isSecure)
+ xml. at isSecure = 1;
+ if (cookie.isSession)
+ xml. at isSession = 1;
+ if (cookie.isHttpOnly)
+ xml. at isHttpOnly = 1;
+ if(!cookie.isSession || saveSession)
+ cookiesAsXml.appendChild(xml);
+ }
+ return cookiesAsXml;
+ }
- // Tell the cookie manager to unload cookies from memory
- // and sync to disk.
- cookieManager.observe(this, "profile-before-change", "");
- // Tell the cookie manager to reload cookies from disk
- cookieManager.observe(this, "profile-do-change", "");
- copyProfileFile("cookies"+this.extn, "cookies-" + name + this.extn);
+ this._loadCookiesFromXml = function(name) {
+ var cookiesAsXml = this["cookiesobj-" + name];
+ if (!cookiesAsXml)
+ return;
+
+ var cookieManager =
+ Cc["@mozilla.org/cookiemanager;1"]
+ .getService(Ci.nsICookieManager2);
+
+ for (var i = 0; i < cookiesAsXml.cookie.length(); i++) {
+ var xml = cookiesAsXml.cookie[i];
+ var value = xml.toString();
+ var name = xml. at name;
+ var host = xml. at host;
+ var path = xml. at path;
+ var expiry = xml. at expiry;
+ var isSecure = (xml. at isSecure == 1);
+ var isSession = (xml. at isSession == 1);
+ var isHttpOnly = (xml. at isHttpOnly == 1);
+ try {
+ cookieManager.add(host, path, name, value, isSecure, isSession, expiry);
+ } catch(e) {
+ // Api changed to add httpOnly cookies support. see mozilla bug #379408
+ if (e.result == Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS)
+ cookieManager.add(host, path, name, value, isSecure, isHttpOnly, isSession, expiry);
+ }
+ }
+ }
+
+ this._cookiesToFile = function(name) {
+ var file = getProfileFile("cookies-" + name + ".xml");
+ var foStream = Cc["@mozilla.org/network/file-output-stream;1"]
+ .createInstance(Ci.nsIFileOutputStream);
+ foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
+ var data = this["cookiesobj-" + name].toString();
+ foStream.write(data, data.length);
+ foStream.close();
+ }
+
+ this._cookiesFromFile = function(name) {
+ var file = getProfileFile("cookies-" + name + ".xml");
+ if (!file.exists())
+ return null;
+ var data = "";
+ var fstream = Cc["@mozilla.org/network/file-input-stream;1"]
+ .createInstance(Ci.nsIFileInputStream);
+ var sstream = Cc["@mozilla.org/scriptableinputstream;1"]
+ .createInstance(Ci.nsIScriptableInputStream);
+ fstream.init(file, -1, 0, 0);
+ sstream.init(fstream);
+
+ var str = sstream.read(4096);
+ while (str.length > 0) {
+ data += str;
+ str = sstream.read(4096);
+ }
+
+ sstream.close();
+ fstream.close();
+ try {
+ var ret = XML(data);
+ } catch(e) { // file has been corrupted; XXX: handle error differently
+ file.remove(false); //XXX: is it necessary to remove it ?
+ var ret = null;
+ }
+ return ret;
+ }
+
+ this.saveCookies = function(name) {
+
+ // transition removes old tor-style cookie file
+ var oldCookieFile = getProfileFile("cookies-"+name+this.extn);
+ if (oldCookieFile.exists()) {
+ oldCookieFile.remove(false);
+ }
+
+ if (!this.prefs.getBoolPref("extensions.torbutton." + name + "_memory_jar")) {
+ // save cookies to xml object
+ this["cookiesobj-" + name] = this._cookiesToXml(false);
+ // save cookies to file
+ this._cookiesToFile(name);
+ } else {
+ // save cookies to xml object
+ this["cookiesobj-" + name] = this._cookiesToXml(true);
+ var file = getProfileFile("cookies-" + name + ".xml");
+ if (file.exists()) {
+ file.remove(false)
+ }
+ }
+
+ // ok, everything's fine
+ this.logger.log(2, "Cookies saved");
};
- this.loadCookies = function(name, deleteSavedCookieJar) {
+ this._oldLoadCookies = function(name, deleteSavedCookieJar) {
var cookieManager =
Cc["@mozilla.org/cookiemanager;1"]
- .getService(Ci.nsIObserver);
+ .getService(Ci.nsICookieManager);
+ cookieManager.QueryInterface(Ci.nsIObserver);
// Tell the cookie manager to unload cookies from memory and disk
var context = "shutdown-cleanse";
cookieManager.observe(this, "profile-before-change", context);
+ // Replace the cookies.txt file with the loaded data
var fn = deleteSavedCookieJar ? moveProfileFile : copyProfileFile;
+ fn("cookies-"+name+this.extn, "cookies"+this.extn);
// Tell the cookie manager to reload cookies from disk
- if (this.is_ff3) {
- var cookieFile = getProfileFile("cookies-"+name+this.extn);
- // Workaround for Firefox bug 439384:
- loadCookiesFromFile(cookieFile);
- // Tell the cookie manager to unload cookies from memory
- // and sync to disk.
- cookieManager.observe(this, "profile-before-change", "");
- // Tell the cookie manager to reload cookies from disk
- cookieManager.observe(this, "profile-do-change", "");
+ cookieManager.observe(this, "profile-do-change", context);
+ this.logger.log(2, "Cookies reloaded");
+ };
- // Following fails b/c of FF Bug 439384. It is the alternative
- // to the above lines.
- // Replace the cookies.sqlite file with the loaded data
- // fn("cookies-"+name+this.extn, "cookies"+this.extn);
- // still notify cookieManager to call initDB, and reset mDBConn
- //cookieManager.observe(this, "profile-do-change", context);
- } else {
- // Replace the cookies.txt file with the loaded data
- fn("cookies-"+name+this.extn, "cookies"+this.extn);
- cookieManager.observe(this, "profile-do-change", context);
+ this.loadCookies = function(name, deleteSavedCookieJar) {
+ // remove cookies before loading old ones
+ this.clearCookies();
+
+ /* transition code from old jars */
+ if (!this.is_ff3) {
+ var oldCookieFile = getProfileFile("cookies-"+name+this.extn);
+ if (oldCookieFile.exists()) {
+ this._oldLoadCookies(name, deleteSavedCookieJar);
+ if (oldCookieFile.exists()) {
+ oldCookieFile.remove(false);
+ }
+ }
}
+
+ if (!this.prefs.getBoolPref("extensions.torbutton." + name + "_memory_jar")) {
+ // load cookies from file
+ this["cookiesobj-" + name] = this._cookiesFromFile(name);
+ }
+
+ //delete file if needed
+ if (deleteSavedCookieJar) {
+ var file = getProfileFile("cookies-" + name + ".xml");
+ if (file.exists())
+ file.remove(false);
+ }
+
+ // load cookies from xml object
+ this._loadCookiesFromXml(name);
+
+ // ok, everything's fine
this.logger.log(2, "Cookies reloaded");
};
@@ -173,9 +267,41 @@
this.extn = ".txt";
}
-
// This JSObject is exported directly to chrome
this.wrappedJSObject = this;
+
+ var jarThis = this;
+ this.timerCallback = {
+ QueryInterface: function(iid) {
+ if (!iid.equals(Component.interfaces.nsISupports) &&
+ !iid.equals(Component.interfaces.nsITimer)) {
+ Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
+ return null;
+ }
+ return this;
+ },
+ notify: function() {
+ // this refers to timerCallback object. use jarThis to reference
+ // CookieJarSelector object.
+ jarThis.logger.log(2, "Got timer update. Saving cookies");
+ var tor_enabled =
+ jarThis.prefs.getBoolPref("extensions.torbutton.tor_enabled");
+
+ if(tor_enabled !=
+ jarThis.prefs.getBoolPref("extensions.torbutton.settings_applied")) {
+ jarThis.logger.log(3, "Neat. Timer fired during transition.");
+ return;
+ }
+
+ if(tor_enabled) {
+ jarThis.saveCookies("tor");
+ } else {
+ jarThis.saveCookies("nontor");
+ }
+ jarThis.logger.log(2, "Timer done. Cookies saved");
+ }
+ }
+
}
/**
@@ -186,14 +312,18 @@
const nsISupports = Components.interfaces.nsISupports;
const nsIClassInfo = Components.interfaces.nsIClassInfo;
+const nsIObserver = Components.interfaces.nsIObserver;
+const nsITimer = Components.interfaces.nsITimer;
const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
const nsIObserverService = Components.interfaces.nsIObserverService;
+const nsICategoryManager = Components.interfaces.nsICategoryManager;
CookieJarSelector.prototype =
{
QueryInterface: function(iid)
{
if (!iid.equals(nsIClassInfo) &&
+ !iid.equals(nsIObserver) &&
!iid.equals(nsISupports)) {
Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
return null;
@@ -219,6 +349,29 @@
// method of nsIClassInfo
getHelperForLanguage: function(count) { return null; },
+ // method of nsIObserver
+ observe : function(aSubject, aTopic, aData) {
+ switch(aTopic) {
+ case "app-startup":
+ var obsSvc = Components.classes["@mozilla.org/observer-service;1"].getService(nsIObserverService);
+ obsSvc.addObserver(this, "profile-after-change", false);
+ obsSvc.addObserver(this, "quit-application", false);
+ break;
+
+ case "profile-after-change":
+ // after profil loading, initialize a timer to call timerCallback
+ // at a specified interval
+ this.timer.initWithCallback(this.timerCallback, 60 * 1000, nsITimer.TYPE_REPEATING_SLACK); // 1 minute
+ break;
+
+ // put some stuff you want applied at firefox shutdown
+ case "quit-application":
+ break;
+ }
+ },
+
+ timer: Components.classes["@mozilla.org/timer;1"].createInstance(nsITimer),
+
}
var CookieJarSelectorFactory = new Object();
@@ -230,6 +383,7 @@
return null;
}
if (!iid.equals(nsIClassInfo) &&
+ !iid.equals(nsIObserver) &&
!iid.equals(nsISupports)) {
Components.returnCode = Cr.NS_ERROR_NO_INTERFACE;
return null;
@@ -249,8 +403,20 @@
fileSpec,
location,
type);
+ var catman = Components.classes['@mozilla.org/categorymanager;1'].getService(nsICategoryManager);
+ catman.addCategoryEntry("app-startup", kMODULE_NAME, kMODULE_CONTRACTID, true, true);
}
+CookieJarSelectorModule.unregisterSelf =
+function (compMgr, fileSpec, location, type)
+{
+ var catman = Components.classes['@mozilla.org/categorymanager;1'].getService(nsICategoryManager);
+ catman.deleteCategoryEntry("app-startup", kMODULE_NAME, true);
+ compMgr = compMgr.QueryInterface(nsIComponentRegistrar);
+ compMgr.unregisterFactoryLocation(kMODULE_CID,
+ fileSpec);
+}
+
CookieJarSelectorModule.getClassObject = function (compMgr, cid, iid)
{
if (cid.equals(kMODULE_CID))
More information about the tor-commits
mailing list