Bug 1119765 - Joining and Leaving a Loop room quickly can leave the room as full. Ensure we send the leave notification if we've already sent the join. r=mikedeboer,a=sylvestre
authorMark Banner <standard8@mozilla.com>
Tue, 13 Jan 2015 15:16:49 +0000
changeset 242878 9b99fc7b7c20
parent 242876 454907933777
child 242879 5d185a7d03b5
push id4326
push usermbanner@mozilla.com
push date2015-01-15 13:33 +0000
treeherdermozilla-beta@9b99fc7b7c20 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer, sylvestre
bugs1119765
milestone36.0
Bug 1119765 - Joining and Leaving a Loop room quickly can leave the room as full. Ensure we send the leave notification if we've already sent the join. r=mikedeboer,a=sylvestre
browser/components/loop/content/shared/js/activeRoomStore.js
browser/components/loop/standalone/content/js/standaloneRoomViews.js
browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
browser/components/loop/test/shared/activeRoomStore_test.js
--- a/browser/components/loop/content/shared/js/activeRoomStore.js
+++ b/browser/components/loop/content/shared/js/activeRoomStore.js
@@ -25,16 +25,18 @@ loop.store.ActiveRoomStore = (function()
     // The initial state of the room
     INIT: "room-init",
     // The store is gathering the room data
     GATHER: "room-gather",
     // The store has got the room data
     READY: "room-ready",
     // Obtaining media from the user
     MEDIA_WAIT: "room-media-wait",
+    // Joining the room is taking place
+    JOINING: "room-joining",
     // The room is known to be joined on the loop-server
     JOINED: "room-joined",
     // The room is connected to the sdk server.
     SESSION_CONNECTED: "room-session-connected",
     // There are participants in the room.
     HAS_PARTICIPANTS: "room-has-participants",
     // There was an issue with the room
     FAILED: "room-failed",
@@ -292,16 +294,18 @@ loop.store.ActiveRoomStore = (function()
       this.setStoreState({roomState: ROOM_STATES.MEDIA_WAIT});
     },
 
     /**
      * Handles the action that signifies when media permission has been
      * granted and starts joining the room.
      */
     gotMediaPermission: function() {
+      this.setStoreState({roomState: ROOM_STATES.JOINING});
+
       this._mozLoop.rooms.join(this._storeState.roomToken,
         function(error, responseData) {
           if (error) {
             this.dispatchAction(new sharedActions.RoomFailure({error: error}));
             return;
           }
 
           this.dispatchAction(new sharedActions.JoinedRoom({
@@ -468,17 +472,18 @@ loop.store.ActiveRoomStore = (function()
 
       this._sdkDriver.disconnectSession();
 
       if (this._timeout) {
         clearTimeout(this._timeout);
         delete this._timeout;
       }
 
-      if (this._storeState.roomState === ROOM_STATES.JOINED ||
+      if (this._storeState.roomState === ROOM_STATES.JOINING ||
+          this._storeState.roomState === ROOM_STATES.JOINED ||
           this._storeState.roomState === ROOM_STATES.SESSION_CONNECTED ||
           this._storeState.roomState === ROOM_STATES.HAS_PARTICIPANTS) {
         this._mozLoop.rooms.leave(this._storeState.roomToken,
           this._storeState.sessionToken);
       }
 
       this.setStoreState({roomState: nextState || ROOM_STATES.ENDED});
     },
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js
@@ -87,16 +87,17 @@ loop.standaloneRoomViews = (function(moz
           return (
             React.DOM.div({className: "room-inner-info-area"}, 
               React.DOM.p({className: "prompt-media-message"}, 
                 msg
               )
             )
           );
         }
+        case ROOM_STATES.JOINING:
         case ROOM_STATES.JOINED:
         case ROOM_STATES.SESSION_CONNECTED: {
           return (
             React.DOM.div({className: "room-inner-info-area"}, 
               React.DOM.p({className: "empty-room-message"}, 
                 mozL10n.get("rooms_only_occupant_label")
               )
             )
@@ -285,17 +286,17 @@ loop.standaloneRoomViews = (function(moz
       document.body.classList.add("is-standalone-room");
     },
 
     componentWillUnmount: function() {
       this.stopListening(this.props.activeRoomStore);
     },
 
     /**
-     * Watches for when we transition to JOINED room state, so we can request
+     * Watches for when we transition to MEDIA_WAIT room state, so we can request
      * user media access.
      *
      * @param  {Object} nextProps (Unused)
      * @param  {Object} nextState Next state object.
      */
     componentWillUpdate: function(nextProps, nextState) {
       if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
           nextState.roomState === ROOM_STATES.MEDIA_WAIT) {
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
@@ -87,16 +87,17 @@ loop.standaloneRoomViews = (function(moz
           return (
             <div className="room-inner-info-area">
               <p className="prompt-media-message">
                 {msg}
               </p>
             </div>
           );
         }
+        case ROOM_STATES.JOINING:
         case ROOM_STATES.JOINED:
         case ROOM_STATES.SESSION_CONNECTED: {
           return (
             <div className="room-inner-info-area">
               <p className="empty-room-message">
                 {mozL10n.get("rooms_only_occupant_label")}
               </p>
             </div>
@@ -285,17 +286,17 @@ loop.standaloneRoomViews = (function(moz
       document.body.classList.add("is-standalone-room");
     },
 
     componentWillUnmount: function() {
       this.stopListening(this.props.activeRoomStore);
     },
 
     /**
-     * Watches for when we transition to JOINED room state, so we can request
+     * Watches for when we transition to MEDIA_WAIT room state, so we can request
      * user media access.
      *
      * @param  {Object} nextProps (Unused)
      * @param  {Object} nextState Next state object.
      */
     componentWillUpdate: function(nextProps, nextState) {
       if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
           nextState.roomState === ROOM_STATES.MEDIA_WAIT) {
--- a/browser/components/loop/test/shared/activeRoomStore_test.js
+++ b/browser/components/loop/test/shared/activeRoomStore_test.js
@@ -350,16 +350,22 @@ describe("loop.store.ActiveRoomStore", f
     });
   });
 
   describe("#gotMediaPermission", function() {
     beforeEach(function() {
       store.setStoreState({roomToken: "tokenFake"});
     });
 
+    it("should set the room state to JOINING", function() {
+      store.gotMediaPermission();
+
+      expect(store.getStoreState().roomState).eql(ROOM_STATES.JOINING);
+    });
+
     it("should call rooms.join on mozLoop", function() {
       store.gotMediaPermission();
 
       sinon.assert.calledOnce(fakeMozLoop.rooms.join);
       sinon.assert.calledWith(fakeMozLoop.rooms.join, "tokenFake");
     });
 
     it("should dispatch `JoinedRoom` on success", function() {
@@ -672,16 +678,27 @@ describe("loop.store.ActiveRoomStore", f
     it("should call mozLoop.rooms.leave", function() {
       store.windowUnload();
 
       sinon.assert.calledOnce(fakeMozLoop.rooms.leave);
       sinon.assert.calledWithExactly(fakeMozLoop.rooms.leave,
         "fakeToken", "1627384950");
     });
 
+    it("should call mozLoop.rooms.leave if the room state is JOINING",
+      function() {
+        store.setStoreState({roomState: ROOM_STATES.JOINING});
+
+        store.windowUnload();
+
+        sinon.assert.calledOnce(fakeMozLoop.rooms.leave);
+        sinon.assert.calledWithExactly(fakeMozLoop.rooms.leave,
+          "fakeToken", "1627384950");
+      });
+
     it("should set the state to CLOSING", function() {
       store.windowUnload();
 
       expect(store._storeState.roomState).eql(ROOM_STATES.CLOSING);
     });
   });
 
   describe("#leaveRoom", function() {