IndexedDatabaseManager::InitWindowless fails with NS_ERROR_FAILURE in FF27

UNCONFIRMED
Unassigned

Status

()

Core
DOM: IndexedDB
UNCONFIRMED
4 years ago
4 years ago

People

(Reporter: Mindaugas <LA-MJ>, Unassigned)

Tracking

27 Branch
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

4 years ago
OK, so AFAIK, you must use initWindowless to be able to access IDB from chrome until FF26.

Bug 832883 says it is to be removed in the future but calling it in FF27 breaks our add-on with NS_ERROR_FAILURE even though that function is still defined.

So how do you figure we should test for this?
(Reporter)

Comment 1

4 years ago
It happens during initialization of IDB functionality (calling Services.scriptloader.loadSubScript() in bootstrap.js)

Comment 2

4 years ago
(In reply to 4mr.minj from comment #1)
> It happens during initialization of IDB functionality (calling
> Services.scriptloader.loadSubScript() in bootstrap.js)

Can you provide more details ?
(Reporter)

Comment 3

4 years ago
We add a window listener 
>Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator).addListener()
with
>onOpenWindow: function(aWindow) {
>	// Wait for the window to finish loading
>	let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
>		.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
>	domWindow.addEventListener('load', function() {
>		domWindow.removeEventListener('load', arguments.callee, false);
>		_gLoader.loadIntoWindow(domWindow);
>	}, false);
>}
_gloader is the scope of another script created with loadSubScript()

loadIntoWindow() checks for domWindow.document and #appcontent and initializes our global object Foo where
>Services.scriptloader.loadSubScript(url, domWindow, 'UTF-8');
is called for each script (our add-on is divided into modules).

The IDB specific script runs
>var idbManager = Cc["@mozilla.org/dom/indexeddb/manager;1"]
>	.getService(Components.interfaces.nsIIndexedDatabaseManager);
>if (typeof idbManager.initWindowless === 'function') {
>	Foo.IDBProxy = {};
>	idbManager.initWindowless(Foo.IDBProxy);
>}

and fails at this point with
>Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIIndexedDatabaseManager.initWindowless]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"
(Reporter)

Comment 4

4 years ago
OK, here is the fix:
(In reply to Jan Varga [:janv] from https://bugzilla.mozilla.org/show_bug.cgi?id=832883#c36)
> Hm, take a look at this JS code:
> http://mxr.mozilla.org/mozilla-central/source/addon-sdk/source/lib/sdk/
> indexed-db.js#30
> 
> and let me know if that doesn't work for you
> 
> Btw, this is going to change again, bug 921478.
> One will have to call
> |Components.utils.importGlobalProperties(["indexedDB"])| to get IndexedDB
> e.g. in chrome.

Comment 5

4 years ago
Ok, so the first thing you need to know is that initWindowless() takes only global objects.
Anyway, you shouldn't need to call it in FF 27.

If you extension needs to be backwards compatible, you can just check if |indexedDB| is already defined, something like this:
http://mxr.mozilla.org/mozilla-central/source/addon-sdk/source/lib/sdk/indexed-db.js#30
(Reporter)

Comment 6

4 years ago
OK, but this won't do. I forgot why I needed this in the first place.

indexedDB is defined in domWindow anyway...

However we also have a chrome://preferences.html page which includes the same script and fails with
> UnknownError: The operation failed for reasons unrelated to the database itself and not covered by any other error code.
at the |typeof indexedDB| check itself!

Back to the original question: How do I test for this? :/
(Reporter)

Comment 7

4 years ago
you can try it yourself by running it in web console (ctrl+shift+K) of e.g. about:addons

Comment 8

4 years ago
Hm, I don't know why |typeof indexedDB| would throw.
Will need to debug it...
(Reporter)

Comment 9

4 years ago
I got the idea to use initWindowless from https://bugzilla.mozilla.org/show_bug.cgi?id=587797#c50

And it worked fine until FF27.

Comment 10

4 years ago
Hm, I see.
If you are in a chrome window, the getter nsGlobalWindow::GetIndexedDB() actually tries to init IndexedDB, but it fails in ThirdPartyUtils or something.

A brutal way how to solve your problem could be to just wrap initWindowless() in a try/catch block.
InitWindowless returns NS_ERROR_FAILURE if the passed object is not a global object or indexedDB is already defined on the object.

Comment 11

4 years ago
A better approach would be to use something like typeof which doesn't call the getter for indexedDB.
Take a look at:
http://stackoverflow.com/questions/1894792/determining-if-a-javascript-object-has-a-given-property
(Reporter)

Comment 12

4 years ago
(In reply to Jan Varga [:janv] from comment #11)
> A better approach would be to use something like typeof which doesn't call
> the getter for indexedDB.
> Take a look at:
> http://stackoverflow.com/questions/1894792/determining-if-a-javascript-
> object-has-a-given-property
You are kidding right?

Did you forget what I've written?
> you can try it yourself by running it in web console (ctrl+shift+K) of e.g. about:addons
http://i.imagebanana.com/img/mfg9fs46/AddonsManagerMozillaFirefox_001.png
This is FF25, does not happen in FF27.

> Ok, so the first thing you need to know is that initWindowless() takes only
> global objects.
I don't know what you mean by 'global objects' but in FF25 in that context this === self === content === window and calling initWindowless() on any of them throws NS_ERROR_FAILURE
gBrowser is undefined.

A working solution:
>var hasIDB = false;
>try {
>	// works in bootstrap.js and FF27 chrome (preferences.html)
>	hasIDB = (typeof indexedDB !== 'undefined' || typeof mozIndexedDB !== 'undefined');
>}
>catch (e) {
>	// FF25 preferences.html throws 'UnknownError'
>}
>finally {
>	if (!hasIDB) {
>		var idbManager = Cc['@mozilla.org/dom/indexeddb/manager;1']
>			.getService(Ci.nsIIndexedDatabaseManager);
>		if (typeof idbManager.initWindowless === 'function') {
>			// FF26 and earlier
>			Foo.IDBProxy = {};
>			idbManager.initWindowless(Foo.IDBProxy);
>		}
>		else {
>			// in the future in FF28?
>			Cu.importGlobalProperties(['indexedDB']);
>		}
>	}
>}
This is messed up.

Comment 13

4 years ago
importGlobalProperties(['indexedDB']) just landed on the trunk (FF28) and I'm going to request a permission to land on aurora too (FF 27), so the "automatic lazy IDB initialization" shouldn't appear in official releases.

Comment 14

4 years ago
Is this bug fixed/obsolete now?
Flags: needinfo?(Jan.Varga)
(Reporter)

Comment 15

4 years ago
FF27 lets us make use of importGlobalProperties so there is no need to call initWindowless.

However, prior to FF27, there is no simple way of getting indexedDB to work in chrome://myapp/preferences.html

Sure you can call FF26 obsolete unless some of our users happen to be using it :P

AFAIK FF24 is ESR now.

Comment 16

4 years ago
I'm sorry, the fix for bug 921478 wasn't backported to FF 27, and now it's too late :(
Next ESR shouldn't be affected. The problem should be visible only in FF 27.
FF 28 and later releases will provide importGlobalProperties([indexedDB]).
Flags: needinfo?(Jan.Varga)

Updated

4 years ago
Duplicate of this bug: 979567
You need to log in before you can comment on or make changes to this bug.