--- a/services/crypto/WeaveCrypto.cpp
+++ b/services/crypto/WeaveCrypto.cpp
@@ -45,16 +45,22 @@
#include "plbase64.h"
#include "prmem.h"
#include "secerr.h"
#include "pk11func.h"
#include "keyhi.h"
#include "nss.h"
+/*
+ * In a number of places we use stack buffers to hold smallish temporary data.
+ * 4K is plenty big for the exptected uses, and avoids poking holes in the
+ * heap for small allocations. (Yes, we still check for overflow.)
+ */
+#define STACK_BUFFER_SIZE 4096
NS_IMPL_ISUPPORTS1(WeaveCrypto, IWeaveCrypto)
WeaveCrypto::WeaveCrypto() :
mAlgorithm(SEC_OID_AES_256_CBC),
mKeypairBits(2048)
{
}
@@ -268,19 +274,19 @@ WeaveCrypto::CommonCrypt(const char *inp
{
nsresult rv = NS_OK;
PK11SymKey *symKey = nsnull;
PK11Context *ctx = nsnull;
PK11SlotInfo *slot = nsnull;
SECItem *ivParam = nsnull;
PRUint32 maxOutputSize;
- char keyData[aSymmetricKey.Length()];
+ char keyData[STACK_BUFFER_SIZE];
PRUint32 keyDataSize = sizeof(keyData);
- char ivData[aIV.Length()];
+ char ivData[STACK_BUFFER_SIZE];
PRUint32 ivDataSize = sizeof(ivData);
rv = DecodeBase64(aSymmetricKey, keyData, &keyDataSize);
NS_ENSURE_SUCCESS(rv, rv);
rv = DecodeBase64(aIV, ivData, &ivDataSize);
NS_ENSURE_SUCCESS(rv, rv);
SECItem keyItem = {siBuffer, (unsigned char*)keyData, keyDataSize};
@@ -463,18 +469,18 @@ WeaveCrypto::DeriveKeyFromPassphrase(con
const nsACString& aSalt,
PK11SymKey **aSymKey)
{
nsresult rv;
PromiseFlatCString fPass(aPassphrase);
SECItem passphrase = {siBuffer, (unsigned char *)fPass.get(), fPass.Length()};
- char saltBytes[aSalt.Length()];
- PRUint32 saltBytesLength = aSalt.Length();
+ char saltBytes[STACK_BUFFER_SIZE];
+ PRUint32 saltBytesLength = sizeof(saltBytes);
rv = DecodeBase64(aSalt, saltBytes, &saltBytesLength);
NS_ENSURE_SUCCESS(rv, rv);
SECItem salt = {siBuffer, (unsigned char*)saltBytes, saltBytesLength};
// http://mxr.mozilla.org/seamonkey/source/security/nss/lib/pk11wrap/pk11pbe.c#1261
// Bug 436577 prevents us from just using SEC_OID_PKCS5_PBKDF2 here
SECOidTag pbeAlg = mAlgorithm;
@@ -526,17 +532,17 @@ WeaveCrypto::WrapPrivateKey(SECKEYPrivat
nsresult rv;
SECStatus s;
PK11SymKey *pbeKey = nsnull;
// Convert our passphrase to a symkey and get the IV in the form we want.
rv = DeriveKeyFromPassphrase(aPassphrase, aSalt, &pbeKey);
NS_ENSURE_SUCCESS(rv, rv);
- char ivData[aIV.Length()];
+ char ivData[STACK_BUFFER_SIZE];
PRUint32 ivDataSize = sizeof(ivData);
rv = DecodeBase64(aIV, ivData, &ivDataSize);
NS_ENSURE_SUCCESS(rv, rv);
SECItem ivItem = {siBuffer, (unsigned char*)ivData, ivDataSize};
// AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD
CK_MECHANISM_TYPE wrapMech = PK11_AlgtagToMechanism(mAlgorithm);
wrapMech = PK11_GetPadMechanism(wrapMech);
@@ -549,17 +555,17 @@ WeaveCrypto::WrapPrivateKey(SECKEYPrivat
if (!ivParam) {
NS_WARNING("Couldn't create IV param");
return NS_ERROR_FAILURE;
}
// Use a stack buffer to hold the wrapped key. NSS says about 1200 bytes for
// a 2048-bit RSA key, so our 4096 byte buffer should be plenty.
- unsigned char stackBuffer[4096];
+ unsigned char stackBuffer[STACK_BUFFER_SIZE];
SECItem wrappedKey = {siBuffer, stackBuffer, sizeof(stackBuffer)};
s = PK11_WrapPrivKey(aPrivateKey->pkcs11Slot,
pbeKey, aPrivateKey,
wrapMech, ivParam,
&wrappedKey, nsnull);
SECITEM_FreeItem(ivParam, PR_TRUE);
@@ -603,17 +609,20 @@ WeaveCrypto::EncodePublicKey(SECKEYPubli
/*
* GenerateRandomBytes
*/
NS_IMETHODIMP
WeaveCrypto::GenerateRandomBytes(PRUint32 aByteCount,
nsACString& aEncodedBytes)
{
nsresult rv;
- char random[aByteCount];
+ char random[STACK_BUFFER_SIZE];
+
+ if (aByteCount > STACK_BUFFER_SIZE)
+ return NS_ERROR_OUT_OF_MEMORY;
rv = PK11_GenerateRandom((unsigned char *)random, aByteCount);
NS_ENSURE_SUCCESS(rv, rv);
rv = EncodeBase64(random, aByteCount, aEncodedBytes);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@@ -626,17 +635,20 @@ WeaveCrypto::GenerateRandomBytes(PRUint3
NS_IMETHODIMP
WeaveCrypto::GenerateRandomIV(nsACString& aEncodedBytes)
{
nsresult rv;
CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(mAlgorithm);
PRUint32 size = PK11_GetIVLength(mech);
- char random[size];
+ char random[STACK_BUFFER_SIZE];
+
+ if (size > STACK_BUFFER_SIZE)
+ return NS_ERROR_OUT_OF_MEMORY;
rv = PK11_GenerateRandom((unsigned char *)random, size);
NS_ENSURE_SUCCESS(rv, rv);
rv = EncodeBase64(random, size, aEncodedBytes);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@@ -737,29 +749,29 @@ WeaveCrypto::WrapSymmetricKey(const nsAC
PK11SlotInfo *slot = nsnull;
PK11SymKey *symKey = nsnull;
SECKEYPublicKey *pubKey = nsnull;
CERTSubjectPublicKeyInfo *pubKeyInfo = nsnull;
CK_MECHANISM_TYPE keyMech, wrapMech;
// Step 1. Get rid of the base64 encoding on the inputs.
- char publicKeyBuffer[aPublicKey.Length()];
- PRUint32 publicKeyBufferSize = aPublicKey.Length();
+ char publicKeyBuffer[STACK_BUFFER_SIZE];
+ PRUint32 publicKeyBufferSize = sizeof(publicKeyBuffer);
rv = DecodeBase64(aPublicKey, publicKeyBuffer, &publicKeyBufferSize);
NS_ENSURE_SUCCESS(rv, rv);
SECItem pubKeyData = {siBuffer, (unsigned char *)publicKeyBuffer, publicKeyBufferSize};
- char symKeyBuffer[aSymmetricKey.Length()];
- PRUint32 symKeyBufferSize = aSymmetricKey.Length();
+ char symKeyBuffer[STACK_BUFFER_SIZE];
+ PRUint32 symKeyBufferSize = sizeof(symKeyBuffer);
rv = DecodeBase64(aSymmetricKey, symKeyBuffer, &symKeyBufferSize);
NS_ENSURE_SUCCESS(rv, rv);
SECItem symKeyData = {siBuffer, (unsigned char *)symKeyBuffer, symKeyBufferSize};
- char wrappedBuffer[4096];
+ char wrappedBuffer[STACK_BUFFER_SIZE];
SECItem wrappedKey = {siBuffer, (unsigned char *)wrappedBuffer, sizeof(wrappedBuffer)};
// Step 2. Put the symmetric key bits into a P11 key object.
slot = PK11_GetInternalSlot();
if (!slot) {
NS_WARNING("Can't get internal PK11 slot");
@@ -864,34 +876,34 @@ WeaveCrypto::UnwrapSymmetricKey(const ns
SECItem *keyID = nsnull;
CK_ATTRIBUTE_TYPE privKeyUsage[] = { CKA_UNWRAP };
PRUint32 privKeyUsageLength = sizeof(privKeyUsage) / sizeof(CK_ATTRIBUTE_TYPE);
// Step 1. Get rid of the base64 encoding on the inputs.
- char privateKeyBuffer[aWrappedPrivateKey.Length()];
- PRUint32 privateKeyBufferSize = aWrappedPrivateKey.Length();
+ char privateKeyBuffer[STACK_BUFFER_SIZE];
+ PRUint32 privateKeyBufferSize = sizeof(privateKeyBuffer);
rv = DecodeBase64(aWrappedPrivateKey, privateKeyBuffer, &privateKeyBufferSize);
NS_ENSURE_SUCCESS(rv, rv);
SECItem wrappedPrivKey = {siBuffer, (unsigned char *)privateKeyBuffer, privateKeyBufferSize};
- char wrappedKeyBuffer[aWrappedSymmetricKey.Length()];
- PRUint32 wrappedKeyBufferSize = aWrappedSymmetricKey.Length();
+ char wrappedKeyBuffer[STACK_BUFFER_SIZE];
+ PRUint32 wrappedKeyBufferSize = sizeof(wrappedKeyBuffer);
rv = DecodeBase64(aWrappedSymmetricKey, wrappedKeyBuffer, &wrappedKeyBufferSize);
NS_ENSURE_SUCCESS(rv, rv);
SECItem wrappedSymKey = {siBuffer, (unsigned char *)wrappedKeyBuffer, wrappedKeyBufferSize};
// Step 2. Convert the passphrase to a symmetric key and get the IV in the proper form.
rv = DeriveKeyFromPassphrase(aPassphrase, aSalt, &pbeKey);
NS_ENSURE_SUCCESS(rv, rv);
- char ivData[aIV.Length()];
+ char ivData[STACK_BUFFER_SIZE];
PRUint32 ivDataSize = sizeof(ivData);
rv = DecodeBase64(aIV, ivData, &ivDataSize);
NS_ENSURE_SUCCESS(rv, rv);
SECItem ivItem = {siBuffer, (unsigned char*)ivData, ivDataSize};
// AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD
CK_MECHANISM_TYPE wrapMech = PK11_AlgtagToMechanism(mAlgorithm);
wrapMech = PK11_GetPadMechanism(wrapMech);
--- a/services/sync/locales/en-US/wizard.dtd
+++ b/services/sync/locales/en-US/wizard.dtd
@@ -1,89 +1,99 @@
-<!ENTITY serverError1.description "Server Error: ">
-<!ENTITY serverError2.description ", ">
-
-<!ENTITY wizard.title "Weave Setup">
-
-<!ENTITY intro.title "Welcome to Weave">
-<!ENTITY intro.description "[description of Weave]">
-<!ENTITY intro-more.label "Learn more">
-<!ENTITY intro-more.link "http://labs.mozilla.com">
-
-<!ENTITY welcome.title "Installation Type">
-<!ENTITY curUser-title.label "Sign In">
-<!ENTITY curUser.description "Sign into your existing account to set up Weave on this computer.">
-<!ENTITY newUser-title.label "Get Started">
-<!ENTITY newUser.description "Create a new account.">
-
-<!ENTITY verify.title "Account Verification (Step 1 of 3)">
-<!ENTITY username.label "User name:">
-<!ENTITY password.label "Password:">
-<!ENTITY passphrase.label "Passphrase:">
-<!ENTITY reminder.label "Forgot your password? ">
-<!ENTITY unverified.label "Unverified">
-<!ENTITY recovery.link "https://sm-labs01.mozilla.org:81/client/forgot.php">
-
-<!ENTITY create.title "Create Account (Step 1 of 5)">
-<!ENTITY createUsername.label "Desired login name:">
-<!ENTITY createUsernameHint.label "Examples: Maria, Maria.Emerson">
-<!ENTITY createPassword.label "Choose a password:">
-<!ENTITY createPasswordHint.label "Minimum of 5 characters in length.">
-<!ENTITY createReenterPassword.label "Re-enter password:">
-<!ENTITY createEmail.label "Current email address:">
-<!ENTITY createEmailHint.label "e.g. yourname@domain.com">
-
-<!ENTITY create2.title "Create Account (Step 2 of 5)">
-
-<!ENTITY passphrase.description "You must also now choose an encryption passphrase that is different from your password. This will be used to protect your data on the server.">
-<!ENTITY passphrase-more.label "Learn More">
-<!ENTITY passphrase-more.link "http://labs.mozilla.com">
-
-<!ENTITY reenterPassphrase.label "Re-enter passphrase:">
-<!ENTITY moreInfo.label "More information on choosing a phrase.">
-
-<!ENTITY create3.title "Create Account (Step 3 of 5)">
-
-<!ENTITY instanceName.description "Name this device... explain why... ">
-<!ENTITY instanceName.label "Device name:">
-<!ENTITY examples.label "Examples: "Home computer", "Mobile phone", "Work laptop"">
-
-<!ENTITY data.description "Choose the data that you would like Weave to store for you.">
-<!ENTITY bookmarks.label "Bookmarks">
-<!ENTITY history.label "Browsing History">
-<!ENTITY cookies.label "Cookies">
-<!ENTITY passwords.label "Saved Passwords">
-<!ENTITY tabs.label "Tabs">
-<!ENTITY formdata.label "Saved Form Data">
-
-<!ENTITY captcha.label "Type the characters you see in the image below:">
-<!ENTITY captchaDirections.label "">
-<!ENTITY reloadCaptcha.text "Reload">
-<!ENTITY captchaHint.label "Letters are not case-sensitive.">
-
-<!ENTITY terms.label "Terms of Service">
-<!ENTITY acceptTerms.label "I have read and accept the Terms of Service.">
-
-<!ENTITY final.description "Your account will be created with the following preferences [this screen in progress]">
-
-<!ENTITY initialLogin.label "Signing you in.">
-<!ENTITY initialPrefs.label "Setting your preferences.">
-<!ENTITY initialReset.label "Clearing your default bookmarks.">
-<!ENTITY initialSync.label "Synchronizing your data.">
-<!ENTITY finalStep1Finished.label "Signed in.">
-<!ENTITY finalStep2.label "Synchronizing data...">
-<!ENTITY finalStep3Finished.label "Data synchronized.">
+<!ENTITY wizard.title "Weave Setup">
+
+<!ENTITY intro.title "Welcome to Weave">
+<!ENTITY intro-weave.description "Weave is an experimental prototype from Mozilla Labs that integrates online services with Firefox. ">
+<!ENTITY intro-more.label "Learn more about the Weave project">
+<!ENTITY intro-more.link "http://labs.mozilla.com">
+<!ENTITY intro-warning.description "Warning: Use at your own risk! Backup Firefox data before continuing with installation.">
+
+<!ENTITY eula.title "Software License Agreement">
+<!ENTITY eula.description "Terms and conditions for using this software.">
+<!ENTITY eula.accept "I accept the terms of the License Agreement">
+<!ENTITY eula.decline "I do NOT accept the terms of the License Agreement">
+
+<!ENTITY welcome.title "Installation Type">
+<!ENTITY curUser-title.label "Sign In">
+<!ENTITY curUser.description "Sign into your existing account to set up Weave on this computer.">
+<!ENTITY newUser-title.label "Get Started">
+<!ENTITY newUser.description "Create a new account and upload your Weave data to the server.">
+
+<!ENTITY verify.title "Account Verification (Step 1 of 3)">
+<!ENTITY username.label "User name:">
+<!ENTITY password.label "Password:">
+<!ENTITY passphrase.label "Passphrase:">
+<!ENTITY reminder.label "Forgot your password? ">
+<!ENTITY unverified.label "Unverified">
+<!ENTITY recovery.link "https://sm-labs01.mozilla.org:81/client/forgot.php">
+
+<!ENTITY create.title "Create Account (Step 1 of 5)">
+<!ENTITY createUsername.label "Desired login name:">
+<!ENTITY createUsernameHint.label "Examples: Maria, Maria.Emerson">
+<!ENTITY createPassword.label "Choose a password:">
+<!ENTITY createPasswordHint.label "Minimum of 5 characters in length.">
+<!ENTITY createReenterPassword.label "Re-enter password:">
+<!ENTITY createEmail.label "Current email address:">
+<!ENTITY createEmailHint.label "e.g. yourname@domain.com">
+
+<!ENTITY create2.title "Create Account (Step 2 of 5)">
+
+<!ENTITY passphrase.description "You must also now choose an encryption passphrase that is different from your password. This will be used to protect your data on the server.">
+<!ENTITY passphrase-more.label "Learn More">
+<!ENTITY passphrase-more.link "http://labs.mozilla.com">
+
+<!ENTITY reenterPassphrase.label "Re-enter passphrase:">
+<!ENTITY moreInfo.label "More information on choosing a phrase.">
+
+<!ENTITY create3.title "Create Account (Step 3 of 5)">
+
+<!ENTITY instanceName.description "Choose a name for this device for Weave">
+<!ENTITY instanceName.label "Device name:">
+<!ENTITY examples.label "Examples: "Home computer", "Mobile phone", "Work laptop"">
+
+<!ENTITY data.description "Choose the data that you would like Weave to store for you.">
+<!ENTITY bookmarks.label "Bookmarks">
+<!ENTITY history.label "Browsing History">
+<!ENTITY cookies.label "Cookies">
+<!ENTITY passwords.label "Saved Passwords">
+<!ENTITY tabs.label "Tabs">
+<!ENTITY formdata.label "Saved Form Data">
+
+<!ENTITY captcha.label "Type the characters you see in the image below:">
+<!ENTITY captchaDirections.label "">
+<!ENTITY reloadCaptcha.text "Reload">
+<!ENTITY captchaHint.label "Letters are not case-sensitive.">
+
+<!ENTITY terms.label "Terms of Service">
+<!ENTITY acceptTerms.label "I have read and accept the Terms of Service.">
+
+<!ENTITY final.description "Weave perform an initial synchronization with the following settings. Continue to the next wizard page to accept.">
+
+<!ENTITY initialLogin.label "Signing you in.">
+<!ENTITY initialPrefs.label "Setting your preferences.">
+<!ENTITY initialReset.label "Clearing your default bookmarks.">
+<!ENTITY initialSync.label "Synchronizing your data.">
+<!ENTITY finalStep1Finished.label "Signed in.">
+<!ENTITY finalStep2.label "Synchronizing data...">
+<!ENTITY finalStep3Finished.label "Data synchronized.">
<!ENTITY thankyou.title "Thank you!">
-<!ENTITY thankyou.description "You successfully installed Weave. etc... ">
+<!ENTITY thankyou.description "Weave has been installed on this device and your data has been synchronized. To change your Weave preferences, use the Weave tab of your browser preferences. ">
+
+
+<!ENTITY final-pref-title.description "Preferences">
+<!ENTITY final-account-title.description "Account">
+<!ENTITY final-sync-title.description "Initial Synchronization">
+
+<!ENTITY userCheckFailed1.description "Our server is having problems and we couldn't check that username. ">
+<!ENTITY userCheckFailed2.description " to try again, or click "Done" to exit the setup wizard and try again later.">
-<!ENTITY final-pref-title.description "Preferences">
<!ENTITY final-account-title.description "Account">
<!ENTITY final-sync-title.description "Initial Synchronization">
-<!ENTITY userCheckFailed1.description "Our server is having problems and we couldn't check that username. ">
-<!ENTITY userCheckFailed2.description " to try again, or click "Done" to exit the setup wizard and try again later.">
-
-<!ENTITY finished.description "Good job. You installed Weave. You can change preferences in the Weave tab...">
-<!ENTITY initialLoginFailed1.description "Our server is having problems and we couldn't log you in. ">
-<!ENTITY initialLoginFailed2.description " to try again, or click "Done" to exit the setup wizard and try again later.">
-<!ENTITY initialSyncFailed1.description "Our server is having problems and we couldn't synchronize your data. ">
-<!ENTITY initialSyncFailed2.description " to try again, or click "Done" to exit the setup wizard and try again later.">
-
-<!ENTITY clickHere.text "Click here">
-<!ENTITY tryAgain.text "Try again">
+<!ENTITY finished.description "Good job. You installed Weave. You can change preferences in the Weave tab...">
+<!ENTITY initialLoginFailed1.description "Our server is having problems and we couldn't log you in. ">
+<!ENTITY initialLoginFailed2.description " to try again, or click "Done" to exit the setup wizard and try again later.">
+<!ENTITY initialSyncFailed1.description "Our server is having problems and we couldn't synchronize your data. ">
+<!ENTITY initialSyncFailed2.description " to try again, or click "Done" to exit the setup wizard and try again later.">
+
+<!ENTITY clickHere.text "Click here">
+<!ENTITY tryAgain.text "Try again">
+
+<!ENTITY serverError1.description "Server Error: ">
+<!ENTITY serverError2.description ", ">
--- a/services/sync/locales/en-US/wizard.properties
+++ b/services/sync/locales/en-US/wizard.properties
@@ -35,17 +35,17 @@ create-mail-inuse.label = Emali
create-captcha-missing.label = Captcha response missing
create-password-missing.label = Password missing
create-password-incorrect.label = Password incorrect
create-success.label = Account for %S created.
final-pref-value.label = %S
final-account-value.label = Username: %S
-final-sync-value.label = [Explain that a sync will happen]
+final-sync-value.label = Weave will upload your data to the server.
final-success.label = Weave was successfully installed.
default-name.label = %S's Firefox
default-name-nouser.label = Firefox
bookmarks.label = Bookmarks
history.label = Browsing History
cookies.label = Cookies
--- a/services/sync/modules/async.js
+++ b/services/sync/modules/async.js
@@ -187,16 +187,18 @@ Generator.prototype = {
if (e.asyncStack.indexOf(formatAsyncFrame(this._initFrame)) == -1)
e.addAsyncFrame(this._initFrame);
} else {
e = new AsyncException(this.asyncStack, e);
}
this._exception = e;
+ } else if (e.message && e.message == 'Cannot acquire lock (internal lock)') {
+ this._log.warn("Exception: " + Utils.exceptionStr(e));
} else {
this._log.error("Exception: " + Utils.exceptionStr(e));
this._log.debug("Stack trace:\n" + Utils.stackTrace(e));
}
// continue execution of caller.
// in the case of StopIteration we could return an error right
// away, but instead it's easiest/best to let the caller handle
--- a/services/sync/modules/dav.js
+++ b/services/sync/modules/dav.js
@@ -247,19 +247,16 @@ DAVCollection.prototype = {
let headers = {'Content-type': 'text/xml; charset="utf-8"',
'Depth': '0'};
headers.__proto__ = this._defaultHeaders;
return this._makeRequest.async(this, onComplete, "PROPFIND", path,
headers, data);
},
LOCK: function DC_LOCK(path, data, onComplete) {
- if (!this._lockAllowed)
- throw "Cannot acquire lock (internal lock)";
-
let headers = {'Content-type': 'text/xml; charset="utf-8"',
'Depth': 'infinity',
'Timeout': 'Second-600'};
headers.__proto__ = this._defaultHeaders;
return this._makeRequest.async(this, onComplete, "LOCK", path, headers, data);
},
UNLOCK: function DC_UNLOCK(path, onComplete) {
@@ -314,24 +311,17 @@ DAVCollection.prototype = {
if (lock)
headers['If'] = "<" + lock.URL + "> (<" + lock.token + ">)";
// Make a call to make sure it's working
this._makeRequest.async(this, self.cb, "GET", "", headers);
let resp = yield;
this._log.debug("checkLogin got response status " + resp.status);
- // XXX would be nice if 404 == invalid username, 401 == invalid password.
- let retmsg = "";
- if (resp.status == 401)
- retmsg = "invalid username or password";
- else if (resp.status < 200 || resp.status >= 300)
- retmsg = "server error";
-
- self.done(retmsg);
+ self.done(resp.status);
},
// Locking
_getActiveLock: function DC__getActiveLock() {
let self = yield;
let ret = null;
@@ -359,50 +349,59 @@ DAVCollection.prototype = {
this._log.trace("No active lock token found");
self.done({URL: this._baseURL, token: ret});
},
lock: function DC_lock() {
let self = yield;
this._log.trace("Acquiring lock");
+ if (!this._lockAllowed)
+ throw {message: "Cannot acquire lock (internal lock)"};
+ this._lockAllowed = false;
if (DAVLocks['default']) {
this._log.debug("Lock called, but we already hold a token");
+ this._lockAllowed = true;
self.done();
return;
}
this.LOCK("lock",
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
"<D:lockinfo xmlns:D=\"DAV:\">\n" +
" <D:locktype><D:write/></D:locktype>\n" +
" <D:lockscope><D:exclusive/></D:lockscope>\n" +
"</D:lockinfo>", self.cb);
let resp = yield;
- if (resp.status < 200 || resp.status >= 300)
+ if (resp.status < 200 || resp.status >= 300) {
+ this._lockAllowed = true;
return;
+ }
let tokens = Utils.xpath(resp.responseXML, '//D:locktoken/D:href');
let token = tokens.iterateNext();
if (token) {
DAVLocks['default'] = {
URL: this._baseURL,
token: token.textContent
};
}
if (!DAVLocks['default']) {
this._log.warn("Could not acquire lock");
+ this._lockAllowed = true;
self.done();
return;
}
this._log.trace("Lock acquired");
+ this._lockAllowed = true;
+
self.done(DAVLocks['default']);
},
unlock: function DC_unlock() {
let self = yield;
this._log.trace("Releasing lock");
--- a/services/sync/modules/engines/cookies.js
+++ b/services/sync/modules/engines/cookies.js
@@ -1,8 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jono DiCarlo <jdicarlo@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
const EXPORTED_SYMBOLS = ['CookieEngine', 'CookieTracker', 'CookieStore'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://weave/log4moz.js");
Cu.import("resource://weave/engines.js");
--- a/services/sync/modules/engines/forms.js
+++ b/services/sync/modules/engines/forms.js
@@ -1,21 +1,109 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Anant Narayanan <anant@kix.in>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
const EXPORTED_SYMBOLS = ['FormEngine'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://weave/log4moz.js");
Cu.import("resource://weave/util.js");
Cu.import("resource://weave/engines.js");
Cu.import("resource://weave/syncCores.js");
Cu.import("resource://weave/stores.js");
Cu.import("resource://weave/trackers.js");
+/*
+ * Generate GUID from a name,value pair.
+ * If the concatenated length is less than 40, we just Base64 the JSON.
+ * Otherwise, we Base64 the JSON of the name and SHA1 of the value.
+ * The first character of the key determines which method we used:
+ * '0' for full Base64, '1' for SHA-1'ed val.
+ */
+function _generateFormGUID(nam, val) {
+ var key;
+ var con = nam + val;
+
+ var jso = Cc["@mozilla.org/dom/json;1"].
+ createInstance(Ci.nsIJSON);
+
+ if (con.length <= 40) {
+ key = '0' + btoa(jso.encode([nam, val]));
+ } else {
+ val = Utils.sha1(val);
+ key = '1' + btoa(jso.encode([nam, val]));
+ }
+
+ return key;
+}
+
+/*
+ * Unwrap a name,value pair from a GUID.
+ * Return an array [sha1ed, name, value]
+ * sha1ed is a boolean determining if the value is SHA-1'ed or not.
+ */
+function _unwrapFormGUID(guid) {
+ var jso = Cc["@mozilla.org/dom/json;1"].
+ createInstance(Ci.nsIJSON);
+
+ var ret;
+ var dec = atob(guid.slice(1));
+ var obj = jso.decode(dec);
+
+ switch (guid[0]) {
+ case '0':
+ ret = [false, obj[0], obj[1]];
+ break;
+ case '1':
+ ret = [true, obj[0], obj[1]];
+ break;
+ default:
+ this._log.warn("Unexpected GUID header: " + guid[0] + ", aborting!");
+ return false;
+ }
+
+ return ret;
+}
+
function FormEngine(pbeId) {
this._init(pbeId);
}
FormEngine.prototype = {
get name() { return "forms"; },
get logName() { return "FormEngine"; },
get serverPrefix() { return "user-data/forms/"; },
@@ -66,17 +154,17 @@ FormSyncCore.prototype = {
var found = false;
var stmnt = this._formDB.createStatement("SELECT * FROM moz_formhistory");
/* Same performance restrictions as PasswordSyncCore apply here:
caching required */
while (stmnt.executeStep()) {
var nam = stmnt.getUTF8String(1);
var val = stmnt.getUTF8String(2);
- var key = Utils.sha1(nam + val);
+ var key = _generateFormGUID(nam, val);
if (key == GUID)
found = true;
}
return found;
},
@@ -110,39 +198,71 @@ FormStore.prototype = {
__formHistory: null,
get _formHistory() {
if (!this.__formHistory)
this.__formHistory = Cc["@mozilla.org/satchel/form-history;1"].
getService(Ci.nsIFormHistory2);
return this.__formHistory;
},
+ _getValueFromSHA1: function FormStore__getValueFromSHA1(name, sha) {
+ var query = "SELECT value FROM moz_formhistory WHERE fieldname = '" + name + "'";
+ var stmnt = this._formDB.createStatement(query);
+ var found = false;
+
+ while (stmnt.executeStep()) {
+ var val = stmnt.getUTF8String(0);
+ if (Utils.sha1(val) == sha) {
+ found = val;
+ break;
+ }
+ }
+ return found;
+ },
+
_createCommand: function FormStore__createCommand(command) {
- this._log.info("FormStore got createCommand: " + command );
+ this._log.info("FormStore got createCommand: " + command);
this._formHistory.addEntry(command.data.name, command.data.value);
},
_removeCommand: function FormStore__removeCommand(command) {
- this._log.info("FormStore got removeCommand: " + command );
- this._formHistory.removeEntry(command.data.name, command.data.value);
+ this._log.info("FormStore got removeCommand: " + command);
+
+ var data = _unwrapFormGUID(command.GUID);
+ if (!data) {
+ this._log.warn("Invalid GUID found, ignoring remove request.");
+ return;
+ }
+
+ var nam = data[1];
+ var val = data[2];
+ if (data[0]) {
+ val = this._getValueFromSHA1(nam, val);
+ }
+
+ if (val) {
+ this._formHistory.removeEntry(nam, val);
+ } else {
+ this._log.warn("Form value not found from GUID, ignoring remove request.");
+ }
},
_editCommand: function FormStore__editCommand(command) {
- this._log.info("FormStore got editCommand: " + command );
+ this._log.info("FormStore got editCommand: " + command);
this._log.warn("Form syncs are expected to only be create/remove!");
},
wrap: function FormStore_wrap() {
var items = [];
var stmnt = this._formDB.createStatement("SELECT * FROM moz_formhistory");
while (stmnt.executeStep()) {
var nam = stmnt.getUTF8String(1);
var val = stmnt.getUTF8String(2);
- var key = Utils.sha1(nam + val);
+ var key = _generateFormGUID(nam, val);
items[key] = { name: nam, value: val };
}
return items;
},
wipe: function FormStore_wipe() {
--- a/services/sync/modules/engines/history.js
+++ b/services/sync/modules/engines/history.js
@@ -1,8 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dan Mills <thunder@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
const EXPORTED_SYMBOLS = ['HistoryEngine'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://weave/log4moz.js");
Cu.import("resource://weave/util.js");
--- a/services/sync/modules/engines/passwords.js
+++ b/services/sync/modules/engines/passwords.js
@@ -1,8 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Justin Dolske <dolske@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
const EXPORTED_SYMBOLS = ['PasswordEngine'];
const Cu = Components.utils;
Cu.import("resource://weave/util.js");
Cu.import("resource://weave/engines.js");
Cu.import("resource://weave/syncCores.js");
Cu.import("resource://weave/stores.js");
--- a/services/sync/modules/engines/tabs.js
+++ b/services/sync/modules/engines/tabs.js
@@ -1,8 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Myk Melez <myk@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
const EXPORTED_SYMBOLS = ['TabEngine'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://weave/util.js");
Cu.import("resource://weave/async.js");
@@ -72,21 +108,21 @@ TabSyncCore.prototype = {
// window-specific tabs look the same when identified by URL.
// Get the set of all real and virtual tabs.
let tabs = this._engine.store.wrap();
// XXX Should we convert both to nsIURIs and then use nsIURI::equals
// to compare them?
if (GUID in tabs) {
- this._log.debug("_itemExists: " + GUID + " exists");
+ this._log.trace("_itemExists: " + GUID + " exists");
return true;
}
- this._log.debug("_itemExists: " + GUID + " doesn't exist");
+ this._log.trace("_itemExists: " + GUID + " doesn't exist");
return false;
},
_commandLike: function TSC_commandLike(a, b) {
// Not implemented.
return false;
}
};
@@ -328,32 +364,32 @@ TabStore.prototype = {
let session = this._json.decode(this._sessionStore.getBrowserState());
for (let i = 0; i < session.windows.length; i++) {
let window = session.windows[i];
// For some reason, session store uses one-based array index references,
// (f.e. in the "selectedWindow" and each tab's "index" properties), so we
// convert them to and from JavaScript's zero-based indexes as needed.
let windowID = i + 1;
- this._log.debug("_wrapRealTabs: window " + windowID);
+ this._log.trace("_wrapRealTabs: window " + windowID);
for (let j = 0; j < window.tabs.length; j++) {
let tab = window.tabs[j];
// The session history entry for the page currently loaded in the tab.
// We use the URL of the current page as the ID for the tab.
let currentEntry = tab.entries[tab.index - 1];
if (!currentEntry || !currentEntry.url) {
this._log.warn("_wrapRealTabs: no current entry or no URL, can't " +
"identify " + this._json.encode(tab));
continue;
}
let tabID = currentEntry.url;
- this._log.debug("_wrapRealTabs: tab " + tabID);
+ this._log.trace("_wrapRealTabs: tab " + tabID);
// The ID property of each entry in the tab, which I think contains
// nsISHEntry::ID, changes every time session store restores the tab,
// so we can't sync them, or we would generate edit commands on every
// restart (even though nothing has actually changed).
for each (let entry in tab.entries)
delete entry.ID;
--- a/services/sync/modules/faultTolerance.js
+++ b/services/sync/modules/faultTolerance.js
@@ -1,8 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Atul Varma <varmaa@toolness.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
const Cu = Components.utils;
Cu.import("resource://weave/log4moz.js");
const EXPORTED_SYMBOLS = ["FaultTolerance"];
FaultTolerance = {
get Service() {
if (!this._Service)
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -255,18 +255,22 @@ WeaveSvc.prototype = {
this._scheduleTimer.cancel();
this._scheduleTimer = null;
}
this._log.info("Weave scheduler disabled");
},
_onSchedule: function WeaveSync__onSchedule() {
if (this.enabled) {
- this._log.info("Running scheduled sync");
- this._notify("syncAsNeeded", this._lock(this._syncAsNeeded)).async(this);
+ if (!DAV.allowLock) {
+ this._log.info("Skipping scheduled sync; local operation in progress")
+ } else {
+ this._log.info("Running scheduled sync");
+ this._notify("syncAsNeeded", this._lock(this._syncAsNeeded)).async(this);
+ }
}
},
_initLogs: function WeaveSync__initLogs() {
this._log = Log4Moz.Service.getLogger("Service.Main");
this._log.level =
Log4Moz.Level[Utils.prefs.getCharPref("log.logger.service.main")];
@@ -504,26 +508,26 @@ WeaveSvc.prototype = {
_verifyLogin: function WeaveSync__verifyLogin(username, password) {
let self = yield;
this._log.debug("Verifying login for user " + username);
DAV.baseURL = Utils.prefs.getCharPref("serverURL");
DAV.defaultPrefix = "user/" + username;
- DAV.checkLogin.async(DAV, self.cb, username, password);
- let resultMsg = yield;
+ this._log.info("Using server URL: " + DAV.baseURL + DAV.defaultPrefix);
- // If we got an error message, throw it. [need to throw to cause the
- // _notify() wrapper to generate an error notification for observers].
- if (resultMsg) {
- this._log.debug("Login verification: " + resultMsg);
- throw resultMsg;
+ let status = yield DAV.checkLogin.async(DAV, self.cb, username, password);
+ if (status == 404) {
+ // create user directory (for self-hosted webdav shares)
+ // XXX do this in login?
+ yield this._checkUserDir.async(this, self.cb);
+ status = yield DAV.checkLogin.async(DAV, self.cb, username, password);
}
-
+ Utils.ensureStatus(status, "Login verification failed");
},
login: function WeaveSync_login(onComplete) {
this._localLock(this._notify("login", this._login)).async(this, onComplete);
},
_login: function WeaveSync__login() {
let self = yield;
@@ -534,25 +538,22 @@ WeaveSvc.prototype = {
if (!this.password)
throw "No password given or found in password manager";
DAV.baseURL = Utils.prefs.getCharPref("serverURL");
DAV.defaultPrefix = "user/" + this.userPath;
this._log.info("Using server URL: " + DAV.baseURL + DAV.defaultPrefix);
- this._versionCheck.async(this, self.cb);
- yield;
- this._getKeypair.async(this, self.cb);
- yield;
-
- this._loggedIn = true;
+ yield this._versionCheck.async(this, self.cb);
+ yield this._getKeypair.async(this, self.cb);
this._setSchedule(this.schedule);
+ this._loggedIn = true;
self.done(true);
},
logout: function WeaveSync_logout() {
this._log.info("Logging out");
this._disableSchedule();
this._loggedIn = false;
ID.get('WeaveID').setTempPassword(null); // clear cached password
--- a/services/sync/modules/sharing.js
+++ b/services/sync/modules/sharing.js
@@ -1,8 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Atul Varma <varmaa@toolness.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
EXPORTED_SYMBOLS = ["Sharing"];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://weave/async.js");
--- a/services/sync/modules/stores.js
+++ b/services/sync/modules/stores.js
@@ -163,17 +163,18 @@ SnapshotStore.prototype = {
// special-case guid changes
let newGUID = command.data.GUID,
oldGUID = command.GUID;
this._data[newGUID] = this._data[oldGUID];
delete this._data[oldGUID];
for (let GUID in this._data) {
- if (this._data[GUID].parentGUID == oldGUID)
+ if (("parentGUID" in this._data[GUID]) &&
+ (this._data[GUID].parentGUID == oldGUID))
this._data[GUID].parentGUID = newGUID;
}
}
for (let prop in command.data) {
if (prop == "GUID")
continue;
this._data[command.GUID][prop] = command.data[prop];
}
--- a/services/sync/modules/trackers.js
+++ b/services/sync/modules/trackers.js
@@ -9,17 +9,17 @@
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Bookmarks Sync.
*
* The Initial Developer of the Original Code is Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2007
+ * Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Anant Narayanan <anant@kix.in>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
--- a/services/sync/modules/util.js
+++ b/services/sync/modules/util.js
@@ -198,17 +198,17 @@ let Utils = {
for (let key in thing)
ret[key] = Utils.deepCopy(thing[key]);
}
return ret;
},
exceptionStr: function Weave_exceptionStr(e) {
- let message = e.message? e.message : e;
+ let message = e.message ? e.message : e;
let location = "";
if (e.location)
// It's a wrapped nsIException.
location = e.location;
else if (e.fileName && e.lineNumber)
// It's a standard JS exception.
location = "file '" + e.fileName + "', line " + e.lineNumber;
@@ -302,41 +302,16 @@ let Utils = {
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);
},
- 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);
-
- let log = Log4Moz.Service.getLogger("Service.Util");
- log.debug("Running command: " + binary.path + " " + args.join(" "));
-
- 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");
--- a/services/sync/modules/xmpp/authenticationLayer.js
+++ b/services/sync/modules/xmpp/authenticationLayer.js
@@ -1,8 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jono DiCarlo <jdicarlo@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
const EXPORTED_SYMBOLS = [ "PlainAuthenticator", "Md5DigestAuthenticator" ];
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
Cu.import("resource://weave/log4moz.js");
--- a/services/sync/modules/xmpp/transportLayer.js
+++ b/services/sync/modules/xmpp/transportLayer.js
@@ -1,8 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jono DiCarlo <jdicarlo@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
const EXPORTED_SYMBOLS = ['HTTPPollingTransport'];
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cu = Components.utils;
Cu.import("resource://weave/log4moz.js");
--- a/services/sync/modules/xmpp/xmppClient.js
+++ b/services/sync/modules/xmpp/xmppClient.js
@@ -1,8 +1,44 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Bookmarks Sync.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Jono DiCarlo <jdicarlo@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
const EXPORTED_SYMBOLS = ['XmppClient', 'HTTPPollingTransport', 'PlainAuthenticator', 'Md5DigestAuthenticator'];
// See www.xulplanet.com/tutorials/mozsdk/sockets.php
// http://www.xmpp.org/specs/rfc3920.html
// http://www.process-one.net/docs/ejabberd/guide_en.html
// http://www.xulplanet.com/tutorials/mozsdk/xmlparse.php
// http://developer.mozilla.org/en/docs/xpcshell
// http://developer.mozilla.org/en/docs/Writing_xpcshell-based_unit_tests
--- a/services/sync/services-sync.js
+++ b/services/sync/services-sync.js
@@ -1,9 +1,9 @@
-pref("extensions.weave.serverURL", "https://sm-labs01.mozilla.org:81/");
+pref("extensions.weave.serverURL", "https://services.mozilla.com/0.2/");
pref("extensions.weave.username", "nobody");
pref("extensions.weave.encryption", "aes-256-cbc");
pref("extensions.weave.lastversion", "firstrun");
pref("extensions.weave.lastsync", "0");
pref("extensions.weave.ui.syncnow", true);
@@ -13,17 +13,17 @@ pref("extensions.weave.autoconnect", tru
pref("extensions.weave.enabled", true);
pref("extensions.weave.schedule", 1);
pref("extensions.weave.syncOnQuit.enabled", true);
pref("extensions.weave.engine.bookmarks", true);
pref("extensions.weave.engine.history", true);
pref("extensions.weave.engine.cookies", true );
-pref("extensions.weave.engine.passwords", true );
+pref("extensions.weave.engine.passwords", false);
pref("extensions.weave.engine.forms", true );
pref("extensions.weave.engine.tabs", true);
pref("extensions.weave.log.appender.console", "Warn");
pref("extensions.weave.log.appender.dump", "Error");
pref("extensions.weave.log.appender.briefLog", "Info");
pref("extensions.weave.log.appender.debugLog", "Trace");
old mode 120000
new mode 100644
--- a/services/sync/tests/unit/Makefile
+++ b/services/sync/tests/unit/Makefile
@@ -1,1 +1,2 @@
-../harness/Makefile
\ No newline at end of file
+all:
+ ${MAKE} -f ../harness/Makefile
--- a/services/sync/tests/unit/fake_login_manager.js
+++ b/services/sync/tests/unit/fake_login_manager.js
@@ -22,16 +22,17 @@ let fakeSampleLogins = [
function FakeLoginManager(fakeLogins) {
this.fakeLogins = fakeLogins;
let self = this;
Utils.getLoginManager = function fake_getLoginManager() {
// Return a fake nsILoginManager object.
return {
+ removeAllLogins: function() { self.fakeLogins = []; },
getAllLogins: function() { return self.fakeLogins; },
addLogin: function(login) {
getTestLogger().info("nsILoginManager.addLogin() called " +
"with hostname '" + login.hostname + "'.");
self.fakeLogins.push(login);
}
};
};
--- a/services/sync/tests/unit/head_first.js
+++ b/services/sync/tests/unit/head_first.js
@@ -269,59 +269,122 @@ function FakeFilesystemService(contents)
function FakeGUIDService() {
let latestGUID = 0;
Utils.makeGUID = function fake_makeGUID() {
return "fake-guid-" + latestGUID++;
};
}
-function SyncTestingInfrastructure() {
+function SyncTestingInfrastructure(engineFactory) {
let __fakePasswords = {
'Mozilla Services Password': {foo: "bar"},
'Mozilla Services Encryption Passphrase': {foo: "passphrase"}
};
let __fakePrefs = {
"encryption" : "none",
"log.logger.service.crypto" : "Debug",
"log.logger.service.engine" : "Debug",
"log.logger.async" : "Debug",
"xmpp.enabled" : false
};
Cu.import("resource://weave/identity.js");
+ Cu.import("resource://weave/util.js");
ID.set('WeaveID',
new Identity('Mozilla Services Encryption Passphrase', 'foo'));
this.fakePasswordService = new FakePasswordService(__fakePasswords);
this.fakePrefService = new FakePrefService(__fakePrefs);
this.fakeDAVService = new FakeDAVService({});
this.fakeTimerService = new FakeTimerService();
this.logStats = initTestLogging();
this.fakeFilesystem = new FakeFilesystemService({});
this.fakeGUIDService = new FakeGUIDService();
+ this._logger = getTestLogger();
+ this._engineFactory = engineFactory;
+ this._clientStates = [];
+
+ this.saveClientState = function pushClientState(label) {
+ let state = Utils.deepCopy(this.fakeFilesystem.fakeContents);
+ let currContents = this.fakeFilesystem.fakeContents;
+ this.fakeFilesystem.fakeContents = [];
+ let engine = this._engineFactory();
+ let snapshot = Utils.deepCopy(engine._store.wrap());
+ this._clientStates[label] = {state: state, snapshot: snapshot};
+ this.fakeFilesystem.fakeContents = currContents;
+ };
+
+ this.restoreClientState = function restoreClientState(label) {
+ let state = this._clientStates[label].state;
+ let snapshot = this._clientStates[label].snapshot;
+
+ function _restoreState() {
+ let self = yield;
+
+ this.fakeFilesystem.fakeContents = [];
+ let engine = this._engineFactory();
+ engine._store.wipe();
+ let originalSnapshot = Utils.deepCopy(engine._store.wrap());
+
+ engine._core.detectUpdates(self.cb, originalSnapshot, snapshot);
+ let commands = yield;
+
+ engine._store.applyCommands.async(engine._store, self.cb, commands);
+ yield;
+
+ this.fakeFilesystem.fakeContents = Utils.deepCopy(state);
+ }
+
+ let self = this;
+
+ function restoreState(cb) {
+ _restoreState.async(self, cb);
+ }
+
+ this.runAsyncFunc("restore client state of " + label,
+ restoreState);
+ };
+
this.__makeCallback = function __makeCallback() {
this.__callbackCalled = false;
let self = this;
return function callback() {
self.__callbackCalled = true;
};
};
+ this.doSync = function doSync(name) {
+ let self = this;
+
+ function freshEngineSync(cb) {
+ let engine = self._engineFactory();
+ engine.sync(cb);
+ }
+
+ this.runAsyncFunc(name, freshEngineSync);
+ };
+
this.runAsyncFunc = function runAsyncFunc(name, func) {
- let logger = getTestLogger();
+ let logger = this._logger;
logger.info("-----------------------------------------");
logger.info("Step '" + name + "' starting.");
logger.info("-----------------------------------------");
func(this.__makeCallback());
while (this.fakeTimerService.processCallback()) {}
do_check_true(this.__callbackCalled);
for (name in Async.outstandingGenerators)
logger.warn("Outstanding generator exists: " + name);
do_check_eq(this.logStats.errorsLogged, 0);
do_check_eq(Async.outstandingGenerators.length, 0);
logger.info("Step '" + name + "' succeeded.");
};
+
+ this.resetClientState = function resetClientState() {
+ this.fakeFilesystem.fakeContents = {};
+ let engine = this._engineFactory();
+ engine._store.wipe();
+ };
}
--- a/services/sync/tests/unit/test_bookmark_syncing.js
+++ b/services/sync/tests/unit/test_bookmark_syncing.js
@@ -1,65 +1,110 @@
Cu.import("resource://weave/engines/bookmarks.js");
+Cu.import("resource://weave/util.js");
+Cu.import("resource://weave/async.js");
+
+Function.prototype.async = Async.sugar;
load("bookmark_setup.js");
// ----------------------------------------
// Test Logic
// ----------------------------------------
function FakeMicrosummaryService() {
return {hasMicrosummary: function() { return false; }};
}
-function run_test() {
- var syncTesting = new SyncTestingInfrastructure();
+function makeBookmarksEngine() {
+ let engine = new BookmarksEngine();
+ engine._store.__ms = new FakeMicrosummaryService();
+ return engine;
+}
- function freshEngineSync(cb) {
- let engine = new BookmarksEngine();
- engine._store.__ms = new FakeMicrosummaryService();
- engine.sync(cb);
- };
+function run_test() {
+ // -----
+ // Setup
+ // -----
- function resetProfile() {
- // Simulate going to another computer by removing stuff from our
- // objects.
- syncTesting.fakeFilesystem.fakeContents = {};
- bms.removeItem(boogleBm);
- bms.removeItem(yoogleBm);
- }
+ var syncTesting = new SyncTestingInfrastructure(makeBookmarksEngine);
let bms = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
cleanUp();
+ // -----------
+ // Test Proper
+ // -----------
+
let boogleBm = bms.insertBookmark(bms.bookmarksMenuFolder,
uri("http://www.boogle.com"),
-1,
"Boogle");
bms.setItemGUID(boogleBm, "boogle-bookmark-guid");
- syncTesting.runAsyncFunc("initial sync w/ one bookmark", freshEngineSync);
+ syncTesting.doSync("initial sync w/ one bookmark");
- syncTesting.runAsyncFunc("trivial re-sync", freshEngineSync);
+ syncTesting.doSync("trivial re-sync");
let yoogleBm = bms.insertBookmark(bms.bookmarksMenuFolder,
uri("http://www.yoogle.com"),
-1,
"Yoogle");
bms.setItemGUID(yoogleBm, "yoogle-bookmark-guid");
- syncTesting.runAsyncFunc("add bookmark and re-sync", freshEngineSync);
+ syncTesting.doSync("add bookmark and re-sync");
bms.moveItem(yoogleBm,
bms.bookmarksMenuFolder,
0);
- syncTesting.runAsyncFunc("swap bookmark order and re-sync",
- freshEngineSync);
+ syncTesting.doSync("swap bookmark order and re-sync");
+
+ syncTesting.saveClientState("first computer");
+
+ syncTesting.resetClientState();
+
+ syncTesting.doSync("re-sync on second computer");
+
+ let zoogleBm = bms.insertBookmark(bms.bookmarksMenuFolder,
+ uri("http://www.zoogle.com"),
+ -1,
+ "Zoogle");
+ bms.setItemGUID(zoogleBm, "zoogle-bookmark-guid");
+
+ syncTesting.doSync("add bookmark on second computer and resync");
+
+ syncTesting.saveClientState("second computer");
+
+ syncTesting.restoreClientState("first computer");
+ syncTesting.doSync("re-sync on first computer");
- resetProfile();
+ let binkBm1 = bms.insertBookmark(bms.bookmarksMenuFolder,
+ uri("http://www.bink.com"),
+ -1,
+ "Bink");
+ bms.setItemGUID(binkBm1, "bink-bookmark-guid-1");
+
+ syncTesting.doSync("add bookmark 'bink' on first computer and resync");
+ syncTesting.restoreClientState("second computer");
- syncTesting.runAsyncFunc("re-sync on second computer", freshEngineSync);
+ let binkBm2 = bms.insertBookmark(bms.bookmarksMenuFolder,
+ uri("http://www.bink.com"),
+ -1,
+ "Bink");
+
+ bms.setItemGUID(binkBm2, "bink-bookmark-guid-2");
+
+ syncTesting.doSync("Manually add same bookmark 'bink', but with " +
+ "different GUID, to second computer and resync");
+
+ binkBm2 = bms.getBookmarkIdsForURI(uri("http://www.bink.com"), {})[0];
+
+ do_check_eq(bms.getItemGUID(binkBm2), "bink-bookmark-guid-1");
+
+ // --------
+ // Teardown
+ // --------
cleanUp();
}
--- a/services/sync/tests/unit/test_bookmark_syncing.log.expected
+++ b/services/sync/tests/unit/test_bookmark_syncing.log.expected
@@ -170,11 +170,188 @@ Service.BStore TRACE Processing command:
Service.BStore DEBUG -> creating bookmark "Yoogle"
Service.SnapStore INFO Saving snapshot to disk
Testing INFO Opening 'weave/snapshots/bookmarks.json' for writing.
Testing INFO Writing data to local file 'weave/snapshots/bookmarks.json': {"version":2,"GUID":"fake-guid-0","snapshot":{"menu":{"type":"folder"},"toolbar":{"type":"folder"},"unfiled":{"type":"folder"},"boogle-bookmark-guid":{"parentGUID":"menu","index":1,"type":"bookmark","title":"Boogle","URI":"http://www.boogle.com/","tags":[],"keyword":null},"yoogle-bookmark-guid":{"parentGUID":"menu","index":0,"type":"bookmark","title":"Yoogle","URI":"http://www.yoogle.com/","tags":[],"keyword":null}}}
Service.BmkEngine INFO Actual changes for server: 0
Service.BmkEngine DEBUG Actual changes for server: []
Service.BmkEngine INFO Sync complete
Testing INFO Step 're-sync on second computer' succeeded.
+Testing INFO -----------------------------------------
+Testing INFO Step 'add bookmark on second computer and resync' starting.
+Testing INFO -----------------------------------------
+Testing INFO Opening 'weave/snapshots/bookmarks.json' for reading.
+Testing INFO Reading from stream.
+Service.SnapStore INFO Read saved snapshot from disk
+Service.BmkEngine INFO Beginning sync
+Testing INFO HTTP MKCOL on user-data/bookmarks/deltas
+Service.RemoteStore DEBUG Downloading status file
+Testing INFO HTTP GET from user-data/bookmarks/status.json, returning status 200
+Service.Resource DEBUG GET request successful
+Service.JsonFilter DEBUG Decoding JSON data
+Service.RemoteStore DEBUG Downloading status file... done
+Service.BmkEngine INFO Local snapshot version: 2
+Service.BmkEngine INFO Server maxVersion: 2
+Service.RemoteStore DEBUG Using last sync snapshot as server snapshot (snap version == max version)
+Service.RemoteStore TRACE Local snapshot version == server maxVersion
+Service.BmkEngine INFO Reconciling client/server updates
+Service.BMSync DEBUG Reconciling 1 against 0 commands
+Service.BmkEngine INFO Changes for client: 0
+Service.BmkEngine INFO Predicted changes for server: 1
+Service.BmkEngine INFO Client conflicts: 0
+Service.BmkEngine INFO Server conflicts: 0
+Service.BmkEngine INFO Actual changes for server: 1
+Service.BmkEngine DEBUG Actual changes for server: [{"action":"create","GUID":"zoogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null}}]
+Service.BmkEngine INFO Uploading changes to server
+Service.JsonFilter DEBUG Encoding data as JSON
+Service.CryptoFilter DEBUG Encrypting data
+Service.Crypto DEBUG NOT encrypting data
+Testing INFO HTTP PUT to user-data/bookmarks/deltas/3 with data: [{"action":"create","GUID":"zoogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null}}]
+Service.ResourceSet DEBUG PUT request successful
+Service.JsonFilter DEBUG Encoding data as JSON
+Testing INFO HTTP PUT to user-data/bookmarks/status.json with data: {"GUID":"fake-guid-0","formatVersion":2,"snapVersion":0,"maxVersion":3,"snapEncryption":"none","deltasEncryption":"none","itemCount":6}
+Service.Resource DEBUG PUT request successful
+Service.BmkEngine INFO Successfully updated deltas and status on server
+Service.SnapStore INFO Saving snapshot to disk
+Testing INFO Opening 'weave/snapshots/bookmarks.json' for writing.
+Testing INFO Writing data to local file 'weave/snapshots/bookmarks.json': {"version":3,"GUID":"fake-guid-0","snapshot":{"yoogle-bookmark-guid":{"parentGUID":"menu","index":0,"type":"bookmark","title":"Yoogle","URI":"http://www.yoogle.com/","tags":[],"keyword":null},"boogle-bookmark-guid":{"parentGUID":"menu","index":1,"type":"bookmark","title":"Boogle","URI":"http://www.boogle.com/","tags":[],"keyword":null},"zoogle-bookmark-guid":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null},"menu":{"type":"folder"},"toolbar":{"type":"folder"},"unfiled":{"type":"folder"}}}
+Service.BmkEngine INFO Sync complete
+Testing INFO Step 'add bookmark on second computer and resync' succeeded.
+Testing INFO -----------------------------------------
+Testing INFO Step 'restore client state of first computer' starting.
+Testing INFO -----------------------------------------
+Service.BStore TRACE Processing command: {"action":"create","GUID":"yoogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":0,"type":"bookmark","title":"Yoogle","URI":"http://www.yoogle.com/","tags":[],"keyword":null}}
+Service.BStore DEBUG -> creating bookmark "Yoogle"
+Service.BStore TRACE Processing command: {"action":"create","GUID":"boogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":1,"type":"bookmark","title":"Boogle","URI":"http://www.boogle.com/","tags":[],"keyword":null}}
+Service.BStore DEBUG -> creating bookmark "Boogle"
+Testing INFO Step 'restore client state of first computer' succeeded.
+Testing INFO -----------------------------------------
+Testing INFO Step 're-sync on first computer' starting.
+Testing INFO -----------------------------------------
+Testing INFO Opening 'weave/snapshots/bookmarks.json' for reading.
+Testing INFO Reading from stream.
+Service.SnapStore INFO Read saved snapshot from disk
+Service.BmkEngine INFO Beginning sync
+Testing INFO HTTP MKCOL on user-data/bookmarks/deltas
+Service.RemoteStore DEBUG Downloading status file
+Testing INFO HTTP GET from user-data/bookmarks/status.json, returning status 200
+Service.Resource DEBUG GET request successful
+Service.JsonFilter DEBUG Decoding JSON data
+Service.RemoteStore DEBUG Downloading status file... done
+Service.BmkEngine INFO Local snapshot version: 2
+Service.BmkEngine INFO Server maxVersion: 3
+Service.RemoteStore DEBUG Using last sync snapshot as starting point for server snapshot
+Service.RemoteStore INFO Downloading server deltas
+Testing INFO HTTP GET from user-data/bookmarks/deltas/3, returning status 200
+Service.ResourceSet DEBUG GET request successful
+Service.CryptoFilter DEBUG Decrypting data
+Service.Crypto DEBUG NOT decrypting data
+Service.JsonFilter DEBUG Decoding JSON data
+Service.SnapStore TRACE Processing command: {"action":"create","GUID":"zoogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null}}
+Service.BmkEngine INFO Reconciling client/server updates
+Service.BMSync DEBUG Reconciling 0 against 1 commands
+Service.BmkEngine INFO Changes for client: 1
+Service.BmkEngine INFO Predicted changes for server: 0
+Service.BmkEngine INFO Client conflicts: 0
+Service.BmkEngine INFO Server conflicts: 0
+Service.BmkEngine INFO Applying changes locally
+Service.SnapStore TRACE Processing command: {"action":"create","GUID":"zoogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null}}
+Service.BStore TRACE Processing command: {"action":"create","GUID":"zoogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null}}
+Service.BStore DEBUG -> creating bookmark "Zoogle"
+Service.SnapStore INFO Saving snapshot to disk
+Testing INFO Opening 'weave/snapshots/bookmarks.json' for writing.
+Testing INFO Writing data to local file 'weave/snapshots/bookmarks.json': {"version":3,"GUID":"fake-guid-0","snapshot":{"yoogle-bookmark-guid":{"parentGUID":"menu","index":0,"type":"bookmark","title":"Yoogle","URI":"http://www.yoogle.com/","tags":[],"keyword":null},"boogle-bookmark-guid":{"parentGUID":"menu","index":1,"type":"bookmark","title":"Boogle","URI":"http://www.boogle.com/","tags":[],"keyword":null},"menu":{"type":"folder"},"toolbar":{"type":"folder"},"unfiled":{"type":"folder"},"zoogle-bookmark-guid":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null}}}
+Service.BmkEngine INFO Actual changes for server: 0
+Service.BmkEngine DEBUG Actual changes for server: []
+Service.BmkEngine INFO Sync complete
+Testing INFO Step 're-sync on first computer' succeeded.
+Testing INFO -----------------------------------------
+Testing INFO Step 'add bookmark 'bink' on first computer and resync' starting.
+Testing INFO -----------------------------------------
+Testing INFO Opening 'weave/snapshots/bookmarks.json' for reading.
+Testing INFO Reading from stream.
+Service.SnapStore INFO Read saved snapshot from disk
+Service.BmkEngine INFO Beginning sync
+Testing INFO HTTP MKCOL on user-data/bookmarks/deltas
+Service.RemoteStore DEBUG Downloading status file
+Testing INFO HTTP GET from user-data/bookmarks/status.json, returning status 200
+Service.Resource DEBUG GET request successful
+Service.JsonFilter DEBUG Decoding JSON data
+Service.RemoteStore DEBUG Downloading status file... done
+Service.BmkEngine INFO Local snapshot version: 3
+Service.BmkEngine INFO Server maxVersion: 3
+Service.RemoteStore DEBUG Using last sync snapshot as server snapshot (snap version == max version)
+Service.RemoteStore TRACE Local snapshot version == server maxVersion
+Service.BmkEngine INFO Reconciling client/server updates
+Service.BMSync DEBUG Reconciling 1 against 0 commands
+Service.BmkEngine INFO Changes for client: 0
+Service.BmkEngine INFO Predicted changes for server: 1
+Service.BmkEngine INFO Client conflicts: 0
+Service.BmkEngine INFO Server conflicts: 0
+Service.BmkEngine INFO Actual changes for server: 1
+Service.BmkEngine DEBUG Actual changes for server: [{"action":"create","GUID":"bink-bookmark-guid-1","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":3,"type":"bookmark","title":"Bink","URI":"http://www.bink.com/","tags":[],"keyword":null}}]
+Service.BmkEngine INFO Uploading changes to server
+Service.JsonFilter DEBUG Encoding data as JSON
+Service.CryptoFilter DEBUG Encrypting data
+Service.Crypto DEBUG NOT encrypting data
+Testing INFO HTTP PUT to user-data/bookmarks/deltas/4 with data: [{"action":"create","GUID":"bink-bookmark-guid-1","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":3,"type":"bookmark","title":"Bink","URI":"http://www.bink.com/","tags":[],"keyword":null}}]
+Service.ResourceSet DEBUG PUT request successful
+Service.JsonFilter DEBUG Encoding data as JSON
+Testing INFO HTTP PUT to user-data/bookmarks/status.json with data: {"GUID":"fake-guid-0","formatVersion":2,"snapVersion":0,"maxVersion":4,"snapEncryption":"none","deltasEncryption":"none","itemCount":7}
+Service.Resource DEBUG PUT request successful
+Service.BmkEngine INFO Successfully updated deltas and status on server
+Service.SnapStore INFO Saving snapshot to disk
+Testing INFO Opening 'weave/snapshots/bookmarks.json' for writing.
+Testing INFO Writing data to local file 'weave/snapshots/bookmarks.json': {"version":4,"GUID":"fake-guid-0","snapshot":{"yoogle-bookmark-guid":{"parentGUID":"menu","index":0,"type":"bookmark","title":"Yoogle","URI":"http://www.yoogle.com/","tags":[],"keyword":null},"boogle-bookmark-guid":{"parentGUID":"menu","index":1,"type":"bookmark","title":"Boogle","URI":"http://www.boogle.com/","tags":[],"keyword":null},"zoogle-bookmark-guid":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null},"bink-bookmark-guid-1":{"parentGUID":"menu","index":3,"type":"bookmark","title":"Bink","URI":"http://www.bink.com/","tags":[],"keyword":null},"menu":{"type":"folder"},"toolbar":{"type":"folder"},"unfiled":{"type":"folder"}}}
+Service.BmkEngine INFO Sync complete
+Testing INFO Step 'add bookmark 'bink' on first computer and resync' succeeded.
+Testing INFO -----------------------------------------
+Testing INFO Step 'restore client state of second computer' starting.
+Testing INFO -----------------------------------------
+Service.BStore TRACE Processing command: {"action":"create","GUID":"yoogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":0,"type":"bookmark","title":"Yoogle","URI":"http://www.yoogle.com/","tags":[],"keyword":null}}
+Service.BStore DEBUG -> creating bookmark "Yoogle"
+Service.BStore TRACE Processing command: {"action":"create","GUID":"boogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":1,"type":"bookmark","title":"Boogle","URI":"http://www.boogle.com/","tags":[],"keyword":null}}
+Service.BStore DEBUG -> creating bookmark "Boogle"
+Service.BStore TRACE Processing command: {"action":"create","GUID":"zoogle-bookmark-guid","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null}}
+Service.BStore DEBUG -> creating bookmark "Zoogle"
+Testing INFO Step 'restore client state of second computer' succeeded.
+Testing INFO -----------------------------------------
+Testing INFO Step 'Manually add same bookmark 'bink', but with different GUID, to second computer and resync' starting.
+Testing INFO -----------------------------------------
+Testing INFO Opening 'weave/snapshots/bookmarks.json' for reading.
+Testing INFO Reading from stream.
+Service.SnapStore INFO Read saved snapshot from disk
+Service.BmkEngine INFO Beginning sync
+Testing INFO HTTP MKCOL on user-data/bookmarks/deltas
+Service.RemoteStore DEBUG Downloading status file
+Testing INFO HTTP GET from user-data/bookmarks/status.json, returning status 200
+Service.Resource DEBUG GET request successful
+Service.JsonFilter DEBUG Decoding JSON data
+Service.RemoteStore DEBUG Downloading status file... done
+Service.BmkEngine INFO Local snapshot version: 3
+Service.BmkEngine INFO Server maxVersion: 4
+Service.RemoteStore DEBUG Using last sync snapshot as starting point for server snapshot
+Service.RemoteStore INFO Downloading server deltas
+Testing INFO HTTP GET from user-data/bookmarks/deltas/4, returning status 200
+Service.ResourceSet DEBUG GET request successful
+Service.CryptoFilter DEBUG Decrypting data
+Service.Crypto DEBUG NOT decrypting data
+Service.JsonFilter DEBUG Decoding JSON data
+Service.SnapStore TRACE Processing command: {"action":"create","GUID":"bink-bookmark-guid-1","depth":1,"parents":["menu"],"data":{"parentGUID":"menu","index":3,"type":"bookmark","title":"Bink","URI":"http://www.bink.com/","tags":[],"keyword":null}}
+Service.BmkEngine INFO Reconciling client/server updates
+Service.BMSync DEBUG Reconciling 1 against 1 commands
+Service.BmkEngine INFO Changes for client: 1
+Service.BmkEngine INFO Predicted changes for server: 0
+Service.BmkEngine INFO Client conflicts: 0
+Service.BmkEngine INFO Server conflicts: 0
+Service.BmkEngine INFO Applying changes locally
+Service.SnapStore TRACE Processing command: {"action":"edit","GUID":"bink-bookmark-guid-2","data":{"GUID":"bink-bookmark-guid-1"}}
+Service.BStore TRACE Processing command: {"action":"edit","GUID":"bink-bookmark-guid-2","data":{"GUID":"bink-bookmark-guid-1"}}
+Service.SnapStore INFO Saving snapshot to disk
+Testing INFO Opening 'weave/snapshots/bookmarks.json' for writing.
+Testing INFO Writing data to local file 'weave/snapshots/bookmarks.json': {"version":4,"GUID":"fake-guid-0","snapshot":{"yoogle-bookmark-guid":{"parentGUID":"menu","index":0,"type":"bookmark","title":"Yoogle","URI":"http://www.yoogle.com/","tags":[],"keyword":null},"boogle-bookmark-guid":{"parentGUID":"menu","index":1,"type":"bookmark","title":"Boogle","URI":"http://www.boogle.com/","tags":[],"keyword":null},"zoogle-bookmark-guid":{"parentGUID":"menu","index":2,"type":"bookmark","title":"Zoogle","URI":"http://www.zoogle.com/","tags":[],"keyword":null},"menu":{"type":"folder"},"toolbar":{"type":"folder"},"unfiled":{"type":"folder"},"bink-bookmark-guid-1":{"parentGUID":"menu","index":3,"type":"bookmark","title":"Bink","URI":"http://www.bink.com/","tags":[],"keyword":null}}}
+Service.BmkEngine INFO Actual changes for server: 0
+Service.BmkEngine DEBUG Actual changes for server: []
+Service.BmkEngine INFO Sync complete
+Testing INFO Step 'Manually add same bookmark 'bink', but with different GUID, to second computer and resync' succeeded.
*** test finished
*** exiting
*** PASS ***
--- a/services/sync/tests/unit/test_password_syncing.js
+++ b/services/sync/tests/unit/test_password_syncing.js
@@ -2,41 +2,36 @@ Cu.import("resource://weave/engines/pass
load("fake_login_manager.js");
// ----------------------------------------
// Test Logic
// ----------------------------------------
function run_test() {
- var syncTesting = new SyncTestingInfrastructure();
+ function passwdFactory() { return new PasswordEngine(); }
+ var syncTesting = new SyncTestingInfrastructure(passwdFactory);
var fakeLoginManager = new FakeLoginManager(fakeSampleLogins);
- function freshEngineSync(cb) {
- let engine = new PasswordEngine();
- engine.sync(cb);
- };
+ syncTesting.doSync("initial sync");
- syncTesting.runAsyncFunc("initial sync", freshEngineSync);
-
- syncTesting.runAsyncFunc("trivial re-sync", freshEngineSync);
+ syncTesting.doSync("trivial re-sync");
fakeLoginManager.fakeLogins.push(
{hostname: "www.yoogle.com",
formSubmitURL: "http://www.yoogle.com/search",
httpRealm: "",
username: "",
password: "",
usernameField: "test_person2",
passwordField: "test_password2"}
);
- syncTesting.runAsyncFunc("add user and re-sync", freshEngineSync);
+ syncTesting.doSync("add user and re-sync");
fakeLoginManager.fakeLogins.pop();
- syncTesting.runAsyncFunc("remove user and re-sync", freshEngineSync);
+ syncTesting.doSync("remove user and re-sync");
- syncTesting.fakeFilesystem.fakeContents = {};
- fakeLoginManager.fakeLogins = [];
+ syncTesting.resetClientState();
- syncTesting.runAsyncFunc("resync on second computer", freshEngineSync);
+ syncTesting.doSync("resync on second computer");
}
--- a/services/sync/tests/unit/test_password_syncing.log.expected
+++ b/services/sync/tests/unit/test_password_syncing.log.expected
@@ -1,46 +1,41 @@
*** test pending
Testing INFO -----------------------------------------
Testing INFO Step 'initial sync' starting.
Testing INFO -----------------------------------------
Service.PasswordEngine INFO Beginning sync
-Testing INFO HTTP MKCOL on user-data/passwords/
+Testing INFO HTTP MKCOL on user-data/passwords/deltas
Service.RemoteStore DEBUG Downloading status file
Testing INFO HTTP GET from user-data/passwords/status.json, returning status 404
Service.PasswordEngine INFO Initial upload to server
Service.JsonFilter DEBUG Encoding data as JSON
Testing INFO HTTP PUT to user-data/passwords/keys.json with data: {"ring":{},"bulkIV":null}
Service.Resource DEBUG PUT request successful
Service.JsonFilter DEBUG Encoding data as JSON
Service.CryptoFilter DEBUG Encrypting data
Service.Crypto DEBUG NOT encrypting data
Testing INFO HTTP PUT to user-data/passwords/snapshot.json with data: {"805ec58eb8dcded602999967e139be21acd0f194":{"hostname":"www.boogle.com","formSubmitURL":"http://www.boogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person","passwordField":"test_password"}}
Service.Resource DEBUG PUT request successful
Service.JsonFilter DEBUG Encoding data as JSON
-Service.CryptoFilter DEBUG Encrypting data
-Service.Crypto DEBUG NOT encrypting data
-Testing INFO HTTP PUT to user-data/passwords/deltas.json with data: []
-Service.Resource DEBUG PUT request successful
-Service.JsonFilter DEBUG Encoding data as JSON
Testing INFO HTTP PUT to user-data/passwords/status.json with data: {"GUID":"fake-guid-0","formatVersion":2,"snapVersion":0,"maxVersion":0,"snapEncryption":"none","deltasEncryption":"none","itemCount":1}
Service.Resource DEBUG PUT request successful
Service.RemoteStore INFO Full upload to server successful
Service.SnapStore INFO Saving snapshot to disk
Testing INFO Opening 'weave/snapshots/passwords.json' for writing.
Testing INFO Writing data to local file 'weave/snapshots/passwords.json': {"version":0,"GUID":"fake-guid-0","snapshot":{"805ec58eb8dcded602999967e139be21acd0f194":{"hostname":"www.boogle.com","formSubmitURL":"http://www.boogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person","passwordField":"test_password"}}}
Testing INFO Step 'initial sync' succeeded.
Testing INFO -----------------------------------------
Testing INFO Step 'trivial re-sync' starting.
Testing INFO -----------------------------------------
Testing INFO Opening 'weave/snapshots/passwords.json' for reading.
Testing INFO Reading from stream.
Service.SnapStore INFO Read saved snapshot from disk
Service.PasswordEngine INFO Beginning sync
-Testing INFO HTTP MKCOL on user-data/passwords/
+Testing INFO HTTP MKCOL on user-data/passwords/deltas
Service.RemoteStore DEBUG Downloading status file
Testing INFO HTTP GET from user-data/passwords/status.json, returning status 200
Service.Resource DEBUG GET request successful
Service.JsonFilter DEBUG Decoding JSON data
Service.RemoteStore DEBUG Downloading status file... done
Service.PasswordEngine INFO Local snapshot version: 0
Service.PasswordEngine INFO Server maxVersion: 0
Service.RemoteStore DEBUG Using last sync snapshot as server snapshot (snap version == max version)
@@ -49,17 +44,17 @@ Service.PasswordEngine INFO Sync complet
Testing INFO Step 'trivial re-sync' succeeded.
Testing INFO -----------------------------------------
Testing INFO Step 'add user and re-sync' starting.
Testing INFO -----------------------------------------
Testing INFO Opening 'weave/snapshots/passwords.json' for reading.
Testing INFO Reading from stream.
Service.SnapStore INFO Read saved snapshot from disk
Service.PasswordEngine INFO Beginning sync
-Testing INFO HTTP MKCOL on user-data/passwords/
+Testing INFO HTTP MKCOL on user-data/passwords/deltas
Service.RemoteStore DEBUG Downloading status file
Testing INFO HTTP GET from user-data/passwords/status.json, returning status 200
Service.Resource DEBUG GET request successful
Service.JsonFilter DEBUG Decoding JSON data
Service.RemoteStore DEBUG Downloading status file... done
Service.PasswordEngine INFO Local snapshot version: 0
Service.PasswordEngine INFO Server maxVersion: 0
Service.RemoteStore DEBUG Using last sync snapshot as server snapshot (snap version == max version)
@@ -68,43 +63,38 @@ Service.PasswordEngine INFO Reconciling
Service.PasswordSync DEBUG Reconciling 1 against 0 commands
Service.PasswordEngine INFO Changes for client: 0
Service.PasswordEngine INFO Predicted changes for server: 1
Service.PasswordEngine INFO Client conflicts: 0
Service.PasswordEngine INFO Server conflicts: 0
Service.PasswordEngine INFO Actual changes for server: 1
Service.PasswordEngine DEBUG Actual changes for server: [{"action":"create","GUID":"1b3869fc36234b39cd354f661ed1d7d148394ca3","depth":0,"parents":[],"data":{"hostname":"www.yoogle.com","formSubmitURL":"http://www.yoogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person2","passwordField":"test_password2"}}]
Service.PasswordEngine INFO Uploading changes to server
-Testing INFO HTTP GET from user-data/passwords/deltas.json, returning status 200
-Service.Resource DEBUG GET request successful
-Service.CryptoFilter DEBUG Decrypting data
-Service.Crypto DEBUG NOT decrypting data
-Service.JsonFilter DEBUG Decoding JSON data
Service.JsonFilter DEBUG Encoding data as JSON
Service.CryptoFilter DEBUG Encrypting data
Service.Crypto DEBUG NOT encrypting data
-Testing INFO HTTP PUT to user-data/passwords/deltas.json with data: [[{"action":"create","GUID":"1b3869fc36234b39cd354f661ed1d7d148394ca3","depth":0,"parents":[],"data":{"hostname":"www.yoogle.com","formSubmitURL":"http://www.yoogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person2","passwordField":"test_password2"}}]]
-Service.Resource DEBUG PUT request successful
+Testing INFO HTTP PUT to user-data/passwords/deltas/1 with data: [{"action":"create","GUID":"1b3869fc36234b39cd354f661ed1d7d148394ca3","depth":0,"parents":[],"data":{"hostname":"www.yoogle.com","formSubmitURL":"http://www.yoogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person2","passwordField":"test_password2"}}]
+Service.ResourceSet DEBUG PUT request successful
Service.JsonFilter DEBUG Encoding data as JSON
Testing INFO HTTP PUT to user-data/passwords/status.json with data: {"GUID":"fake-guid-0","formatVersion":2,"snapVersion":0,"maxVersion":1,"snapEncryption":"none","deltasEncryption":"none","itemCount":2}
Service.Resource DEBUG PUT request successful
Service.PasswordEngine INFO Successfully updated deltas and status on server
Service.SnapStore INFO Saving snapshot to disk
Testing INFO Opening 'weave/snapshots/passwords.json' for writing.
Testing INFO Writing data to local file 'weave/snapshots/passwords.json': {"version":1,"GUID":"fake-guid-0","snapshot":{"805ec58eb8dcded602999967e139be21acd0f194":{"hostname":"www.boogle.com","formSubmitURL":"http://www.boogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person","passwordField":"test_password"},"1b3869fc36234b39cd354f661ed1d7d148394ca3":{"hostname":"www.yoogle.com","formSubmitURL":"http://www.yoogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person2","passwordField":"test_password2"}}}
Service.PasswordEngine INFO Sync complete
Testing INFO Step 'add user and re-sync' succeeded.
Testing INFO -----------------------------------------
Testing INFO Step 'remove user and re-sync' starting.
Testing INFO -----------------------------------------
Testing INFO Opening 'weave/snapshots/passwords.json' for reading.
Testing INFO Reading from stream.
Service.SnapStore INFO Read saved snapshot from disk
Service.PasswordEngine INFO Beginning sync
-Testing INFO HTTP MKCOL on user-data/passwords/
+Testing INFO HTTP MKCOL on user-data/passwords/deltas
Service.RemoteStore DEBUG Downloading status file
Testing INFO HTTP GET from user-data/passwords/status.json, returning status 200
Service.Resource DEBUG GET request successful
Service.JsonFilter DEBUG Decoding JSON data
Service.RemoteStore DEBUG Downloading status file... done
Service.PasswordEngine INFO Local snapshot version: 1
Service.PasswordEngine INFO Server maxVersion: 1
Service.RemoteStore DEBUG Using last sync snapshot as server snapshot (snap version == max version)
@@ -113,63 +103,61 @@ Service.PasswordEngine INFO Reconciling
Service.PasswordSync DEBUG Reconciling 1 against 0 commands
Service.PasswordEngine INFO Changes for client: 0
Service.PasswordEngine INFO Predicted changes for server: 1
Service.PasswordEngine INFO Client conflicts: 0
Service.PasswordEngine INFO Server conflicts: 0
Service.PasswordEngine INFO Actual changes for server: 1
Service.PasswordEngine DEBUG Actual changes for server: [{"action":"remove","GUID":"1b3869fc36234b39cd354f661ed1d7d148394ca3","depth":0,"parents":[]}]
Service.PasswordEngine INFO Uploading changes to server
-Testing INFO HTTP GET from user-data/passwords/deltas.json, returning status 200
-Service.Resource DEBUG GET request successful
-Service.CryptoFilter DEBUG Decrypting data
-Service.Crypto DEBUG NOT decrypting data
-Service.JsonFilter DEBUG Decoding JSON data
Service.JsonFilter DEBUG Encoding data as JSON
Service.CryptoFilter DEBUG Encrypting data
Service.Crypto DEBUG NOT encrypting data
-Testing INFO HTTP PUT to user-data/passwords/deltas.json with data: [[{"action":"create","GUID":"1b3869fc36234b39cd354f661ed1d7d148394ca3","depth":0,"parents":[],"data":{"hostname":"www.yoogle.com","formSubmitURL":"http://www.yoogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person2","passwordField":"test_password2"}}],[{"action":"remove","GUID":"1b3869fc36234b39cd354f661ed1d7d148394ca3","depth":0,"parents":[]}]]
-Service.Resource DEBUG PUT request successful
+Testing INFO HTTP PUT to user-data/passwords/deltas/2 with data: [{"action":"remove","GUID":"1b3869fc36234b39cd354f661ed1d7d148394ca3","depth":0,"parents":[]}]
+Service.ResourceSet DEBUG PUT request successful
Service.JsonFilter DEBUG Encoding data as JSON
Testing INFO HTTP PUT to user-data/passwords/status.json with data: {"GUID":"fake-guid-0","formatVersion":2,"snapVersion":0,"maxVersion":2,"snapEncryption":"none","deltasEncryption":"none","itemCount":1}
Service.Resource DEBUG PUT request successful
Service.PasswordEngine INFO Successfully updated deltas and status on server
Service.SnapStore INFO Saving snapshot to disk
Testing INFO Opening 'weave/snapshots/passwords.json' for writing.
Testing INFO Writing data to local file 'weave/snapshots/passwords.json': {"version":2,"GUID":"fake-guid-0","snapshot":{"805ec58eb8dcded602999967e139be21acd0f194":{"hostname":"www.boogle.com","formSubmitURL":"http://www.boogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person","passwordField":"test_password"}}}
Service.PasswordEngine INFO Sync complete
Testing INFO Step 'remove user and re-sync' succeeded.
Testing INFO -----------------------------------------
Testing INFO Step 'resync on second computer' starting.
Testing INFO -----------------------------------------
Service.PasswordEngine INFO Beginning sync
-Testing INFO HTTP MKCOL on user-data/passwords/
+Testing INFO HTTP MKCOL on user-data/passwords/deltas
Service.RemoteStore DEBUG Downloading status file
Testing INFO HTTP GET from user-data/passwords/status.json, returning status 200
Service.Resource DEBUG GET request successful
Service.JsonFilter DEBUG Decoding JSON data
Service.RemoteStore DEBUG Downloading status file... done
Service.PasswordEngine DEBUG Remote/local sync GUIDs do not match. Forcing initial sync.
Service.PasswordEngine INFO Local snapshot version: -1
Service.PasswordEngine INFO Server maxVersion: 2
Service.RemoteStore TRACE Getting latest from snap --> scratch
Service.RemoteStore INFO Downloading all server data from scratch
-Service.RemoteStore DEBUG Downloading server snapshot
Testing INFO HTTP GET from user-data/passwords/snapshot.json, returning status 200
Service.Resource DEBUG GET request successful
Service.CryptoFilter DEBUG Decrypting data
Service.Crypto DEBUG NOT decrypting data
Service.JsonFilter DEBUG Decoding JSON data
-Service.RemoteStore DEBUG Downloading server deltas
-Testing INFO HTTP GET from user-data/passwords/deltas.json, returning status 200
-Service.Resource DEBUG GET request successful
+Testing INFO HTTP GET from user-data/passwords/deltas/1, returning status 200
+Service.ResourceSet DEBUG GET request successful
Service.CryptoFilter DEBUG Decrypting data
Service.Crypto DEBUG NOT decrypting data
Service.JsonFilter DEBUG Decoding JSON data
Service.SnapStore TRACE Processing command: {"action":"create","GUID":"1b3869fc36234b39cd354f661ed1d7d148394ca3","depth":0,"parents":[],"data":{"hostname":"www.yoogle.com","formSubmitURL":"http://www.yoogle.com/search","httpRealm":"","username":"","password":"","usernameField":"test_person2","passwordField":"test_password2"}}
+Testing INFO HTTP GET from user-data/passwords/deltas/2, returning status 200
+Service.ResourceSet DEBUG GET request successful
+Service.CryptoFilter DEBUG Decrypting data
+Service.Crypto DEBUG NOT decrypting data
+Service.JsonFilter DEBUG Decoding JSON data
Service.SnapStore TRACE Processing command: {"action":"remove","GUID":"1b3869fc36234b39cd354f661ed1d7d148394ca3","depth":0,"parents":[]}
Service.PasswordEngine INFO Reconciling client/server updates
Service.PasswordSync DEBUG Reconciling 0 against 1 commands
Service.PasswordEngine INFO Changes for client: 1
Service.PasswordEngine INFO Predicted changes for server: 0
Service.PasswordEngine INFO Client conflicts: 0
Service.PasswordEngine INFO Server conflicts: 0
Service.PasswordEngine INFO Applying changes locally