Bug 1267835 - Land version 1.3.1 of the Loop system add-on in mozilla-central, rs=Standard8 for already reviewed code. a=ritu
authorMark Banner <standard8@mozilla.com>
Tue, 24 May 2016 17:07:33 -0700
changeset 378913 4c0231d73fd385e773ce5a804b499643c99471c6
parent 378912 9664c4ce553a598fad98a08306a832178f01ca77
child 378914 70fa82df113befb915e6d2b9ebe7201762d1ed7c
push id21011
push usermak77@bonardo.net
push dateThu, 16 Jun 2016 13:40:45 +0000
reviewersStandard8, ritu
bugs1267835
milestone47.0
Bug 1267835 - Land version 1.3.1 of the Loop system add-on in mozilla-central, rs=Standard8 for already reviewed code. a=ritu
browser/extensions/loop/bootstrap.js
browser/extensions/loop/chrome/test/mochitest/.eslintrc
browser/extensions/loop/chrome/test/mochitest/browser.ini
browser/extensions/loop/chrome/test/mochitest/browser_copypanel.js
browser/extensions/loop/chrome/test/mochitest/browser_panel_privateBrowsing.js
browser/extensions/loop/chrome/test/mochitest/head.js
browser/extensions/loop/install.rdf.in
--- a/browser/extensions/loop/bootstrap.js
+++ b/browser/extensions/loop/bootstrap.js
@@ -188,26 +188,37 @@ var WindowListener = {
       /**
        * Opens the panel for Loop and sizes it appropriately.
        *
        * @param {event}  event   The event opening the panel, used to anchor
        *                         the panel to the button which triggers it.
        * @return {Promise}
        */
       openPanel: function(event) {
+        if (PrivateBrowsingUtils.isWindowPrivate(window)) {
+          return Promise.reject();
+        }
+
         return new Promise((resolve) => {
           let callback = iframe => {
             let mm = iframe.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
             if (!("messageManager" in iframe)) {
               iframe.messageManager = mm;
             }
-            this.hookWindowCloseForPanelClose(iframe);
+
+            if (!this._panelInitialized) {
+              this.hookWindowCloseForPanelClose(iframe);
+              this._panelInitialized = true;
+            }
 
             mm.sendAsyncMessage("Social:WaitForDocumentVisible");
-            mm.addMessageListener("Social:DocumentVisible", () => resolve(mm));
+            mm.addMessageListener("Social:DocumentVisible", function onDocumentVisible() {
+              mm.removeMessageListener("Social:DocumentVisible", onDocumentVisible);
+              resolve(mm);
+            });
 
             let buckets = this.constants.LOOP_MAU_TYPE;
             this.LoopAPI.sendMessageToHandler({
               name: "TelemetryAddValue",
               data: ["LOOP_ACTIVITY_COUNTER", buckets.OPEN_PANEL]
             });
           };
 
--- a/browser/extensions/loop/chrome/test/mochitest/.eslintrc
+++ b/browser/extensions/loop/chrome/test/mochitest/.eslintrc
@@ -13,16 +13,17 @@
     "is": false,
     "info": false,
     "ok": false,
     "registerCleanupFunction": false,
     // head.js items
     "HAWK_TOKEN_LENGTH": true,
     "checkLoggedOutState": false,
     "checkFxAOAuthTokenData": false,
+    "cleanupPanel": false,
     "loadLoopPanel": false,
     "getLoopString": false,
     "gMozLoopAPI": true,
     "mockDb": true,
     "mockPushHandler": true,
     "OpenBrowserWindow": true,
     "promiseDeletedOAuthParams": false,
     "promiseOAuthGetRegistration": false,
--- a/browser/extensions/loop/chrome/test/mochitest/browser.ini
+++ b/browser/extensions/loop/chrome/test/mochitest/browser.ini
@@ -10,13 +10,14 @@ support-files =
 [browser_loop_fxa_server.js]
 [browser_LoopRooms_channel.js]
 [browser_menuitem.js]
 [browser_mozLoop_appVersionInfo.js]
 [browser_mozLoop_chat.js]
 [browser_mozLoop_context.js]
 [browser_mozLoop_infobar.js]
 [browser_mozLoop_socialShare.js]
+[browser_panel_privateBrowsing.js]
 [browser_mozLoop_sharingListeners.js]
 [browser_mozLoop_telemetry.js]
 [browser_sharingTitleListeners.js]
 [browser_throttler.js]
 [browser_toolbarbutton.js]
--- a/browser/extensions/loop/chrome/test/mochitest/browser_copypanel.js
+++ b/browser/extensions/loop/chrome/test/mochitest/browser_copypanel.js
@@ -3,20 +3,21 @@
 
 "use strict";
 
 let gConstants;
 LoopAPI.inspect()[1].GetAllConstants({}, constants => { return (gConstants = constants); });
 
 let { goDoCommand, gURLBar } = window;
 
-registerCleanupFunction(() => {
-  document.getElementById("loop-notification-panel").hidePopup();
+function cleanUp() {
+  cleanupPanel();
   LoopUI.removeCopyPanel();
-});
+}
+registerCleanupFunction(cleanUp);
 
 /**
  * Cleanup function to allow the loop panel to finish opening then close it.
  */
 function waitForLoopPanelShowHide() {
   return new Promise(resolve => {
     let panel = document.getElementById("loop-notification-panel");
     panel.addEventListener("popupshown", function onShow() {
@@ -27,29 +28,29 @@ function waitForLoopPanelShowHide() {
       panel.removeEventListener("popuphidden", onHidden);
       resolve();
     });
   });
 }
 
 // Even with max threshold, no panel if already shown.
 add_task(function* test_init_copy_panel_already_shown() {
-  LoopUI.removeCopyPanel();
+  cleanUp();
   Services.prefs.setIntPref("loop.copy.ticket", -1);
   Services.prefs.setBoolPref("loop.copy.shown", true);
 
   yield LoopUI.maybeAddCopyPanel();
 
   Assert.equal(document.getElementById("loop-copy-notification-panel"), null, "copy panel doesn't exist for already shown");
   Assert.equal(Services.prefs.getIntPref("loop.copy.ticket"), -1, "ticket should be unchanged");
 });
 
 // Even with max threshold, no panel if private browsing.
 add_task(function* test_init_copy_panel_private() {
-  LoopUI.removeCopyPanel();
+  cleanUp();
   Services.prefs.setIntPref("loop.copy.ticket", -1);
 
   let win = OpenBrowserWindow({ private: true });
   yield new Promise(resolve => win.addEventListener("load", resolve));
   yield win.LoopUI.maybeAddCopyPanel();
 
   Assert.equal(win.document.getElementById("loop-copy-notification-panel"), null, "copy panel doesn't exist for private browsing");
   Assert.equal(Services.prefs.getIntPref("loop.copy.ticket"), -1, "ticket should be unchanged");
@@ -60,17 +61,17 @@ add_task(function* test_init_copy_panel_
 /**
  * Helper function for testing clicks on the copy panel.
  * @param {String} domain Text to put in the urlbar to assist in debugging.
  * @param {Function} onIframe Callback to interact with iframe contents.
  */
 function testClick(domain, onIframe) {
   let histogram = Services.telemetry.getHistogramById("LOOP_COPY_PANEL_ACTIONS");
   histogram.clear();
-  LoopUI.removeCopyPanel();
+  cleanUp();
   gURLBar.value = "http://" + domain + "/";
 
   return new Promise(resolve => {
     // Continue testing when the click has been handled.
     LoopUI.addCopyPanel(detail => resolve([histogram, detail]));
     gURLBar.focus();
     gURLBar.select();
     goDoCommand("cmd_copy");
new file mode 100644
--- /dev/null
+++ b/browser/extensions/loop/chrome/test/mochitest/browser_panel_privateBrowsing.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var win;
+
+registerCleanupFunction(function* () {
+  if (win) {
+    yield BrowserTestUtils.closeWindow(win);
+  }
+});
+
+add_task(function* test_panel_should_be_shown() {
+  registerCleanupFunction(function* () {
+    cleanupPanel();
+  });
+
+  yield window.LoopUI.openPanel();
+
+  Assert.notEqual(document.getElementById("loop-notification-panel"), null, "Panel exists");
+});
+
+add_task(function* test_init_copy_panel_private() {
+  let rejected = false;
+  win = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
+
+  try {
+    yield win.LoopUI.openPanel();
+  }
+  catch (ex) {
+    rejected = true;
+  }
+
+  Assert.ok(rejected, "openPanel promise should have been rejected");
+  Assert.equal(win.document.getElementById("loop-notification-panel").childNodes.length, 0, "Panel doesn't exist for private browsing");
+});
--- a/browser/extensions/loop/chrome/test/mochitest/head.js
+++ b/browser/extensions/loop/chrome/test/mochitest/head.js
@@ -1,32 +1,44 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 /* exported HAWK_TOKEN_LENGTH, LoopRooms, promiseWaitForCondition,
             loadLoopPanel, promiseOAuthParamsSetup, resetFxA, checkLoggedOutState,
             promiseDeletedOAuthParams, promiseOAuthGetRegistration,
-            getLoopString, mockPushHandler, channelID, mockDb, LoopAPI */
+            getLoopString, mockPushHandler, channelID, mockDb, LoopAPI,
+            cleanupPanel */
 
 const HAWK_TOKEN_LENGTH = 64;
 const {
   LOOP_SESSION_TYPE,
   MozLoopServiceInternal,
   MozLoopService
 } = Cu.import("chrome://loop/content/modules/MozLoopService.jsm", {});
 const { LoopAPI } = Cu.import("chrome://loop/content/modules/MozLoopAPI.jsm", {});
 const { LoopRooms } = Cu.import("chrome://loop/content/modules/LoopRooms.jsm", {});
 
 // Cache this value only once, at the beginning of a
 // test run, so that it doesn't pick up the offline=true
 // if offline mode is requested multiple times in a test run.
 const WAS_OFFLINE = Services.io.offline;
 
+function cleanupPanel() {
+  let loopPanel = document.getElementById("loop-notification-panel");
+  loopPanel.hidePopup();
+  let btn = document.getElementById("loop-button");
+  let frameId = btn.getAttribute("notificationFrameId");
+  let frame = document.getElementById(frameId);
+  if (frame) {
+    frame.remove();
+  }
+}
+
 function promisePanelLoaded() {
   return new Promise((resolve) => {
     let loopPanel = document.getElementById("loop-notification-panel");
     let btn = document.getElementById("loop-button");
 
     // Wait for the popup to be shown if it's not already, then we can get the iframe and
     // wait for the iframe's load to be completed.
     if (loopPanel.state == "closing" || loopPanel.state == "closed") {
@@ -43,35 +55,29 @@ function promisePanelLoaded() {
 
     function onpopupshown() {
       let iframe = document.getElementById(btn.getAttribute("notificationFrameId"));
 
       if (iframe.contentDocument &&
           iframe.contentDocument.readyState == "complete") {
         resolve();
       } else {
-        iframe.addEventListener("load", function panelOnLoad() {
-          iframe.removeEventListener("load", panelOnLoad, true);
-          // We do this in an execute soon to allow any other event listeners to
-          // be handled, just in case.
+        // Wait for the panel to completely load before continuing.
+        iframe.contentWindow.addEventListener("loopPanelInitialized", function onInit() {
+          iframe.contentWindow.removeEventListener("loopPanelInitialized", onInit);
           resolve();
-        }, true);
+        });
       }
     }
 
     // Remove the iframe after each test. This also avoids mochitest complaining
     // about leaks on shutdown as we intentionally hold the iframe open for the
     // life of the application.
     registerCleanupFunction(function() {
-      loopPanel.hidePopup();
-      let frameId = btn.getAttribute("notificationFrameId");
-      let frame = document.getElementById(frameId);
-      if (frame) {
-        frame.remove();
-      }
+      cleanupPanel();
     });
   });
 }
 
 function waitForCondition(condition, nextTest, errorMsg) {
   var tries = 0;
   var interval = setInterval(function() {
     if (tries >= 200) {
--- a/browser/extensions/loop/install.rdf.in
+++ b/browser/extensions/loop/install.rdf.in
@@ -4,17 +4,17 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 #filter substitution
 
 <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
   <Description about="urn:mozilla:install-manifest">
     <em:id>loop@mozilla.org</em:id>
     <em:bootstrap>true</em:bootstrap>
-    <em:version>1.3.0</em:version>
+    <em:version>1.3.1</em:version>
     <em:type>2</em:type>
 
     <!-- Target Application this extension can install into,
          with minimum and maximum supported versions. -->
     <em:targetApplication>
       <Description>
         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
         <em:minVersion>46.0a1</em:minVersion>