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 225387 e3eb0b80e2177b80fe6fef435f5c45594632e78a
parent 225386 d38a25838b95788e773f96441734b4f4a2639636
child 225388 42facc20012909005a392e7ccbaee6505d75ab92
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstandard8
bugs1065155
milestone34.0a2
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
       });
     },