diff --git a/browser/base/content/browser-loop.js b/browser/base/content/browser-loop.js index 2c4270cd8111..0f27072bad18 100644 --- a/browser/base/content/browser-loop.js +++ b/browser/base/content/browser-loop.js @@ -206,6 +206,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PanelFrame", "resource:///modules/Panel let state = ""; if (MozLoopService.errors.size) { state = "error"; + } else if (MozLoopService.screenShareActive) { + state = "action"; } else if (aReason == "login" && MozLoopService.userProfile) { state = "active"; } else if (MozLoopService.doNotDisturb) { diff --git a/browser/components/loop/MozLoopAPI.jsm b/browser/components/loop/MozLoopAPI.jsm index 0bea0dc8acc3..a1a62faf6928 100644 --- a/browser/components/loop/MozLoopAPI.jsm +++ b/browser/components/loop/MozLoopAPI.jsm @@ -747,6 +747,22 @@ function injectLoopAPI(targetWindow) { UITour.notify(subject); } }, + + /** + * Used to record the screen sharing state for a window so that it can + * be reflected on the toolbar button. + * + * @param {String} windowId The id of the conversation window the state + * is being changed for. + * @param {Boolean} active Whether or not screen sharing is now active. + */ + setScreenShareState: { + enumerable: true, + writable: true, + value: function(windowId, active) { + MozLoopService.setScreenShareState(windowId, active); + } + } }; function onStatusChanged(aSubject, aTopic, aData) { diff --git a/browser/components/loop/MozLoopService.jsm b/browser/components/loop/MozLoopService.jsm index 23b573350752..243ccb41e43f 100644 --- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -1046,6 +1046,7 @@ let gInitializeTimerFunc = (deferredInitialization) => { */ this.MozLoopService = { _DNSService: gDNSService, + _activeScreenShares: [], get channelIDs() { // Channel ids that will be registered with the PushServer for notifications @@ -1654,5 +1655,33 @@ this.MozLoopService = { addConversationContext: function(windowId, context) { MozLoopServiceInternal.conversationContexts.set(windowId, context); + }, + + /** + * Used to record the screen sharing state for a window so that it can + * be reflected on the toolbar button. + * + * @param {String} windowId The id of the conversation window the state + * is being changed for. + * @param {Boolean} active Whether or not screen sharing is now active. + */ + setScreenShareState: function(windowId, active) { + if (active) { + this._activeScreenShares.push(windowId); + } else { + var index = this._activeScreenShares.indexOf(windowId); + if (index != -1) { + this._activeScreenShares.splice(index, 1); + } + } + + MozLoopServiceInternal.notifyStatusChanged(); + }, + + /** + * Returns true if screen sharing is active in at least one window. + */ + get screenShareActive() { + return this._activeScreenShares.length > 0; } }; diff --git a/browser/components/loop/content/shared/js/activeRoomStore.js b/browser/components/loop/content/shared/js/activeRoomStore.js index 71ca3c557ce6..6b282ce79409 100644 --- a/browser/components/loop/content/shared/js/activeRoomStore.js +++ b/browser/components/loop/content/shared/js/activeRoomStore.js @@ -380,6 +380,10 @@ loop.store.ActiveRoomStore = (function() { */ screenSharingState: function(actionData) { this.setStoreState({screenSharingState: actionData.state}); + + this._mozLoop.setScreenShareState( + this.getStoreState().windowId, + actionData.state === SCREEN_SHARE_STATES.ACTIVE); }, /** @@ -417,6 +421,13 @@ loop.store.ActiveRoomStore = (function() { windowUnload: function() { this._leaveRoom(ROOM_STATES.CLOSING); + // If we're closing the window, then ensure the screensharing state + // is cleared. We don't do this on leave room, as we might still be + // sharing. + this._mozLoop.setScreenShareState( + this.getStoreState().windowId, + false); + if (!this._onUpdateListener) { return; } diff --git a/browser/components/loop/standalone/content/js/standaloneMozLoop.js b/browser/components/loop/standalone/content/js/standaloneMozLoop.js index cc77c65ba2d4..35c5a701d3cd 100644 --- a/browser/components/loop/standalone/content/js/standaloneMozLoop.js +++ b/browser/components/loop/standalone/content/js/standaloneMozLoop.js @@ -268,9 +268,10 @@ loop.StandaloneMozLoop = (function(mozL10n) { return localStorage.getItem(prefName); }, - // Dummy function to reflect those in the desktop mozLoop that we - // don't currently use. - addConversationContext: function() {} + // Dummy functions to reflect those in the desktop mozLoop that we + // don't currently use in standalone. + addConversationContext: function() {}, + setScreenShareState: function() {} }; return StandaloneMozLoop; diff --git a/browser/components/loop/test/mochitest/browser_toolbarbutton.js b/browser/components/loop/test/mochitest/browser_toolbarbutton.js index 6da937c610b7..a28d2b1e6955 100644 --- a/browser/components/loop/test/mochitest/browser_toolbarbutton.js +++ b/browser/components/loop/test/mochitest/browser_toolbarbutton.js @@ -104,3 +104,11 @@ add_task(function* test_panelToggle_on_click() { LoopUI.toolbarButton.node.click(); Assert.strictEqual(LoopUI.panel.state, "closed", "Panel should be closed"); }); + +add_task(function* test_screen_share() { + Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state"); + MozLoopService.setScreenShareState("1", true); + Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "action", "Check button is in action state"); + MozLoopService.setScreenShareState("1", false); + Assert.strictEqual(LoopUI.toolbarButton.node.getAttribute("state"), "", "Check button is in default state"); +}); diff --git a/browser/components/loop/test/shared/activeRoomStore_test.js b/browser/components/loop/test/shared/activeRoomStore_test.js index adea63635987..b17bfccc925b 100644 --- a/browser/components/loop/test/shared/activeRoomStore_test.js +++ b/browser/components/loop/test/shared/activeRoomStore_test.js @@ -30,7 +30,8 @@ describe("loop.store.ActiveRoomStore", function () { leave: sinon.stub(), on: sinon.stub(), off: sinon.stub() - } + }, + setScreenShareState: sinon.stub() }; fakeSdkDriver = { @@ -648,6 +649,10 @@ describe("loop.store.ActiveRoomStore", function () { }); describe("#screenSharingState", function() { + beforeEach(function() { + store.setStoreState({windowId: "1234"}); + }); + it("should save the state", function() { store.screenSharingState(new sharedActions.ScreenSharingState({ state: SCREEN_SHARE_STATES.ACTIVE @@ -655,6 +660,24 @@ describe("loop.store.ActiveRoomStore", function () { expect(store.getStoreState().screenSharingState).eql(SCREEN_SHARE_STATES.ACTIVE); }); + + it("should set screen sharing active when the state is active", function() { + store.screenSharingState(new sharedActions.ScreenSharingState({ + state: SCREEN_SHARE_STATES.ACTIVE + })); + + sinon.assert.calledOnce(fakeMozLoop.setScreenShareState); + sinon.assert.calledWithExactly(fakeMozLoop.setScreenShareState, "1234", true); + }); + + it("should set screen sharing inactive when the state is inactive", function() { + store.screenSharingState(new sharedActions.ScreenSharingState({ + state: SCREEN_SHARE_STATES.INACTIVE + })); + + sinon.assert.calledOnce(fakeMozLoop.setScreenShareState); + sinon.assert.calledWithExactly(fakeMozLoop.setScreenShareState, "1234", false); + }); }); describe("#receivingScreenShare", function() { @@ -696,10 +719,20 @@ describe("loop.store.ActiveRoomStore", function () { store.setStoreState({ roomState: ROOM_STATES.JOINED, roomToken: "fakeToken", - sessionToken: "1627384950" + sessionToken: "1627384950", + windowId: "1234" }); }); + it("should set screen sharing inactive", function() { + store.screenSharingState(new sharedActions.ScreenSharingState({ + state: SCREEN_SHARE_STATES.INACTIVE + })); + + sinon.assert.calledOnce(fakeMozLoop.setScreenShareState); + sinon.assert.calledWithExactly(fakeMozLoop.setScreenShareState, "1234", false); + }); + it("should reset the multiplexGum", function() { store.windowUnload();