Closed Bug 851426 Opened 12 years ago Closed 12 years ago

"TypeError: hiddenWindow.document.body is null" when creating a Panel

Categories

(Add-on SDK Graveyard :: General, defect, P1)

defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: u463949, Assigned: zer0)

References

Details

Attachments

(2 files, 4 obsolete files)

User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0 Build ID: 20130307122351 Steps to reproduce: I have been getting reports about my add-on not initializing properly lately. I have not been able to reproduce this, but one user sent me a backtrace: ========================== Timestamp: 03/14/2013 08:26:23 AM Error: self-destructing-cookies: An exception occurred. TypeError: hiddenWindow.document.body is null resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/frame/hidden-frame.js 96 Traceback (most recent call last): File "resource://gre/modules/NetUtil.jsm", line 140, in aCallback(pipe.inputStream, aStatusCode, aRequest); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/net/url.js", line 49, in resolve(data); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 142, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 36, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 116, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 142, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 36, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 116, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 142, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 36, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 116, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 142, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 36, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 116, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 142, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 36, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 116, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 142, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 122, in then else result.then(resolved, rejected) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 36, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 116, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 54, in effort try { return f(options) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 116, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 142, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 36, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 116, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 54, in effort try { return f(options) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/addon/runner.js", line 91, in onLocalizationReady run(options); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/addon/runner.js", line 135, in run quit: exit File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/self-destructing-cookies/lib/main.js", line 102, in exports.main introduction: newInstall File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/self-destructing-cookies/lib/gui-desktop.js", line 66, in exports.setup contentScriptFile: self.data.url("toolbar.js"), File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/panel.js", line 365, in exports.Panel exports.Panel = function(options) Panel(options) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/deprecated/traits.js", line 114, in Trait return self.constructor.apply(self, arguments) || self._public; File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/panel.js", line 88, in Panel this._init(options); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/content/symbiont.js", line 70, in Symbiont onUnload: function onUnload() { File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/deprecated/api-utils.js", line 42, in PublicCtor privateCtor.apply(obj, arguments); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/frame/hidden-frame.js", line 96, in HiddenFrame hiddenWindow.document.body.appendChild(hostFrame); ========= The root cause seems to be a "TypeError: hiddenWindow.document.body is null" that is thrown when I create a Panel. I call the constructor in the usual way: ========= sdcpanel = Panel({ width: 300, height: 230, contentURL: self.data.url("toolbar.html"), contentScriptFile: self.data.url("toolbar.js"), }); ========= It seems that this is a regression that was introduced with Firefox 19.0.2. It happens on various operating systems (I have reports from Windows as well as Linux). Some users report this happening every time they load the add-on, while others can work around this by re-installing the add-on every time they start the browser. Actual results: I received lots of complaints. Expected results: No exceptions; the Panel is created.
Can you attach a xpi of your addon or link to the source? What SDK version is it using?
I'm using "Add-on SDK 1.13.2 (42893f920fb6c5598a0b5f524e838fd3fddb3848)". I have just attached the xpi in question to this bug.
A lot of reports have been coming from Debian users running Iceweasel (but not exclusively). I have been able to reproduce this error by running a Debian Wheezy LiveCD from here: http://live.debian.net/cdimage/release/next/amd64/iso-hybrid/debian-wheezy-live-rc1-amd64-xfce-desktop.iso in a VM and updating IceWeasel to version 19.0.2. That seems like a good way to trigger it. Let me know if you need more information or would like me to try something.
As a crude workaround, I have deferred the add-on's initialization by wrapping it inside a 500ms timeout. That seems to help. It looks like this may be timing-dependent.
Can this be reported with standard Firefox? Can it be reproduced with the stabilization or master branches of the SDK repository? Matteo, can you take a look at this?
Assignee: nobody → zer0
Flags: needinfo?(accounts)
Priority: -- → P1
The problem still exists in the stabilization branch (Add-on SDK 1.14rc1-6-gf1c2781-dirty (f1c2781691eeb152d89aaafa288248dd457b7d74-dirty). (the "-dirty" is the result of me having to work around a bug in 1.14 to make the SDK work with Iceweasel at all, see the addendum) The backtrace is slightly different, however: ===================== TypeError: hiddenWindow.document.documentElement is null resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/frame/hidden-frame.js 73 Traceback (most recent call last): File "resource://gre/modules/NetUtil.jsm", line 140, in aCallback(pipe.inputStream, aStatusCode, aRequest); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/net/url.js", line 49, in resolve(data); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 143, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 37, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 117, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 143, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 37, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 117, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 143, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 37, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 117, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 143, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 37, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 117, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 143, in resolve while (pending.length) result.then.apply(result, pending.shift()) File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 37, in then return { then: function then(resolve) { resolve(value) } } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 117, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 143, in resolve ine 117, in resolved function resolved(value) { deferred.resolve(resolve(value)) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/core/promise.js", line 55, in effort try { return f(options) } File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/addon/runner.js", line 90, in onLocalizationReady run(options); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/addon/runner.js", line 122, in run let program = main(options.loader, options.main); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/self-destructing-cookies/lib/main.js", line 40, in var GUI = require("./gui-desktop.js"); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/loader/cuddlefish.js", line 129, in options<.load result = load(loader, module); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/self-destructing-cookies/lib/gui-desktop.js", line 25, in var Panel = require("sdk/panel").Panel; File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/loader/cuddlefish.js", line 129, in options<.load result = load(loader, module); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/panel.js", line 17, in const { Symbiont } = require('./content/content'); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/loader/cuddlefish.js", line 129, in options<.load result = load(loader, module); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/content/content.js", line 13, in exports.Symbiont = require('./symbiont').Symbiont; File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/loader/cuddlefish.js", line 129, in options<.load result = load(loader, module); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/content/symbiont.js", line 14, in const hiddenFrames = require('../frame/hidden-frame'); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/loader/cuddlefish.js", line 129, in options<.load result = load(loader, module); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/frame/hidden-frame.js", line 81, in var hostFrame = makeHostFrame(); File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/frame/hidden-frame.js", line 73, in makeHostFrame namespaceURI: hiddenWindow.document.documentElement.namespaceURI, ================= It seems that this only happens to approx. 0.1% of users. I have not been able to reproduce it with a Mozilla build of Firefox. I do however have a cluster of 3 problem reports of users running Firefox 20.0 (build 20130307075451) on Windows XP that experience this behaviour. That might be another combination that triggers this bug. I don't have a Windows machine to try it out though. PS: it seems that the stabilization branch of the SDK currently does not run on Iceweasel at all ("Error: Unsupported Application: the module sdk/tabs/tab currently supports only Firefox, Fennec").
Flags: needinfo?(accounts)
I saw the same backtrace with iceweasel 19 and 20 with addon-sdk-1.14. The bug renders addon-sdk 1.14 "almost useless" on current Debian system. Unless people switch to firefox from iceweasel.
It's not just Iceweasel, it seems to be reproducible on just about every rebranded product. I've also had reports from IceDragon and PaleMoon.
It seems that when makeFrame was called, the hiddenWindow.document had not been fully loaded. Thus hiddenWindow.document.documentElement is null. The patch delayed the action until the hiddenWindow document was loaded. The patch works for me.
Ove Soerensen, when you said "it's not just Icewasel" in comment 9, are you referring to "Unsupported Application" error, or this panel bug? Now the "Unsupported Application" error is fixed in master, so you should be able to run the Add-on SDK on rebranded products: could you confirm if the panel's bug is still present in master? Could you also confirm if it happens only on Iceweasel or rebranded product in general? Unfortunately I haven't a Linux machine to use; could you also check that this URL: chrome://global/content/mozilla.xhtml set in the location address works as expected? Thanks!
Flags: needinfo?(accounts)
Ok, let me be clear: I'm not talking about the "unsupported application" error. I know that's an automatic no-go for every re-branded product with 1.14 and has been fixed in master. I'm talking about the "TypeError: hiddenWindow.document.body is null" bug when creating a Panel. Here's what I know for a fact about this: - it is very reproducible with IceWeasel 19 and SDK 1.13, it happens as soon as a panel is created - it is very reproducible with IceWeasel 19 and SDK 1.14, provided you remove the check that causes the "unsupported application" error. It happens as soon as the panel module is required - it seems to be reproducible with other rebranded products and SDK 1.13. I have a backtrace from a user running IceDragon under Windows, so it definitely can happen there. I have a report from PaleMoon that fits this description, but the user did not respond to my request for a backtrace - I have three reports from users running an earlier version of Firefox 20 under Windows in the add-on compatibility reporter that fit the bug, but no way to contact them and no backtrace. Those were for the SDK 1.13 version of my add-on. - I just tried my luck again with IceWeasel 20 and "Add-on SDK firefox-23-04-26-2013-6-g2bcad99 (2bcad997c2d1378a87bb98493bee0ae70044ccce)". I built the add-on with "--force-use-bundled-sdk". When I install the .xpi it runs fine. When I restart the browser, nothing happens and my main.js file does not even get executed. If a place a console.log statement in the very first line, before all the "require"s it will not run. There are no exceptions in the log. The add-on is listed as enabled and the preferences-page is there, but non-functional. The LogLevel is set appriopriately. I know this because the line gets logged when the add-on loads successfully.
Flags: needinfo?(accounts)
Thanks for the info. I'm still a bit confusing on the last point: this behavior happens only if you require a panel, or to any kind of add-on? To be precise, if you have an add-on with `main.js` with only a `console.error` as content, it's properly displayed on the Error Console or not at all? Also, could you please check that paste the link I gave in my previous comment result in a properly loaded page ("The Book of Mozilla") and content type is "application/xhtml+xml", in the browsers that doesn't work as expected? You said that SDK 1.13 also has this issue: it means that it works in SDK 1.12?
Flags: needinfo?(accounts)
Sorry, I forgot about that part of your question. "chrome://global/content/mozilla.xhtml" displays as it should and has the proper content-type. Furthermore, I can confirm that the following add-on: ---------------- console.error("loading panel"); var Panel = require("sdk/panel").Panel; const NUM = 10; var panels = []; console.error("panel loaded"); for (var i = 0; i < NUM; i++) { panels[i] = Panel({contentURL: "about:mozilla", width: 300, height: 230}); } console.error("created some panels"); -------------------- when packaged with "Add-on SDK firefox-23-04-26-2013-6-g2bcad99 (2bcad997c2d1378a87bb98493bee0ae70044ccce)" and "--force-use-bundled-sdk" does *not* display anything in the console when it is loaded by Iceweasel 20.0 during browser startup. It *does* perform as expected, when it is disabled and enabled again at runtime.
Flags: needinfo?(accounts)
As the backtrace showed: File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/self-destructing-cookies /lib/gui-desktop.js", line 25, in var Panel = require("sdk/panel").Panel; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "resource://jid0-9xfbwuwnvpx4wwsfbwmcm4jj69e-at-jetpack/addon-sdk/lib/sdk/loader /cuddlefish.js", line 129, in options<.load result = load(loader, module); It always crash at "require('sdk/panel').Panel". Actually my addon crashed at "require('sdk/widget')". It means that whenever a GUI widget is used at addon *startup*, it crashes. If the requiring GUI was delay 500ms with setTimeout, the addon load without problem, as Ove Soerensen described at comment 5. When the addon initialize the GUI, it attach an iframe to the appShellService.hiddenDOMWindow in sdk/frame/hidden-frame.js. Somehow on the iceweasel, the hiddenDOMWindow was not completely loaded at the time. Therefore the crash with the exception "TypeError: hiddenWindow.document.documentElement is null". It happened on iceweasel might because iceweasel is built using some different compiler flags from the official binary? My patch makes the sdk waited until hiddenWindow was loaded before creating an iframe. It at least fixed the symptom.
Bug Filler, thanks for your patch but it's outdated because it's written on top of Add-on SDK 1.14 and not the master. If you could rewrite using the last source I would love to land it! On master, you have to take a look on the module `addon/window`. Notice that you should check if the document is already loaded, or at least "interactive" (check `isInteractive` on `window/utils`), in that case you can resolve a promise immediately instead of attach an event that could not be fired – or fired for a different reason. I asked to Ove Soerensen if a simple add-on works on master – no GUI involved, just a `console.error` or `console.log` – because Add-on SDK rely on hiddenWindow for start everything. To be clear: every add-on has its own window, and this window is created using the `hiddenWindow`. If the `hiddenWindow` is not ready, so the `document` is `null`, nothing should works. Not only the `Panel`, but also the Add-on itself shouldn't start. This it seems match what Ove Soerensen said: > When I restart the browser, nothing happens and my main.js file > does not evenget executed. If a place a console.log statement in > the very first line, before all the "require"s it will not run. > There are no exceptions in the log. The add-on is listed as enabled > and the preferences-page is there, but non-functional. The LogLevel > is set appriopriately. I know this because the line gets logged when > the add-on loads successfully. So, because the hidden window's document should be "already ready" when add-on code is executed, it seems to me that the rebranded products does something different. Maybe the platform code of Iceweasel assign to the hiddenWindow a new URL at runtime, and that's why it's still 'loading' when the add-ons trying to use it, I don't know. That's could be a problem because it's not uncommon have code like that: let document = Cc["@mozilla.org/appshell/appShellService;1"]. getService(Ci.nsIAppShellService). hiddenDOMWindow.document; (This is actually from Mozilla source base) And of course it won't work, because `document` will be `null`. In Add-on SDK this is easy to fix – just waiting for the document to be ready if is not already; but this could be an indicator of a bigger problem on platform side. It could be worthy check with the Iceweasel developers too.
As an additional data point, I would like to mention that the same problem exists in IceDragon running on Windows - main.js does not get executed during browser startup when the add-on is packaged with the SDK's master branch. Disabling and re-enabling the add-on works. Unless Debian and Comodo made the same changes, there might be something else going on.
Well yeah, iceweasel won't start main.js and shows no backtrace at all with git version of addon-sdk. It's all happened between the commit ea266834f3c3243dfd0a5f680988b2f3fa7477a8 and 86c5fcd61c8c883f2d80d43256ba66d65b626591. Further test showed that when getHiddenWindow() was called, it's already ready. No problem here now. However, the defer() in sdk/addon/window.js never got resolved. The signal eventTarget.addEventListener("DOMContentLoaded",...) have never been fired. As a result, the run(option) in sdk/addon/runner.js had never been called. neither had main.js been loaded. I'd no idea on what happened to the eventTarget in iceweasel.
I was too quick on the conclusion. The hiddenWindow does have a proper hiddenWindow.document.documentElement.namespaceURI. But if I log isInteractive(hiddenWindow), a "false" is printed. I don't know what that implicates. And I really don't know how to defer on waiting isInteractive(awindow) to be true.
Bug Filler, I think it's ok. You can dump the `document.readyState` to double check: console.log(hiddenWindow.document.readyState); In case of Iceweasel, I suspect it will returns "loading" instead of "complete" (or "interactive"). I'm assuming the namespaceURI is: http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul So, my assumption is that somehow in rebranded product the hiddenWindow is not ready yet when the add-on code is running, where it's supposed to be. So in the Add-on SDK we're no waiting for it. We should check if the hiddenWindow's document is ready before makes the frame in `addon/window`, or makes the frame immediately if the hiddenWindow's document is ready: if (hiddenWindow.document && isInteractive(hiddenWindow)) { console.log("hiddenWindow is ready, do stuff"); } else { hiddenWindow.addEventListener("DOMContentLoaded", function ready(event) { this.removeEventListener(event.type, ready); console.log("NOW hiddenWindow is ready, do stuff"); }); } If a code like that will log the text in the rebranded product, we can create a promise that will do the job.
The readystate was "uninitialized" of hiddenWindow after getHiddenWindow(). The namespaceURI is "http://www.w3.org/1999/xhtml". The uninitialized explained why addEventListener to it will not get a "DOMContentLoaded" event. If I delayed just for 1ms and readystate turned to "loading". Now addEventListener to "DOMContentLoaded" will deliver an event to my callback. Seems like the current thread is hogging the CPU slice. This works: let hiddenWindow = getHiddenWindow(); let defered_hidden = defer(); if (hiddenWindow.document && isInteractive(hiddenWindow)) { console.log("hiddenWindow is ready, do stuff"); defered_hidden.resolve(hiddenWindow); } else { require("../timers").setTimeout(function() { console.log("readystate setTimeout", hiddenWindow.document.readyState); hiddenWindow.addEventListener("DOMContentLoaded", function ready(event) { console.log("readystate again", hiddenWindow.document.readyState); this.removeEventListener(event.type, ready); console.log("NOW hiddenWindow is ready, do stuff"); defered_hidden.resolve(hiddenWindow); }, false); }, 1); } How to hook it up with defer of the addon iframe window is not clear. The whole file of window.js was written at global level...
This patch just create a hiddenWindow ready promise. Then wrap the iframe creation into a function so that its promise can be chained after the hiddenWindow promise resovled.
Attachment #742691 - Attachment is obsolete: true
Update to previous patch. This is a problem. The line: export.window = window; cause my widget stop showing up on addon bar. cross out the line make the widget show up. No idea what the window do. If export.window = window was put at the function level, a exception is given: TypeError: null is not extensible resource://come2china-at-mozbugbox/addon-sdk/lib/sdk/addon/window.js 82 Traceback (most recent call last): File "resource://come2china-at-mozbugbox/addon-sdk/lib/sdk/addon/window.js", line 37, in ready resolve(); File "resource://come2china-at-mozbugbox/addon-sdk/lib/sdk/core/promise.js", line 187, in resolve result.then(observer.resolve, observer.reject); File "resource://come2china-at-mozbugbox/addon-sdk/lib/sdk/core/promise.js", line 45, in then return { then: function then(fulfill) { fulfill(value); } }; File "resource://come2china-at-mozbugbox/addon-sdk/lib/sdk/core/promise.js", line 120, in resolve deferred.resolve(onFulfill ? onFulfill(value) : value); File "resource://come2china-at-mozbugbox/addon-sdk/lib/sdk/addon/window.js", line 82, in createIFrame exports.window = window;
Attachment #743605 - Attachment is obsolete: true
We could set the `window` after the `hiddenWindow` is ready, and having it `null` in the meanwhile. Something like: Object.defineProperty(exports, "window", { get: function() window }); However I fill like with the `setTimeout` we're adding a bunch of empiric workaround. Also I was expected to have the `namespaceURI` as XUL, that's also odd. We should figure out why in rebranded product that is so much different than Firefox in this context.
I was sure I was missing something: it didn't make sense to me that only rebranded products where affected to this bug, and in fact the key point was understand why that. I totally forgot that we're still using the application's name, instead of the application's GUID, to identify the right topic to use as "startup" of the application: https://github.com/mozilla/addon-sdk/blob/master/lib/sdk/addon/runner.js#L22-L28 So, because we use the name, Firefox got "sessionstore-windows-restored", where Iceweasel and any other rebranded Firefox got "final-ui-startup" instead. That could be the discriminant about the timing issue for hiddenWindow. What we need to do, is something similar to bug 855651, where instead of using the app name directly we use the `is` method of `xul-app` module, that checks for GUID, therefore `is('Firefox')` returns `true` for Iceweasel too. Bug Filler, if you're still willing to do this fix, I would suggest to take a look to the bug 855651's patch and doing something similar in `addon/runner`. The approach are mostly the same (in the bug 855651 we had a hashmap with App Name / Version Range, where here we have a hashmap with App Name / Topic Name). If you need a hand or any further details, please feel free to ask.
Matteo, thanks. You nailed it! Here is the patch that works.
Attachment #743626 - Attachment is obsolete: true
Thanks to you! I will review your patch right now, but the credit goes to Irakli that remember to me that we're still using this topic's stuff in our code: then I realize that was exactly the same issue we had in bug 855651 where we compare just the app name. It was the bell that rings in my head all the time. :)
Comment on attachment 744611 [details] [diff] [review] test event topic using GUID instead of name string. Review of attachment 744611 [details] [diff] [review]: ----------------------------------------------------------------- Added some code convention nit; the main point is about be sure we iterate only the own properties of `NAME2TOPIC`. ::: lib/sdk/addon/runner.js @@ +28,5 @@ > }; > > // Gets the topic that fit best as application startup event, in according with > // the current application (e.g. Firefox, Fennec, Thunderbird...) > +let APP_STARTUP = 'final-ui-startup'; I would move this line after the definition of `NAME2TOPIC`, to have all the topics in the same place; and add a comment to be explicit about default value. Something like: const NAME2TOPIC = { ... }; // Set 'final-ui-startup' as default topic for unknown applications let appStartup = 'final-ui-startup'; // Gets the topic that fit best as application startup event, in according with etc. Notice also that I changed the variable's name, because it's not a constant anymore – to be consistent with our naming convention. Of course you will have to change the other occurrence of `APP_STARTUP` in the code. @@ +29,5 @@ > > // Gets the topic that fit best as application startup event, in according with > // the current application (e.g. Firefox, Fennec, Thunderbird...) > +let APP_STARTUP = 'final-ui-startup'; > +for (let name_key in NAME2TOPIC) { The variable's name should be `nameKey` in case, but I would suggest to use just `name`. Because `for…in` iterate all the properties of an object – so, also in the prototype chain – we should use `hasOwnProperty` to be safe. So you could have: for (let name in NAME2TOPIC) { if (NAME2TOPIC.hasOwnProperty(name) && xulApp.is(name)) { appStartup = NAME2TOPIC[name]; break; } } An alternative approach could be use `Object.keys` – that returns an array with the object's own enumerable properties: for (let name of Object.keys(NAME2TOPIC)) if (xulApp.is(name)) { appStartup = NAME2TOPIC[name]; break; }
Attachment #744611 - Flags: review-
thanks for the review. Here is the updated patch.
Attachment #744611 - Attachment is obsolete: true
Thanks to you! I forgot a bracket in my example but I will add it before landing the patch, to be consistent with our code guidelines. Let me know the name you want to be listed in the contributors' page: https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/credits.html And if you have a github account or a web page you want to link!
Flags: needinfo?(mozbugbox)
Using "mozbugbox" as id will be fine. I mostly use bitbucket now, at https://bitbucket.org/mozbugbox
Flags: needinfo?(mozbugbox)
Commits pushed to master at https://github.com/mozilla/addon-sdk https://github.com/mozilla/addon-sdk/commit/5588a65a1d83a8b9e82b3c01bb06ab1f25d2f81b Bug 851426 - "TypeError: hiddenWindow.document.body is null" when creating a Panel - Fixed the observer's topic for rebranded products https://github.com/mozilla/addon-sdk/commit/ee416db963b15ef8551b4ca62973c7709fa6e4b9 Merge pull request #1001 from ZER0/rebranded-topic/851426 fix Bug 851426 - "TypeError: hiddenWindow.document.body is null" when creating a Panel r=@ZER0
Status: UNCONFIRMED → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Commits pushed to integration at https://github.com/mozilla/addon-sdk https://github.com/mozilla/addon-sdk/commit/5588a65a1d83a8b9e82b3c01bb06ab1f25d2f81b Bug 851426 - "TypeError: hiddenWindow.document.body is null" when creating a Panel https://github.com/mozilla/addon-sdk/commit/ee416db963b15ef8551b4ca62973c7709fa6e4b9 Merge pull request #1001 from ZER0/rebranded-topic/851426
Depends on: 875812
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: