This commit is contained in:
Olli.Pettay%helsinki.fi 2008-02-26 14:47:52 +00:00
Родитель 17544b3970
Коммит b8363a260c
5 изменённых файлов: 97 добавлений и 10 удалений

Просмотреть файл

@ -93,11 +93,12 @@ class nsBindingManager;
class nsIDOMNodeList;
class mozAutoSubtreeModified;
struct JSObject;
class nsFrameLoader;
// IID for the nsIDocument interface
#define NS_IDOCUMENT_IID \
{ 0x626d86d2, 0x615f, 0x4a12, \
{ 0x94, 0xd8, 0xe3, 0xdb, 0x3a, 0x29, 0x83, 0x72 } }
{ 0x3c441ae9, 0xaa82, 0x4102, \
{ 0xa3, 0x16, 0x3b, 0x97, 0x2b, 0x60, 0x2b, 0x05 } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -951,6 +952,7 @@ public:
// Do nothing.
}
virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader) = 0;
protected:
~nsIDocument()
{

Просмотреть файл

@ -158,6 +158,8 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
#include "nsCCUncollectableMarker.h"
#include "nsIContentPolicy.h"
#include "nsFrameLoader.h"
#ifdef MOZ_LOGGING
// so we can get logging even in release builds
#define FORCE_PR_LOG 1
@ -2719,6 +2721,17 @@ nsDocument::EndUpdate(nsUpdateType aUpdateType)
if (mScriptLoader) {
mScriptLoader->RemoveExecuteBlocker();
}
if (mUpdateNestLevel == 0) {
PRUint32 length = mFinalizableFrameLoaders.Length();
if (length > 0) {
nsTArray<nsRefPtr<nsFrameLoader> > loaders;
mFinalizableFrameLoaders.SwapElements(loaders);
for (PRInt32 i = 0; i < length; ++i) {
loaders[i]->Finalize();
}
}
}
}
void
@ -3825,6 +3838,21 @@ nsDocument::FlushSkinBindings()
mBindingManager->FlushSkinBindings();
}
nsresult
nsDocument::FinalizeFrameLoader(nsFrameLoader* aLoader)
{
if (mInDestructor) {
return NS_ERROR_FAILURE;
}
if (mUpdateNestLevel == 0) {
nsRefPtr<nsFrameLoader> loader = aLoader;
loader->Finalize();
} else {
mFinalizableFrameLoaders.AppendElement(aLoader);
}
return NS_OK;
}
struct DirTable {
const char* mName;
PRUint8 mValue;

Просмотреть файл

@ -648,6 +648,8 @@ public:
nsIDOMNodeList** aResult);
virtual NS_HIDDEN_(void) FlushSkinBindings();
virtual NS_HIDDEN_(nsresult) FinalizeFrameLoader(nsFrameLoader* aLoader);
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDocument, nsIDocument)
/**
@ -839,6 +841,8 @@ private:
// Member to store out last-selected stylesheet set.
nsString mLastStyleSheetSet;
nsTArray<nsRefPtr<nsFrameLoader> > mFinalizableFrameLoaders;
};

Просмотреть файл

@ -73,6 +73,26 @@
#include "nsGkAtoms.h"
#include "nsINameSpaceManager.h"
#include "nsThreadUtils.h"
class nsAsyncDocShellDestroyer : public nsRunnable
{
public:
nsAsyncDocShellDestroyer(nsIDocShell* aDocShell)
: mDocShell(aDocShell)
{
}
NS_IMETHOD Run()
{
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
if (base_win) {
base_win->Destroy();
}
}
nsRefPtr<nsIDocShell> mDocShell;
};
// Bug 136580: Limit to the number of nested content frames that can have the
// same URL. This is to stop content that is recursively loading
// itself. Note that "#foo" on the end of URL doesn't affect
@ -140,6 +160,7 @@ NS_IMETHODIMP
nsFrameLoader::LoadURI(nsIURI* aURI)
{
NS_PRECONDITION(aURI, "Null URI?");
NS_ENSURE_STATE(!mDestroyCalled);
if (!aURI)
return NS_ERROR_INVALID_POINTER;
@ -227,11 +248,27 @@ nsFrameLoader::GetDocShell(nsIDocShell **aDocShell)
return NS_OK;
}
void
nsFrameLoader::Finalize()
{
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
if (base_win) {
base_win->Destroy();
}
mDocShell = nsnull;
}
NS_IMETHODIMP
nsFrameLoader::Destroy()
{
if (mDestroyCalled) {
return NS_OK;
}
mDestroyCalled = PR_TRUE;
nsCOMPtr<nsIDocument> doc;
if (mOwnerContent) {
nsCOMPtr<nsIDocument> doc = mOwnerContent->GetDocument();
doc = mOwnerContent->GetOwnerDoc();
if (doc) {
doc->SetSubDocumentFor(mOwnerContent, nsnull);
@ -259,13 +296,20 @@ nsFrameLoader::Destroy()
win_private->SetFrameElementInternal(nsnull);
}
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
if ((mInDestructor || !doc ||
NS_FAILED(doc->FinalizeFrameLoader(this))) && mDocShell) {
nsCOMPtr<nsIRunnable> event = new nsAsyncDocShellDestroyer(mDocShell);
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
NS_DispatchToCurrentThread(event);
if (base_win) {
base_win->Destroy();
}
// Let go of our docshell now that the async destroyer holds on to
// the docshell.
mDocShell = nsnull;
}
// NOTE: 'this' may very well be gone by now.
return NS_OK;
}
@ -282,6 +326,7 @@ nsFrameLoader::EnsureDocShell()
if (mDocShell) {
return NS_OK;
}
NS_ENSURE_STATE(!mDestroyCalled);
// Get our parent docshell off the document of mOwnerContent
// XXXbz this is such a total hack.... We really need to have a

Просмотреть файл

@ -57,15 +57,21 @@ public:
nsFrameLoader(nsIContent *aOwner) :
mOwnerContent(aOwner),
mDepthTooGreat(PR_FALSE),
mIsTopLevelContent(PR_FALSE)
mIsTopLevelContent(PR_FALSE),
mDestroyCalled(PR_FALSE),
mInDestructor(PR_FALSE)
{}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsFrameLoader)
NS_DECL_NSIFRAMELOADER
NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI);
void Finalize();
private:
~nsFrameLoader() { nsFrameLoader::Destroy(); }
~nsFrameLoader() {
mInDestructor = PR_TRUE;
nsFrameLoader::Destroy();
}
NS_HIDDEN_(nsresult) EnsureDocShell();
NS_HIDDEN_(void) GetURL(nsString& aURL);
@ -75,6 +81,8 @@ private:
nsIContent *mOwnerContent; // WEAK
PRPackedBool mDepthTooGreat;
PRPackedBool mIsTopLevelContent;
PRPackedBool mDestroyCalled;
PRPackedBool mInDestructor;
};
#endif