Bug 518018 - Default to serverURL instead of userAPI on 404 cluster check
authorEdward Lee <edilee@mozilla.com>
Mon, 21 Sep 2009 17:13:41 -0700
changeset 45765 5fe3e29d93c310b7204b944bd0f26f180bdc2afc
parent 45764 829ed681db42d0c19f2d2129dc751674ca036735
child 45766 b5ced222e65807395f0b363b5c44193d89381883
push id14033
push useredward.lee@engineering.uiuc.edu
push dateWed, 23 Jun 2010 22:21:35 +0000
treeherdermozilla-central@227db4ad8cdf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs518018
Bug 518018 - Default to serverURL instead of userAPI on 404 cluster check Rework server/user/misc prefs to allow relative paths and full urls for generating API paths. Cache string properties of generated URLs under the storageAPI instead of using dynamic getters.
services/sync/modules/engines.js
services/sync/modules/service.js
services/sync/modules/util.js
services/sync/services-sync.js
--- a/services/sync/modules/engines.js
+++ b/services/sync/modules/engines.js
@@ -291,35 +291,22 @@ SyncEngine.prototype = {
 
   _recordObj: CryptoWrapper,
 
   _init: function _init() {
     Engine.prototype._init.call(this);
     this.loadToFetch();
   },
 
-  get baseURL() {
-    let url = Svc.Prefs.get("clusterURL");
-    if (!url)
-      return null;
-    if (url[url.length-1] != '/')
-      url += '/';
-    url += "0.5/";
-    return url;
-  },
+  get storageURL() Svc.Prefs.get("clusterURL") + "0.5/" +
+    ID.get("WeaveID").username + "/storage/",
 
-  get engineURL() {
-    return this.baseURL + ID.get('WeaveID').username +
-      '/storage/' + this.name + '/';
-  },
+  get engineURL() this.storageURL + this.name,
 
-  get cryptoMetaURL() {
-    return this.baseURL + ID.get('WeaveID').username +
-      '/storage/crypto/' + this.name;
-  },
+  get cryptoMetaURL() this.storageURL + "crypto/" + this.name,
 
   get lastSync() {
     return parseFloat(Svc.Prefs.get(this.name + ".lastSync", "0"));
   },
   set lastSync(value) {
     // Reset the pref in-case it's a number instead of a string
     Svc.Prefs.reset(this.name + ".lastSync");
     // Store the value as a string to keep floating point precision
--- a/services/sync/modules/service.js
+++ b/services/sync/modules/service.js
@@ -200,51 +200,49 @@ WeaveSvc.prototype = {
     else
       Svc.Prefs.reset("username");
 
     // fixme - need to loop over all Identity objects - needs some rethinking...
     ID.get('WeaveID').username = value;
     ID.get('WeaveCryptoID').username = value;
 
     // FIXME: need to also call this whenever the username pref changes
-    this._genKeyURLs();
+    this._updateCachedURLs();
   },
 
   get password password() ID.get("WeaveID").password,
   set password password(value) ID.get("WeaveID").password = value,
 
   get passphrase passphrase() ID.get("WeaveCryptoID").password,
   set passphrase passphrase(value) ID.get("WeaveCryptoID").password = value,
 
-  get baseURL() {
-    return Utils.getURLPref("serverURL");
-  },
-  set baseURL(value) {
-    Svc.Prefs.set("serverURL", value);
+  get serverURL() Svc.Prefs.get("serverURL"),
+  set serverURL(value) Svc.Prefs.set("serverURL", value),
+
+  get clusterURL() Svc.Prefs.get("clusterURL"),
+  set clusterURL(value) {
+    Svc.Prefs.set("clusterURL", value);
+    this._updateCachedURLs();
   },
 
-  get miscURL() {
-    return Utils.getURLPref("miscURL");
-  },
-  set miscURL(value) {
-    Svc.Prefs.set("miscURL", value);
+  get miscAPI() {
+    // Append to the serverURL if it's a relative fragment
+    let misc = Svc.Prefs.get("miscURL");
+    if (misc.indexOf(":") == -1)
+      misc = this.serverURL + misc;
+    return misc + "1/";
   },
 
-  get clusterURL() {
-    return Utils.getURLPref("clusterURL", null, "0.5/");
+  get userAPI() {
+    // Append to the serverURL if it's a relative fragment
+    let user = Svc.Prefs.get("userURL");
+    if (user.indexOf(":") == -1)
+      user = this.serverURL + user;
+    return user + "1/";
   },
-  set clusterURL(value) {
-    Svc.Prefs.set("clusterURL", value);
-    this._genKeyURLs();
-  },
-
-  get userURL() this.clusterURL + this.username,
-  get infoURL() this.userURL + "/info/collections",
-
-  get userPath() { return ID.get('WeaveID').username; },
 
   get isLoggedIn() { return this._loggedIn; },
 
   get isQuitting() { return this._isQuitting; },
   set isQuitting(value) { this._isQuitting = value; },
 
   get keyGenEnabled() { return this._keyGenEnabled; },
   set keyGenEnabled(value) { this._keyGenEnabled = value; },
@@ -260,20 +258,27 @@ WeaveSvc.prototype = {
       return false;
     this._locked = true;
     return true;
   },
   unlock: function Svc_unlock() {
     this._locked = false;
   },
 
-  _genKeyURLs: function WeaveSvc__genKeyURLs() {
-    let url = this.userURL;
-    PubKeys.defaultKeyUri = url + "/storage/keys/pubkey";
-    PrivKeys.defaultKeyUri = url + "/storage/keys/privkey";
+  _updateCachedURLs: function _updateCachedURLs() {
+    let storageAPI = this.clusterURL + "0.5/";
+    let userBase = storageAPI + this.username + "/";
+    this._log.debug("Caching URLs under storage user base: " + userBase);
+
+    // Generate and cache various URLs under the storage API for this user
+    this.infoURL = userBase + "info/collections";
+    this.storageURL = userBase + "storage/";
+    this.metaURL = this.storageURL + "meta/global";
+    PubKeys.defaultKeyUri = this.storageURL + "keys/pubkey";
+    PrivKeys.defaultKeyUri = this.storageURL + "keys/privkey";
   },
 
   _checkCrypto: function WeaveSvc__checkCrypto() {
     let ok = false;
 
     try {
       let iv = Svc.Crypto.generateRandomIV();
       if (iv.length == 24)
@@ -327,17 +332,17 @@ WeaveSvc.prototype = {
 
     // Create Weave identities (for logging in, and for encryption)
     ID.set('WeaveID', new Identity('Mozilla Services Password', this.username));
     Auth.defaultAuthenticator = new BasicAuthenticator(ID.get('WeaveID'));
 
     ID.set('WeaveCryptoID',
            new Identity('Mozilla Services Encryption Passphrase', this.username));
 
-    this._genKeyURLs();
+    this._updateCachedURLs();
 
     if (Svc.Prefs.get("autoconnect"))
       this._autoConnect();
   },
 
   _initLogs: function WeaveSvc__initLogs() {
     this._log = Log4Moz.repository.getLogger("Service.Main");
     this._log.level =
@@ -452,51 +457,50 @@ WeaveSvc.prototype = {
   },
 
   // These are global (for all engines)
 
   // gets cluster from central LDAP server and returns it, or null on error
   _findCluster: function _findCluster() {
     this._log.debug("Finding cluster for user " + this.username);
 
-    let res = new Resource(this.baseURL + "1/" + this.username + "/node/weave");
+    let res = new Resource(this.userAPI + this.username + "/node/weave");
     try {
       let node = res.get();
       switch (node.status) {
         case 404:
           this._log.debug("Using serverURL as data cluster (multi-cluster support disabled)");
-          return this.baseURL;
+          return this.serverURL;
         case 0:
         case 200:
           return node;
         default:
           this._log.debug("Unexpected response code: " + node.status);
           break;
       }
     } catch (e) {
       this._log.debug("Network error on findCluster");
       this.status.setLoginStatus(LOGIN_FAILED_NETWORK_ERROR);
       throw e;
     }
   },
 
   // gets cluster from central LDAP server and sets this.clusterURL
   _setCluster: function _setCluster() {
+    // Make sure we didn't get some unexpected response for the cluster
     let cluster = this._findCluster();
-    if (cluster) {
-      if (cluster == this.clusterURL)
-        return false;
+    if (cluster == null)
+      return false;
 
-      this._log.debug("Saving cluster setting");
-      this.clusterURL = cluster;
-      return true;
-    }
+    // Don't update stuff if we already have the right cluster
+    if (cluster == this.clusterURL)
+      return false;
 
-    this._log.debug("Error setting cluster for user " + this.username);
-    return false;
+    this.clusterURL = cluster;
+    return true;
   },
 
   // update cluster if required. returns false if the update was not required
   _updateCluster: function _updateCluster() {
     let cTime = Date.now();
     let lastUp = parseFloat(Svc.Prefs.get("lastClusterUpdate"));
     if (!lastUp || ((cTime - lastUp) >= CLUSTER_BACKOFF)) {
       if (this._setCluster()) {
@@ -574,17 +578,17 @@ WeaveSvc.prototype = {
 
       this.passphrase = newphrase;
 
       return true;
     }))(),
 
   changePassword: function WeaveSvc_changePassword(newpass)
     this._catch(this._notify("changepwd", "", function() {
-      let url = this.baseURL + '1/' + this.username + "/password";
+      let url = this.userAPI + this.username + "/password";
       let res = new Weave.Resource(url);
       let resp = res.post(newpass);
       if (resp.status != 200) {
         this._log.info("Password change failed: " + resp);
         throw "Could not change password";
       }
 
       this.password = newpass;
@@ -735,17 +739,17 @@ WeaveSvc.prototype = {
     case "9":
       return "weak-password";
     default:
       return "generic-server-error";
     }
   },
 
   checkUsername: function WeaveSvc_checkUsername(username) {
-    let url = this.baseURL + "1/" + username;
+    let url = this.userAPI + username;
     let res = new Resource(url);
     res.authenticator = new NoOpAuthenticator();
 
     let data = "";
     try {
       data = res.get();
       if (data.status == 200 && data == "0")
         return "available";
@@ -760,17 +764,17 @@ WeaveSvc.prototype = {
                                             captchaChallenge, captchaResponse)
   {
     let payload = JSON.stringify({
       "password": password, "email": email,
       "captcha-challenge": captchaChallenge,
       "captcha-response": captchaResponse
     });
 
-    let url = this.baseURL + '1/' + username;
+    let url = this.userAPI + username;
     let res = new Resource(url);
     res.authenticator = new Weave.NoOpAuthenticator();
 
     let error = "generic-server-error";
     try {
       let register = res.put(payload);
       if (register.success) {
         this._log.info("Account created: " + register);
@@ -789,17 +793,17 @@ WeaveSvc.prototype = {
   },
 
   // stuff we need to to after login, before we can really do
   // anything (e.g. key setup)
   _remoteSetup: function WeaveSvc__remoteSetup() {
     let reset = false;
 
     this._log.debug("Fetching global metadata record");
-    let meta = Records.import(this.userURL + "/storage/meta/global");
+    let meta = Records.import(this.metaURL);
 
     let remoteVersion = (meta && meta.payload.storageVersion)?
       meta.payload.storageVersion : "";
 
     this._log.debug(["Weave Version:", WEAVE_VERSION, "Compatible:",
       COMPATIBLE_VERSION, "Remote:", remoteVersion].join(" "));
 
     if (!meta || !meta.payload.storageVersion || !meta.payload.syncID ||
@@ -1183,17 +1187,17 @@ WeaveSvc.prototype = {
     this._log.info("Reset client data from freshStart.");
     this._log.info("Client metadata wiped, deleting server data");
     this.wipeServer();
 
     // XXX Bug 504125 Wait a while after wiping so that the DELETEs replicate
     Sync.sleep(2000);
 
     this._log.debug("Uploading new metadata record");
-    meta = new WBORecord(this.userURL + "/storage/meta/global");
+    meta = new WBORecord(this.metaURL);
     meta.payload.syncID = Clients.syncID;
     this._updateRemoteVersion(meta);
   },
 
   _updateRemoteVersion: function WeaveSvc__updateRemoteVersion(meta) {
     // Don't update if the remote version is already newer
     if (Svc.Version.compare(meta.payload.storageVersion, WEAVE_VERSION) >= 0)
       return;
@@ -1240,17 +1244,17 @@ WeaveSvc.prototype = {
       // Grab all the collections for the user and delete each one
       let info = new Resource(this.infoURL).get();
       for (let name in info.obj) {
         try {
           // If we have a list of engines, make sure it's one we want
           if (engines && engines.indexOf(name) == -1)
             continue;
 
-          new Resource(this.userURL + "/storage/" + name).delete();
+          new Resource(this.storageURL + name).delete();
         }
         catch(ex) {
           this._log.debug("Exception on wipe of '" + name + "': " + Utils.exceptionStr(ex));
         }
       }
     }))(),
 
   /**
--- a/services/sync/modules/util.js
+++ b/services/sync/modules/util.js
@@ -485,35 +485,16 @@ let Utils = {
   },
 
   makeURL: function Weave_makeURL(URIString) {
     let url = Utils.makeURI(URIString);
     url.QueryInterface(Ci.nsIURL);
     return url;
   },
 
-  // ensures url ends with a slash, optionally adds an extra string at the end
-  slashify: function Weave_slashify(url, extra) {
-    if (url[url.length-1] != '/')
-      url += '/';
-    if (extra)
-      url += extra;
-    return url;
-  },
-
-  //
-  getURLPref: function Weave_getURLPref(pref, def, extra) {
-    let url = Svc.Prefs.get(pref);
-    if (!url && typeof(def) == "undefined")
-      throw pref + " not set";
-    else if (!url)
-      return def;
-    return Utils.slashify(url, extra);
-  },
-
   xpath: function Weave_xpath(xmlDoc, xpathString) {
     let root = xmlDoc.ownerDocument == null ?
       xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement;
     let nsResolver = xmlDoc.createNSResolver(root);
 
     return xmlDoc.evaluate(xpathString, xmlDoc, nsResolver,
                            Ci.nsIDOMXPathResult.ANY_TYPE, null);
   },
--- a/services/sync/services-sync.js
+++ b/services/sync/services-sync.js
@@ -1,10 +1,11 @@
 pref("extensions.weave.serverURL", "@server_url@");
-pref("extensions.weave.miscURL", "https://auth.services.mozilla.com/misc/");
+pref("extensions.weave.userURL", "user/");
+pref("extensions.weave.miscURL", "misc/");
 pref("extensions.weave.termsURL", "https://labs.mozilla.com/projects/weave/tos/");
 
 pref("extensions.weave.encryption", "aes-256-cbc");
 
 pref("extensions.weave.lastversion", "firstrun");
 
 pref("extensions.weave.ui.syncnow", true);
 pref("extensions.weave.ui.sharebookmarks", false);