Bug 1399413 - add mochitests to check multi-tabs gUM. r?jib draft
authorMunro Mengjue Chiang <mchiang@mozilla.com>
Tue, 07 Nov 2017 18:53:47 +0800
changeset 694112 ff3518e2947d84473b29346f085df8d2869d379f
parent 693455 e9f50dbb2a5672fcc4b99c46ed0bf27514796e03
child 739250 15c9f5668265f2da8cea57b7bb62e7f8707a5e79
push id88038
push userbmo:mchiang@mozilla.com
push dateTue, 07 Nov 2017 10:54:09 +0000
reviewersjib
bugs1399413
milestone58.0a1
Bug 1399413 - add mochitests to check multi-tabs gUM. r?jib MozReview-Commit-ID: 8ZtD1ArafvN
browser/base/content/test/webrtc/browser.ini
browser/base/content/test/webrtc/browser_devices_get_user_media_multi_process_camera.js
browser/base/content/test/webrtc/browser_devices_get_user_media_multi_process_screen.js
--- a/browser/base/content/test/webrtc/browser.ini
+++ b/browser/base/content/test/webrtc/browser.ini
@@ -7,16 +7,20 @@ support-files =
 
 [browser_devices_get_user_media.js]
 skip-if = (os == "linux" && debug) # linux: bug 976544
 [browser_devices_get_user_media_anim.js]
 [browser_devices_get_user_media_in_frame.js]
 skip-if = debug # bug 1369731
 [browser_devices_get_user_media_multi_process.js]
 skip-if = debug && (os == "win" || os == "mac") # bug 1393761
