From 63d5b3742bfa437614116c155419b02d25c03acc Mon Sep 17 00:00:00 2001 From: Mike de Boer Date: Tue, 24 Feb 2015 17:16:27 +0100 Subject: [PATCH] Bug 1133493: add e10s-friendly API to fetch a tab's outer window ID. r=florian,Standard8 --- browser/base/content/content.js | 7 +++ browser/components/loop/MozLoopAPI.jsm | 24 ++++++++++ .../loop/test/mochitest/browser.ini | 1 + .../mochitest/browser_mozLoop_tabSharing.js | 41 +++++++++++++++++ .../components/loop/test/mochitest/head.js | 44 +++++++++++++++++++ 5 files changed, 117 insertions(+) create mode 100644 browser/components/loop/test/mochitest/browser_mozLoop_tabSharing.js diff --git a/browser/base/content/content.js b/browser/base/content/content.js index b4c78fe67915..78058b1ccabc 100644 --- a/browser/base/content/content.js +++ b/browser/base/content/content.js @@ -931,6 +931,13 @@ ContentWebRTC.init(); addMessageListener("webrtc:Allow", ContentWebRTC); addMessageListener("webrtc:Deny", ContentWebRTC); addMessageListener("webrtc:StopSharing", ContentWebRTC); +addMessageListener("webrtc:StartBrowserSharing", () => { + let windowID = content.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils).outerWindowID; + sendAsyncMessage("webrtc:response:StartBrowserSharing", { + windowID: windowID + }); +}); function gKeywordURIFixup(fixupInfo) { fixupInfo.QueryInterface(Ci.nsIURIFixupInfo); diff --git a/browser/components/loop/MozLoopAPI.jsm b/browser/components/loop/MozLoopAPI.jsm index b7fdb597e3aa..889349ca696b 100644 --- a/browser/components/loop/MozLoopAPI.jsm +++ b/browser/components/loop/MozLoopAPI.jsm @@ -257,6 +257,30 @@ function injectLoopAPI(targetWindow) { } }, + getActiveTabWindowId: { + enumerable: true, + writable: true, + value: function(callback) { + let win = Services.wm.getMostRecentWindow("navigator:browser"); + let browser = win && win.gBrowser.selectedTab.linkedBrowser; + if (!win || !browser) { + // This may happen when an undocked conversation window is the only + // window left. + let err = new Error("No tabs available to share."); + MozLoopService.log.error(err); + callback(cloneValueInto(err, targetWindow)); + return; + } + + let mm = browser.messageManager; + mm.addMessageListener("webrtc:response:StartBrowserSharing", function listener(message) { + mm.removeMessageListener("webrtc:response:StartBrowserSharing", listener); + callback(null, message.data.windowID); + }); + mm.sendAsyncMessage("webrtc:StartBrowserSharing"); + } + }, + /** * Returns the window data for a specific conversation window id. * diff --git a/browser/components/loop/test/mochitest/browser.ini b/browser/components/loop/test/mochitest/browser.ini index fb2503a0b356..20391398ed66 100644 --- a/browser/components/loop/test/mochitest/browser.ini +++ b/browser/components/loop/test/mochitest/browser.ini @@ -21,5 +21,6 @@ skip-if = e10s skip-if = buildapp == 'mulet' [browser_toolbarbutton.js] [browser_mozLoop_pluralStrings.js] +[browser_mozLoop_tabSharing.js] [browser_mozLoop_telemetry.js] skip-if = e10s diff --git a/browser/components/loop/test/mochitest/browser_mozLoop_tabSharing.js b/browser/components/loop/test/mochitest/browser_mozLoop_tabSharing.js new file mode 100644 index 000000000000..928e214aa7fd --- /dev/null +++ b/browser/components/loop/test/mochitest/browser_mozLoop_tabSharing.js @@ -0,0 +1,41 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * This is an integration test to make sure that passing window IDs is working as + * expected, with or without e10s enabled - rather than just testing MozLoopAPI + * alone. + */ + +const {injectLoopAPI} = Cu.import("resource:///modules/loop/MozLoopAPI.jsm"); +gMozLoopAPI = injectLoopAPI({}); + +let promiseTabWindowId = function() { + return new Promise(resolve => { + gMozLoopAPI.getActiveTabWindowId((err, windowId) => { + Assert.equal(null, err, "No error should've occurred."); + Assert.equal(typeof windowId, "number", "We should have a window ID"); + resolve(windowId); + }); + }); +}; + +add_task(function* test_windowIdFetch_simple() { + Assert.ok(gMozLoopAPI, "mozLoop should exist"); + + yield promiseTabWindowId(); +}); + +add_task(function* test_windowIdFetch_multipleTabs() { + let previousTab = gBrowser.selectedTab; + let previousTabId = yield promiseTabWindowId(); + + let tab = gBrowser.selectedTab = gBrowser.addTab(); + yield promiseTabLoadEvent(tab, "about:mozilla"); + let tabId = yield promiseTabWindowId(); + Assert.ok(tabId !== previousTabId, "Tab contentWindow IDs shouldn't be the same"); + gBrowser.removeTab(tab); + + tabId = yield promiseTabWindowId(); + Assert.equal(previousTabId, tabId, "Window IDs should be back to what they were"); +}); diff --git a/browser/components/loop/test/mochitest/head.js b/browser/components/loop/test/mochitest/head.js index 902fe4ad1600..086b53fd3e71 100644 --- a/browser/components/loop/test/mochitest/head.js +++ b/browser/components/loop/test/mochitest/head.js @@ -176,6 +176,50 @@ function promiseOAuthGetRegistration(baseURL) { }); } +/** + * Waits for a load (or custom) event to finish in a given tab. If provided + * load an uri into the tab. + * + * @param tab + * The tab to load into. + * @param [optional] url + * The url to load, or the current url. + * @param [optional] event + * The load event type to wait for. Defaults to "load". + * @return {Promise} resolved when the event is handled. + * @resolves to the received event + * @rejects if a valid load event is not received within a meaningful interval + */ +function promiseTabLoadEvent(tab, url, eventType="load") { + return new Promise((resolve, reject) => { + info("Wait tab event: " + eventType); + + function handle(event) { + if (event.originalTarget != tab.linkedBrowser.contentDocument || + event.target.location.href == "about:blank" || + (url && event.target.location.href != url)) { + info("Skipping spurious '" + eventType + "'' event" + + " for " + event.target.location.href); + return; + } + clearTimeout(timeout); + tab.linkedBrowser.removeEventListener(eventType, handle, true); + info("Tab event received: " + eventType); + resolve(event); + } + + let timeout = setTimeout(() => { + if (tab.linkedBrowser) + tab.linkedBrowser.removeEventListener(eventType, handle, true); + reject(new Error("Timed out while waiting for a '" + eventType + "'' event")); + }, 30000); + + tab.linkedBrowser.addEventListener(eventType, handle, true, true); + if (url) + tab.linkedBrowser.loadURI(url); + }); +} + function getLoopString(stringID) { return MozLoopServiceInternal.localizedStrings.get(stringID); }