Bug 1035348 - Part 1: Move GET/calls to MozLoopService. r=Standard8
authorPaul Kerr [:pkerr] <pkerr@mozilla.com>
Wed, 10 Sep 2014 15:22:32 +0100
changeset 225338 185c8c55c7e83411a9f00c629b620da82b7b7b79
parent 225337 dbfa16c4d3ccb4d06199012563bd7b9accfa7996
child 225339 2d8503a6be1f12f7014d0512715e2ffb92e806d0
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
bugs1035348
milestone34.0a2
Bug 1035348 - Part 1: Move GET/calls to MozLoopService. r=Standard8
browser/components/loop/MozLoopAPI.jsm
browser/components/loop/MozLoopService.jsm
browser/components/loop/content/js/client.js
browser/components/loop/content/js/conversation.js
browser/components/loop/content/js/conversation.jsx
browser/components/loop/content/shared/js/models.js
--- a/browser/components/loop/MozLoopAPI.jsm
+++ b/browser/components/loop/MozLoopAPI.jsm
@@ -117,16 +117,33 @@ function injectLoopAPI(targetWindow) {
     locale: {
       enumerable: true,
       get: function() {
         return MozLoopService.locale;
       }
     },
 
     /**
+     * Returns the callData for a specific callDataId
+     *
+     * The data was retrieved from the LoopServer via a GET/calls/<version> request
+     * triggered by an incoming message from the LoopPushServer.
+     *
+     * @param {int} loopCallId
+     * @returns {callData} The callData or undefined if error.
+     */
+    getCallData: {
+      enumerable: true,
+      writable: true,
+      value: function(loopCallId) {
+        return Cu.cloneInto(MozLoopService.getCallData(loopCallId), targetWindow);
+      }
+    },
+
+    /**
      * Returns the contacts API.
      *
      * @returns {Object} The contacts API object
      */
     contacts: {
       enumerable: true,
       get: function() {
         if (contactsAPI) {
--- a/browser/components/loop/MozLoopService.jsm
+++ b/browser/components/loop/MozLoopService.jsm
@@ -81,16 +81,18 @@ let gErrors = new Map();
 /**
  * Internal helper methods and state
  *
  * The registration is a two-part process. First we need to connect to
  * and register with the push server. Then we need to take the result of that
  * and register with the Loop server.
  */
 let MozLoopServiceInternal = {
+  callsData: {data: undefined},
+
   // The uri of the Loop server.
   get loopServerUri() Services.prefs.getCharPref("loop.server"),
 
   /**
    * The initial delay for push registration. This ensures we don't start
    * kicking off straight after browser startup, just a few seconds later.
    */
   get initialRegistrationDelayMilliseconds() {
@@ -368,19 +370,32 @@ 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");
 
-    this.openChatWindow(null,
-                        this.localizedStrings["incoming_call_title2"].textContent,
-                        "about:loopconversation#incoming/" + version);
+    /* Request the information on the new call(s) associated with this version. */
+    this.hawkRequest("/calls?version=" + version, "GET").then(response => {
+      try {
+        let respData = JSON.parse(response.body);
+        if (respData.calls && respData.calls[0]) {
+          this.callsData.data = respData.calls[0];
+          this.openChatWindow(null,
+            this.localizedStrings["incoming_call_title2"].textContent,
+            "about:loopconversation#incoming/" + version);
+        } else {
+          console.warn("Error: missing calls[] in response");
+        }
+      } catch (err) {
+        console.warn("Error parsing calls info", err);
+      }
+    });
   },
 
   /**
    * A getter to obtain and store the strings for loop. This is structured
    * for use by l10n.js.
    *
    * @returns {Object} a map of element ids with attributes to set.
    */
@@ -873,16 +888,29 @@ this.MozLoopService = {
       return Services.prefs.getComplexValue("general.useragent.locale",
         Ci.nsISupportsString).data;
     } catch (ex) {
       return "en-US";
     }
   },
 
   /**
+   * Returns the callData for a specific callDataId
+   *
+   * The data was retrieved from the LoopServer via a GET/calls/<version> request
+   * triggered by an incoming message from the LoopPushServer.
+   *
+   * @param {int} loopCallId
+   * @return {callData} The callData or undefined if error.
+   */
+  getCallData: function(loopCallId) {
+    return MozLoopServiceInternal.callsData.data;
+  },
+
+  /**
    * Set any character preference under "loop.".
    *
    * @param {String} prefName The name of the pref without the preceding "loop."
    * @param {String} value The value to set.
    *
    * Any errors thrown by the Mozilla pref API are logged to the console.
    */
   setLoopCharPref: function(prefName, value) {
--- a/browser/components/loop/content/js/client.js
+++ b/browser/components/loop/content/js/client.js
@@ -182,45 +182,12 @@ loop.Client = (function($) {
         if (err) {
           cb(err);
           return;
         }
 
         this._requestCallUrlInternal(nickname, cb);
       }.bind(this));
     },
-
-    /**
-     * Requests call information from the server for all calls since the
-     * given version.
-     *
-     * @param  {String} version the version identifier from the push
-     *                          notification
-     * @param  {Function} cb Callback(err, calls)
-     */
-    requestCallsInfo: function(version, cb) {
-      // XXX It is likely that we'll want to move some of this to whatever
-      // opens the chat window, but we'll need to decide on this in bug 1002418
-      if (!version) {
-        throw new Error("missing required parameter version");
-      }
-
-      this.mozLoop.hawkRequest("/calls?version=" + version, "GET", null,
-                               function (error, responseText) {
-        if (error) {
-          this._failureHandler(cb, error);
-          return;
-        }
-
-        try {
-          var callsData = JSON.parse(responseText);
-
-          cb(null, this._validate(callsData, expectedCallProperties));
-        } catch (err) {
-          console.log("Error requesting calls info", err);
-          cb(err);
-        }
-      }.bind(this));
-    }
   };
 
   return Client;
 })(jQuery);
--- a/browser/components/loop/content/js/conversation.js
+++ b/browser/components/loop/content/js/conversation.js
@@ -152,17 +152,17 @@ loop.conversation = (function(OT, mozL10
    * Required options:
    * - {loop.shared.models.ConversationModel} conversation Conversation model.
    * - {loop.shared.models.NotificationCollection} notifications
    *
    * @type {loop.shared.router.BaseConversationRouter}
    */
   var ConversationRouter = loop.desktopRouter.DesktopConversationRouter.extend({
     routes: {
-      "incoming/:version": "incoming",
+      "incoming/:callId": "incoming",
       "call/accept": "accept",
       "call/decline": "decline",
       "call/ongoing": "conversation",
       "call/declineAndBlock": "declineAndBlock",
       "call/feedback": "feedback"
     },
 
     /**
@@ -177,53 +177,44 @@ loop.conversation = (function(OT, mozL10
      */
     endCall: function() {
       this.navigate("call/feedback", {trigger: true});
     },
 
     /**
      * Incoming call route.
      *
-     * @param {String} loopVersion The version from the push notification, set
-     *                             by the router from the URL.
+     * @param {String} callId  Identifier assigned by the LoopService
+     *                         to this incoming call.
      */
-    incoming: function(loopVersion) {
+    incoming: function(callId) {
       navigator.mozLoop.startAlerting();
-      this._conversation.set({loopVersion: loopVersion});
       this._conversation.once("accept", function() {
         this.navigate("call/accept", {trigger: true});
       }.bind(this));
       this._conversation.once("decline", function() {
         this.navigate("call/decline", {trigger: true});
       }.bind(this));
       this._conversation.once("declineAndBlock", function() {
         this.navigate("call/declineAndBlock", {trigger: true});
       }.bind(this));
       this._conversation.once("call:incoming", this.startCall, this);
       this._conversation.once("change:publishedStream", this._checkConnected, this);
       this._conversation.once("change:subscribedStream", this._checkConnected, this);
 
-      this._client.requestCallsInfo(loopVersion, function(err, sessionData) {
-        if (err) {
-          console.error("Failed to get the sessionData", err);
-          // XXX Not the ideal response, but bug 1047410 will be replacing
-          // this by better "call failed" UI.
-          this._notifications.errorL10n("cannot_start_call_session_not_ready");
-          return;
-        }
-
-        // XXX For incoming calls we might have more than one call queued.
-        // For now, we'll just assume the first call is the right information.
-        // We'll probably really want to be getting this data from the
-        // background worker on the desktop client.
-        // Bug 1032700 should fix this.
-        this._conversation.setIncomingSessionData(sessionData[0]);
-
-        this._setupWebSocketAndCallView();
-      }.bind(this));
+      var callData = navigator.mozLoop.getCallData(callId);
+      if (!callData) {
+        console.error("Failed to get the call data");
+        // XXX Not the ideal response, but bug 1047410 will be replacing
+        // this by better "call failed" UI.
+        this._notifications.errorL10n("cannot_start_call_session_not_ready");
+        return;
+      }
+      this._conversation.setIncomingSessionData(callData);
+      this._setupWebSocketAndCallView();
     },
 
     /**
      * Used to set up the web socket connection and navigate to the
      * call view if appropriate.
      */
     _setupWebSocketAndCallView: function() {
       this._websocket = new loop.CallConnectionWebSocket({
--- a/browser/components/loop/content/js/conversation.jsx
+++ b/browser/components/loop/content/js/conversation.jsx
@@ -152,17 +152,17 @@ loop.conversation = (function(OT, mozL10
    * Required options:
    * - {loop.shared.models.ConversationModel} conversation Conversation model.
    * - {loop.shared.models.NotificationCollection} notifications
    *
    * @type {loop.shared.router.BaseConversationRouter}
    */
   var ConversationRouter = loop.desktopRouter.DesktopConversationRouter.extend({
     routes: {
-      "incoming/:version": "incoming",
+      "incoming/:callId": "incoming",
       "call/accept": "accept",
       "call/decline": "decline",
       "call/ongoing": "conversation",
       "call/declineAndBlock": "declineAndBlock",
       "call/feedback": "feedback"
     },
 
     /**
@@ -177,53 +177,44 @@ loop.conversation = (function(OT, mozL10
      */
     endCall: function() {
       this.navigate("call/feedback", {trigger: true});
     },
 
     /**
      * Incoming call route.
      *
-     * @param {String} loopVersion The version from the push notification, set
-     *                             by the router from the URL.
+     * @param {String} callId  Identifier assigned by the LoopService
+     *                         to this incoming call.
      */
-    incoming: function(loopVersion) {
+    incoming: function(callId) {
       navigator.mozLoop.startAlerting();
-      this._conversation.set({loopVersion: loopVersion});
       this._conversation.once("accept", function() {
         this.navigate("call/accept", {trigger: true});
       }.bind(this));
       this._conversation.once("decline", function() {
         this.navigate("call/decline", {trigger: true});
       }.bind(this));
       this._conversation.once("declineAndBlock", function() {
         this.navigate("call/declineAndBlock", {trigger: true});
       }.bind(this));
       this._conversation.once("call:incoming", this.startCall, this);
       this._conversation.once("change:publishedStream", this._checkConnected, this);
       this._conversation.once("change:subscribedStream", this._checkConnected, this);
 
-      this._client.requestCallsInfo(loopVersion, function(err, sessionData) {
-        if (err) {
-          console.error("Failed to get the sessionData", err);
-          // XXX Not the ideal response, but bug 1047410 will be replacing
-          // this by better "call failed" UI.
-          this._notifications.errorL10n("cannot_start_call_session_not_ready");
-          return;
-        }
-
-        // XXX For incoming calls we might have more than one call queued.
-        // For now, we'll just assume the first call is the right information.
-        // We'll probably really want to be getting this data from the
-        // background worker on the desktop client.
-        // Bug 1032700 should fix this.
-        this._conversation.setIncomingSessionData(sessionData[0]);
-
-        this._setupWebSocketAndCallView();
-      }.bind(this));
+      var callData = navigator.mozLoop.getCallData(callId);
+      if (!callData) {
+        console.error("Failed to get the call data");
+        // XXX Not the ideal response, but bug 1047410 will be replacing
+        // this by better "call failed" UI.
+        this._notifications.errorL10n("cannot_start_call_session_not_ready");
+        return;
+      }
+      this._conversation.setIncomingSessionData(callData);
+      this._setupWebSocketAndCallView();
     },
 
     /**
      * Used to set up the web socket connection and navigate to the
      * call view if appropriate.
      */
     _setupWebSocketAndCallView: function() {
       this._websocket = new loop.CallConnectionWebSocket({
--- a/browser/components/loop/content/shared/js/models.js
+++ b/browser/components/loop/content/shared/js/models.js
@@ -13,20 +13,17 @@ loop.shared.models = (function(l10n) {
    * Conversation model.
    */
   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
-      loopVersion:  undefined,     // Loop version for /calls/ information. This
-                                   // is the version received from the push
-                                   // notification and is used by the server to
-                                   // determine the pending calls
+      loopCallId:   undefined,     // LoopService id for incoming session
       sessionId:    undefined,     // OT session id
       sessionToken: undefined,     // OT session token
       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.