зеркало из https://github.com/mozilla/pjs.git
Bug 751999: Split SetDocShell apart to make this code easier to read. r=jst
This commit is contained in:
Родитель
b41b0e9390
Коммит
ec7b0d3b86
|
@ -4676,7 +4676,7 @@ nsDocShell::Destroy()
|
|||
|
||||
if (mScriptGlobal) {
|
||||
nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mScriptGlobal));
|
||||
win->SetDocShell(nsnull);
|
||||
win->DetachFromDocShell();
|
||||
|
||||
mScriptGlobal = nsnull;
|
||||
}
|
||||
|
|
|
@ -2141,109 +2141,135 @@ void
|
|||
nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
|
||||
{
|
||||
NS_ASSERTION(IsOuterWindow(), "Uh, SetDocShell() called on inner window!");
|
||||
MOZ_ASSERT(aDocShell);
|
||||
|
||||
if (aDocShell == mDocShell)
|
||||
if (aDocShell == mDocShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
// SetDocShell(nsnull) means the window is being torn down. Drop our
|
||||
mDocShell = aDocShell; // Weak Reference
|
||||
|
||||
NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
|
||||
|
||||
if (mFrames) {
|
||||
mFrames->SetDocShell(aDocShell);
|
||||
}
|
||||
|
||||
// Get our enclosing chrome shell and retrieve its global window impl, so
|
||||
// that we can do some forwarding to the chrome document.
|
||||
nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
|
||||
mDocShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
|
||||
mChromeEventHandler = do_QueryInterface(chromeEventHandler);
|
||||
if (!mChromeEventHandler) {
|
||||
// We have no chrome event handler. If we have a parent,
|
||||
// get our chrome event handler from the parent. If
|
||||
// we don't have a parent, then we need to make a new
|
||||
// window root object that will function as a chrome event
|
||||
// handler and receive all events that occur anywhere inside
|
||||
// our window.
|
||||
nsCOMPtr<nsIDOMWindow> parentWindow;
|
||||
GetParent(getter_AddRefs(parentWindow));
|
||||
if (parentWindow.get() != static_cast<nsIDOMWindow*>(this)) {
|
||||
nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(parentWindow));
|
||||
mChromeEventHandler = piWindow->GetChromeEventHandler();
|
||||
}
|
||||
else {
|
||||
NS_NewWindowRoot(this, getter_AddRefs(mChromeEventHandler));
|
||||
}
|
||||
}
|
||||
|
||||
bool docShellActive;
|
||||
mDocShell->GetIsActive(&docShellActive);
|
||||
mIsBackground = !docShellActive;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::DetachFromDocShell()
|
||||
{
|
||||
NS_ASSERTION(IsOuterWindow(), "Uh, DetachFromDocShell() called on inner window!");
|
||||
|
||||
// DetachFromDocShell means the window is being torn down. Drop our
|
||||
// reference to the script context, allowing it to be deleted
|
||||
// later. Meanwhile, keep our weak reference to the script object
|
||||
// (mJSObject) so that it can be retrieved later (until it is
|
||||
// finalized by the JS GC).
|
||||
|
||||
if (!aDocShell) {
|
||||
NS_ASSERTION(PR_CLIST_IS_EMPTY(&mTimeouts),
|
||||
"Uh, outer window holds timeouts!");
|
||||
NS_ASSERTION(PR_CLIST_IS_EMPTY(&mTimeouts),
|
||||
"Uh, outer window holds timeouts!");
|
||||
|
||||
// Call FreeInnerObjects on all inner windows, not just the current
|
||||
// one, since some could be held by WindowStateHolder objects that
|
||||
// are GC-owned.
|
||||
for (nsRefPtr<nsGlobalWindow> inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
|
||||
inner != this;
|
||||
inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
|
||||
NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == this,
|
||||
"bad outer window pointer");
|
||||
inner->FreeInnerObjects();
|
||||
}
|
||||
|
||||
// Make sure that this is called before we null out the document.
|
||||
NotifyDOMWindowDestroyed(this);
|
||||
|
||||
NotifyWindowIDDestroyed("outer-window-destroyed");
|
||||
|
||||
nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
|
||||
|
||||
if (currentInner) {
|
||||
NS_ASSERTION(mDoc, "Must have doc!");
|
||||
|
||||
// Remember the document's principal.
|
||||
mDocumentPrincipal = mDoc->NodePrincipal();
|
||||
|
||||
// Release our document reference
|
||||
mDocument = nsnull;
|
||||
mDoc = nsnull;
|
||||
mFocusedNode = nsnull;
|
||||
}
|
||||
|
||||
ClearControllers();
|
||||
|
||||
mChromeEventHandler = nsnull; // force release now
|
||||
|
||||
if (mArguments) {
|
||||
// We got no new document after someone called
|
||||
// SetArguments(), drop our reference to the arguments.
|
||||
mArguments = nsnull;
|
||||
mArgumentsLast = nsnull;
|
||||
mArgumentsOrigin = nsnull;
|
||||
}
|
||||
|
||||
if (mContext) {
|
||||
mContext->GC(js::gcreason::SET_DOC_SHELL);
|
||||
mContext = nsnull;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCycleCollector_DEBUG_shouldBeFreed(mContext);
|
||||
nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
|
||||
#endif
|
||||
// Call FreeInnerObjects on all inner windows, not just the current
|
||||
// one, since some could be held by WindowStateHolder objects that
|
||||
// are GC-owned.
|
||||
for (nsRefPtr<nsGlobalWindow> inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
|
||||
inner != this;
|
||||
inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
|
||||
NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == this,
|
||||
"bad outer window pointer");
|
||||
inner->FreeInnerObjects();
|
||||
}
|
||||
|
||||
mDocShell = aDocShell; // Weak Reference
|
||||
// Make sure that this is called before we null out the document.
|
||||
NotifyDOMWindowDestroyed(this);
|
||||
|
||||
NotifyWindowIDDestroyed("outer-window-destroyed");
|
||||
|
||||
nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
|
||||
|
||||
if (currentInner) {
|
||||
JSObject* obj = currentInner->FastGetGlobalJSObject();
|
||||
if (obj) {
|
||||
JSContext* cx;
|
||||
nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
|
||||
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
js::NukeChromeCrossCompartmentWrappersForGlobal(cx, obj,
|
||||
js::NukeForGlobalObject);
|
||||
}
|
||||
|
||||
NS_ASSERTION(mDoc, "Must have doc!");
|
||||
|
||||
// Remember the document's principal.
|
||||
mDocumentPrincipal = mDoc->NodePrincipal();
|
||||
|
||||
// Release our document reference
|
||||
mDocument = nsnull;
|
||||
mDoc = nsnull;
|
||||
mFocusedNode = nsnull;
|
||||
}
|
||||
|
||||
ClearControllers();
|
||||
|
||||
mChromeEventHandler = nsnull; // force release now
|
||||
|
||||
if (mArguments) {
|
||||
// We got no new document after someone called
|
||||
// SetArguments(), drop our reference to the arguments.
|
||||
mArguments = nsnull;
|
||||
mArgumentsLast = nsnull;
|
||||
mArgumentsOrigin = nsnull;
|
||||
}
|
||||
|
||||
if (mContext) {
|
||||
mContext->GC(js::gcreason::SET_DOC_SHELL);
|
||||
mContext = nsnull;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCycleCollector_DEBUG_shouldBeFreed(mContext);
|
||||
nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
|
||||
#endif
|
||||
|
||||
mDocShell = nsnull; // Weak Reference
|
||||
|
||||
NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
|
||||
|
||||
if (mFrames)
|
||||
mFrames->SetDocShell(aDocShell);
|
||||
|
||||
if (!mDocShell) {
|
||||
MaybeForgiveSpamCount();
|
||||
CleanUp(false);
|
||||
} else {
|
||||
// Get our enclosing chrome shell and retrieve its global window impl, so
|
||||
// that we can do some forwarding to the chrome document.
|
||||
nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
|
||||
mDocShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
|
||||
mChromeEventHandler = do_QueryInterface(chromeEventHandler);
|
||||
if (!mChromeEventHandler) {
|
||||
// We have no chrome event handler. If we have a parent,
|
||||
// get our chrome event handler from the parent. If
|
||||
// we don't have a parent, then we need to make a new
|
||||
// window root object that will function as a chrome event
|
||||
// handler and receive all events that occur anywhere inside
|
||||
// our window.
|
||||
nsCOMPtr<nsIDOMWindow> parentWindow;
|
||||
GetParent(getter_AddRefs(parentWindow));
|
||||
if (parentWindow.get() != static_cast<nsIDOMWindow*>(this)) {
|
||||
nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(parentWindow));
|
||||
mChromeEventHandler = piWindow->GetChromeEventHandler();
|
||||
}
|
||||
else NS_NewWindowRoot(this, getter_AddRefs(mChromeEventHandler));
|
||||
}
|
||||
|
||||
bool docShellActive;
|
||||
mDocShell->GetIsActive(&docShellActive);
|
||||
mIsBackground = !docShellActive;
|
||||
if (mFrames) {
|
||||
mFrames->SetDocShell(nsnull);
|
||||
}
|
||||
|
||||
MaybeForgiveSpamCount();
|
||||
CleanUp(false);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -320,6 +320,7 @@ public:
|
|||
virtual NS_HIDDEN_(bool) WouldReuseInnerWindow(nsIDocument *aNewDocument);
|
||||
|
||||
virtual NS_HIDDEN_(void) SetDocShell(nsIDocShell* aDocShell);
|
||||
virtual void DetachFromDocShell();
|
||||
virtual NS_HIDDEN_(nsresult) SetNewDocument(nsIDocument *aDocument,
|
||||
nsISupports *aState,
|
||||
bool aForceReuseInnerWindow);
|
||||
|
@ -810,7 +811,7 @@ protected:
|
|||
// could own objects that are implemented in JavaScript, then those
|
||||
// objects will keep the global object (this object) alive. To prevent
|
||||
// these cycles, ownership of such members must be released in
|
||||
// |CleanUp| and |SetDocShell|.
|
||||
// |CleanUp| and |DetachFromDocShell|.
|
||||
|
||||
// This member is also used on both inner and outer windows, but
|
||||
// for slightly different purposes. On inner windows it means the
|
||||
|
|
|
@ -48,8 +48,8 @@ class nsIArray;
|
|||
class nsPIWindowRoot;
|
||||
|
||||
#define NS_PIDOMWINDOW_IID \
|
||||
{ 0xf0bafbe6, 0xe45c, 0x490e, \
|
||||
{ 0xa2, 0x1c, 0xfe, 0x14, 0x2f, 0xb6, 0x34, 0xba } }
|
||||
{ 0xfcc2db29, 0x03ba, 0x4eb3, \
|
||||
{ 0x96, 0xb8, 0xea, 0x0f, 0x6f, 0x1f, 0x61, 0x55 } }
|
||||
|
||||
class nsPIDOMWindow : public nsIDOMWindowInternal
|
||||
{
|
||||
|
@ -351,10 +351,16 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Set or unset the docshell in the window.
|
||||
* Set the docshell in the window. Must not be called with a null docshell
|
||||
* (use DetachFromDocShell for that).
|
||||
*/
|
||||
virtual void SetDocShell(nsIDocShell *aDocShell) = 0;
|
||||
|
||||
/**
|
||||
* Detach an outer window from its docshell.
|
||||
*/
|
||||
virtual void DetachFromDocShell() = 0;
|
||||
|
||||
/**
|
||||
* Set a new document in the window. Calling this method will in
|
||||
* most cases create a new inner window. If this method is called on
|
||||
|
|
Загрузка…
Ссылка в новой задаче