From d7369a90e14847a84e64cc4faa720ce1b8ea501a Mon Sep 17 00:00:00 2001 From: Edward Lee Date: Thu, 25 Jun 2009 14:26:33 -0700 Subject: [PATCH 1/6] Bug 500518 - Update fennec login screen to use richpref styling Use a richlistbox with richpref styling for input/buttons like the rest of the weave prefs. Hide password/passphrase after entering, but keep them visible when entering for the first time. --- services/sync/locales/en-US/fennec.properties | 4 ---- 1 file changed, 4 deletions(-) diff --git a/services/sync/locales/en-US/fennec.properties b/services/sync/locales/en-US/fennec.properties index cbd1e9abac7e..34e69f9f4d71 100644 --- a/services/sync/locales/en-US/fennec.properties +++ b/services/sync/locales/en-US/fennec.properties @@ -13,10 +13,6 @@ fennec.sync.error.generic = Weave had an error when trying to sync. fennec.sync.status = Syncing %S... fennec.sync.status.detail = Syncing (%S %S)... -fennec.username.here = Your Username Here -fennec.password.here = Your Password Here -fennec.passphrase.here = Your Passphrase Here - fennec.turn.weave.off = Turn Weave Off fennec.turn.weave.on = Turn Weave On From b8e79586ebf14e8a873e2893743e46a52ed3a806 Mon Sep 17 00:00:00 2001 From: Anant Narayanan Date: Thu, 25 Jun 2009 16:13:52 -0700 Subject: [PATCH 2/6] Add some docs for Resource module --- services/sync/modules/resource.js | 117 ++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 5 deletions(-) diff --git a/services/sync/modules/resource.js b/services/sync/modules/resource.js index b83d2ef52e5b..44e835ed67ff 100644 --- a/services/sync/modules/resource.js +++ b/services/sync/modules/resource.js @@ -52,6 +52,10 @@ Cu.import("resource://weave/auth.js"); Function.prototype.async = Async.sugar; +// = RequestException = +// +// This function raises an exception through the call +// stack for a failed network request. function RequestException(resource, action, request) { this._resource = resource; this._action = action; @@ -69,12 +73,21 @@ RequestException.prototype = { } }; +// = Resource = +// +// Represents a remote network resource, identified by a URI. function Resource(uri) { this._init(uri); } Resource.prototype = { _logName: "Net.Resource", + // ** {{{ Resource.authenticator }}} ** + // + // Getter and setter for the authenticator module + // responsible for this particular resource. The authenticator + // module may modify the headers to perform authentication + // while performing a request for the resource, for example. get authenticator() { if (this._authenticator) return this._authenticator; @@ -85,6 +98,11 @@ Resource.prototype = { this._authenticator = value; }, + // ** {{{ Resource.headers }}} ** + // + // Getter for access to received headers after the request + // for the resource has been made, setter for headers to be included + // while making a request for the resource. get headers() { return this.authenticator.onRequest(this._headers); }, @@ -99,6 +117,9 @@ Resource.prototype = { } }, + // ** {{{ Resource.uri }}} ** + // + // URI representing this resource. get uri() { return this._uri; }, @@ -111,12 +132,18 @@ Resource.prototype = { this._uri = value; }, + // ** {{{ Resource.spec }}} ** + // + // Get the string representation of the URI. get spec() { if (this._uri) return this._uri.spec; return null; }, + // ** {{{ Resource.data }}} ** + // + // Get and set the data encapulated in the resource. _data: null, get data() this._data, set data(value) { @@ -131,6 +158,11 @@ Resource.prototype = { get downloaded() this._downloaded, get dirty() this._dirty, + // ** {{{ Resource.filters }}} ** + // + // Filters are used to perform pre and post processing on + // requests made for resources. Use these methods to add, + // remove and clear filters applied to the resource. _filters: null, pushFilter: function Res_pushFilter(filter) { this._filters.push(filter); @@ -151,19 +183,28 @@ Resource.prototype = { this._filters = []; }, + // ** {{{ Resource._createRequest }}} ** + // + // This method returns a new IO Channel for requests to be made + // through. It is never called directly, only {{{_request}}} uses it + // to obtain a request channel. + // _createRequest: function Res__createRequest() { this._lastChannel = Svc.IO.newChannel(this.spec, null, null). QueryInterface(Ci.nsIRequest); + // Always validate the cache: let loadFlags = this._lastChannel.loadFlags; loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; loadFlags |= Ci.nsIRequest.INHIBIT_CACHING; this._lastChannel.loadFlags = loadFlags; this._lastChannel = this._lastChannel.QueryInterface(Ci.nsIHttpChannel); - + + // Setup a callback to handle bad HTTPS certificates. this._lastChannel.notificationCallbacks = new badCertListener(); - - let headers = this.headers; // avoid calling the authorizer more than once + + // Avoid calling the authorizer more than once + let headers = this.headers; for (let key in headers) { if (key == 'Authorization') this._log.trace("HTTP Header " + key + ": ***** (suppressed)"); @@ -178,6 +219,10 @@ Resource.prototype = { this._lastProgress = Date.now(); }, + // ** {{{ Resource.filterUpload }}} ** + // + // Apply pre-request filters. Currently, this is done before + // any PUT request. filterUpload: function Res_filterUpload(onComplete) { let fn = function() { let self = yield; @@ -188,6 +233,10 @@ Resource.prototype = { fn.async(this, onComplete); }, + // ** {{{ Resource.filterDownload }}} ** + // + // Apply post-request filters. Currently, this done after + // any GET request. filterDownload: function Res_filterUpload(onComplete) { let fn = function() { let self = yield; @@ -199,6 +248,11 @@ Resource.prototype = { fn.async(this, onComplete); }, + // ** {{{ Resource._request }}} ** + // + // Perform a particular HTTP request on the resource. This method + // is never called directly, but is used by the high-level + // {{{get}}}, {{{put}}}, {{{post}}} and {{delete}} methods. _request: function Res__request(action, data) { let self = yield; let iter = 0; @@ -207,6 +261,8 @@ Resource.prototype = { if ("undefined" != typeof(data)) this._data = data; + // PUT and POST are trreated differently because + // they have payload data. if ("PUT" == action || "POST" == action) { yield this.filterUpload(self.cb); this._log.trace(action + " Body:\n" + this._data); @@ -222,6 +278,8 @@ Resource.prototype = { channel.setUploadStream(stream, type, this._data.length); } + // Setup a channel listener so that the actual network operation + // is performed asynchronously. let listener = new ChannelListener(self.cb, this._onProgress, this._log); channel.requestMethod = action; this._data = yield channel.asyncOpen(listener, null); @@ -253,23 +311,40 @@ Resource.prototype = { self.done(this._data); }, + // ** {{{ Resource.get }}} ** + // + // Perform an asynchronous HTTP GET for this resource. + // onComplete will be called on completion of the request. get: function Res_get(onComplete) { this._request.async(this, onComplete, "GET"); }, - + + // ** {{{ Resource.get }}} ** + // + // Perform a HTTP PUT for this resource. put: function Res_put(onComplete, data) { this._request.async(this, onComplete, "PUT", data); }, + // ** {{{ Resource.post }}} ** + // + // Perform a HTTP POST for this resource. post: function Res_post(onComplete, data) { this._request.async(this, onComplete, "POST", data); }, + // ** {{{ Resource.delete }}} ** + // + // Perform a HTTP DELETE for this resource. delete: function Res_delete(onComplete) { this._request.async(this, onComplete, "DELETE"); } }; +// = ChannelListener = +// +// This object implements the {{{nsIStreamListener}}} interface +// and is called as the network operation proceeds. function ChannelListener(onComplete, onProgress, logger) { this._onComplete = onComplete; this._onProgress = onProgress; @@ -302,11 +377,24 @@ ChannelListener.prototype = { } }; -/* Parses out single WBOs from a full dump */ +// = RecordParser = +// +// This object retrives single WBOs from a stream of incoming +// JSON. This should be useful for performance optimizations +// in cases where memory is low (on Fennec, for example). +// +// XXX: Note that this parser is currently not used because we +// are yet to figure out the best way to integrate it with the +// asynchronous nature of {{{ChannelListener}}}. Ed's work in the +// Sync module will make this easier in the future. function RecordParser(data) { this._data = data; } RecordParser.prototype = { + // ** {{{ RecordParser.getNextRecord }}} ** + // + // Returns a single WBO from the stream of JSON received + // so far. getNextRecord: function RecordParser_getNextRecord() { let start; let bCount = 0; @@ -333,11 +421,23 @@ RecordParser.prototype = { return false; }, + // ** {{{ RecordParser.append }}} ** + // + // Appends data to the current internal buffer + // of received data by the parser. The buffer + // is continously processed as {{{getNextRecord}}} + // is called, so the caller need not keep a copy + // of the data passed to this function. append: function RecordParser_append(data) { this._data += data; } }; +// = JsonFilter = +// +// Currently, the only filter used in conjunction with +// {{{Resource.filters}}}. It simply encodes outgoing records +// as JSON, and decodes incoming JSON into JS objects. function JsonFilter() { let level = "Debug"; try { level = Utils.prefs.getCharPref("log.logger.network.jsonFilter"); } @@ -359,6 +459,13 @@ JsonFilter.prototype = { } }; +// = badCertListener = +// +// We use this listener to ignore bad HTTPS +// certificates and continue a request on a network +// channel. Probably not a very smart thing to do, +// but greatly simplifies debugging and is just very +// convenient. function badCertListener() { } badCertListener.prototype = { From 4046e5cd82727b41c9a6f91b6652f42a4d2a8f6b Mon Sep 17 00:00:00 2001 From: Edward Lee Date: Thu, 25 Jun 2009 17:27:03 -0700 Subject: [PATCH 3/6] Bug 500551 - Failed to load XPCOM component WeaveCrypto.so Only try loading WeaveCrypto maemo binary on Linux (until we get Linux_arm-msvc). --- services/sync/WeaveCrypto.so | Bin 56986 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 services/sync/WeaveCrypto.so diff --git a/services/sync/WeaveCrypto.so b/services/sync/WeaveCrypto.so deleted file mode 100755 index 0259efa9c6626898ec69c1abcc980b723f688f0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56986 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 LT7qN0kP!bL_4K;I From dd9ce3521e62657ffa7f5dd7d28ada736e473035 Mon Sep 17 00:00:00 2001 From: Edward Lee Date: Thu, 25 Jun 2009 22:46:14 -0700 Subject: [PATCH 4/6] Bug 500598 - Undefined item in tabContainer.childNodes after closing tabs The childNodes NodeList keeps its indices even after removal, so it's safer to convert the array-like thing into an actual array. Condense the QueryInterface code to the instanceof magic. --- services/sync/modules/engines/tabs.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/services/sync/modules/engines/tabs.js b/services/sync/modules/engines/tabs.js index 5f9093826c0b..5d22706cf35c 100644 --- a/services/sync/modules/engines/tabs.js +++ b/services/sync/modules/engines/tabs.js @@ -200,16 +200,12 @@ TabStore.prototype = { while (enumerator.hasMoreElements()) { let window = enumerator.getNext(); let tabContainer = window.getBrowser().tabContainer; - for each (let tabChild in tabContainer.childNodes) { - if (!tabChild) { - this._log.warn("Undefined item in tabContainer.childNodes."); - continue; - } - if (!tabChild.QueryInterface) - continue; - let tab = tabChild.QueryInterface(Ci.nsIDOMNode); - if (!tab) + + // Grab each tab child from the array-like child NodeList + for each (let tab in Array.slice(tabContainer.childNodes)) { + if (!(tab instanceof Ci.nsIDOMNode)) continue; + let tabState = JSON.parse(this._sessionStore.getTabState(tab)); // Skip empty (i.e. just-opened, no history yet) tabs: if (tabState.entries.length == 0) From b6e3b95d2daa1d92d8e442faf9c4f1bc293f942f Mon Sep 17 00:00:00 2001 From: Edward Lee Date: Thu, 25 Jun 2009 22:52:28 -0700 Subject: [PATCH 5/6] Convert a log.info to log.debug for passwords so it doesn't clutter the brief log. --- services/sync/modules/engines/passwords.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/sync/modules/engines/passwords.js b/services/sync/modules/engines/passwords.js index b9ff74bb4e9c..982fe05a4927 100644 --- a/services/sync/modules/engines/passwords.js +++ b/services/sync/modules/engines/passwords.js @@ -112,7 +112,7 @@ PasswordStore.prototype = { let logins = Svc.Login.searchLogins({}, prop); if (logins.length > 0) { - this._log.info(logins.length + " items matching " + id + " found."); + this._log.debug(logins.length + " items matching " + id + " found."); return logins[0]; } else { this._log.trace("No items matching " + id + " found. Ignoring"); From 432b95d30f93da087ca5b5430081d15c8dda19a9 Mon Sep 17 00:00:00 2001 From: Dan Mills Date: Wed, 1 Jul 2009 11:51:52 -0700 Subject: [PATCH 6/6] switch from autogenerated load-module tests to a single test that loads all modules --- services/sync/tests/unit/test_load_modules.js | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 services/sync/tests/unit/test_load_modules.js diff --git a/services/sync/tests/unit/test_load_modules.js b/services/sync/tests/unit/test_load_modules.js new file mode 100644 index 000000000000..13dec34b8e7b --- /dev/null +++ b/services/sync/tests/unit/test_load_modules.js @@ -0,0 +1,48 @@ +const modules = ["async.js", + "auth.js", + "base_records/collection.js", + "base_records/crypto.js", + "base_records/keys.js", + "base_records/wbo.js", + "constants.js", + "engines/bookmarks.js", + "engines/clientData.js", + "engines/cookies.js", + "engines/extensions.js", + "engines/forms.js", + "engines/history.js", + "engines/input.js", + "engines/microformats.js", + "engines/passwords.js", + "engines/plugins.js", + "engines/prefs.js", + "engines/tabs.js", + "engines/themes.js", + "engines.js", + "ext/Observers.js", + "ext/Preferences.js", + "faultTolerance.js", + "identity.js", + "log4moz.js", + "notifications.js", + "resource.js", + "service.js", + "stores.js", + "trackers.js", + "type_records/bookmark.js", + "type_records/clientData.js", + "type_records/forms.js", + "type_records/history.js", + "type_records/passwords.js", + "type_records/prefs.js", + "type_records/tabs.js", + "util.js", + "wrap.js"]; + +function run_test() { + for each (let m in modules) { + dump("Attempting to load resource://weave/" + m + "\n"); + Components.utils.import("resource://weave/" + m, {}); + } +} +