Skip to content

Commit

Permalink
Bug 462076 - Dynamically inserted iframes on refresh sometimes trade …
Browse files Browse the repository at this point in the history
…places, r=bz
  • Loading branch information
Olli Pettay authored and Olli Pettay committed Aug 17, 2010
1 parent 838688f commit 75b4ffd
Show file tree
Hide file tree
Showing 36 changed files with 963 additions and 96 deletions.
9 changes: 7 additions & 2 deletions content/base/public/nsIDocument.h
Expand Up @@ -118,8 +118,8 @@ class Element;


#define NS_IDOCUMENT_IID \
{ 0xb2274bc3, 0x4a1c, 0x4e64, \
{ 0x8d, 0xe4, 0x3b, 0xc6, 0x50, 0x28, 0x84, 0x38 } }
{ 0xba594543, 0x95f6, 0x4160, \
{ 0x90, 0x32, 0x82, 0x87, 0x16, 0x5d, 0x59, 0x7a } }

// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
Expand Down Expand Up @@ -1425,6 +1425,8 @@ class nsIDocument : public nsINode
mHavePendingPaint = PR_FALSE;
}

// This returns true when the document tree is being teared down.
PRBool InUnlinkOrDeletion() { return mInUnlinkOrDeletion; }
protected:
~nsIDocument()
{
Expand Down Expand Up @@ -1561,6 +1563,9 @@ class nsIDocument : public nsINode
// True while this document is being cloned to a static document.
PRPackedBool mCreatingStaticClone;

// True iff the document is being unlinked or deleted.
PRPackedBool mInUnlinkOrDeletion;

// True if document has ever had script handling object.
PRPackedBool mHasHadScriptHandlingObject;

Expand Down
11 changes: 11 additions & 0 deletions content/base/src/nsDocument.cpp
Expand Up @@ -1489,6 +1489,7 @@ nsDocument::~nsDocument()
#endif

mInDestructor = PR_TRUE;
mInUnlinkOrDeletion = PR_TRUE;

// Clear mObservers to keep it in sync with the mutationobserver list
mObservers.Clear();
Expand Down Expand Up @@ -1768,6 +1769,8 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END


NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
tmp->mInUnlinkOrDeletion = PR_TRUE;

// Clear out our external resources
tmp->mExternalResourceMap.Shutdown();

Expand Down Expand Up @@ -1807,6 +1810,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
//
// In rare cases where you think an unlink will help here, add one
// manually.

tmp->mInUnlinkOrDeletion = PR_FALSE;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END


Expand Down Expand Up @@ -1964,6 +1969,8 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
// links one by one
DestroyElementMaps();

PRBool oldVal = mInUnlinkOrDeletion;
mInUnlinkOrDeletion = PR_TRUE;
PRUint32 count = mChildren.ChildCount();
{ // Scope for update
MOZ_AUTO_DOC_UPDATE(this, UPDATE_CONTENT_MODEL, PR_TRUE);
Expand All @@ -1980,6 +1987,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
content->UnbindFromTree();
}
}
mInUnlinkOrDeletion = oldVal;
mCachedRootElement = nsnull;

// Reset our stylesheets
Expand Down Expand Up @@ -6948,10 +6956,13 @@ nsDocument::Destroy()

RemovedFromDocShell();

PRBool oldVal = mInUnlinkOrDeletion;
mInUnlinkOrDeletion = PR_TRUE;
PRUint32 i, count = mChildren.ChildCount();
for (i = 0; i < count; ++i) {
mChildren.ChildAt(i)->DestroyContent();
}
mInUnlinkOrDeletion = oldVal;

mLayoutHistoryState = nsnull;

Expand Down
24 changes: 21 additions & 3 deletions content/base/src/nsFrameLoader.cpp
Expand Up @@ -90,6 +90,7 @@
#include "nsEventDispatcher.h"
#include "nsISHistory.h"
#include "nsISHistoryInternal.h"
#include "nsIDocShellHistory.h"
#include "nsIDOMNSHTMLDocument.h"
#include "nsIXULWindow.h"

Expand Down Expand Up @@ -190,7 +191,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
NS_INTERFACE_MAP_END

