Eclipse embeds Mozilla via C++ (more precisely, Java calling C++ via JNI).
Mozilla versions 1.4 through xulrunner 1.9.0 are supported by compiling
against mozilla 1.4 (to satisfy a handful of C functions like
NS_GetComponentManager, NS_NewLocalFile, etc.), and by making all runtime
C++ calls directly via the object's method table (eg.- to invoke
QueryInterface on any object the function at method table index 0 is
invoked, AddRef is at method table index 1, etc.). This allows methods that
did not exist in mozilla 1.4 to be called if it is determined at runtime
that the user's mozilla/xulrunner version is new enough to contain the
method.
To do these direct vtable invocations, the shape of objects that methods are
invoked on needs to be known, so that the method at the correct table index
gets invoked. To determine this the interface IID is used to tell us what
to expect. For example, in one spot nsIHelperAppLauncher.Cancel() is
invoked with something like:
if
(aHelperAppLauncherDialogInstance.QueryInterface(nsIHelperAppLauncher_1.8IID
) == NS_OK) {
/* mozilla 1.8.0 */
nsIHelperAppLauncherInstance.invokeMethod(index3,
arg=NS_BINDING_ABORTED); // Cancel
} else {
/* mozilla pre-1.8 */
nsIHelperAppLauncherInstance.invokeMethod(index8, noArgs); // Cancel
}
Given this approach, is there any way to not be broken every time mozilla
IIDs change? It has become a ritual to look for broken interfaces between
major mozilla releases (eg.- 1.7 to 1.8), but it looks like we'll now be
broken in xulrunner 1.9.1 as well since nsIDocShell's IID has changed in the
1.9.1 beta stream. It's not a big deal to make a fix on our end that adds
the new IID to the collection of IIDs that are tried when an nsIDocShell is
needed, but it means that eclipse versions < 3.5 (3.5 to be released in
June) will be broken if xulrunner 1.9.1 is detected on the user's system.
Sorry for the long post, but I think our case is unusual for embeddors, so
it seemed worth explaining in more detail.
Grant
Actually, I think your case is pretty similar to that of any other C++
embeddor: if you compile against a particular Gecko version but use
interfaces that change from that version to the next one, you end up
having to at least recompile to deal with the new version.
The only way I can think of offhand to deal with this is to stick to
frozen (de jure or de facto) interfaces. That's not always possible,
but it does reduce the pain...
Inthis case, might I ask what you needed to use nsIDocShell for?
Whatever it is, we should find a better way to expose it.
-Boris
nsIDocShell.LoadStream() is used to set the Browser's content from a
client-provided string. Maybe there's another way of doing this? We use
many other unfrozen interfaces, but it would be nice for this one to go away
if possible.
I'll ask a follow-up question to my last one, much shorter this time. How
would a C++ app that's embedding mozilla (mozilla version unknown in
advance, it's whatever install is detected at runtime) do a QI for the
install's "current" implementation of an interface? So, something like a
dynamic version of
"nsIWebBrowserInstance.QueryInterface(nsIDocShell.NS_IDOCSHELL_IID)" where
NS_IDOCSHELL_IID is the IID of the nsIDocShell in the running mozilla, not
the one that was compiled against?
Grant
"Boris Zbarsky" <bzba...@mit.edu> wrote in message
news:2I2dnWS86u_5hwvU...@mozilla.org...
You could use a data: URI, no? That won't work for giving a particular
hostport to the data, though; do you need that to work?
> I'll ask a follow-up question to my last one, much shorter this time. How
> would a C++ app that's embedding mozilla (mozilla version unknown in
> advance, it's whatever install is detected at runtime) do a QI for the
> install's "current" implementation of an interface?
I don't think you can do that very easily... I suppose for scriptable
interfaces you could fetch the nsID via xpti or some such, like
XPConnect does it...
-Boris
> nsIDocShell.LoadStream() is used to set the Browser's content from a
> client-provided string. Maybe there's another way of doing this? We use
> many other unfrozen interfaces, but it would be nice for this one to go away
> if possible.
>
> I'll ask a follow-up question to my last one, much shorter this time. How
> would a C++ app that's embedding mozilla (mozilla version unknown in
> advance, it's whatever install is detected at runtime) do a QI for the
> install's "current" implementation of an interface? So, something like a
> dynamic version of
> "nsIWebBrowserInstance.QueryInterface(nsIDocShell.NS_IDOCSHELL_IID)" where
> NS_IDOCSHELL_IID is the IID of the nsIDocShell in the running mozilla, not
> the one that was compiled against?
Let's look at the question slightly differently: if the C++ app were to ask
for whatever nsIDocShell is in th efuture, what could it then do with it? It
couldn't safely call any of the methods. Those method signature might have
changed, or their position in the vtable might have changed.
The only way you could be sure, forever into the future, that
nsIDocShell.LoadStream always has the same binary signature, is to use
nsIInterfaceInfo to actually check whether a method with that name exists,
and whether the signature is the same.
--BDS
Even if you determined that LoadStream existed with the same
signature, short of using XPTCall you're not going to be able to call
it, unless it happens to be in the same position in the vtable of the
interface.
You'd really need something akin to IDispatch. Bug 327689 -
nsIScriptableObject is where something like that is/was being done.
Seems to have stagnated, though.
David
--
jst
Moreso, as I understand it, even this is a false hope, because interface IDs don't just represent a vtable and method signatures, they represent the semantic behavior of the method as well. If the *way* in which a method is to be used changes, or if what it does changes (e.g. it starts throwing a new exception in specified use) the interface ID must still be changed, even tho the method signature and its index in the vtable might remain the same.
There really is no panacea here; you can only work with the interface versions you know about. That JS interactions with all this can get away with doing otherwise is due both to intermediary layers that prevent the sort of problems a C++-style mistake will cause and to "cheating" and assuming behaviors remain the same even when names and, in certain modes of interaction, interface names or IDs, change.
Jeff
It seems that the current approach of using GRE_GetGREPathWithProperties to
detect an available xulrunner to use is not ideal for us, since:
- many non-frozen mozilla interfaces are used (the non-frozen functionality
is needed)
- linux distros seem keen to always include the latest xulrunner versions,
including beta versions
-> this caused last-minute pain for eclipse's June 2008 release since
distros also switched from including xulrunner-1.9b5 to the newly-released
xulrunner-1.9 in June, which had a changed nsIDocShell IID
-> eclipse 3.4.1, which was released in September 2008, already won't
work[1] on a distro like rawhide since it has a 1.9.1-stream xulrunner with
a changed nsIDocShell IID
I'll investigate Boris' suggestion for removing the nsIDocShell dependency,
but this is only one example, there are many other non-frozen interfaces
that can break us by changing their IID.
I guess an alternative approach would be for eclipse to ship a xulrunner to
use, and given this information this will probably be considered. It just
seems unfortunate since the GRE_GetGREPathWithProperties mechanism exists,
and linux distros typically do provide a xulrunner (though given these
issues, can any app (excluding those that only use frozen interfaces)
actually make use of these distro-provided xulrunners for any length of
time?). Anyways, thanks again to everyone for your answers.
Grant
[1] "won't work" == "nsIDocShell interface won't be found" || "if an upper
version limit of < 1.9.1 had been specified for GRE_GetGREPathWithProperties
then no xulrunner would be found"
"dbradley" <dbra...@gmail.com> wrote in message
news:f96f4941-1943-47e5...@o11g2000yql.googlegroups.com...
> I guess an alternative approach would be for eclipse to ship a xulrunner to
> use, and given this information this will probably be considered. It just
> seems unfortunate since the GRE_GetGREPathWithProperties mechanism exists,
> and linux distros typically do provide a xulrunner (though given these
> issues, can any app (excluding those that only use frozen interfaces)
> actually make use of these distro-provided xulrunners for any length of
> time?). Anyways, thanks again to everyone for your answers.
Embedding apps are strongly encouraged to use a maxversion and ask for
versions of XULRunner that they have been tested with. Therefore, if you've
tested Eclipse with XULRunner 1.8 -> 1.9 (but not 1.9.1), you should specify
a minversion of 1.8 and a maxversion of 1.9.0.*.
--BDS
Either way, the hope is that an eclipse release does not have its browser
functionality break or "expire" within a few months of being shipped when
used on up-to-date linux distros, especially given the array of
eclipse-based apps that use slightly-old maintenance stream eclipse releases
for their better stability.
Grant
[1] I don't think mozilla interfaces have changed within previous major
releases, but I could be wrong, maybe they just haven't been in interfaces
used by us previously
"Benjamin Smedberg" <benj...@smedbergs.us> wrote in message
news:94ydnWfT0dtnHADU...@mozilla.org...
> [1] I don't think mozilla interfaces have changed within previous major
> releases, but I could be wrong, maybe they just haven't been in interfaces
> used by us previously
We made an explicit promise not to change interfaces for 1.8.1. We made the
exact opposite promise for 1.9.1, acknowledging that we would be changing
interfaces.
The only reason upgrading a distro would break Eclipse is if it removed the
older major versions when it installed the newer ones. If Eclipse is part of
the distro packaging, I'd hope it could indicate which version of the
mozilla runtime it depends on.
If it's not part of the distro packaging, and you're providing separate
binary builds, I highly recommend shipping your own internal copy of
XULRunner as well... treating Mozilla as a system library is pain and hurt.
--BDS
It's even more subtle than that (and unfortunately in a non-helpful
way): the semantic meaning is actually spread out across IIDs, contract
IDs, and even CIDs. Almost none of this semantic meaning distribution
is delineated at all (or even documented). What little documentation
does exist is spread out across IDL files, .h files, MDC, Bugzilla, and
even newsgroup/email archives.
Dan
Just came across this issue when I tried to run Eclipse on openSUSE 11.1
(where I obviously have xulrunner 1.9.1b3 installed).
Speaking for openSUSE Eclipse is included and could require
mozilla-xulrunner190 (if maxversion would be correct). We usually keep
older xulrunners available if any shipped package still need it (and
it's at least a bit of upstream security supported still).
(Currently there are mozilla-xulrunner181 and mozilla-xulrunner190
officially available for openSUSE 11.1).
Actually the distributor should be mainly held responsible for keeping
Eclipse running. Eclipse should set the GRE range as safe as possible
though and the distributors should be aware of the requirements so they
could modify the required version if it works or keep it and be aware
that dropping a compatible version of xulrunner also will break Eclipse.
Eclipse should make sure to be compatible with the latest available
xulrunner with new releases so that distributors don't need to ship
older xulrunner that long (as security support is not quite long for
Mozilla browsers).
Wolfgang