Bug 966560 - fix bugs with time skew fix in bug 957863; r=jedp
authorChris Karlof <ckarlof@mozilla.com>
Fri, 31 Jan 2014 16:43:36 -0800
changeset 182435 9003e6d7c532d17025de85b35ccd974a666244f4
parent 182434 0646c830546569210fb0722a6d9d290402c7955d
child 182436 0fec802029d0b9b0947235f5ac39d6f188e2ce4c
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjedp
bugs966560, 957863
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 966560 - fix bugs with time skew fix in bug 957863; r=jedp
services/common/hawk.js
services/common/rest.js
services/fxaccounts/FxAccounts.jsm
services/sync/modules/browserid_identity.js
services/sync/tests/unit/test_browserid_identity.js
--- a/services/common/hawk.js
+++ b/services/common/hawk.js
@@ -189,13 +189,17 @@ HawkClient.prototype = {
     };
 
     let extra = {
       now: this.now(),
       localtimeOffsetMsec: this.localtimeOffsetMsec,
     };
 
     let request = new HAWKAuthenticatedRESTRequest(uri, credentials, extra);
-    request[method](payloadObj, onComplete);
+    if (method == "post" || method == "put") {
+      request[method](payloadObj, onComplete);
+    } else {
+      request[method](onComplete);
+    }
 
     return deferred.promise;
   }
 }
--- a/services/common/rest.js
+++ b/services/common/rest.js
@@ -758,26 +758,32 @@ this.HAWKAuthenticatedRESTRequest =
   this.now = extra.now || Date.now();
   this.localtimeOffsetMsec = extra.localtimeOffsetMsec || 0;
   this._log.trace("local time, offset: " + this.now + ", " + (this.localtimeOffsetMsec));
 };
 HAWKAuthenticatedRESTRequest.prototype = {
   __proto__: RESTRequest.prototype,
 
   dispatch: function dispatch(method, data, onComplete, onProgress) {
+    let contentType = "text/plain";
+    if (method == "POST" || method == "PUT") {
+      contentType = "application/json";
+    }
     if (this.credentials) {
       let options = {
         now: this.now,
         localtimeOffsetMsec: this.localtimeOffsetMsec,
         credentials: this.credentials,
         payload: data && JSON.stringify(data) || "",
-        contentType: "application/json; charset=utf-8",
+        contentType: contentType,
       };
       let header = CryptoUtils.computeHAWK(this.uri, method, options);
       this.setHeader("Authorization", header.field);
       this._log.trace("hawk auth header: " + header.field);
     }
 
+    this.setHeader("Content-Type", contentType);
+
     return RESTRequest.prototype.dispatch.call(
       this, method, data, onComplete, onProgress
     );
   }
 };
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -380,25 +380,16 @@ InternalMethods.prototype = {
     return this.fxAccountsClient.resendVerificationEmail(data.sessionToken);
   },
 
   notifyObservers: function(topic) {
     log.debug("Notifying observers of " + topic);
     Services.obs.notifyObservers(null, topic, null);
   },
 