nsFrameLoader*
nsFrameLoader::Create(nsIContent* aOwner)
nsFrameLoader::Create(nsIContent* aOwner, PRBool aNetworkCreated)
{
NS_ENSURE_TRUE(aOwner, nsnull);
nsIDocument* doc = aOwner->GetOwnerDoc();
Expand All @@ -199,7 +200,7 @@ nsFrameLoader::Create(nsIContent* aOwner)
doc->IsStaticDocument()),
nsnull);

return new nsFrameLoader(aOwner);
return new nsFrameLoader(aOwner, aNetworkCreated);
}

NS_IMETHODIMP
Expand Down Expand Up @@ -1196,17 +1197,27 @@ nsFrameLoader::Destroy()
}

nsCOMPtr<nsIDocument> doc;
PRBool dynamicSubframeRemoval = PR_FALSE;
if (mOwnerContent) {
doc = mOwnerContent->GetOwnerDoc();

if (doc) {
dynamicSubframeRemoval = !mIsTopLevelContent && !doc->InUnlinkOrDeletion();
doc->SetSubDocumentFor(mOwnerContent, nsnull);
}

mOwnerContent = nsnull;
}
DestroyChild();


// Seems like this is a dynamic frame removal.
if (dynamicSubframeRemoval) {
nsCOMPtr<nsIDocShellHistory> dhistory = do_QueryInterface(mDocShell);
if (dhistory) {
dhistory->RemoveFromSessionHistory();
}
}

// Let the tree owner know we're gone.
if (mIsTopLevelContent) {
nsCOMPtr<nsIDocShellTreeItem> ourItem = do_QueryInterface(mDocShell);
Expand Down Expand Up @@ -1329,6 +1340,13 @@ nsFrameLoader::MaybeCreateDocShell()
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);

if (!mNetworkCreated) {
nsCOMPtr<nsIDocShellHistory> history = do_QueryInterface(mDocShell);
if (history) {
history->SetCreatedDynamically(PR_TRUE);
}
}

// Get the frame name and tell the docshell about it.
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
Expand Down
11 changes: 8 additions & 3 deletions content/base/src/nsFrameLoader.h
Expand Up @@ -84,15 +84,16 @@ class nsFrameLoader : public nsIFrameLoader
#endif

protected:
nsFrameLoader(nsIContent *aOwner) :
nsFrameLoader(nsIContent *aOwner, PRBool aNetworkCreated) :
mOwnerContent(aOwner),
mDepthTooGreat(PR_FALSE),
mIsTopLevelContent(PR_FALSE),
mDestroyCalled(PR_FALSE),
mNeedsAsyncDestroy(PR_FALSE),
mInSwap(PR_FALSE),
mInShow(PR_FALSE),
mHideCalled(PR_FALSE)
mHideCalled(PR_FALSE),
mNetworkCreated(aNetworkCreated)
#ifdef MOZ_IPC
, mDelayRemoteDialogs(PR_FALSE)
, mRemoteWidgetCreated(PR_FALSE)
Expand All @@ -113,7 +114,7 @@ class nsFrameLoader : public nsIFrameLoader
nsFrameLoader::Destroy();
}

static nsFrameLoader* Create(nsIContent* aOwner);
static nsFrameLoader* Create(nsIContent* aOwner, PRBool aNetworkCreated);

NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsFrameLoader)
Expand Down Expand Up @@ -221,6 +222,10 @@ class nsFrameLoader : public nsIFrameLoader
PRPackedBool mInSwap : 1;
PRPackedBool mInShow : 1;
PRPackedBool mHideCalled : 1;
// True when the object is created for an element which the parser has
// created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
// it may lose the flag.
PRPackedBool mNetworkCreated : 1;

