Closed
Bug 256911
Opened 21 years ago
Closed 20 years ago
SetWebBrowserChrome holds invalide nsCOMPtr refs
Categories
(Core :: DOM: Navigation, defect)
Core
DOM: Navigation
Tracking
()
RESOLVED
FIXED
People
(Reporter: jhpedemonte, Assigned: adamlock)
Details
Attachments
(3 files, 3 obsolete files)
3.88 KB,
patch
|
Details | Diff | Splinter Review | |
3.21 KB,
text/plain
|
Details | |
24.43 KB,
patch
|
darin.moz
:
review+
shaver
:
superreview+
|
Details | Diff | Splinter Review |
This code in nsDocShellTreeOwner::SetWebBrowserChrome() is wrong:
833 nsCOMPtr<nsIEmbeddingSiteWindow>
ownerWin(do_QueryInterface(aWebBrowserChrome));
834 nsCOMPtr<nsIInterfaceRequestor>
requestor(do_QueryInterface(aWebBrowserChrome));
835
836 // it's ok for ownerWin or requestor to be null.
837 mWebBrowserChrome = aWebBrowserChrome;
838 mOwnerWin = ownerWin;
839 mOwnerRequestor = requestor;
It assigns the nsCOMPtrs ownerWin and requestor to simple pointers. So when it
goes out of scope, the nsCOMPtrs are destroyed, and mOwnerWin and
mOwnerRequestor hold no longer valid references.
Comment 1•21 years ago
|
||
Javier and I discussed this case, and we think that it might just be best to
support this broken pattern since it is so commonplace :-(
Moreover, it would be tricky to fix the code SetWebBrowserChrome code since it
is depending on holding weak references to avoid reference cycles.
We came up with a way of arranging the stub objects so that this usage can work.
Comment 2•21 years ago
|
||
Here's the patch I applied to ipcDConnectService.cpp, which is based on
Javier's patch for nsJavaXPTCStub.cpp.
that's extremely bogus, if the object is implemented with tearoffs, then it's dead.
Comment 4•21 years ago
|
||
From #developers:
<timeless> [this bug] makes me very unhappy
<timeless> quote from my comment
<timeless> that's extremely bogus, if the object is implemented with tearoffs,
then it's dead.
<darin> timeless: it makes me unhappy too
<darin> timeless: but what can i do? this pattern is used in a lot of places.
<timeless> track them down and shoot them
<timeless> :)
<darin> timeless: do you have time to fix them?
<darin> i don't
<timeless> i think i can find volunteers
<timeless> can you setup logging which would detect the problems and report stacks/
* timeless eyes ctho
<darin> timeless: if you want to do all of that then feel free
<timeless> i can get the volunteers, i'm not sure about the detection... clearly
you guys have some way of recognizing it
<timeless> is it just a matter of making objects auto wrapped by something?
<timeless> e.g. could we hack a build so that nsCOMPtr stores a dcom object instead?
<darin> timeless: we don't have a way of detecting the problem... instead, we
just make the lifetime of the tearoffs correspond to the lifetime of the
'master' object
<timeless> darin: would my suggestion work?
<darin> timeless: yeah, you could probably create a wrapper that has its
lifetime bound to that of the master, but when accessed talks to the tearoff
object. the wrapper's AddRef/Release would AddRef/Release the tearoff as well
as the master. the wrapper could then detect that it is being used with a dead
tearoff.
<timeless> could you write this up into the bug?
Comment 5•21 years ago
|
||
so, it is not possible to completely work around nsDocShellTreeItem. we need to
fix it to take at least one owning reference to the aWebBrowserChrome parameter.
Reporter | ||
Comment 6•21 years ago
|
||
The problem I'm having with my Java embedding work is as follows: the
nsIWebBrowserChrome and nsIEmbeddingSiteWindow interfaces are implemented as a
Java object, which then gets passed to nsWebBrowser::SetContainerWindow(). In
order to handle this, I create a temporary XPCOM stub object to pass in.
SetContainerWindow() calls SetWebBrowserChrome(), where the fun happens. When
the program exits the scope of that function, the XPCOM stub object has a ref
count of 1, and mWebBrowserChrome, mOwnerWin, and mOwnerRequestor all point to
it. But when returning back into Java, the temporary XPCOM stub object gets
released, and now those 3 supposed 'weak refs' point to nothing.
I was able to fix this by making them actual nsIWeakReferences. This works for
my code since my implementation of weak references hold a weak ref to the
actual Java object, not a weak ref to the XPCOM stub.
This change makes it necessary for implementors of nsIWebBrowserChrome to also
implement nsISupportsWeakReference, hence the change to
gtk/src/EmbedWindow.cpp.
This patch fixes the specific issue I had, but it looks like there are other
member variables that could be changed to nsIWeakReferences.
Comment 7•21 years ago
|
||
ooooh... so, this means that embedders have to implement
nsISupportsWeakReference or suddenly all bets are off, right? that means an
incompatible change in our frozen embedding API, right? :-(
is it possible instead to make our Java objects keep an owning reference to the
XPTC stubs somehow?
Reporter | ||
Comment 8•21 years ago
|
||
I discussed this with Darin and we weren't able to come up with a good solution
for fixing this on my end. So instead, I present this patch, based on a
suggestion by Darin. Here, we save an actual weak reference if the passed in
object implements nsISupportsWeakReference. If not, it does what it does now.
So this uses weak refs for my case and fixes that, but doesn't change how
current embeddors work.
Reporter | ||
Updated•21 years ago
|
Attachment #162091 -
Attachment is obsolete: true
Comment 9•21 years ago
|
||
should not the IID change, though someone feel free to correct me if I am wrong
on this.
Comment 10•21 years ago
|
||
The IID does not need to change, IMO: the interface is both binary and
semantically compatible with what we have today (assuming that Javier tested the
current case =) ), so revving the IID would cause needless incompatibility.
I like this approach, as I discussed with Darin on IRC. Well done.
Comment 11•21 years ago
|
||
Reporter | ||
Comment 12•21 years ago
|
||
New patch addressing Darin's comments. Also, I created some helper functions
to get the appropriate member variable, depending on whether we're using
weakrefs or not. Also, fixed several places where the code was checking the
status of the non-weakref member variables; this would fail in the weakref case
since they are always null.
Attachment #162224 -
Attachment is obsolete: true
Reporter | ||
Updated•21 years ago
|
Attachment #162626 -
Flags: review?(darin)
Comment 13•21 years ago
|
||
Comment on attachment 162626 [details] [diff] [review]
embedding patch v3
>Index: browser/webBrowser/nsWebBrowser.cpp
> NS_IMETHODIMP nsWebBrowser::GetContainerWindow(nsIWebBrowserChrome** aTopWindow)
> {
> NS_ENSURE_ARG_POINTER(aTopWindow);
>
>+ if(mDocShellTreeOwner) {
>+ if (mDocShellTreeOwner->mWebBrowserChromeSupportsWeak) {
>+ return mDocShellTreeOwner->mWebBrowserChromeWeak->
>+ QueryReferent(NS_GET_IID(nsIWebBrowserChrome),
>+ NS_REINTERPRET_CAST(void**, aTopWindow));
>+ }
> *aTopWindow = mDocShellTreeOwner->mWebBrowserChrome;
>- else
>+ } else {
> *aTopWindow = nsnull;
>+ }
> NS_IF_ADDREF(*aTopWindow);
>
> return NS_OK;
> }
it seems like this function wants to return NS_OK even when *aTopWindow
is null. but QueryReferent might return an error when it fails to
return non-null. should you make that case return NS_OK too? my guess
is "yes"
>Index: components/windowwatcher/src/nsWindowWatcher.cpp
>+ nsCOMPtr<nsISupportsWeakReference> supportsweak(do_QueryInterface(inChrome));
>+ if (supportsweak) {
>+ mChromeSupportsWeak = PR_TRUE;
>+ supportsweak->GetWeakReference(getter_AddRefs(mChromeWeak));
>+ } else {
>+ mChromeSupportsWeak = PR_FALSE;
>+ mChrome = inChrome;
>+ }
use mChromeWeak != nsnull in place of mChromeSupportsWeak?
Attachment #162626 -
Flags: review?(darin) → review-
Reporter | ||
Comment 14•21 years ago
|
||
New patch with Darin's suggestions.
Attachment #162626 -
Attachment is obsolete: true
Reporter | ||
Updated•21 years ago
|
Attachment #162637 -
Flags: review?(darin)
Comment 15•21 years ago
|
||
Comment on attachment 162637 [details] [diff] [review]
embedding patch v3.1
i think you need to set mChromeWeak to null when you do "mChrome = inChrome;"
r=darin with that fixed
Attachment #162637 -
Flags: review?(darin) → review+
Reporter | ||
Updated•21 years ago
|
Attachment #162637 -
Flags: superreview?(shaver)
Comment 16•21 years ago
|
||
Comment on attachment 162637 [details] [diff] [review]
embedding patch v3.1
>+ nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome;
>+ GetWebBrowserChrome(getter_AddRefs(webBrowserChrome));
>+
>+ NS_ENSURE_STATE(mTreeOwner || webBrowserChrome);
Given that virtually no of the callers of GetWebBrowserChrome seem to check the
result returned, and that the only failure mode is signalled by a null
WBC, I think we should just have it return an already_AddReffed<>.
> NS_IMETHODIMP
> nsDocShellTreeOwner::SetPosition(PRInt32 aX, PRInt32 aY)
> {
>- if (mOwnerWin)
>- {
>- return mOwnerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
>- aX, aY, 0, 0);
>+ nsCOMPtr<nsIEmbeddingSiteWindow> ownerWin;
>+ if (NS_SUCCEEDED(GetOwnerWin(getter_AddRefs(ownerWin)))) {
>+ return ownerWin->SetDimensions(nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION,
>+ aX, aY, 0, 0);
> }
> return NS_ERROR_NULL_POINTER;
> }
Dominant brace style is this file seems to be
if (foo)
{
then;
}
even for single-line then bodies. I greatly prefer your style (when
consistently
applied to single-line then bodies following single-line if predicates), but I
think
we should maintain consistency here.
>+ } else {
>+ if (mWebBrowserChrome) {
>+ *aChrome = mWebBrowserChrome;
>+ NS_ADDREF(mWebBrowserChrome);
>+ return NS_OK;
>+ }
>+ }
Fold that to
}
else if (mWebBrowserChrome)
{
please. (To eliminate excess block, and brace-conform.)
>+ if (mWebBrowserChromeWeak != nsnull) {
>+ return mWebBrowserChromeWeak->
>+ QueryReferent(NS_GET_IID(nsIEmbeddingSiteWindow),
>+ NS_REINTERPRET_CAST(void**, aWindow));
>+ } else {
>+ if (mOwnerWin) {
No need for else-after-return. (Here or elsewhere.)
>+ nsresult GetWebBrowserChrome(nsIWebBrowserChrome** aWindow);
>+ nsresult GetOwnerWin(nsIEmbeddingSiteWindow** aWindow);
>+ nsresult GetOwnerRequestor(nsIInterfaceRequestor** aWindow);
Some comments here about lifecycle and weak/strong ref management would be
greatly appreciated (as in the interface def, IMO).
With those changes, sr=shaver. If you want to discuss the return type of GWBC,
I'm amenable to reasonable arguments. =)
Attachment #162637 -
Flags: superreview?(shaver) → superreview+
Reporter | ||
Comment 17•20 years ago
|
||
Committed to trunk with Shaver's suggestions.
Status: NEW → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•