Bug 1065155: Check both Hawk sessions when PushServer notification received. Record session type with call data. r=standard8
authorPaul Kerr [:pkerr] <pkerr@mozilla.com>
Fri, 19 Sep 2014 14:35:37 -0700
changeset 229511 289416a752ff2e19186616e1d2d73bea6c97c0b1
parent 229510 60995a021d7444a753766b47188af661f5b20c47
child 229512 413411cde2b5cfda4432e7c3e4c62289a955cf73
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstandard8
bugs1065155
milestone35.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 1065155: Check both Hawk sessions when PushServer notification received. Record session type with call data. r=standard8
browser/components/loop/MozLoopService.jsm
browser/components/loop/content/shared/js/models.js
--- a/browser/components/loop/MozLoopService.jsm
+++ b/browser/components/loop/MozLoopService.jsm
@@ -391,20 +391,29 @@ let MozLoopServiceInternal = {
 
     let credentials;
     if (sessionToken) {
       // true = use a hex key, as required by the server (see bug 1032738).
       credentials = deriveHawkCredentials(sessionToken, "sessionToken",
                                           2 * 32, true);
     }
 
-    return gHawkClient.request(path, method, credentials, payloadObj).catch(error => {
-      console.error("Loop hawkRequest error:", error);
-      throw error;
-    });
+    return gHawkClient.request(path, method, credentials, payloadObj);
+  },
+
+  /**
+   * Generic hawkRequest onError handler for the hawkRequest promise.
+   *
+   * @param {Object} error - error reporting object
+   *
+   */
+
+  _hawkRequestError: function(error) {
+    console.error("Loop hawkRequest error:", error);
+    throw error;
   },
 
   getSessionTokenPrefName: function(sessionType) {
     let suffix;
     switch (sessionType) {
       case LOOP_SESSION_TYPE.GUEST:
         suffix = "";
         break;
@@ -570,41 +579,77 @@ let MozLoopServiceInternal = {
       return;
     }
 
     // We set this here as it is assumed that once the user receives an incoming
     // call, they'll have had enough time to see the terms of service. See
     // bug 1046039 for background.
     Services.prefs.setCharPref("loop.seenToS", "seen");
 
-    /* Request the information on the new call(s) associated with this version. */
-    this.hawkRequest(LOOP_SESSION_TYPE.GUEST,
-      "/calls?version=" + version, "GET").then(response => {
-      try {
-        let respData = JSON.parse(response.body);
-        if (respData.calls && Array.isArray(respData.calls)) {
-          respData.calls.forEach((callData) => {
-            if (!this.callsData.inUse) {
-              this.callsData.inUse = true;
-              this.callsData.data = callData;
-              this.openChatWindow(
-                null,
-                this.localizedStrings["incoming_call_title2"].textContent,
-                "about:loopconversation#incoming/" + callData.callId);
-            } else {
-              this._returnBusy(callData);
-            }
-          });
-        } else {
-          console.warn("Error: missing calls[] in response");
-        }
-      } catch (err) {
-        console.warn("Error parsing calls info", err);
+    // Request the information on the new call(s) associated with this version.
+    // The registered FxA session is checked first, then the anonymous session.
+    // Make the call to get the GUEST session regardless of whether the FXA
+    // request fails.
+
+    this._getCalls(LOOP_SESSION_TYPE.FXA, version).catch(() => {});
+    this._getCalls(LOOP_SESSION_TYPE.GUEST, version).catch(
+      error => {this._hawkRequestError(error);});
+  },
+
+  /**
+   * Make a hawkRequest to GET/calls?=version for this session type.
+   *
+   * @param {LOOP_SESSION_TYPE} sessionType - type of hawk token used
+   *        for the GET operation.
+   * @param {Object} version - LoopPushService notification version
+   *
+   * @returns {Promise}
+   *
+   */
+
+  _getCalls: function(sessionType, version) {
+    return this.hawkRequest(sessionType, "/calls?version=" + version, "GET").then(
+      response => {this._processCalls(response, sessionType);}
+    );
+  },
+
+  /**
+   * Process the calls array returned from a GET/calls?version request.
+   * Only one active call is permitted at this time.
+   *
+   * @param {Object} response - response payload from GET
+   *
+   * @param {LOOP_SESSION_TYPE} sessionType - type of hawk token used
+   *        for the GET operation.
+   *
+   */
+
+  _processCalls: function(response, sessionType) {
+    try {
+      let respData = JSON.parse(response.body);
+      if (respData.calls && Array.isArray(respData.calls)) {
+        respData.calls.forEach((callData) => {
+          if (!this.callsData.inUse) {
+            this.callsData.inUse = true;
+            callData.sessionType = sessionType;
+            this.callsData.data = callData;
+            this.openChatWindow(
+              null,
+              this.localizedStrings["incoming_call_title2"].textContent,
+              "about:loopconversation#incoming/" + callData.callId);
+          } else {
+            this._returnBusy(callData);
+          }
+        });
+      } else {
+        console.warn("Error: missing calls[] in response");
       }
-    });
+    } catch (err) {
+      console.warn("Error parsing calls info", err);
+    }
   },
 
    /**
    * Open call progress websocket and terminate with a reason of busy
    * the server.
    *
    * @param {callData} Must contain the progressURL, callId and websocketToken
    *                   returned by the LoopService.
@@ -792,17 +837,18 @@ let MozLoopServiceInternal = {
         throw new Error("Invalid FxA hawk token returned");
       }
       let prefType = Services.prefs.getPrefType(this.getSessionTokenPrefName(SESSION_TYPE));
       if (prefType == Services.prefs.PREF_INVALID) {
         throw new Error("No FxA hawk token returned and we don't have one saved");
       }
 
       return JSON.parse(response.body);
-    });
+    },
+    error => {this._hawkRequestError(error);});
   },
 
   /**
    * Get the OAuth client constructed with Loop OAauth parameters.
    *
    * @return {Promise}
    */
   promiseFxAOAuthClient: Task.async(function* () {
@@ -870,17 +916,18 @@ let MozLoopServiceInternal = {
     }
 
     let payload = {
       code: code,
       state: state,
     };
     return this.hawkRequest(LOOP_SESSION_TYPE.FXA, "/fxa-oauth/token", "POST", payload).then(response => {
       return JSON.parse(response.body);
-    });
+    },
+    error => {this._hawkRequestError(error);});
   },
 
   /**
    * Called once gFxAOAuthClient fires onComplete.
    *
    * @param {Deferred} deferred used to resolve or reject the gFxAOAuthClientPromise
    * @param {Object} result (with code and state)
    */
@@ -1314,11 +1361,12 @@ this.MozLoopService = {
    *                            transmitted with the request.
    * @returns {Promise}
    *        Returns a promise that resolves to the response of the API call,
    *        or is rejected with an error.  If the server response can be parsed
    *        as JSON and contains an 'error' property, the promise will be
    *        rejected with this JSON-parsed response.
    */
   hawkRequest: function(sessionType, path, method, payloadObj) {
-    return MozLoopServiceInternal.hawkRequest(sessionType, path, method, payloadObj);
+    return MozLoopServiceInternal.hawkRequest(sessionType, path, method, payloadObj).catch(
+      error => {this._hawkRequestError(error);});
   },
 };
--- a/browser/components/loop/content/shared/js/models.js
+++ b/browser/components/loop/content/shared/js/models.js
@@ -15,16 +15,17 @@ loop.shared.models = (function(l10n) {
   var ConversationModel = Backbone.Model.extend({
     defaults: {
       connected:    false,         // Session connected flag
       ongoing:      false,         // Ongoing call flag
       callerId:     undefined,     // Loop caller id
       loopToken:    undefined,     // Loop conversation token
       sessionId:    undefined,     // OT session id
       sessionToken: undefined,     // OT session token
+      sessionType:  undefined,     // Hawk session type
       apiKey:       undefined,     // OT api key
       callId:       undefined,     // The callId on the server
       progressURL:  undefined,     // The websocket url to use for progress
       websocketToken: undefined,   // The token to use for websocket auth, this is
                                    // stored as a hex string which is what the server
                                    // requires.
       callType:     undefined,     // The type of incoming call selected by
                                    // other peer ("audio" or "audio-video")
@@ -133,16 +134,17 @@ loop.shared.models = (function(l10n) {
      *
      * @param {Object} sessionData Conversation session information.
      */
     setIncomingSessionData: function(sessionData) {
       // Explicit property assignment to prevent later "surprises"
       this.set({
         sessionId:      sessionData.sessionId,
         sessionToken:   sessionData.sessionToken,
+        sessionType:    sessionData.sessionType,
         apiKey:         sessionData.apiKey,
         callId:         sessionData.callId,
         progressURL:    sessionData.progressURL,
         websocketToken: sessionData.websocketToken.toString(16),
         callType:       sessionData.callType || "audio-video",
         callToken:      sessionData.callToken
       });
     },