exception when I try to pass object inherited from nsIWebProgressListener to registerListener of nsIMsgProgress interface

RESOLVED WONTFIX

Status

()

RESOLVED WONTFIX
14 years ago
14 years ago

People

(Reporter: surkov, Assigned: dbradley)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

1.29 KB, application/vnd.mozilla.xul+xml
Details
(Reporter)

Description

14 years ago
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a5) Gecko/20041122
Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.8a5) Gecko/20041122

Components.interfaces.nsIWebProgressListener is javascript object witch defines
constants of the form STATE_xxx as properties. I create javascript object to
pass it to registerListener method of nsIMsgProgress interface. This object
realizes methods of nsIWebProgressListener interface and is inherited from
Components.interfaces.nsIWebProgressListener in order to include these
constants. When I try to pass it to registerListener() then I get exception
Error: uncaught exception: ["Could not convert JavaScript argument arg 0
[nsIMsgProgress.registerListener]"  nsresult: "0x80570009
(NS_ERROR_XPC_BAD_CONVERT_JS)" ].

I don't know exactly this problem relates to xpconnect or realization of
'@mozilla.org/messenger/progress;1' object. I seem the problem lies in wrong
Components.interfaces.nsIWebProgressListener javascript object.

Reproducible: Always
Steps to Reproduce:

function msgprogresslistener()
{
	this.__proto__=Components.interfaces.nsIWebProgressListener;
	this.nsiprogress = Components.classes["@mozilla.org/messenger/progress;1"].
			createInstance(Components.interfaces.nsIMsgProgress);

	this.onLocationChange=function(webProgress, request, location){}
	this.onProgressChange=function( webProgress, request, curSelfProgress,
maxSelfProgress, curTotalProgress, maxTotalProgress){}
	this.onSecurityChange=function( webProgress, request, state){}
	this.onStateChange=function(webProgress, request, stateFlags, status){}
	this.onStatusChange=function(webProgress, request, status, message){}

        this.nsiprogress.registerListener(this);
}

var listener=new msgprogresslistener();
(Assignee)

Comment 1

14 years ago
1. You didn't define QueryInterface.
2. Declaring the proto as components.interfaces.nsIWhatever is unecessary.

You'll want to check out
http://lxr.mozilla.org/seamonkey/source/xpcom/sample/nsSample.js for an example
of implementing an XPCOM interface in JS.
Status: UNCONFIRMED → RESOLVED
Last Resolved: 14 years ago
Resolution: --- → INVALID
(Reporter)

Comment 2

14 years ago
1. I'll define QueryInterface() the next way:

this.QueryInterface=function(iid){
	if(iid.equals(Components.interfaces.nsIWebProgressListener)||
		iid.equals(Components.interfaces.nsISupports)) return this;
         	Components.returnCode=Components.results.NS_ERROR_NO_INTERFACE;
		return null;
	}
}

2. Declaring the proto as components.interfaces.nsIWhatever is unecessary. But
it is comfortably to use defined there constants.

If I'll add QueryInterface() then problem will be actual as before.
Status: RESOLVED → UNCONFIRMED
Resolution: INVALID → ---
(Reporter)

Comment 3

14 years ago
I'll define QueryInterface() as

this.QueryInterface=function(iid){
	if(iid.equals(Components.interfaces.nsIWebProgressListener)||
		iid.equals(Components.interfaces.nsISupports)) return this;
	}
        Components.returnCode=Components.results.NS_ERROR_NO_INTERFACE;
	return null;
}
(Reporter)

Comment 4

14 years ago
Created attachment 167168 [details]
testcase
(Reporter)

Comment 5

14 years ago
Comment on attachment 167168 [details]
testcase

copy to local disc and run it
So.. the problem is in fact that the proto is set to
Components.interfaces.nsIWebProgressListener.... if I remove that line,
everything works.
Putting Components.interfaces.nsIWebProgressListener on an objects prototype
means that a QueryInterface() method is inherited (since interfaces have a QI
method), so that function needs to be overridden in order for things to work
right. If this is still a problem with a QueryInterface() method on the instance
object that shadows the one on the proto, then there's more to this...
Johnny, see the testcase.  It does have a this.QueryInterface method...
This is an automated message, with ID "auto-resolve01".

This bug has had no comments for a long time. Statistically, we have found that
bug reports that have not been confirmed by a second user after three months are
highly unlikely to be the source of a fix to the code.

While your input is very important to us, our resources are limited and so we
are asking for your help in focussing our efforts. If you can still reproduce
this problem in the latest version of the product (see below for how to obtain a
copy) or, for feature requests, if it's not present in the latest version and
you still believe we should implement it, please visit the URL of this bug
(given at the top of this mail) and add a comment to that effect, giving more
reproduction information if you have it.

If it is not a problem any longer, you need take no action. If this bug is not
changed in any way in the next two weeks, it will be automatically resolved.
Thank you for your help in this matter.

The latest beta releases can be obtained from:
Firefox:     http://www.mozilla.org/projects/firefox/
Thunderbird: http://www.mozilla.org/products/thunderbird/releases/1.5beta1.html
Seamonkey:   http://www.mozilla.org/projects/seamonkey/
(Reporter)

Comment 10

14 years ago
confirm Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.9a1) Gecko/20050909
SeaMonkey/1.1a
Confirming, but this may be invalid.  We end up calling
XPCConvert::JSObject2NativeInterface, which calls
XPCWrappedNative::GetWrappedNativeOfJSObject on the JSObject passed in.  This
method walks the prototype chain and returns the first XPCWrappedNative that it
finds in this chain.  In this case, that would be the XPCWrappedNative for the
nsJSIID (since we have an IID object as a prototype).  So we try to QI the
nsJSIID object to nsIWebProgressListener and that throws, of course... So we
return false from JSObject2NativeInterface, and that makes XPConnect to throw an
exception.

So my only question in all this is why GetWrappedNativeOfJSObject() walks the
prototype chain.  I really don't understand why it's doing that.  jst, you have
blame for this code, but that's the XPCDOM branch landing, so maybe jband knows
something about this?
Status: UNCONFIRMED → NEW
Ever confirmed: true
OS: Windows 2000 → All
Hardware: PC → All

Comment 12

14 years ago
If it were up to me I'd resolve this as WONTFIX.

I wouldn't say that XPCWrappedNative::GetWrappedNativeOfJSObject "returns the
first XPCWrappedNative that it finds in this chain". There are a bunch of cases
and various posibilities for continue'ing the proto chain walk. Also note that
in the non-funobj case it starts with 'self' before walking any prototypes.

Nevertheless, it is the normal case for tearoffs or 'normal' user inheritence to
be implemented via the prototype chain. Arguably, we could check for an explicit
QI method on the JSObject. But, I think that would add significant overhead for
the *much* more common cases. And, I'm afraid to think about the security
implications or what might break from that change.

I think the answer for the original reporter remains "don't do that".
Yeah.  That's basically what jst and I decided earlier today on irc...
Status: NEW → RESOLVED
Last Resolved: 14 years ago14 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.