Bug 1107967 - 'Stop sharing' doesn't work on teared off tabs, r=felipe.
authorFlorian Quèze <florian@queze.net>
Thu, 11 Dec 2014 00:02:39 +0100
changeset 219113 6e31e40ecf17d61447fdb681245c09c766b19af0
parent 219112 9612347414cb445646b48a9a88b0e7fd2702cc1b
child 219114 cf7a81a592ba732cc6968cca2c6253479c685271
push id27956
push userkwierso@gmail.com
push dateFri, 12 Dec 2014 00:47:19 +0000
treeherdermozilla-central@32a2c5bd2f68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfelipe
bugs1107967
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1107967 - 'Stop sharing' doesn't work on teared off tabs, r=felipe.
browser/modules/webrtcUI.jsm
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -65,16 +65,23 @@ this.webrtcUI = {
       let browser = aStream.browser;
       let browserWindow = browser.ownerDocument.defaultView;
       let tab = browserWindow.gBrowser &&
                 browserWindow.gBrowser.getTabForBrowser(browser);
       return {uri: state.documentURI, tab: tab, browser: browser, types: types};
     });
   },
 
+  swapBrowserForNotification: function(aOldBrowser, aNewBrowser) {
+    for (let stream of this._streams) {
+      if (stream.browser == aOldBrowser)
+        stream.browser = aNewBrowser;
+    };
+  },
+
   showSharingDoorhanger: function(aActiveStream, aType) {
     let browserWindow = aActiveStream.browser.ownerDocument.defaultView;
     if (aActiveStream.tab) {
       browserWindow.gBrowser.selectedTab = aActiveStream.tab;
     } else {
       aActiveStream.browser.focus();
     }
     browserWindow.focus();
@@ -179,41 +186,43 @@ function prompt(aBrowser, aRequest) {
   let mainLabel;
   if (sharingScreen) {
     mainLabel = stringBundle.getString("getUserMedia.shareSelectedItems.label");
   }
   else {
     let string = stringBundle.getString("getUserMedia.shareSelectedDevices.label");
     mainLabel = PluralForm.get(requestTypes.length, string);
   }
+
+  let notification; // Used by action callbacks.
   let mainAction = {
     label: mainLabel,
     accessKey: stringBundle.getString("getUserMedia.shareSelectedDevices.accesskey"),
     // The real callback will be set during the "showing" event. The
     // empty function here is so that PopupNotifications.show doesn't
     // reject the action.
     callback: function() {}
   };
 
   let secondaryActions = [
     {
       label: stringBundle.getString("getUserMedia.denyRequest.label"),
       accessKey: stringBundle.getString("getUserMedia.denyRequest.accesskey"),
       callback: function () {
-        denyRequest(aBrowser, aRequest);
+        denyRequest(notification.browser, aRequest);
       }
     }
   ];
 
   if (!sharingScreen) { // Bug 1037438: implement 'never' for screen sharing.
     secondaryActions.push({
       label: stringBundle.getString("getUserMedia.never.label"),
       accessKey: stringBundle.getString("getUserMedia.never.accesskey"),
       callback: function () {
-        denyRequest(aBrowser, aRequest);
+        denyRequest(notification.browser, aRequest);
         // Let someone save "Never" for http sites so that they can be stopped from
         // bothering you with doorhangers.
         let perms = Services.perms;
         if (audioDevices.length)
           perms.add(uri, "microphone", perms.DENY_ACTION);
         if (videoDevices.length)
           perms.add(uri, "camera", perms.DENY_ACTION);
       }
@@ -277,20 +286,20 @@ function prompt(aBrowser, aRequest) {
         // and will grant audio access immediately.
         if ((!audioDevices.length || micPerm) && (!videoDevices.length || camPerm)) {
           // All permissions we were about to request are already persistently set.
           let allowedDevices = [];
           if (videoDevices.length && camPerm == perms.ALLOW_ACTION)
             allowedDevices.push(videoDevices[0].deviceIndex);
           if (audioDevices.length && micPerm == perms.ALLOW_ACTION)
             allowedDevices.push(audioDevices[0].deviceIndex);
-          aBrowser.messageManager.sendAsyncMessage("webrtc:Allow",
-                                                   {callID: aRequest.callID,
-                                                    windowID: aRequest.windowID,
-                                                    devices: allowedDevices});
+          let mm = this.browser.messageManager;
+          mm.sendAsyncMessage("webrtc:Allow", {callID: aRequest.callID,
+                                               windowID: aRequest.windowID,
+                                               devices: allowedDevices});
           this.remove();
           return true;
         }
       }
 
       function listDevices(menupopup, devices) {
         while (menupopup.lastChild)
           menupopup.removeChild(menupopup.lastChild);
@@ -399,36 +408,38 @@ function prompt(aBrowser, aRequest) {
             allowedDevices.push(audioDeviceIndex);
           if (aRemember) {
             perms.add(uri, "microphone",
                       allowMic ? perms.ALLOW_ACTION : perms.DENY_ACTION);
           }
         }
 
         if (!allowedDevices.length) {
-          denyRequest(aBrowser, aRequest);
+          denyRequest(notification.browser, aRequest);
           return;
         }
 
-        aBrowser.messageManager.sendAsyncMessage("webrtc:Allow",
-                                                 {callID: aRequest.callID,
-                                                  windowID: aRequest.windowID,
-                                                  devices: allowedDevices});
+        let mm = notification.browser.messageManager
+        mm.sendAsyncMessage("webrtc:Allow", {callID: aRequest.callID,
+                                             windowID: aRequest.windowID,
+                                             devices: allowedDevices});
       };
       return false;
     }
   };
 
   let anchorId = "webRTC-shareDevices-notification-icon";
   if (requestTypes.length == 1 && requestTypes[0] == "Microphone")
     anchorId = "webRTC-shareMicrophone-notification-icon";
   if (requestTypes.indexOf("Screen") != -1)
     anchorId = "webRTC-shareScreen-notification-icon";
-  chromeWin.PopupNotifications.show(aBrowser, "webRTC-shareDevices", message,
-                                    anchorId, mainAction, secondaryActions, options);
+  notification =
+    chromeWin.PopupNotifications.show(aBrowser, "webRTC-shareDevices", message,
+                                      anchorId, mainAction, secondaryActions,
+                                      options);
 }
 
 function getGlobalIndicator() {
 #ifndef XP_MACOSX
   const INDICATOR_CHROME_URI = "chrome://browser/content/webrtcIndicator.xul";
   const features = "chrome,dialog=yes,titlebar=no,popup=yes";
 
   return Services.ww.openWindow(null, INDICATOR_CHROME_URI, "_blank", features, []);
@@ -696,16 +707,17 @@ function updateBrowserSpecificIndicator(
   } else if (aState.microphone) {
     captureState = "Microphone";
   }
 
   let chromeWin = aBrowser.ownerDocument.defaultView;
   let stringBundle = chromeWin.gNavigatorBundle;
 
   let windowId = aState.windowId;
+  let notification; // Used by action callbacks.
   let mainAction = {
     label: stringBundle.getString("getUserMedia.continueSharing.label"),
     accessKey: stringBundle.getString("getUserMedia.continueSharing.accesskey"),
     callback: function () {},
     dismiss: true
   };
   let secondaryActions = [{
     label: stringBundle.getString("getUserMedia.stopSharing.label"),
@@ -716,73 +728,89 @@ function updateBrowserSpecificIndicator(
       let perms = Services.perms;
       if (aState.camera &&
           perms.testExactPermission(uri, "camera") == perms.ALLOW_ACTION)
         perms.remove(host, "camera");
       if (aState.microphone &&
           perms.testExactPermission(uri, "microphone") == perms.ALLOW_ACTION)
         perms.remove(host, "microphone");
 
-      aBrowser.messageManager.sendAsyncMessage("webrtc:StopSharing", windowId);
+      let mm = notification.browser.messageManager;
+      mm.sendAsyncMessage("webrtc:StopSharing", windowId);
     }
   }];
   let options = {
     hideNotNow: true,
     dismissed: true,
-    eventCallback: function(aTopic) {
+    eventCallback: function(aTopic, aNewBrowser) {
       if (aTopic == "shown") {
         let PopupNotifications = this.browser.ownerDocument.defaultView.PopupNotifications;
         let popupId = captureState == "Microphone" ? "Microphone" : "Devices";
         PopupNotifications.panel.firstChild.setAttribute("popupid", "webRTC-sharing" + popupId);
       }
-      return aTopic == "swapping";
+
+      if (aTopic == "swapping") {
+        webrtcUI.swapBrowserForNotification(this.browser, aNewBrowser);
+        return true;
+      }
+
+      return false;
     }
   };
   if (captureState) {
     let anchorId = captureState == "Microphone" ? "webRTC-sharingMicrophone-notification-icon"
                                                 : "webRTC-sharingDevices-notification-icon";
     let message = stringBundle.getString("getUserMedia.sharing" + captureState + ".message2");
-    chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingDevices", message,
-                                      anchorId, mainAction, secondaryActions, options);
+    notification =
+      chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingDevices", message,
+                                        anchorId, mainAction, secondaryActions, options);
   }
   else {
     removeBrowserNotification(aBrowser,"webRTC-sharingDevices");
   }
 
   // Now handle the screen sharing indicator.
   if (!aState.screen) {
     removeBrowserNotification(aBrowser,"webRTC-sharingScreen");
     return;
   }
 
+  let screenSharingNotif; // Used by action callbacks.
   options = {
     hideNotNow: true,
     dismissed: true,
-    eventCallback: function(aTopic) {
+    eventCallback: function(aTopic, aNewBrowser) {
       if (aTopic == "shown") {
         let PopupNotifications = this.browser.ownerDocument.defaultView.PopupNotifications;
         PopupNotifications.panel.firstChild.setAttribute("popupid", "webRTC-sharingScreen");
       }
-      return aTopic == "swapping";
+
+      if (aTopic == "swapping") {
+        webrtcUI.swapBrowserForNotification(this.browser, aNewBrowser);
+        return true;
+      }
+
+      return false;
     }
   };
   secondaryActions = [{
     label: stringBundle.getString("getUserMedia.stopSharing.label"),
     accessKey: stringBundle.getString("getUserMedia.stopSharing.accesskey"),
     callback: function () {
-      aBrowser.messageManager.sendAsyncMessage("webrtc:StopSharing",
-                                               "screen:" + windowId);
+      let mm = screenSharingNotif.browser.messageManager;
+      mm.sendAsyncMessage("webrtc:StopSharing", "screen:" + windowId);
     }
   }];
   // If we are sharing both a window and the screen, we show 'Screen'.
   let stringId = "getUserMedia.sharing" + aState.screen;
-  chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingScreen",
-                                    stringBundle.getString(stringId + ".message"),
-                                    "webRTC-sharingScreen-notification-icon",
-                                    mainAction, secondaryActions, options);
+  screenSharingNotif =
+    chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingScreen",
+                                      stringBundle.getString(stringId + ".message"),
+                                      "webRTC-sharingScreen-notification-icon",
+                                      mainAction, secondaryActions, options);
 }
 
 function removeBrowserNotification(aBrowser, aNotificationId) {
   let win = aBrowser.ownerDocument.defaultView;
   let notification =
     win.PopupNotifications.getNotification(aNotificationId, aBrowser);
   if (notification)
     win.PopupNotifications.remove(notification);