+[browser_devices_get_user_media_multi_process_camera.js]
+skip-if = debug && (os == "win" || os == "mac") # bug 1393761
+[browser_devices_get_user_media_multi_process_screen.js]
+skip-if = debug && (os == "win" || os == "mac") # bug 1393761
 [browser_devices_get_user_media_screen.js]
 [browser_devices_get_user_media_tear_off_tab.js]
 [browser_devices_get_user_media_unprompted_access.js]
 [browser_devices_get_user_media_unprompted_access_in_frame.js]
 [browser_devices_get_user_media_unprompted_access_tear_off_tab.js]
 skip-if = (os == "win" && bits == 64) # win8: bug 1334752
 [browser_devices_get_user_media_unprompted_access_queue_request.js]
 [browser_webrtc_hooks.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_multi_process_camera.js
@@ -0,0 +1,115 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var gTests = [
+
+{
+  desc: "getUserMedia camera in a first process + camera in a second process",
+  run: async function checkMultiProcessCamera() {
+
+    // Request camera in the first tab.
+    let promise = promisePopupNotificationShown("webRTC-shareDevices");
+    await promiseRequestDevice(false, true);
+    await promise;
+    await expectObserverCalled("getUserMedia:request");
+
+    checkDeviceSelectors(false, true);
+
+    let indicator = promiseIndicatorWindow();
+    await promiseMessage("ok", () => {
+      PopupNotifications.panel.firstChild.button.click();
+    });
+    await expectObserverCalled("getUserMedia:response:allow");
+    await expectObserverCalled("recording-device-events");
+    Assert.deepEqual((await getMediaCaptureState()), {video: true},
+                     "expected camera to be shared");
+
+    await indicator;
+    await checkSharingUI({video: true});
+
+    ok(webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator shown");
+    ok(webrtcUI.showCameraIndicator, "webrtcUI wants the camera indicator shown");
+    ok(!webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator hidden");
+    is(webrtcUI.getActiveStreams(true).length, 1, "1 active camera stream");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 1, "1 active stream");
+
+    await expectNoObserverCalled();
+
+    // If we have reached the max process count already, increase it to ensure
+    // our new tab can have its own content process.
+    var ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                 .getService(Ci.nsIMessageBroadcaster);
+    ppmm.QueryInterface(Ci.nsIProcessScriptLoader);
+    let childCount = ppmm.childCount;
+    let maxContentProcess = Services.prefs.getIntPref("dom.ipc.processCount");
+    // The first check is because if we are on a branch where e10s-multi is
+    // disabled, we want to keep testing e10s with a single content process.
+    // The + 1 is because ppmm.childCount also counts the chrome process
+    // (which also runs process scripts).
+    if (maxContentProcess > 1 && childCount == maxContentProcess + 1) {
+      await SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount",
+                                                childCount]]});
+    }
+
+    // Open a new tab with a different hostname.
+    let url = gBrowser.currentURI.spec.replace("https://example.com/",
+                                               "http://127.0.0.1:8888/");
+    let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+    tab.linkedBrowser.messageManager.loadFrameScript(CONTENT_SCRIPT_HELPER, true);
+
+    // Request camera in the second tab.
+    promise = promisePopupNotificationShown("webRTC-shareDevices");
+    await promiseRequestDevice(false, true);
+    await promise;
+    await expectObserverCalled("getUserMedia:request");
+
+    checkDeviceSelectors(false, true);
+
+    await promiseMessage("ok", () => {
+      PopupNotifications.panel.firstChild.button.click();
+    });
+    await expectObserverCalled("getUserMedia:response:allow");
+    await expectObserverCalled("recording-device-events");
+
+    await checkSharingUI({video: true}, window, {video: true});
+
+    ok(webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator shown");
+    ok(webrtcUI.showCameraIndicator, "webrtcUI wants the camera indicator shown");
+    ok(!webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator hidden");
+    is(webrtcUI.getActiveStreams(true).length, 2, "2 active camera streams");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 2, "2 active streams");
+
+    info("removing the second tab");
+    await BrowserTestUtils.removeTab(tab);
+
+    // Check that we still show the sharing indicators for the first tab's stream.
+    await promiseWaitForCondition(() => webrtcUI.showCameraIndicator);
+    ok(webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator shown");
+    ok(webrtcUI.showCameraIndicator, "webrtcUI wants the camera indicator shown");
+    ok(!webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator hidden");
+    is(webrtcUI.getActiveStreams(true).length, 1, "1 active camera stream");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 1, "1 active stream");
+
+    await checkSharingUI({video: true});
+
+    // When both tabs use the same content process, the frame script for the
+    // first tab receives observer notifications for things happening in the
+    // second tab, so let's clear the observer call counts before we cleanup
+    // in the first tab.
+    await ignoreObserversCalled();
+
+    // Close the first tab's stream and verify that all indicators are removed.
+    await closeStream();
+
+    ok(!webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator hidden");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 0, "0 active streams");
+  }
+},
+
+];
+
+add_task(async function test() {
+  SimpleTest.requestCompleteLog();
+  await runTests(gTests);
+});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/webrtc/browser_devices_get_user_media_multi_process_screen.js
@@ -0,0 +1,119 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var gTests = [
+
+{
+  desc: "getUserMedia screen sharing in a first process + screen sharing in a second process",
+  run: async function checkMultiProcessScreen() {
+
+    // Request screen sharing in the first tab.
+    let promise = promisePopupNotificationShown("webRTC-shareDevices");
+    await promiseRequestDevice(false, true, null, "screen");
+    await promise;
+    await expectObserverCalled("getUserMedia:request");
+
+    is(PopupNotifications.getNotification("webRTC-shareDevices").anchorID,
+       "webRTC-shareScreen-notification-icon", "anchored to device icon");
+    checkDeviceSelectors(false, false, true);
+
+    // Select the first screen so that we can have a stream.
+    document.getElementById("webRTC-selectWindow-menulist").getItemAtIndex(2).doCommand();
+
+    let indicator = promiseIndicatorWindow();
+    await promiseMessage("ok", () => {
+      PopupNotifications.panel.firstChild.button.click();
+    });
+    await expectObserverCalled("getUserMedia:response:allow");
+    await expectObserverCalled("recording-device-events");
+    Assert.deepEqual((await getMediaCaptureState()), {screen: "Screen"},
+                     "expected screen to be shared");
+
+    await indicator;
+    await checkSharingUI({screen: "Screen"});
+
+    ok(webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator shown");
+    ok(webrtcUI.showScreenSharingIndicator, "webrtcUI wants the screen sharing indicator shown");
+    ok(!webrtcUI.showCameraIndicator, "webrtcUI wants the camera indicator hidden");
+    ok(!webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator hidden");
+    is(webrtcUI.getActiveStreams(false, false, true).length, 1, "1 active screen sharing stream");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 1, "1 active stream");
+
+    await expectNoObserverCalled();
+
+    // If we have reached the max process count already, increase it to ensure
+    // our new tab can have its own content process.
+    var ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
+                 .getService(Ci.nsIMessageBroadcaster);
+    ppmm.QueryInterface(Ci.nsIProcessScriptLoader);
+    let childCount = ppmm.childCount;
+    let maxContentProcess = Services.prefs.getIntPref("dom.ipc.processCount");
+    // The first check is because if we are on a branch where e10s-multi is
+    // disabled, we want to keep testing e10s with a single content process.
+    // The + 1 is because ppmm.childCount also counts the chrome process
+    // (which also runs process scripts).
+    if (maxContentProcess > 1 && childCount == maxContentProcess + 1) {
+      await SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount",
+                                                childCount]]});
+    }
+
+    // Open a new tab with a different hostname.
+    let url = gBrowser.currentURI.spec.replace("https://example.com/",
+                                               "https://example.com/");
+    let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
+    tab.linkedBrowser.messageManager.loadFrameScript(CONTENT_SCRIPT_HELPER, true);
+
+    // Request screen sharing in the second tab.
+    promise = promisePopupNotificationShown("webRTC-shareDevices");
+    await promiseRequestDevice(false, true, null, "screen");
+    await promise;
+    await expectObserverCalled("getUserMedia:request");
+
+    is(PopupNotifications.getNotification("webRTC-shareDevices").anchorID,
+       "webRTC-shareScreen-notification-icon", "anchored to device icon");
+    checkDeviceSelectors(false, false, true);
+
+    // Select the first screen so that we can have a stream.
+    document.getElementById("webRTC-selectWindow-menulist").getItemAtIndex(2).doCommand();
+
+    indicator = promiseIndicatorWindow();
+    await promiseMessage("ok", () => {
+      PopupNotifications.panel.firstChild.button.click();
+    });
+    await expectObserverCalled("getUserMedia:response:allow");
+    await expectObserverCalled("recording-device-events");
+
+    await indicator;
+    await checkSharingUI({screen: "Screen"}, window, {screen: "Screen"});
+
+    ok(webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator shown");
+    ok(webrtcUI.showScreenSharingIndicator, "webrtcUI wants the screen sharing indicator shown");
+    ok(!webrtcUI.showCameraIndicator, "webrtcUI wants the camera indicator hidden");
+    ok(!webrtcUI.showMicrophoneIndicator, "webrtcUI wants the mic indicator hidden");
+    is(webrtcUI.getActiveStreams(false, false, true).length, 2, "2 active desktop sharing streams");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 2, "2 active streams");
+
+    info("removing the second tab");
+    await BrowserTestUtils.removeTab(tab);
+
+    // When both tabs use the same content process, the frame script for the
+    // first tab receives observer notifications for things happening in the
+    // second tab, so let's clear the observer call counts before we cleanup
+    // in the first tab.
+    await ignoreObserversCalled();
+
+    // Close the first tab's stream and verify that all indicators are removed.
+    await closeStream();
+
+    ok(!webrtcUI.showGlobalIndicator, "webrtcUI wants the global indicator hidden");
+    is(webrtcUI.getActiveStreams(true, true, true).length, 0, "0 active streams");
+  }
+},
+
+];
+
+add_task(async function test() {
+  SimpleTest.requestCompleteLog();
+  await runTests(gTests);
+});