Bug 1193764 - Loop's Direct calls hang if the contact hasn't connected to the server at all. r=dmose, a=ritu
authorMark Banner <standard8@mozilla.com>
Thu, 13 Aug 2015 09:09:21 +0100
changeset 288747 af2e137813b628c303c3faf9197aacab82fec0f1
parent 288746 74917ce213120fdc82773c9c336f69f252b6b74e
child 288748 b4bb4d89a4c067254fcbb2f3c2141304443bf7a7
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmose, ritu
bugs1193764
milestone42.0a2
Bug 1193764 - Loop's Direct calls hang if the contact hasn't connected to the server at all. r=dmose, a=ritu
browser/components/loop/content/js/conversationViews.js
browser/components/loop/content/js/conversationViews.jsx
browser/components/loop/content/shared/js/conversationStore.js
browser/components/loop/content/shared/js/utils.js
browser/components/loop/test/desktop-local/conversationViews_test.js
browser/components/loop/test/shared/conversationStore_test.js
--- a/browser/components/loop/content/js/conversationViews.js
+++ b/browser/components/loop/content/js/conversationViews.js
@@ -4,17 +4,16 @@
 
 var loop = loop || {};
 loop.conversationViews = (function(mozL10n) {
   "use strict";
 
   var CALL_STATES = loop.store.CALL_STATES;
   var CALL_TYPES = loop.shared.utils.CALL_TYPES;
   var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
-  var REST_ERRNOS = loop.shared.utils.REST_ERRNOS;
   var WEBSOCKET_REASONS = loop.shared.utils.WEBSOCKET_REASONS;
   var sharedActions = loop.shared.actions;
   var sharedUtils = loop.shared.utils;
   var sharedViews = loop.shared.views;
   var sharedMixins = loop.shared.mixins;
 
   // This duplicates a similar function in contacts.jsx that isn't used in the
   // conversation window. If we get too many of these, we might want to consider
@@ -476,17 +475,17 @@ loop.conversationViews = (function(mozL1
       }
       return React.createElement("p", {className: "error"}, mozL10n.get("unable_retrieve_url"));
     },
 
     _getTitleMessage: function() {
       switch (this.getStoreState().callStateReason) {
         case WEBSOCKET_REASONS.REJECT:
         case WEBSOCKET_REASONS.BUSY:
-        case REST_ERRNOS.USER_UNAVAILABLE:
+        case FAILURE_DETAILS.USER_UNAVAILABLE:
           var contactDisplayName = _getContactDisplayName(this.props.contact);
           if (contactDisplayName.length) {
             return mozL10n.get(
               "contact_unavailable_title",
               {"contactName": contactDisplayName});
           }
 
           return mozL10n.get("generic_contact_unavailable_title");
--- a/browser/components/loop/content/js/conversationViews.jsx
+++ b/browser/components/loop/content/js/conversationViews.jsx
@@ -4,17 +4,16 @@
 
 var loop = loop || {};
 loop.conversationViews = (function(mozL10n) {
   "use strict";
 
   var CALL_STATES = loop.store.CALL_STATES;
   var CALL_TYPES = loop.shared.utils.CALL_TYPES;
   var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
-  var REST_ERRNOS = loop.shared.utils.REST_ERRNOS;
   var WEBSOCKET_REASONS = loop.shared.utils.WEBSOCKET_REASONS;
   var sharedActions = loop.shared.actions;
   var sharedUtils = loop.shared.utils;
   var sharedViews = loop.shared.views;
   var sharedMixins = loop.shared.mixins;
 
   // This duplicates a similar function in contacts.jsx that isn't used in the
   // conversation window. If we get too many of these, we might want to consider
@@ -476,17 +475,17 @@ loop.conversationViews = (function(mozL1
       }
       return <p className="error">{mozL10n.get("unable_retrieve_url")}</p>;
     },
 
     _getTitleMessage: function() {
       switch (this.getStoreState().callStateReason) {
         case WEBSOCKET_REASONS.REJECT:
         case WEBSOCKET_REASONS.BUSY:
-        case REST_ERRNOS.USER_UNAVAILABLE:
+        case FAILURE_DETAILS.USER_UNAVAILABLE:
           var contactDisplayName = _getContactDisplayName(this.props.contact);
           if (contactDisplayName.length) {
             return mozL10n.get(
               "contact_unavailable_title",
               {"contactName": contactDisplayName});
           }
 
           return mozL10n.get("generic_contact_unavailable_title");
--- a/browser/components/loop/content/shared/js/conversationStore.js
+++ b/browser/components/loop/content/shared/js/conversationStore.js
@@ -527,19 +527,19 @@ loop.store = loop.store || {};
       appendContactValues("email");
       appendContactValues("tel", true);
 
       this.client.setupOutgoingCall(contactAddresses,
         this.getStoreState("callType"),
         function(err, result) {
           if (err) {
             console.error("Failed to get outgoing call data", err);
-            var failureReason = "setup";
+            var failureReason = FAILURE_DETAILS.UNKNOWN;
             if (err.errno == REST_ERRNOS.USER_UNAVAILABLE) {
-              failureReason = REST_ERRNOS.USER_UNAVAILABLE;
+              failureReason = FAILURE_DETAILS.USER_UNAVAILABLE;
             }
             this.dispatcher.dispatch(
               new sharedActions.ConnectionFailure({reason: failureReason}));
             return;
           }
 
           // Success, dispatch a new action.
           this.dispatcher.dispatch(
--- a/browser/components/loop/content/shared/js/utils.js
+++ b/browser/components/loop/content/shared/js/utils.js
@@ -71,16 +71,17 @@ var inChrome = typeof Components != "und
     REJECT: "reject",
     TIMEOUT: "timeout"
   };
 
   var FAILURE_DETAILS = {
     MEDIA_DENIED: "reason-media-denied",
     NO_MEDIA: "reason-no-media",
     UNABLE_TO_PUBLISH_MEDIA: "unable-to-publish-media",
+    USER_UNAVAILABLE: "reason-user-unavailable",
     COULD_NOT_CONNECT: "reason-could-not-connect",
     NETWORK_DISCONNECTED: "reason-network-disconnected",
     EXPIRED_OR_INVALID: "reason-expired-or-invalid",
     UNKNOWN: "reason-unknown"
   };
 
   var ROOM_INFO_FAILURES = {
     // There's no data available from the server.
--- a/browser/components/loop/test/desktop-local/conversationViews_test.js
+++ b/browser/components/loop/test/desktop-local/conversationViews_test.js
@@ -436,19 +436,19 @@ describe("loop.conversationViews", funct
         conversationStore.setStoreState({callStateReason: "setup"});
 
         view = mountTestComponent({contact: fakeContact});
 
         sinon.assert.calledWithExactly(document.mozL10n.get,
           "generic_failure_title");
       });
 
-    it("should show 'contact unavailable' when the reason is REST_ERRNOS.USER_UNAVAILABLE",
+    it("should show 'contact unavailable' when the reason is FAILURE_DETAILS.USER_UNAVAILABLE",
       function () {
-        conversationStore.setStoreState({callStateReason: REST_ERRNOS.USER_UNAVAILABLE});
+        conversationStore.setStoreState({callStateReason: FAILURE_DETAILS.USER_UNAVAILABLE});
 
         view = mountTestComponent({contact: fakeContact});
 
         sinon.assert.calledWithExactly(document.mozL10n.get,
           "contact_unavailable_title",
           {contactName: loop.conversationViews
                             ._getContactDisplayName(fakeContact)});
       });
--- a/browser/components/loop/test/shared/conversationStore_test.js
+++ b/browser/components/loop/test/shared/conversationStore_test.js
@@ -4,16 +4,17 @@
 describe("loop.store.ConversationStore", function () {
   "use strict";
 
   var expect = chai.expect;
   var CALL_STATES = loop.store.CALL_STATES;
   var WS_STATES = loop.store.WS_STATES;
   var CALL_TYPES = loop.shared.utils.CALL_TYPES;
   var WEBSOCKET_REASONS = loop.shared.utils.WEBSOCKET_REASONS;
+  var REST_ERRNOS = loop.shared.utils.REST_ERRNOS;
   var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
   var sharedActions = loop.shared.actions;
   var sharedUtils = loop.shared.utils;
   var sandbox, dispatcher, client, store, fakeSessionData, sdkDriver;
   var contact, fakeMozLoop, fakeVideoElement;
   var connectPromise, resolveConnectPromise, rejectConnectPromise;
   var wsCancelSpy, wsCloseSpy, wsDeclineSpy, wsMediaUpSpy, fakeWebsocket;
 
@@ -530,17 +531,33 @@ describe("loop.store.ConversationStore",
           store.setupWindowData(
             new sharedActions.SetupWindowData(fakeSetupWindowData));
 
           sinon.assert.calledOnce(dispatcher.dispatch);
           // Can't use instanceof here, as that matches any action
           sinon.assert.calledWithMatch(dispatcher.dispatch,
             sinon.match.hasOwn("name", "connectionFailure"));
           sinon.assert.calledWithMatch(dispatcher.dispatch,
-            sinon.match.hasOwn("reason", "setup"));
+            sinon.match.hasOwn("reason", FAILURE_DETAILS.UNKNOWN));
+        });
+
+        it("should dispatch a connection failure action on failure with user unavailable", function() {
+          client.setupOutgoingCall.callsArgWith(2, {
+            errno: REST_ERRNOS.USER_UNAVAILABLE
+          });
+
+          store.setupWindowData(
+            new sharedActions.SetupWindowData(fakeSetupWindowData));
+
+          sinon.assert.calledOnce(dispatcher.dispatch);
+          // Can't use instanceof here, as that matches any action
+          sinon.assert.calledWithMatch(dispatcher.dispatch,
+            sinon.match.hasOwn("name", "connectionFailure"));
+          sinon.assert.calledWithMatch(dispatcher.dispatch,
+            sinon.match.hasOwn("reason", FAILURE_DETAILS.USER_UNAVAILABLE));
         });
       });
     });
   });
 
   describe("#acceptCall", function() {
     beforeEach(function() {
       store._websocket = {