Discussion:
Problems activating an object
Barry MacKichan
2014-05-23 18:06:08 UTC
Permalink
I have a XulRunner-based app. We forked the XulRunner code in 2008.

If I embed an object of a certain type in a document, I can control it using JavaScript. But if I save the document and reload it, I get the following situation.

There is a property to tell if the data for the object is loaded. This is obj.readyState. It returns 2 if everything has been loaded. When my code checks for it, it returns void. If I set a JS breakpoint there and then execute that line, it still returns void. If I evaluate "obj.readyState" in Venkman, I get 2. From that point on, I always get 2.

I traced the C++ code in each case. In the case where I evaluated "obj.readyState" in the debugger, I could see the value coming back from the plugin, in NPObjWrapper_GetProperty. When I traced it as my program executed that line, it seemed like the context was messed up.

My question: Is this caused by an incorrect context, like the "NPMethod called on non-NPObject wrapped JSObject" problem for methods? If so, how do I fix it. In the method case, I passed 'obj' explicitly as a parameter, which I can't do in the case of a property.

--Barry
Barry MacKichan
2014-09-14 20:28:12 UTC
Permalink
I never got any response to this, and my search for solutions on the web was fruitless, so I thought I'd come back and say what the solution was. Maybe this can help someone else in the future.

The crucial clue (after many dead ends) was that I noticed that sometimes in the debugger (Venkman) obj.toString() would return ""[object XPCNativeWrapper [object HTMLObjectElement ..]]" and at other times it would return "[[HTMLObjectElement] [class: HTMLObjectElement...]]". In the latter case, everything worked correctly, and in the former it always failed, so it was time to research what XPCNativeWrapper really does.

It is there partly for security, to keep an evil web server from modifying methods on objects in the content document that would be executed in the chrome (main program) code. So a wrapped HTML object element supports only those methods that are in the IDL file for HTMLObjectElement, and it goes to the code in the C++ implementation, skipping over anything defined in JavaScript. (see http://https://developer.mozilla.org/en-US/docs/Xray_vision for more details). It also skips over any properties and methods defined in the plugin.

This is why some methods, such as obj.id, obj.tagName, etc. worked while all the properties and methods built into the plugin object failed when obj was wrapped.

There is a way around this, I discovered yesterday. Given a wrapped object, the .wrappedJSObject property is supposed to return the underlying object, unwrapped. Unfortunately, when you evaluate obj.wrappedJSObject in Venkman, you get void (another curve ball). If you ignore that and execute

if (obj.wrappedJSObject) obj=obj.wrappedJSObject;

in the program, the condition evaluates to true, despite what the debugger said. The above line of code doesn't return an HTMLObjectElement, but a [XPCSafeJSObjectWrapper], but it works. So to fix the code, all that was necessary was the above line in a few key places.

In retrospect, the only times that the plugin methods worked was just after the HTML object element was created and was still being held in memory. They failed every time the object was constructed using the object node in the document (which is always when you have loaded a document containing the plugin data). The debugger evidently finds the wrapped object when it evaluates something, which is why everything always worked in the debugger.

--Barry

Loading...