From 907f537607ea408f02023be4410c0d84242c68f3 Mon Sep 17 00:00:00 2001 From: Dan Mills Date: Wed, 13 Feb 2008 14:30:44 -0800 Subject: [PATCH] put utility functions in an object to avoid namespace pollution --- services/sync/modules/crypto.js | 28 +- services/sync/modules/dav.js | 30 +- services/sync/modules/engines.js | 18 +- services/sync/modules/service.js | 45 +-- services/sync/modules/stores.js | 24 +- services/sync/modules/syncCores.js | 20 +- services/sync/modules/util.js | 428 ++++++++++++++--------------- 7 files changed, 297 insertions(+), 296 deletions(-) diff --git a/services/sync/modules/crypto.js b/services/sync/modules/crypto.js index 1899a08a2b39..9fc2b114da5d 100644 --- a/services/sync/modules/crypto.js +++ b/services/sync/modules/crypto.js @@ -46,7 +46,7 @@ Cu.import("resource://weave/log4moz.js"); Cu.import("resource://weave/constants.js"); Cu.import("resource://weave/util.js"); -Function.prototype.async = generatorAsync; +Function.prototype.async = Utils.generatorAsync; function WeaveCrypto() { this._init(); @@ -131,7 +131,7 @@ WeaveCrypto.prototype = { PBEencrypt: function Crypto_PBEencrypt(onComplete, data, identity, algorithm) { let [self, cont] = yield; - let listener = new EventListener(cont); + let listener = new Utils.EventListener(cont); let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); let ret; @@ -179,7 +179,7 @@ WeaveCrypto.prototype = { } finally { timer = null; - generatorDone(this, self, onComplete, ret); + Utils.generatorDone(this, self, onComplete, ret); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -187,7 +187,7 @@ WeaveCrypto.prototype = { PBEdecrypt: function Crypto_PBEdecrypt(onComplete, data, identity, algorithm) { let [self, cont] = yield; - let listener = new EventListener(cont); + let listener = new Utils.EventListener(cont); let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); let ret; @@ -235,7 +235,7 @@ WeaveCrypto.prototype = { } finally { timer = null; - generatorDone(this, self, onComplete, ret); + Utils.generatorDone(this, self, onComplete, ret); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -268,24 +268,24 @@ function openssl(op, algorithm, input, password) { throw "encryption not supported on this platform: " + os; } - let inputFile = getTmp("input"); - let [inputFOS] = open(inputFile, ">"); + let inputFile = Utils.getTmp("input"); + let [inputFOS] = Utils.open(inputFile, ">"); inputFOS.write(input, input.length); inputFOS.close(); - let outputFile = getTmp("output"); + let outputFile = Utils.getTmp("output"); if (outputFile.exists()) outputFile.remove(false); // nsIProcess doesn't support stdin, so we write a file instead - let passFile = getTmp("pass"); - let [passFOS] = open(passFile, ">", PERMS_PASSFILE); + let passFile = Utils.getTmp("pass"); + let [passFOS] = Utils.open(passFile, ">", PERMS_PASSFILE); passFOS.write(password, password.length); passFOS.close(); try { - runCmd(wrap, getTmp().path, bin, algorithm, op, "-a", "-salt", - "-in", "input", "-out", "output", "-pass", "file:pass"); + Utils.runCmd(wrap, Utils.getTmp().path, bin, algorithm, op, "-a", "-salt", + "-in", "input", "-out", "output", "-pass", "file:pass"); } catch (e) { throw e; } finally { @@ -293,8 +293,8 @@ function openssl(op, algorithm, input, password) { inputFile.remove(false); } - let [outputFIS] = open(outputFile, "<"); - let ret = readStream(outputFIS); + let [outputFIS] = Utils.open(outputFile, "<"); + let ret = Utils.readStream(outputFIS); outputFIS.close(); outputFile.remove(false); diff --git a/services/sync/modules/dav.js b/services/sync/modules/dav.js index 6dc3f04d4ea6..59a37465825a 100644 --- a/services/sync/modules/dav.js +++ b/services/sync/modules/dav.js @@ -45,7 +45,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://weave/log4moz.js"); Cu.import("resource://weave/util.js"); -Function.prototype.async = generatorAsync; +Function.prototype.async = Utils.generatorAsync; /* * DAV object @@ -90,8 +90,8 @@ DAVCollection.prototype = { let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(); request = request.QueryInterface(Ci.nsIDOMEventTarget); - request.addEventListener("load", new EventListener(cont, "load"), false); - request.addEventListener("error", new EventListener(cont, "error"), false); + request.addEventListener("load", new Utils.EventListener(cont, "load"), false); + request.addEventListener("error", new Utils.EventListener(cont, "error"), false); request = request.QueryInterface(Ci.nsIXMLHttpRequest); request.open(op, this._baseURL + path, true); @@ -128,7 +128,7 @@ DAVCollection.prototype = { this._log.error("Exception caught: " + (e.message? e.message : e)); } finally { - generatorDone(this, self, onComplete, ret); + Utils.generatorDone(this, self, onComplete, ret); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -184,7 +184,7 @@ DAVCollection.prototype = { this._log.error("Exception caught: " + (e.message? e.message : e)); } finally { - generatorDone(this, self, onComplete, ret); + Utils.generatorDone(this, self, onComplete, ret); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -244,7 +244,7 @@ DAVCollection.prototype = { this._log.info("Logging in"); - let URI = makeURI(this._baseURL); + let URI = Utils.makeURI(this._baseURL); this._auth = "Basic " + btoa(username + ":" + password); // Make a call to make sure it's working @@ -260,7 +260,7 @@ DAVCollection.prototype = { this._log.error("Exception caught: " + (e.message? e.message : e)); } finally { - generatorDone(this, self, onComplete, this._loggedIn); + Utils.generatorDone(this, self, onComplete, this._loggedIn); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -290,7 +290,7 @@ DAVCollection.prototype = { if (this._authProvider._authFailed || resp.status < 200 || resp.status >= 300) return; - let tokens = xpath(resp.responseXML, '//D:locktoken/D:href'); + let tokens = Utils.xpath(resp.responseXML, '//D:locktoken/D:href'); let token = tokens.iterateNext(); ret = token.textContent; @@ -302,7 +302,7 @@ DAVCollection.prototype = { this._log.debug("Found an active lock token"); else this._log.debug("No active lock token found"); - generatorDone(this, self, onComplete, ret); + Utils.generatorDone(this, self, onComplete, ret); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -331,7 +331,7 @@ DAVCollection.prototype = { if (this._authProvider._authFailed || resp.status < 200 || resp.status >= 300) return; - let tokens = xpath(resp.responseXML, '//D:locktoken/D:href'); + let tokens = Utils.xpath(resp.responseXML, '//D:locktoken/D:href'); let token = tokens.iterateNext(); if (token) this._token = token.textContent; @@ -344,7 +344,7 @@ DAVCollection.prototype = { this._log.info("Lock acquired"); else this._log.warn("Could not acquire lock"); - generatorDone(this, self, onComplete, this._token); + Utils.generatorDone(this, self, onComplete, this._token); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -374,10 +374,10 @@ DAVCollection.prototype = { } finally { if (this._token) { this._log.info("Could not release lock"); - generatorDone(this, self, onComplete, false); + Utils.generatorDone(this, self, onComplete, false); } else { this._log.info("Lock released (or we didn't have one)"); - generatorDone(this, self, onComplete, true); + Utils.generatorDone(this, self, onComplete, true); } yield; // onComplete is responsible for closing the generator } @@ -411,7 +411,7 @@ DAVCollection.prototype = { this._log.debug("Lock released"); else this._log.debug("No lock released"); - generatorDone(this, self, onComplete, unlocked); + Utils.generatorDone(this, self, onComplete, unlocked); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -434,7 +434,7 @@ DAVCollection.prototype = { this._log.error("Exception caught: " + (e.message? e.message : e)); } finally { - generatorDone(this, self, onComplete, stolen); + Utils.generatorDone(this, self, onComplete, stolen); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); diff --git a/services/sync/modules/engines.js b/services/sync/modules/engines.js index 3f56abc12907..987caaad2a42 100644 --- a/services/sync/modules/engines.js +++ b/services/sync/modules/engines.js @@ -49,7 +49,7 @@ Cu.import("resource://weave/crypto.js"); Cu.import("resource://weave/stores.js"); Cu.import("resource://weave/syncCores.js"); -Function.prototype.async = generatorAsync; +Function.prototype.async = Utils.generatorAsync; let Crypto = new WeaveCrypto(); function Engine(davCollection, cryptoId) { @@ -171,7 +171,7 @@ Engine.prototype = { this._log.debug("Server reset failed"); this._os.notifyObservers(null, this._osPrefix + "reset-server:error", ""); } - generatorDone(this, self, onComplete, done) + Utils.generatorDone(this, self, onComplete, done) yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -200,7 +200,7 @@ Engine.prototype = { this._log.debug("Client reset failed"); this._os.notifyObservers(null, this._osPrefix + "reset-client:error", ""); } - generatorDone(this, self, onComplete, done); + Utils.generatorDone(this, self, onComplete, done); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -366,7 +366,7 @@ Engine.prototype = { // Log an error if not the same if (!(serverConflicts.length || - deepEquals(serverChanges, serverDelta))) + Utils.deepEquals(serverChanges, serverDelta))) this._log.warn("Predicted server changes differ from " + "actual server->client diff (can be ignored in many cases)"); @@ -437,10 +437,10 @@ Engine.prototype = { } if (ok && synced) { this._os.notifyObservers(null, this._osPrefix + "sync:success", ""); - generatorDone(this, self, onComplete, true); + Utils.generatorDone(this, self, onComplete, true); } else { this._os.notifyObservers(null, this._osPrefix + "sync:error", ""); - generatorDone(this, self, onComplete, false); + Utils.generatorDone(this, self, onComplete, false); } yield; // onComplete is responsible for closing the generator } @@ -496,7 +496,7 @@ Engine.prototype = { if (status.formatVersion > STORAGE_FORMAT_VERSION) { this._log.error("Server uses storage format v" + status.formatVersion + ", this client understands up to v" + STORAGE_FORMAT_VERSION); - generatorDone(this, self, onComplete, ret) + Utils.generatorDone(this, self, onComplete, ret) return; } @@ -634,7 +634,7 @@ Engine.prototype = { this._log.error("Exception caught: " + (e.message? e.message : e)); } finally { - generatorDone(this, self, onComplete, ret) + Utils.generatorDone(this, self, onComplete, ret) yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -680,7 +680,7 @@ Engine.prototype = { this._log.error("Exception caught: " + (e.message? e.message : e)); } finally { - generatorDone(this, self, onComplete, ret) + Utils.generatorDone(this, self, onComplete, ret) yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); diff --git a/services/sync/modules/service.js b/services/sync/modules/service.js index 54679390faae..5fa5851b4687 100644 --- a/services/sync/modules/service.js +++ b/services/sync/modules/service.js @@ -51,7 +51,7 @@ Cu.import("resource://weave/dav.js"); Cu.import("resource://weave/identity.js"); -Function.prototype.async = generatorAsync; +Function.prototype.async = Utils.generatorAsync; /* * Service singleton @@ -61,6 +61,14 @@ Function.prototype.async = generatorAsync; function WeaveSyncService() { this._init(); } WeaveSyncService.prototype = { + __prefs: null, + get _prefs() { + if (!this.__prefs) + this.__prefs = Cc["@mozilla.org/preferences-service;1"] + .getService(Ci.nsIPrefBranch); + return this.__prefs; + }, + __os: null, get _os() { if (!this.__os) @@ -122,17 +130,13 @@ WeaveSyncService.prototype = { }, get username() { - let branch = Cc["@mozilla.org/preferences-service;1"] - .getService(Ci.nsIPrefBranch); - return branch.getCharPref("extensions.weave.username"); + return this._prefs.getCharPref("extensions.weave.username"); }, set username(value) { - let branch = Cc["@mozilla.org/preferences-service;1"] - .getService(Ci.nsIPrefBranch); if (value) - branch.setCharPref("extensions.weave.username", value); + this._prefs.setCharPref("extensions.weave.username", value); else - branch.clearUserPref("extensions.weave.username"); + this._prefs.clearUserPref("extensions.weave.username"); // fixme - need to loop over all Identity objects - needs some rethinking... this._mozId.username = value; @@ -185,13 +189,11 @@ WeaveSyncService.prototype = { let enabled = false; let schedule = 0; try { - let branch = Cc["@mozilla.org/preferences-service;1"]. - getService(Ci.nsIPrefBranch2); - this._serverURL = branch.getCharPref("extensions.weave.serverURL"); - enabled = branch.getBoolPref("extensions.weave.enabled"); - schedule = branch.getIntPref("extensions.weave.schedule"); + this._serverURL = this._prefs.getCharPref("extensions.weave.serverURL"); + enabled = this._prefs.getBoolPref("extensions.weave.enabled"); + schedule = this._prefs.getIntPref("extensions.weave.schedule"); - branch.addObserver("extensions.weave", this, false); + this._prefs.addObserver("extensions.weave", this, false); } catch (ex) { /* use defaults */ } @@ -215,10 +217,13 @@ WeaveSyncService.prototype = { } }, + _scheduleChanged: function WeaveSync__scheduleChanged() { + }, + _enableSchedule: function WeaveSync__enableSchedule() { this._scheduleTimer = Cc["@mozilla.org/timer;1"]. createInstance(Ci.nsITimer); - let listener = new EventListener(bind2(this, this._onSchedule)); + let listener = new Utils.EventListener(Utils.bind2(this, this._onSchedule)); this._scheduleTimer.initWithCallback(listener, 1800000, // 30 min this._scheduleTimer.TYPE_REPEATING_SLACK); }, @@ -345,7 +350,7 @@ WeaveSyncService.prototype = { //this._log.debug("Login error"); this._os.notifyObservers(null, "weave:service-login:error", ""); } - generatorDone(this, self, onComplete, success); + Utils.generatorDone(this, self, onComplete, success); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -373,7 +378,7 @@ WeaveSyncService.prototype = { this._log.debug("Server lock reset failed"); this._os.notifyObservers(null, "weave:server-lock-reset:error", ""); } - generatorDone(this, self, onComplete, success); + Utils.generatorDone(this, self, onComplete, success); yield; // generatorDone is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -405,7 +410,7 @@ WeaveSyncService.prototype = { this._os.notifyObservers(null, "weave:service:sync:success", ""); else this._os.notifyObservers(null, "weave:service:sync:error", ""); - generatorDone(this, self); + Utils.generatorDone(this, self); yield; // generatorDone is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -427,7 +432,7 @@ WeaveSyncService.prototype = { this._log.error("Exception caught: " + (e.message? e.message : e)); } finally { - generatorDone(this, self); + Utils.generatorDone(this, self); yield; // generatorDone is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -449,7 +454,7 @@ WeaveSyncService.prototype = { this._log.error("Exception caught: " + (e.message? e.message : e)); } finally { - generatorDone(this, self); + Utils.generatorDone(this, self); yield; // generatorDone is responsible for closing the generator } this._log.warn("generator not properly closed"); diff --git a/services/sync/modules/stores.js b/services/sync/modules/stores.js index bc09a0f4a6ee..692bfd5a11e0 100644 --- a/services/sync/modules/stores.js +++ b/services/sync/modules/stores.js @@ -360,7 +360,7 @@ BookmarksStore.prototype = { item.title = node.title; } item.URI = node.uri; - item.tags = this._ts.getTagsForURI(makeURI(node.uri), {}); + item.tags = this._ts.getTagsForURI(Utils.makeURI(node.uri), {}); item.keyword = this._bms.getKeywordForBookmark(node.itemId); } else if (node.type == node.RESULT_TYPE_SEPARATOR) { item.type = "separator"; @@ -404,7 +404,7 @@ BookmarksStore.prototype = { case "bookmark": case "microsummary": { this._log.info(" -> creating bookmark \"" + command.data.title + "\""); - let URI = makeURI(command.data.URI); + let URI = Utils.makeURI(command.data.URI); newId = this._bms.insertBookmark(parentId, URI, command.data.index, @@ -415,7 +415,7 @@ BookmarksStore.prototype = { if (command.data.type == "microsummary") { this._log.info(" \-> is a microsummary"); - let genURI = makeURI(command.data.generatorURI); + let genURI = Utils.makeURI(command.data.generatorURI); try { let micsum = this._ms.createMicrosummary(URI, genURI); this._ms.setMicrosummary(newId, micsum); @@ -433,8 +433,8 @@ BookmarksStore.prototype = { this._log.info(" -> creating livemark \"" + command.data.title + "\""); newId = this._ls.createLivemark(parentId, command.data.title, - makeURI(command.data.siteURI), - makeURI(command.data.feedURI), + Utils.makeURI(command.data.siteURI), + Utils.makeURI(command.data.feedURI), command.data.index); break; case "separator": @@ -498,7 +498,7 @@ BookmarksStore.prototype = { this._bms.setItemTitle(itemId, command.data.title); break; case "URI": - this._bms.changeBookmarkURI(itemId, makeURI(command.data.URI)); + this._bms.changeBookmarkURI(itemId, Utils.makeURI(command.data.URI)); break; case "index": this._bms.moveItem(itemId, this._bms.getFolderIdForItem(itemId), @@ -520,16 +520,16 @@ BookmarksStore.prototype = { this._bms.setKeywordForBookmark(itemId, command.data.keyword); break; case "generatorURI": { - let micsumURI = makeURI(this._bms.getBookmarkURI(itemId)); - let genURI = makeURI(command.data.generatorURI); + let micsumURI = Utils.makeURI(this._bms.getBookmarkURI(itemId)); + let genURI = Utils.makeURI(command.data.generatorURI); let micsum = this._ms.createMicrosummary(micsumURI, genURI); this._ms.setMicrosummary(itemId, micsum); } break; case "siteURI": - this._ls.setSiteURI(itemId, makeURI(command.data.siteURI)); + this._ls.setSiteURI(itemId, Utils.makeURI(command.data.siteURI)); break; case "feedURI": - this._ls.setFeedURI(itemId, makeURI(command.data.feedURI)); + this._ls.setFeedURI(itemId, Utils.makeURI(command.data.feedURI)); break; default: this._log.warn("Can't change item property: " + key); @@ -595,10 +595,10 @@ HistoryStore.prototype = { _createCommand: function HistStore__createCommand(command) { this._log.info(" -> creating history entry: " + command.GUID); try { - this._browserHist.addPageWithDetails(makeURI(command.GUID), + this._browserHist.addPageWithDetails(Utils.makeURI(command.GUID), command.data.title, command.data.time); - this._hsvc.setPageDetails(makeURI(command.GUID), command.data.title, + this._hsvc.setPageDetails(Utils.makeURI(command.GUID), command.data.title, command.data.accessCount, false, false); } catch (e) { this._log.error("Exception caught: " + (e.message? e.message : e)); diff --git a/services/sync/modules/syncCores.js b/services/sync/modules/syncCores.js index 307c36cd7e7a..821ee9774d40 100644 --- a/services/sync/modules/syncCores.js +++ b/services/sync/modules/syncCores.js @@ -46,7 +46,7 @@ Cu.import("resource://weave/log4moz.js"); Cu.import("resource://weave/constants.js"); Cu.import("resource://weave/util.js"); -Function.prototype.async = generatorAsync; +Function.prototype.async = Utils.generatorAsync; /* * SyncCore objects @@ -70,7 +70,7 @@ SyncCore.prototype = { _getEdits: function SC__getEdits(a, b) { let ret = {numProps: 0, props: {}}; for (prop in a) { - if (!deepEquals(a[prop], b[prop])) { + if (!Utils.deepEquals(a[prop], b[prop])) { ret.numProps++; ret.props[prop] = b[prop]; } @@ -91,7 +91,7 @@ SyncCore.prototype = { _detectUpdates: function SC__detectUpdates(onComplete, a, b) { let [self, cont] = yield; - let listener = new EventListener(cont); + let listener = new Utils.EventListener(cont); let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); let cmds = []; @@ -145,7 +145,7 @@ SyncCore.prototype = { } finally { timer = null; - generatorDone(this, self, onComplete, cmds); + Utils.generatorDone(this, self, onComplete, cmds); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); @@ -162,11 +162,11 @@ SyncCore.prototype = { // Check that all other properties are the same // FIXME: could be optimized... for (let key in a) { - if (key != "GUID" && !deepEquals(a[key], b[key])) + if (key != "GUID" && !Utils.deepEquals(a[key], b[key])) return false; } for (let key in b) { - if (key != "GUID" && !deepEquals(a[key], b[key])) + if (key != "GUID" && !Utils.deepEquals(a[key], b[key])) return false; } return true; @@ -189,7 +189,7 @@ SyncCore.prototype = { }, _conflicts: function SC__conflicts(a, b) { - if ((a.GUID == b.GUID) && !deepEquals(a, b)) + if ((a.GUID == b.GUID) && !Utils.deepEquals(a, b)) return true; return false; }, @@ -218,7 +218,7 @@ SyncCore.prototype = { _reconcile: function SC__reconcile(onComplete, listA, listB) { let [self, cont] = yield; - let listener = new EventListener(cont); + let listener = new Utils.EventListener(cont); let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); let propagations = [[], []]; @@ -242,7 +242,7 @@ SyncCore.prototype = { if (skip) return true; - if (deepEquals(a, b)) { + if (Utils.deepEquals(a, b)) { delete listA[i]; // a skip = true; return false; // b @@ -301,7 +301,7 @@ SyncCore.prototype = { } finally { timer = null; - generatorDone(this, self, onComplete, ret); + Utils.generatorDone(this, self, onComplete, ret); yield; // onComplete is responsible for closing the generator } this._log.warn("generator not properly closed"); diff --git a/services/sync/modules/util.js b/services/sync/modules/util.js index e44f911bc32b..f731671b4a66 100644 --- a/services/sync/modules/util.js +++ b/services/sync/modules/util.js @@ -34,10 +34,7 @@ * * ***** END LICENSE BLOCK ***** */ -const EXPORTED_SYMBOLS = ['deepEquals', 'makeFile', 'makeURI', 'xpath', - 'bind2', 'generatorAsync', 'generatorDone', - 'EventListener', - 'runCmd', 'getTmp', 'open', 'readStream']; +const EXPORTED_SYMBOLS = ['Utils']; const Cc = Components.classes; const Ci = Components.interfaces; @@ -52,132 +49,223 @@ Cu.import("resource://weave/log4moz.js"); * Utility functions */ -function deepEquals(a, b) { - if (!a && !b) +let Utils = { + + deepEquals: function Weave_deepEquals(a, b) { + if (!a && !b) + return true; + if (!a || !b) + return false; + + if (typeof(a) != "object" && typeof(b) != "object") + return a == b; + if (typeof(a) != "object" || typeof(b) != "object") + return false; + + for (let key in a) { + if (typeof(a[key]) == "object") { + if (!typeof(b[key]) == "object") + return false; + if (!Utils.deepEquals(a[key], b[key])) + return false; + } else { + if (a[key] != b[key]) + return false; + } + } return true; - if (!a || !b) - return false; + }, - if (typeof(a) != "object" && typeof(b) != "object") - return a == b; - if (typeof(a) != "object" || typeof(b) != "object") - return false; - - for (let key in a) { - if (typeof(a[key]) == "object") { - if (!typeof(b[key]) == "object") - return false; - if (!deepEquals(a[key], b[key])) - return false; - } else { - if (a[key] != b[key]) - return false; - } - } - return true; -} - -function makeFile(path) { - var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); - file.initWithPath(path); - return file; -} - -function makeURI(URIString) { - if (URIString === null || URIString == "") - return null; - let ioservice = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ioservice.newURI(URIString, null, null); -} - -function xpath(xmlDoc, xpathString) { - let root = xmlDoc.ownerDocument == null ? - xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement - let nsResolver = xmlDoc.createNSResolver(root); - - return xmlDoc.evaluate(xpathString, xmlDoc, nsResolver, - Ci.nsIDOMXPathResult.ANY_TYPE, null); -} - -function bind2(object, method) { - return function innerBind() { return method.apply(object, arguments); } -} - -// Meant to be used like this in code that imports this file: -// -// Function.prototype.async = generatorAsync; -// -// So that you can do: -// -// gen = fooGen.async(...); -// ret = yield; -// -// where fooGen is a generator function, and gen is the running generator. -// ret is whatever the generator 'returns' via generatorDone(). - -function generatorAsync(self, extra_args) { - try { - let args = Array.prototype.slice.call(arguments, 1); - let gen = this.apply(self, args); - gen.next(); // must initialize before sending - gen.send([gen, function(data) {continueGenerator(gen, data);}]); - return gen; - } catch (e) { - if (e instanceof StopIteration) { - dump("async warning: generator stopped unexpectedly"); + makeURI: function Weave_makeURI(URIString) { + if (URIString === null || URIString == "") return null; - } else { - dump("Exception caught: " + e.message); + let ioservice = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + return ioservice.newURI(URIString, null, null); + }, + + xpath: function Weave_xpath(xmlDoc, xpathString) { + let root = xmlDoc.ownerDocument == null ? + xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement + let nsResolver = xmlDoc.createNSResolver(root); + + return xmlDoc.evaluate(xpathString, xmlDoc, nsResolver, + Ci.nsIDOMXPathResult.ANY_TYPE, null); + }, + + bind2: function Weave_bind2(object, method) { + return function innerBind() { return method.apply(object, arguments); } + }, + + // Meant to be used like this in code that imports this file: + // + // Function.prototype.async = generatorAsync; + // + // So that you can do: + // + // gen = fooGen.async(...); + // ret = yield; + // + // where fooGen is a generator function, and gen is the running generator. + // ret is whatever the generator 'returns' via generatorDone(). + + generatorAsync: function Weave_generatorAsync(self, extra_args) { + try { + let args = Array.prototype.slice.call(arguments, 1); + let gen = this.apply(self, args); + gen.next(); // must initialize before sending + gen.send([gen, function(data) {Utils.continueGenerator(gen, data);}]); + return gen; + } catch (e) { + if (e instanceof StopIteration) { + dump("async warning: generator stopped unexpectedly"); + return null; + } else { + dump("Exception caught: " + e.message); + } } + }, + + continueGenerator: function Weave_continueGenerator(generator, data) { + try { generator.send(data); } + catch (e) { + if (e instanceof StopIteration) + dump("continueGenerator warning: generator stopped unexpectedly"); + else + dump("Exception caught: " + e.message); + } + }, + + // generators created using Function.async can't simply call the + // callback with the return value, since that would cause the calling + // function to end up running (after the yield) from inside the + // generator. Instead, generators can call this method which sets up + // a timer to call the callback from a timer (and cleans up the timer + // to avoid leaks). It also closes generators after the timeout, to + // keep things clean. + generatorDone: function Weave_generatorDone(object, generator, callback, retval) { + if (object._timer) + throw "Called generatorDone when there is a timer already set." + + let cb = Utils.bind2(object, function(event) { + generator.close(); + generator = null; + object._timer = null; + if (callback) + callback(retval); + }); + + object._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + object._timer.initWithCallback(new Utils.EventListener(cb), + 0, object._timer.TYPE_ONE_SHOT); + }, + + runCmd: function Weave_runCmd() { + var binary; + var args = []; + + for (let i = 0; i < arguments.length; ++i) { + args.push(arguments[i]); + } + + if (args[0] instanceof Ci.nsIFile) { + binary = args.shift(); + } else { + binary = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); + binary.initWithPath(args.shift()); + } + + var p = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + p.init(binary); + + p.run(true, args, args.length); + return p.exitValue; + }, + + getTmp: function Weave_getTmp(name) { + let ds = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties); + + let tmp = ds.get("ProfD", Ci.nsIFile); + tmp.QueryInterface(Ci.nsILocalFile); + + tmp.append("weave"); + tmp.append("tmp"); + if (!tmp.exists()) + tmp.create(tmp.DIRECTORY_TYPE, PERMS_DIRECTORY); + + if (name) + tmp.append(name); + + return tmp; + }, + + open: function open(pathOrFile, mode, perms) { + let stream, file; + + if (pathOrFile instanceof Ci.nsIFile) { + file = pathOrFile; + } else { + file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); + dump("PATH IS" + pathOrFile + "\n"); + file.initWithPath(pathOrFile); + } + + if (!perms) + perms = PERMS_FILE; + + switch(mode) { + case "<": { + if (!file.exists()) + throw "Cannot open file for reading, file does not exist"; + stream = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + stream.init(file, MODE_RDONLY, perms, 0); + stream.QueryInterface(Ci.nsILineInputStream); + } break; + + case ">": { + stream = Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(Ci.nsIFileOutputStream); + stream.init(file, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, perms, 0); + } break; + + case ">>": { + stream = Cc["@mozilla.org/network/file-output-stream;1"]. + createInstance(Ci.nsIFileOutputStream); + stream.init(file, MODE_WRONLY | MODE_CREATE | MODE_APPEND, perms, 0); + } break; + + default: + throw "Illegal mode to open(): " + mode; + } + + return [stream, file]; + }, + + readStream: function Weave_readStream(fis) { + let data = ""; + while (fis.available()) { + let ret = {}; + fis.readLine(ret); + data += ret.value; + } + return data; + }, + + /* + * Event listener object + * Used to handle XMLHttpRequest and nsITimer callbacks + */ + + EventListener: function Weave_EventListener(handler, eventName) { + this._handler = handler; + this._eventName = eventName; + this._log = Log4Moz.Service.getLogger("Service.EventHandler"); } -} +}; -function continueGenerator(generator, data) { - try { generator.send(data); } - catch (e) { - if (e instanceof StopIteration) - dump("continueGenerator warning: generator stopped unexpectedly"); - else - dump("Exception caught: " + e.message); - } -} - -// generators created using Function.async can't simply call the -// callback with the return value, since that would cause the calling -// function to end up running (after the yield) from inside the -// generator. Instead, generators can call this method which sets up -// a timer to call the callback from a timer (and cleans up the timer -// to avoid leaks). It also closes generators after the timeout, to -// keep things clean. -function generatorDone(object, generator, callback, retval) { - if (object._timer) - throw "Called generatorDone when there is a timer already set." - - let cb = bind2(object, function(event) { - generator.close(); - generator = null; - object._timer = null; - if (callback) - callback(retval); - }); - - object._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - object._timer.initWithCallback(new EventListener(cb), - 0, object._timer.TYPE_ONE_SHOT); -} - -/* - * Event listener object - * Used to handle XMLHttpRequest and nsITimer callbacks - */ - -function EventListener(handler, eventName) { - this._handler = handler; - this._eventName = eventName; - this._log = Log4Moz.Service.getLogger("Service.EventHandler"); -} -EventListener.prototype = { +Utils.EventListener.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback, Ci.nsISupports]), // DOM event listener @@ -191,96 +279,4 @@ EventListener.prototype = { this._log.trace("Timer fired"); this._handler(timer); } -}; - -function runCmd() { - var binary; - var args = []; - - for (let i = 0; i < arguments.length; ++i) { - args.push(arguments[i]); - } - - if (args[0] instanceof Ci.nsIFile) { - binary = args.shift(); - } else { - binary = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); - binary.initWithPath(args.shift()); - } - - var p = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); - p.init(binary); - - p.run(true, args, args.length); - return p.exitValue; -} - -function getTmp(name) { - let ds = Cc["@mozilla.org/file/directory_service;1"]. - getService(Ci.nsIProperties); - - let tmp = ds.get("ProfD", Ci.nsIFile); - tmp.QueryInterface(Ci.nsILocalFile); - - tmp.append("weave"); - tmp.append("tmp"); - if (!tmp.exists()) - tmp.create(tmp.DIRECTORY_TYPE, PERMS_DIRECTORY); - - if (name) - tmp.append(name); - - return tmp; -} - -function open(pathOrFile, mode, perms) { - let stream, file; - - if (pathOrFile instanceof Ci.nsIFile) { - file = pathOrFile; - } else { - file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); - file.initWithPath(pathOrFile); - } - - if (!perms) - perms = PERMS_FILE; - - switch(mode) { - case "<": { - if (!file.exists()) - throw "Cannot open file for reading, file does not exist"; - stream = Cc["@mozilla.org/network/file-input-stream;1"]. - createInstance(Ci.nsIFileInputStream); - stream.init(file, MODE_RDONLY, perms, 0); - stream.QueryInterface(Ci.nsILineInputStream); - } break; - - case ">": { - stream = Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(Ci.nsIFileOutputStream); - stream.init(file, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, perms, 0); - } break; - - case ">>": { - stream = Cc["@mozilla.org/network/file-output-stream;1"]. - createInstance(Ci.nsIFileOutputStream); - stream.init(file, MODE_WRONLY | MODE_CREATE | MODE_APPEND, perms, 0); - } break; - - default: - throw "Illegal mode to open(): " + mode; - } - - return [stream, file]; -} - -function readStream(fis) { - let data = ""; - while (fis.available()) { - let ret = {}; - fis.readLine(ret); - data += ret.value; - } - return data; }