Skip to content

Instantly share code, notes, and snippets.

@yurydelendik
Created August 14, 2012 22:33
Show Gist options
  • Save yurydelendik/3353578 to your computer and use it in GitHub Desktop.
Save yurydelendik/3353578 to your computer and use it in GitHub Desktop.
diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1424,17 +1424,17 @@ public:
*/
bool IsStaticDocument() { return mIsStaticDocument; }
/**
* Clones the document and subdocuments and stylesheet etc.
* @param aCloneContainer The container for the clone document.
*/
virtual already_AddRefed<nsIDocument>
- CreateStaticClone(nsISupports* aCloneContainer);
+ CreateStaticClone(nsISupports* aCloneContainer, bool aPreserveLoadedAsData = false);
/**
* If this document is a static clone, this returns the original
* document.
*/
nsIDocument* GetOriginalDocument()
{
MOZ_ASSERT(!mOriginalDocument || !mOriginalDocument->GetOriginalDocument());
@@ -1815,16 +1815,20 @@ protected:
bool mAllowDNSPrefetch;
// True when this document is a static clone of a normal document
bool mIsStaticDocument;
// True while this document is being cloned to a static document.
bool mCreatingStaticClone;
+ // True while this document transfers the LoadedAsData attribute to the
+ // cloned document.
+ bool mPreserveLoadedAsData;
+
// True iff the document is being unlinked or deleted.
bool mInUnlinkOrDeletion;
// True if document has ever had script handling object.
bool mHasHadScriptHandlingObject;
// True if we're an SVG document being used as an image.
bool mIsBeingUsedAsImage;
diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -7517,17 +7517,17 @@ nsDocument::CloneDocHelper(nsDocument* c
// Set scripting object
bool hasHadScriptObject = true;
nsIScriptGlobalObject* scriptObject =
GetScriptHandlingObject(hasHadScriptObject);
NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
clone->SetScriptHandlingObject(scriptObject);
// Make the clone a data document
- clone->SetLoadedAsData(true);
+ clone->SetLoadedAsData(mPreserveLoadedAsData ? mLoadedAsData : true);
// Misc state
// State from nsIDocument
clone->mCharacterSet = mCharacterSet;
clone->mCharacterSetSource = mCharacterSetSource;
clone->mCompatMode = mCompatMode;
clone->mBidiOptions = mBidiOptions;
@@ -7983,21 +7983,22 @@ nsIDocument::FlushPendingLinkUpdates()
nsAutoScriptBlocker scriptBlocker;
mLinksToUpdate.EnumerateEntries(EnumeratePendingLinkUpdates, nullptr);
mLinksToUpdate.Clear();
mHasLinksToUpdate = false;
}
already_AddRefed<nsIDocument>
-nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
+nsIDocument::CreateStaticClone(nsISupports* aCloneContainer, bool aPreserveLoadedAsData)
{
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(this);
NS_ENSURE_TRUE(domDoc, nullptr);
mCreatingStaticClone = true;
+ mPreserveLoadedAsData = aPreserveLoadedAsData;
// Make document use different container during cloning.
nsCOMPtr<nsISupports> originalContainer = GetContainer();
SetContainer(aCloneContainer);
nsCOMPtr<nsIDOMNode> clonedNode;
nsresult rv = domDoc->CloneNode(true, 1, getter_AddRefs(clonedNode));
SetContainer(originalContainer);
diff --git a/docshell/base/nsIContentViewer.idl b/docshell/base/nsIContentViewer.idl
--- a/docshell/base/nsIContentViewer.idl
+++ b/docshell/base/nsIContentViewer.idl
@@ -22,17 +22,17 @@ class nsDOMNavigationTiming;
[ptr] native nsIWidgetPtr(nsIWidget);
[ptr] native nsIDocumentPtr(nsIDocument);
[ref] native nsIntRectRef(nsIntRect);
[ptr] native nsIPresShellPtr(nsIPresShell);
[ptr] native nsPresContextPtr(nsPresContext);
[ptr] native nsIViewPtr(nsIView);
[ptr] native nsDOMNavigationTimingPtr(nsDOMNavigationTiming);
-[scriptable, builtinclass, uuid(26b2380b-4a1a-46cd-b7d8-7600e41c1688)]
+[scriptable, builtinclass, uuid(2f437a72-386b-4a3f-86f2-b7cce6d6d75d)]
interface nsIContentViewer : nsISupports
{
[noscript] void init(in nsIWidgetPtr aParentWidget,
[const] in nsIntRectRef aBounds);
attribute nsISupports container;
@@ -133,17 +133,17 @@ interface nsIContentViewer : nsISupports
* the saved presentation state.
*/
void clearHistoryEntry();
/*
* Change the layout to view the document with page layout (like print preview), but
* dynamic and editable (like Galley layout).
*/
- void setPageMode(in boolean aPageMode, in nsIPrintSettings aPrintSettings);
+ void setPageMode(in boolean aPageMode, in nsIPrintSettings aPrintSettings, in boolean aStaticClone);
/**
* Get the history entry that this viewer will save itself into when
* destroyed. Can return null
*/
readonly attribute nsISHEntry historyEntry;
/*
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1789,20 +1789,23 @@ nsGlobalWindow::SetNewDocument(nsIDocume
}
NS_ASSERTION(!GetCurrentInnerWindow() ||
GetCurrentInnerWindow()->GetExtantDocument() == mDocument,
"Uh, mDocument doesn't match the current inner window "
"document!");
bool wouldReuseInnerWindow = WouldReuseInnerWindow(aDocument);
+ bool equal;
if (aForceReuseInnerWindow &&
!wouldReuseInnerWindow &&
mDoc &&
- mDoc->NodePrincipal() != aDocument->NodePrincipal()) {
+ (!NS_SUCCEEDED(mDoc->NodePrincipal()->Equals(aDocument->NodePrincipal(),
+ &equal)) ||
+ !equal)) {
NS_ERROR("Attempted forced inner window reuse while changing principal");
return NS_ERROR_UNEXPECTED;
}
nsCOMPtr<nsIDocument> oldDoc(do_QueryInterface(mDocument));
nsIScriptContext *scx = GetContextInternal();
NS_ENSURE_TRUE(scx, NS_ERROR_NOT_INITIALIZED);
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -4257,17 +4257,18 @@ DocumentViewerImpl::OnDonePrinting()
mDocument = nullptr;
}
mClosingWhilePrinting = false;
}
}
#endif // NS_PRINTING && NS_PRINT_PREVIEW
}
-NS_IMETHODIMP DocumentViewerImpl::SetPageMode(bool aPageMode, nsIPrintSettings* aPrintSettings)
+NS_IMETHODIMP DocumentViewerImpl::SetPageMode(bool aPageMode, nsIPrintSettings* aPrintSettings,
+ bool aStaticClone)
{
// XXX Page mode is only partially working; it's currently used for
// reftests that require a paginated context
mIsPageMode = aPageMode;
if (mPresShell) {
DestroyPresShell();
}
@@ -4275,16 +4276,26 @@ NS_IMETHODIMP DocumentViewerImpl::SetPag
if (mPresContext) {
DestroyPresContext();
}
mViewManager = nullptr;
mWindow = nullptr;
NS_ENSURE_STATE(mDocument);
+ if (aStaticClone) {
+ nsPIDOMWindow *window = mDocument->GetWindow();
+ nsIDocShell *docShell = window->GetDocShell();
+ NS_ENSURE_TRUE(docShell, NS_ERROR_UNEXPECTED);
+
+ nsCOMPtr<nsIDocument> clonedDoc = mDocument->CreateStaticClone(docShell, true);
+ mDocument->OnPageHide(false, nsnull);
+ mDocument->Destroy();
+ SetDocumentInternal(clonedDoc, true);
+ }
if (aPageMode)
{
mPresContext = CreatePresContext(mDocument,
nsPresContext::eContext_PageLayout, FindContainerView());
NS_ENSURE_TRUE(mPresContext, NS_ERROR_OUT_OF_MEMORY);
mPresContext->SetPaginatedScrolling(true);
mPresContext->SetPrintSettings(aPrintSettings);
nsresult rv = mPresContext->Init(mDeviceContext);
diff --git a/layout/tools/reftest/reftest-content.js b/layout/tools/reftest/reftest-content.js
--- a/layout/tools/reftest/reftest-content.js
+++ b/layout/tools/reftest/reftest-content.js
@@ -198,17 +198,17 @@ function setupPrintMode() {
ps.unwriteableMarginRight = 0;
ps.headerStrLeft = "";
ps.headerStrCenter = "";
ps.headerStrRight = "";
ps.footerStrLeft = "";
ps.footerStrCenter = "";
ps.footerStrRight = "";
- docShell.contentViewer.setPageMode(true, ps);
+ docShell.contentViewer.setPageMode(true, ps, true);
}
function setupDisplayport(contentRootElement) {
if (!contentRootElement) {
return;
}
function attrOrDefault(attr, def) {
@@ -312,17 +312,20 @@ function WaitForTestEnd(contentRootEleme
if (anyPendingPaintsGeneratedInDescendants &&
!windowUtils().isMozAfterPaintPending) {
LogWarning("Internal error: descendant frame generated a MozAfterPaint event, but the root document doesn't have one!");
}
}
function AfterPaintListener(event) {
LogInfo("AfterPaintListener in " + event.target.document.location.href);
- if (event.target.document != currentDoc) {
+ // Use the docShell doc instead of currentDoc because in print mode a
+ // clone of the document is made which means currentDoc no longer
+ // matches event.target.document.
+ if (event.target.document != docShell.contentViewer.DOMDocument) {
// ignore paint events for subframes or old documents in the window.
// Invalidation in subframes will cause invalidation in the toplevel document anyway.
return;
}
SendUpdateCanvasForEvent(event);
// These events are fired immediately after a paint. Don't
// confuse ourselves by firing synchronously if we triggered the
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment