Bug 1083391: Only send panel show/hide events after the panel's document is ready. r=erikvold
authorDave Townsend <dtownsend@oxymoronical.com>
Mon, 20 Oct 2014 11:52:27 -0700
changeset 237824 573f42076ad7fdb321624508c72e7d274b68b39d
parent 237823 3f4673b89e04f1ba3c82e77d07e0b21b7d86ae85
child 237825 caaa0cc9b53d478ec765c6e7b87de4b1d7c250d9
push id660
push userraliiev@mozilla.com
push dateWed, 18 Feb 2015 20:30:48 +0000
treeherdermozilla-release@49e493494178 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserikvold
bugs1083391
milestone36.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 1083391: Only send panel show/hide events after the panel's document is ready. r=erikvold
addon-sdk/source/lib/sdk/panel.js
addon-sdk/source/test/test-panel.js
--- a/addon-sdk/source/lib/sdk/panel.js
+++ b/addon-sdk/source/lib/sdk/panel.js
@@ -132,16 +132,17 @@ const Panel = Class({
   setup: function setup(options) {
     let model = merge({
       defaultWidth: 320,
       defaultHeight: 240,
       focus: true,
       position: Object.freeze({}),
       contextMenu: false
     }, panelContract(options));
+    model.ready = false;
     models.set(this, model);
 
     if (model.contentStyle || model.contentStyleFile) {
       styles.set(this, Style({
         uri: model.contentStyleFile,
         source: model.contentStyle
       }));
     }
@@ -295,25 +296,40 @@ let hides = filter(panelEvents, ({type})
 let ready = filter(panelEvents, ({type, target}) =>
   getAttachEventType(modelFor(panelFor(target))) === type);
 
 // Styles should be always added as soon as possible, and doesn't makes them
 // depends on `contentScriptWhen`
 let start = filter(panelEvents, ({type}) => type === "document-element-inserted");
 
 // Forward panel show / hide events to panel's own event listeners.
-on(shows, "data", ({target}) => emit(panelFor(target), "show"));
+on(shows, "data", ({target}) => {
+  let panel = panelFor(target);
+  if (modelFor(panel).ready)
+    emit(panel, "show");
+});
 
-on(hides, "data", ({target}) => emit(panelFor(target), "hide"));
+on(hides, "data", ({target}) => {
+  let panel = panelFor(target);
+  if (modelFor(panel).ready)
+    emit(panel, "hide");
+});
 
 on(ready, "data", ({target}) => {
   let panel = panelFor(target);
   let window = domPanel.getContentDocument(target).defaultView;
 
   workerFor(panel).attach(window);
+
+  if (!modelFor(panel).ready) {
+    modelFor(panel).ready = true;
+
+    if (viewFor(panel).state == "open")
+      emit(panel, "show");
+  }
 });
 
 on(start, "data", ({target}) => {
   let panel = panelFor(target);
   let window = domPanel.getContentDocument(target).defaultView;
 
   attach(styleFor(panel), window);
 });
--- a/addon-sdk/source/test/test-panel.js
+++ b/addon-sdk/source/test/test-panel.js
@@ -276,27 +276,38 @@ exports["test Resize Panel"] = function(
     browserWindow.focus();
   }
 };
 
 exports["test Hide Before Show"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
 
   let showCalled = false;
-  let panel = Panel({
+  let hideCalled = false;
+  let panel1 = Panel({
     onShow: function () {
       showCalled = true;
     },
     onHide: function () {
-      assert.ok(!showCalled, 'must not emit show if was hidden before');
-      done();
+      hideCalled = true;
     }
   });
-  panel.show();
-  panel.hide();
+  panel1.show();
+  panel1.hide();
+
+  let panel2 = Panel({
+    onShow: function () {
+      assert.ok(!showCalled, 'should not emit show');
+      assert.ok(!hideCalled, 'should not emit hide');
+      panel1.destroy();
+      panel2.destroy();
+      done();
+    },
+  });
+  panel2.show();
 };
 
 exports["test Several Show Hides"] = function(assert, done) {
   const { Panel } = require('sdk/panel');
 
   let hideCalled = 0;
   let panel = Panel({
     contentURL: "about:buildconfig",
@@ -1274,16 +1285,57 @@ exports["test panel addon global object"
 
   yield wait(panel.port, "document-to-addon");
 
   assert.pass("Received an event from the document");
 
   loader.unload();
 }
 
+exports["test panel load doesn't show"] = function*(assert) {
+  let loader = Loader(module);
+
+  let showCount = 0;
+  let panel = loader.require("sdk/panel").Panel({
+    contentScript: "addEventListener('load', function(event) { self.postMessage('load'); });",
+    contentScriptWhen: "start",
+    contentURL: "data:text/html;charset=utf-8,",
+  });
+
+  let shown = defer();
+  let messaged = defer();
+
+  panel.once("show", function() {
+    shown.resolve();
+  });
+
+  panel.once("message", function() {
+    messaged.resolve();
+  });
+
+  panel.show();
+  yield all([shown.promise, messaged.promise]);
+  assert.ok(true, "Saw panel display");
+
+  panel.on("show", function() {
+    assert.fail("Should not have seen another show event")
+  });
+
+  messaged = defer();
+  panel.once("message", function() {
+    assert.ok(true, "Saw panel reload");
+    messaged.resolve();
+  });
+
+  panel.contentURL = "data:text/html;charset=utf-8,<html/>";
+
+  yield messaged.promise;
+  loader.unload();
+}
+
 if (isWindowPBSupported) {
   exports.testGetWindow = function(assert, done) {
     let activeWindow = getMostRecentBrowserWindow();
     open(null, { features: {
       toolbar: true,
       chrome: true,
       private: true
     } }).then(window => {