-  /**
-   * Give xpcshell tests an override point for duration testing. This is
-   * necessary because the tests need to manipulate the date in order to
-   * simulate certificate expiration.
-   */
-  now: function() {
-    return Date.now();
-  },
-
   pollEmailStatus: function pollEmailStatus(sessionToken, why) {
     let myGenerationCount = this.generationCount;
     log.debug("entering pollEmailStatus: " + why + " " + myGenerationCount);
     if (why == "start") {
       // If we were already polling, stop and start again.  This could happen
       // if the user requested the verification email to be resent while we
       // were already polling for receipt of an earlier email.
       this.pollTimeRemaining = this.POLL_SESSION;
@@ -484,16 +475,30 @@ this.FxAccounts = function(mockInternal)
   if (mockInternal) {
     // Exposes the internal object for testing only.
     this.internal = internal;
   }
 }
 this.FxAccounts.prototype = Object.freeze({
   version: DATA_FORMAT_VERSION,
 
+  now: function() {
+    if (this.internal) {
+      return this.internal.now();
+    }
+    return internal.now();
+  },
+
+  get localtimeOffsetMsec() {
+    if (this.internal) {
+      return this.internal.localtimeOffsetMsec;
+    }
+    return internal.localtimeOffsetMsec;
+  },
+
   // set() makes sure that polling is happening, if necessary.
   // get() does not wait for verification, and returns an object even if
   // unverified. The caller of get() must check .verified .
   // The "fxaccounts:onverified" event will fire only when the verified
   // state goes from false to true, so callers must register their observer
   // and then call get(). In particular, it will not fire when the account
   // was found to be verified in a previous boot: if our stored state says
   // the account is verified, the event will never fire. So callers must do:
@@ -615,17 +620,16 @@ this.FxAccounts.prototype = Object.freez
   getKeys: function() {
     return internal.getKeys();
   },
 
   whenVerified: function(userData) {
     return internal.whenVerified(userData);
   },
 
-
   /**
    * Sign the current user out.
    *
    * @return Promise
    *         The promise is rejected if a storage error occurs.
    */
   signOut: function signOut() {
     return internal.signOut();
@@ -651,17 +655,17 @@ this.FxAccounts.prototype = Object.freez
     return this.getSignedInUser().then(accountData => {
       if (!accountData) {
         return null;
       }
       let newQueryPortion = url.indexOf("?") == -1 ? "?" : "&";
       newQueryPortion += "email=" + encodeURIComponent(accountData.email);
       return url + newQueryPortion;
     });
-  },
+  }
 
 });
 
 /**
  * JSONStorage constructor that creates instances that may set/get
  * to a specified file, in a directory that will be created if it
  * doesn't exist.
  *
--- a/services/sync/modules/browserid_identity.js
+++ b/services/sync/modules/browserid_identity.js
@@ -206,21 +206,21 @@ this.BrowserIDManager.prototype = {
   _computeXClientState: function(kBbytes) {
     return CommonUtils.bytesAsHex(this._sha256(kBbytes).slice(0, 16), false);
   },
 
   /**
    * Provide override point for testing token expiration.
    */
   _now: function() {
-    return this._fxaService.internal.now()
+    return this._fxaService.now()
   },
 
   get _localtimeOffsetMsec() {
-    return this._fxaService.internal.localtimeOffsetMsec;
+    return this._fxaService.localtimeOffsetMsec;
   },
 
   get account() {
     return this._account;
   },
 
   /**
    * Sets the active account name.
--- a/services/sync/tests/unit/test_browserid_identity.js
+++ b/services/sync/tests/unit/test_browserid_identity.js
@@ -131,23 +131,31 @@ add_test(function test_resourceAuthentic
   let fxa = new MockFxAccounts();
   fxa._now_is = now;
   fxa.internal.fxAccountsClient = fxaClient;
 
   // Picked up by the signed-in user module
   do_check_eq(fxa.internal.now(), now);
   do_check_eq(fxa.internal.localtimeOffsetMsec, localtimeOffsetMsec);
 
+  do_check_eq(fxa.now(), now);
+  do_check_eq(fxa.localtimeOffsetMsec, localtimeOffsetMsec);
+
   // Mocks within mocks...
   configureFxAccountIdentity(browseridManager, identityConfig);
   browseridManager._fxaService = fxa;
+
   do_check_eq(browseridManager._fxaService.internal.now(), now);
   do_check_eq(browseridManager._fxaService.internal.localtimeOffsetMsec,
       localtimeOffsetMsec);
 
+  do_check_eq(browseridManager._fxaService.now(), now);
+  do_check_eq(browseridManager._fxaService.localtimeOffsetMsec,
+      localtimeOffsetMsec);
+
   let request = new SyncStorageRequest("https://example.net/i/like/pie/");
   let authenticator = browseridManager.getResourceAuthenticator();
   let output = authenticator(request, 'GET');
   dump("output" + JSON.stringify(output));
   let authHeader = output.headers.authorization;
   do_check_true(authHeader.startsWith('Hawk'));
 
   // Skew correction is applied in the header and we're within the two-minute