#ifdef MOZ_IPC
PRPackedBool mDelayRemoteDialogs : 1;
Expand Down
7 changes: 4 additions & 3 deletions content/base/src/nsObjectLoadingContent.cpp
Expand Up @@ -478,6 +478,7 @@ nsObjectLoadingContent::nsObjectLoadingContent()
, mInstantiating(PR_FALSE)
, mUserDisabled(PR_FALSE)
, mSuppressed(PR_FALSE)
, mNetworkCreated(PR_TRUE)
, mFallbackReason(ePluginOtherState)
{
}
Expand Down Expand Up @@ -632,7 +633,7 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
break;
case eType_Document: {
if (!mFrameLoader) {
mFrameLoader = nsFrameLoader::Create(thisContent);
mFrameLoader = nsFrameLoader::Create(thisContent, mNetworkCreated);
if (!mFrameLoader) {
Fallback(PR_FALSE);
return NS_ERROR_UNEXPECTED;
Expand Down Expand Up @@ -1286,7 +1287,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
// Must have a frameloader before creating a frame, or the frame will
// create its own.
if (!mFrameLoader && newType == eType_Document) {
mFrameLoader = nsFrameLoader::Create(thisContent);
mFrameLoader = nsFrameLoader::Create(thisContent, mNetworkCreated);
if (!mFrameLoader) {
mURI = nsnull;
return NS_OK;
Expand Down Expand Up @@ -1989,7 +1990,7 @@ nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const
if (mFrameLoader) {
nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIImageLoadingContent*>((aDest)));
nsFrameLoader* fl = nsFrameLoader::Create(content);
nsFrameLoader* fl = nsFrameLoader::Create(content, PR_FALSE);
if (fl) {
aDest->mFrameLoader = fl;
mFrameLoader->CreateStaticClone(fl);
Expand Down
10 changes: 10 additions & 0 deletions content/base/src/nsObjectLoadingContent.h
Expand Up @@ -134,6 +134,10 @@ class nsObjectLoadingContent : public nsImageLoadingContent
*/
PRInt32 ObjectState() const;

void SetIsNetworkCreated(PRBool aNetworkCreated)
{
mNetworkCreated = aNetworkCreated;
}
protected:
/**
* Load the object from the given URI.
Expand Down Expand Up @@ -399,6 +403,12 @@ class nsObjectLoadingContent : public nsImageLoadingContent
// Blocking status from content policy
PRPackedBool mUserDisabled : 1;
PRPackedBool mSuppressed : 1;

// True when the object is created for an element which the parser has
// created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
// it may lose the flag.
PRPackedBool mNetworkCreated : 1;

// A specific state that caused us to fallback
PluginSupportState mFallbackReason;

Expand Down
9 changes: 6 additions & 3 deletions content/html/content/src/nsGenericHTMLElement.cpp
Expand Up @@ -2873,7 +2873,7 @@ nsGenericHTMLFrameElement::EnsureFrameLoader()
return NS_OK;
}

mFrameLoader = nsFrameLoader::Create(this);
mFrameLoader = nsFrameLoader::Create(this, mNetworkCreated);
return NS_OK;
}

Expand Down Expand Up @@ -2936,7 +2936,10 @@ nsGenericHTMLFrameElement::BindToTree(nsIDocument* aDocument,
// We're in a document now. Kick off the frame load.
LoadSrc();
}


// We're now in document and scripts may move us, so clear
// the mNetworkCreated flag.
mNetworkCreated = PR_FALSE;
return rv;
}

Expand Down Expand Up @@ -2997,7 +3000,7 @@ nsGenericHTMLFrameElement::CopyInnerTo(nsGenericElement* aDest) const
if (doc->IsStaticDocument() && mFrameLoader) {
nsGenericHTMLFrameElement* dest =
static_cast<nsGenericHTMLFrameElement*>(aDest);
nsFrameLoader* fl = nsFrameLoader::Create(dest);
nsFrameLoader* fl = nsFrameLoader::Create(dest, PR_FALSE);
NS_ENSURE_STATE(fl);
dest->mFrameLoader = fl;
static_cast<nsFrameLoader*>(mFrameLoader.get())->CreateStaticClone(fl);
Expand Down
9 changes: 8 additions & 1 deletion content/html/content/src/nsGenericHTMLElement.h
Expand Up @@ -45,6 +45,7 @@
#include "nsIDOMNSHTMLFrameElement.h"
#include "nsFrameLoader.h"
#include "nsGkAtoms.h"
#include "nsContentCreatorFunctions.h"

class nsIDOMAttr;
class nsIDOMEventListener;
Expand Down Expand Up @@ -909,9 +910,11 @@ class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
public nsIFrameLoaderOwner
{
public:
nsGenericHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo)
nsGenericHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
PRUint32 aFromParser)
: nsGenericHTMLElement(aNodeInfo)
{
mNetworkCreated = aFromParser == NS_FROM_PARSER_NETWORK;
}
virtual ~nsGenericHTMLFrameElement();

Expand Down Expand Up @@ -958,6 +961,10 @@ class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
nsresult GetContentDocument(nsIDOMDocument** aContentDocument);

nsRefPtr<nsFrameLoader> mFrameLoader;
// True when the element is created by the parser
// using NS_FROM_PARSER_NETWORK flag.
// If the element is modified, it may lose the flag.
PRPackedBool mNetworkCreated;
};

//----------------------------------------------------------------------
Expand Down
10 changes: 6 additions & 4 deletions content/html/content/src/nsHTMLFrameElement.cpp
Expand Up @@ -46,7 +46,8 @@ class nsHTMLFrameElement : public nsGenericHTMLFrameElement,
public nsIDOMHTMLFrameElement
{
public:
nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo);
nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
PRUint32 aFromParser = NS_NOT_FROM_PARSER);
virtual ~nsHTMLFrameElement();

// nsISupports
Expand Down Expand Up @@ -76,11 +77,12 @@ class nsHTMLFrameElement : public nsGenericHTMLFrameElement,
};


NS_IMPL_NS_NEW_HTML_ELEMENT(Frame)
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Frame)


nsHTMLFrameElement::nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLFrameElement(aNodeInfo)
nsHTMLFrameElement::nsHTMLFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
PRUint32 aFromParser)
: nsGenericHTMLFrameElement(aNodeInfo, aFromParser)
{
}

Expand Down
10 changes: 6 additions & 4 deletions content/html/content/src/nsHTMLIFrameElement.cpp
Expand Up @@ -55,7 +55,8 @@ class nsHTMLIFrameElement : public nsGenericHTMLFrameElement,
#endif
{
public:
nsHTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo);
nsHTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
PRUint32 aFromParser = NS_NOT_FROM_PARSER);
virtual ~nsHTMLIFrameElement();

// nsISupports
Expand Down Expand Up @@ -91,11 +92,12 @@ class nsHTMLIFrameElement : public nsGenericHTMLFrameElement,
};


NS_IMPL_NS_NEW_HTML_ELEMENT(IFrame)
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame)


nsHTMLIFrameElement::nsHTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLFrameElement(aNodeInfo)
nsHTMLIFrameElement::nsHTMLIFrameElement(already_AddRefed<nsINodeInfo> aNodeInfo,
PRUint32 aFromParser)
: nsGenericHTMLFrameElement(aNodeInfo, aFromParser)
{
}

Expand Down
2 changes: 2 additions & 0 deletions content/html/content/src/nsHTMLObjectElement.cpp
Expand Up @@ -151,6 +151,7 @@ nsHTMLObjectElement::nsHTMLObjectElement(already_AddRefed<nsINodeInfo> aNodeInfo
mIsDoneAddingChildren(!aFromParser)
{
RegisterFreezableElement();
SetIsNetworkCreated(aFromParser == NS_FROM_PARSER_NETWORK);
}

nsHTMLObjectElement::~nsHTMLObjectElement()
Expand Down Expand Up @@ -464,6 +465,7 @@ nsHTMLObjectElement::StartObjectLoad(PRBool aNotify)
// get interpreted as the page itself, instead of absence of URI.
LoadObject(nsnull, aNotify, ctype);
}
SetIsNetworkCreated(PR_FALSE);
}

PRInt32
Expand Down
6 changes: 5 additions & 1 deletion content/xul/content/src/nsXULElement.cpp
Expand Up @@ -1978,7 +1978,11 @@ nsXULElement::LoadSrc()
nsXULSlots* slots = static_cast<nsXULSlots*>(GetSlots());
NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
if (!slots->mFrameLoader) {
slots->mFrameLoader = nsFrameLoader::Create(this);
// PR_FALSE as the last parameter so that xul:iframe/browser/editor
// session history handling works like dynamic html:iframes.
// Usually xul elements are used in chrome, which doesn't have
// session history at all.
slots->mFrameLoader = nsFrameLoader::Create(this, PR_FALSE);
NS_ENSURE_TRUE(slots->mFrameLoader, NS_OK);
}

Expand Down

0 comments on commit 75b4ffd

Please sign in to comment.