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
@@ -1143,16 +1143,23 @@ public:
    * @param aFireEvents If PR_TRUE, delayed events (focus/blur) will be fired
    *                    asynchronously.
    */
   virtual void UnsuppressEventHandlingAndFireEvents(PRBool aFireEvents) = 0;
 
   PRUint32 EventHandlingSuppressed() const { return mEventsSuppressed; }
 
   PRBool IsDNSPrefetchAllowed() const { return mAllowDNSPrefetch; }
+
+  PRBool IsPrintDocument() { return mIsPrintDocument; }
+
+  virtual already_AddRefed<nsIDocument>
+  CloneForPrint(nsISupports* aCloneContainer);
+
+  nsIDocument* GetOriginalDocument() { return mOriginalDocument; }
 protected:
   ~nsIDocument()
   {
     // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
     //     releasing it) happens in the nsDocument destructor. We'd prefer to
     //     do it here but nsNodeInfoManager is a concrete class that we don't
     //     want to expose to users of the nsIDocument API outside of Gecko.
   }
@@ -1228,17 +1235,23 @@ protected:
   PRPackedBool mHaveFiredTitleChange;
 
   // True iff IsShowing() should be returning true
   PRPackedBool mIsShowing;
 
   // True iff DNS prefetch is allowed for this document.  Note that if the
   // document has no window, DNS prefetch won't be performed no matter what.
   PRPackedBool mAllowDNSPrefetch;
-  
+
+  PRPackedBool mIsPrintDocument;
+
+  PRPackedBool mCloningForPrint;
+
+  nsCOMPtr<nsIDocument> mOriginalDocument;
+
   // The bidi options for this document.  What this bitfield means is
   // defined in nsBidiUtils.h
   PRUint32 mBidiOptions;
 
   nsCString mContentLanguage;
   nsCString mContentType;
 
   // The document's security info
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
@@ -2990,16 +2990,19 @@ nsDocument::doCreateShell(nsPresContext*
   }
 
   rv = shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Note: we don't hold a ref to the shell (it holds a ref to us)
   NS_ENSURE_TRUE(mPresShells.AppendElementUnlessExists(shell),
                  NS_ERROR_OUT_OF_MEMORY);
+
+  NS_WARN_IF_FALSE(mPresShells.Length() == 1, "More than one presshell!");
+
   shell.swap(*aInstancePtrResult);
 
   return NS_OK;
 }
 
 PRBool
 nsDocument::DeleteShell(nsIPresShell* aShell)
 {
@@ -7376,26 +7379,43 @@ nsDocument::QuerySelectorAll(const nsASt
                              nsIDOMNodeList **aReturn)
 {
   return nsGenericElement::doQuerySelectorAll(this, aSelector, aReturn);
 }
 
 nsresult
 nsDocument::CloneDocHelper(nsDocument* clone) const
 {
+  clone->mIsPrintDocument = mCloningForPrint;
+
   // Init document
   nsresult rv = clone->Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Set URI/principal
   clone->nsDocument::SetDocumentURI(nsIDocument::GetDocumentURI());
   // Must set the principal first, since SetBaseURI checks it.
   clone->SetPrincipal(NodePrincipal());
   clone->mDocumentBaseURI = mDocumentBaseURI;
 
+  if (mCloningForPrint) {
+    nsCOMPtr<nsIChannel> channel = GetChannel();
+    nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
+    if (channel && loadGroup) {
+      clone->Reset(channel, loadGroup);
+    } else {
+      nsIURI* uri = static_cast<const nsIDocument*>(this)->GetDocumentURI();
+      if (uri) {
+        clone->ResetToURI(uri, loadGroup, NodePrincipal());
+      }
+    }
+    nsCOMPtr<nsISupports> container = GetContainer();
+    clone->SetContainer(container);
+  }
+
   // Set scripting object
   PRBool hasHadScriptObject = PR_TRUE;
   nsIScriptGlobalObject* scriptObject =
     GetScriptHandlingObject(hasHadScriptObject);
   NS_ENSURE_STATE(scriptObject || !hasHadScriptObject);
   clone->SetScriptHandlingObject(scriptObject);
 
   // Make the clone a data document
@@ -7576,8 +7596,72 @@ void
 nsIDocument::EnumerateFreezableElements(FreezableElementEnumerator aEnumerator,
                                         void* aData)
 {
   if (!mFreezableElements)
     return;
   EnumerateFreezablesData data = { aEnumerator, aData };
   mFreezableElements->EnumerateEntries(EnumerateFreezables, &data);
 }
+
+already_AddRefed<nsIDocument>
+nsIDocument::CloneForPrint(nsISupports* aCloneContainer)
+{
+  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(this);
+  NS_ENSURE_TRUE(domDoc, nsnull);
+  mCloningForPrint = PR_TRUE;
+
+  // Make document to use different container during cloning.
+  nsCOMPtr<nsISupports> originalContainer = GetContainer();
+  SetContainer(aCloneContainer);
+  nsCOMPtr<nsIDOMNode> clonedNode;
+  nsresult rv = domDoc->CloneNode(PR_TRUE, getter_AddRefs(clonedNode));
+  SetContainer(originalContainer);
+
+  nsCOMPtr<nsIDocument> clonedDoc;
+  if (NS_SUCCEEDED(rv)) {
+    clonedDoc = do_QueryInterface(clonedNode);
+    nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
+    if (clonedDOMDoc) {
+      clonedDoc->mOriginalDocument = this;
+      PRInt32 sheetsCount = GetNumberOfStyleSheets();
+      for (PRInt32 i = 0; i < sheetsCount; ++i) {
+        nsCOMPtr<nsICSSStyleSheet> sheet =
+          do_QueryInterface(GetStyleSheetAt(i));
+        if (sheet) {
+          PRBool applicable = PR_TRUE;
+          sheet->GetApplicable(applicable);
+          if (applicable) {
+            nsCOMPtr<nsICSSStyleSheet> clonedSheet;
+            sheet->Clone(nsnull, nsnull, clonedDoc, nsnull,
+                         getter_AddRefs(clonedSheet));
+            NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
+            if (clonedSheet) {
+              clonedDoc->AddStyleSheet(clonedSheet);
+            }
+          }
+        }
+      }
+
+      sheetsCount = GetNumberOfCatalogStyleSheets();
+      for (PRInt32 i = 0; i < sheetsCount; ++i) {
+        nsCOMPtr<nsICSSStyleSheet> sheet =
+          do_QueryInterface(GetCatalogStyleSheetAt(i));
+        if (sheet) {
+          PRBool applicable = PR_TRUE;
+          sheet->GetApplicable(applicable);
+          if (applicable) {
+            nsCOMPtr<nsICSSStyleSheet> clonedSheet;
+            sheet->Clone(nsnull, nsnull, clonedDoc, nsnull,
+                         getter_AddRefs(clonedSheet));
+            NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
+            if (clonedSheet) {
+              clonedDoc->AddCatalogStyleSheet(clonedSheet);
+            }
+          }
+        }
+      }
+    }
+  }
+  mCloningForPrint = PR_FALSE;
+  return clonedDoc.forget();
+}
+
diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -78,16 +78,18 @@
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 
 #include "nsGkAtoms.h"
 #include "nsINameSpaceManager.h"
 
 #include "nsThreadUtils.h"
+#include "nsICSSStyleSheet.h"
+#include "nsIContentViewer.h"
 
 class nsAsyncDocShellDestroyer : public nsRunnable
 {
 public:
   nsAsyncDocShellDestroyer(nsIDocShell* aDocShell)
     : mDocShell(aDocShell)
   {
   }
@@ -140,17 +142,17 @@ nsFrameLoader::LoadFrame()
 
   src.Trim(" \t\n\r");
 
   if (src.IsEmpty()) {
     src.AssignLiteral("about:blank");
   }
 
   nsIDocument* doc = mOwnerContent->GetOwnerDoc();
-  if (!doc) {
+  if (!doc || doc->IsPrintDocument()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> base_uri = mOwnerContent->GetBaseURI();
   const nsAFlatCString &doc_charset = doc->GetDocumentCharacterSet();
   const char *charset = doc_charset.IsEmpty() ? nsnull : doc_charset.get();
 
   nsCOMPtr<nsIURI> uri;
@@ -410,17 +412,21 @@ AddTreeItemToTreeOwner(nsIDocShellTreeIt
     // chrome, we'll be chrome.  If it is content, we'll be
     // content.
 
     aItem->SetItemType(aParentType);
   }
 
   // Now that we have our type set, add ourselves to the parent, as needed.
   if (aParentNode) {
-    aParentNode->AddChild(aItem);
+    nsCOMPtr<nsIDocShell> d = do_QueryInterface(aParentNode);
+    nsresult rv = aParentNode->AddChild(aItem);
+    PRInt32 childWebshellCount;
+    aParentNode->GetChildCount(&childWebshellCount);
+    NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Adding a child didn't succeed \n");
   }
 
   PRBool retval = PR_FALSE;
   if (aParentType == nsIDocShellTreeItem::typeChrome && isContent) {
     retval = PR_TRUE;
 
     PRBool is_primary = value.LowerCaseEqualsLiteral("content-primary");
 
@@ -789,28 +795,29 @@ 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
   // better setup for doing this.
-  nsIDocument* doc = mOwnerContent->GetDocument();
-  if (!doc) {
+  nsIDocument* doc = mOwnerContent->GetOwnerDoc();
+  if (!doc || !(doc->IsPrintDocument() || mOwnerContent->IsInDoc())) {
     return NS_ERROR_UNEXPECTED;
   }
 
   if (doc->GetDisplayDocument()) {
     // Don't allow subframe loads in external reference documents
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  nsCOMPtr<nsIWebNavigation> parentAsWebNav =
-    do_GetInterface(doc->GetScriptGlobalObject());
+  nsCOMPtr<nsISupports> container =
+    doc->GetContainer();
+  nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(container);
 
   // Create the docshell...
   mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
   // Get the frame name and tell the docshell about it.
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
@@ -1002,8 +1009,32 @@ nsFrameLoader::CheckForRecursiveLoad(nsI
     }
     nsCOMPtr<nsIDocShellTreeItem> temp;
     temp.swap(parentAsItem);
     temp->GetSameTypeParent(getter_AddRefs(parentAsItem));
   }
 
   return NS_OK;
 }
+
+nsresult
+nsFrameLoader::CloneForPrint(nsIFrameLoader* aOriginal)
+{
+  EnsureDocShell();
+  NS_ENSURE_STATE(mDocShell);
+
+  nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(mDocShell);
+  nsCOMPtr<nsIContentViewer> viewer;
+  mDocShell->GetContentViewer(getter_AddRefs(viewer));
+  NS_ENSURE_STATE(viewer);
+
+  nsCOMPtr<nsIDocShell> origDocShell;
+  aOriginal->GetDocShell(getter_AddRefs(origDocShell));
+  nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(origDocShell);
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+  NS_ENSURE_STATE(doc);
+  nsCOMPtr<nsIDocument> clonedDoc = doc->CloneForPrint(mDocShell);
+  nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
+
+  viewer->SetDOMDocument(clonedDOMDoc);
+  return NS_OK;
+}
diff --git a/content/base/src/nsFrameLoader.h b/content/base/src/nsFrameLoader.h
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -72,16 +72,18 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsFrameLoader)
   NS_DECL_NSIFRAMELOADER
   NS_HIDDEN_(nsresult) CheckForRecursiveLoad(nsIURI* aURI);
   nsresult ReallyStartLoading();
   void Finalize();
   nsIDocShell* GetExistingDocShell() { return mDocShell; }
 
+  nsresult CloneForPrint(nsIFrameLoader* aOriginal);
+
   // The guts of an nsIFrameLoaderOwner::SwapFrameLoader implementation.  A
   // frame loader owner needs to call this, and pass in the two references to
   // nsRefPtrs for frame loaders that need to be swapped.
   nsresult SwapWithOtherLoader(nsFrameLoader* aOther,
                                nsRefPtr<nsFrameLoader>& aFirstToSwap,
                                nsRefPtr<nsFrameLoader>& aSecondToSwap);
 private:
 
diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -195,17 +195,16 @@ GK_ATOM(circle, "circle")
 GK_ATOM(cite, "cite")
 GK_ATOM(_class, "class")
 GK_ATOM(classid, "classid")
 GK_ATOM(clear, "clear")
 GK_ATOM(click, "click")
 GK_ATOM(clickcount, "clickcount")
 GK_ATOM(movetoclick, "movetoclick")
 GK_ATOM(clip, "clip")
-GK_ATOM(clonedTextForPrint, "clonedTextForPrint")
 GK_ATOM(close, "close")
 GK_ATOM(closed, "closed")
 GK_ATOM(closemenu, "closemenu")
 GK_ATOM(coalesceduplicatearcs, "coalesceduplicatearcs")
 GK_ATOM(code, "code")
 GK_ATOM(codebase, "codebase")
 GK_ATOM(codetype, "codetype")
 GK_ATOM(col, "col")
diff --git a/content/base/src/nsImageLoadingContent.h b/content/base/src/nsImageLoadingContent.h
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -149,17 +149,17 @@ protected:
    * which cannot happen once the derived class destructor has started
    * calling the base class destructors.
    */
   void DestroyImageLoadingContent();
 
   void ClearBrokenState() { mBroken = PR_FALSE; }
 
   PRBool LoadingEnabled() { return mLoadingEnabled; }
-private:
+
   /**
    * Struct used to manage the image observers.
    */
   struct ImageObserver {
     ImageObserver(imgIDecoderObserver* aObserver) :
       mObserver(aObserver),
       mNext(nsnull)
     {
@@ -244,17 +244,16 @@ private:
   friend class Event;
 
   /* MEMBERS */
 protected:
   nsCOMPtr<imgIRequest> mCurrentRequest;
   nsCOMPtr<imgIRequest> mPendingRequest;
   nsCOMPtr<nsIURI>      mCurrentURI;
 
-private:
   /**
    * Typically we will have only one observer (our frame in the screen
    * prescontext), so we want to only make space for one and to
    * heap-allocate anything past that (saves memory and malloc churn
    * in the common case).  The storage is a linked list, we just
    * happen to actually hold the first observer instead of a pointer
    * to it.
    */
diff --git a/content/base/src/nsTextFragment.cpp b/content/base/src/nsTextFragment.cpp
--- a/content/base/src/nsTextFragment.cpp
+++ b/content/base/src/nsTextFragment.cpp
@@ -101,17 +101,16 @@ nsTextFragment::Shutdown()
     sSpaceSharedString[i] = nsnull;
     sTabSharedString[i] = nsnull;
   }
 }
 
 nsTextFragment::~nsTextFragment()
 {
   ReleaseText();
-  MOZ_COUNT_DTOR(nsTextFragment);
 }
 
 void
 nsTextFragment::ReleaseText()
 {
   if (mState.mLength && m1b && mState.mInHeap) {
     nsMemory::Free(m2b); // m1b == m2b as far as nsMemory is concerned
   }
diff --git a/content/base/src/nsTextFragment.h b/content/base/src/nsTextFragment.h
--- a/content/base/src/nsTextFragment.h
+++ b/content/base/src/nsTextFragment.h
@@ -40,17 +40,16 @@
  * node); if only codepoints below 256 are used, the text is stored as
  * a char*; otherwise the text is stored as a PRUnichar*
  */
 
 #ifndef nsTextFragment_h___
 #define nsTextFragment_h___
 
 #include "nsAString.h"
-#include "nsTraceRefcnt.h"
 class nsString;
 class nsCString;
 
 // XXX should this normalize the code to keep a \u0000 at the end?
 
 // XXX nsTextFragmentPool?
 
 // XXX these need I18N spankage
@@ -84,17 +83,16 @@ public:
   static void Shutdown();
 
   /**
    * Default constructor. Initialize the fragment to be empty.
    */
   nsTextFragment()
     : m1b(nsnull), mAllBits(0)
   {
-    MOZ_COUNT_CTOR(nsTextFragment);
     NS_ASSERTION(sizeof(FragmentBits) == 4, "Bad field packing!");
   }
 
   ~nsTextFragment();
 
   /**
    * Change the contents of this fragment to be a copy of the
    * the argument fragment.
diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -255,18 +255,19 @@ public:
    * XXX XBL2 issue.
    */
   already_AddRefed<nsILoadGroup> GetDocumentLoadGroup();
 
   /** 
    * Returns PR_TRUE if the media has played or completed a seek.
    * Used by video frame to determine whether to paint the poster.
    */
-  PRBool GetPlayedOrSeeked() { return mHasPlayedOrSeeked; }
+  PRBool GetPlayedOrSeeked() const { return mHasPlayedOrSeeked; }
 
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
 protected:
   class MediaLoadListener;
   class LoadNextSourceEvent;
   class SelectResourceEvent;
 
   /**
    * Changes mHasPlayedOrSeeked to aValue. If mHasPlayedOrSeeked changes
    * we'll force a reflow so that the video frame gets reflowed to reflect
@@ -481,9 +482,11 @@ protected:
 
   // PR_TRUE if we are allowed to suspend the decoder because we were paused,
   // autobuffer and autoplay were not set, and we loaded the first frame.
   PRPackedBool mAllowSuspendAfterFirstFrame;
 
   // PR_TRUE if we've played or completed a seek. We use this to determine
   // when the poster frame should be shown.
   PRPackedBool mHasPlayedOrSeeked;
+
+  nsRefPtr<gfxASurface> mPrintSurface;
 };
diff --git a/content/html/content/src/Makefile.in b/content/html/content/src/Makefile.in
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -151,13 +151,15 @@ FORCE_STATIC_LIB = 1
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES	+= \
 		-I$(srcdir)/../../../base/src \
 		-I$(srcdir)/../../../events/src \
 		-I$(srcdir)/../../../xbl/src \
 		-I$(srcdir)/../../../../layout/style \
 		-I$(srcdir)/../../../../layout/tables \
+		-I$(srcdir)/../../../../layout/xul/base/src \
+		-I$(srcdir)/../../../../layout/generic \
 		-I$(srcdir)/../../../../dom/base \
 		-I$(srcdir) \
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -2895,16 +2895,35 @@ nsGenericHTMLFrameElement::DestroyConten
   if (mFrameLoader) {
     mFrameLoader->Destroy();
     mFrameLoader = nsnull;
   }
 
   nsGenericHTMLElement::DestroyContent();
 }
 
+nsresult
+nsGenericHTMLFrameElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsIDocument* doc = aDest->GetOwnerDoc();
+  if (doc->IsPrintDocument() && mFrameLoader) {
+    nsGenericHTMLFrameElement* dest =
+      static_cast<nsGenericHTMLFrameElement*>(aDest);
+    nsFrameLoader* fl = new nsFrameLoader(dest);
+    NS_ENSURE_TRUE(fl, NS_ERROR_OUT_OF_MEMORY);
+    dest->mFrameLoader = fl;
+    rv = fl->CloneForPrint(mFrameLoader);
+  }
+
+  return rv;
+}
+
 //----------------------------------------------------------------------
 
 nsresult
 nsGenericHTMLElement::Blur()
 {
   if (!ShouldBlur(this))
     return NS_OK;
 
diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -913,16 +913,18 @@ public:
   {
     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
   }
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            PRBool aNotify);
   virtual void DestroyContent();
 
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
+
   // nsIDOMNSHTMLElement 
   NS_IMETHOD GetTabIndex(PRInt32 *aTabIndex);
   NS_IMETHOD SetTabIndex(PRInt32 aTabIndex);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsGenericHTMLFrameElement,
                                                      nsGenericHTMLElement)
 
 protected:
diff --git a/content/html/content/src/nsHTMLImageElement.cpp b/content/html/content/src/nsHTMLImageElement.cpp
--- a/content/html/content/src/nsHTMLImageElement.cpp
+++ b/content/html/content/src/nsHTMLImageElement.cpp
@@ -143,16 +143,18 @@ public:
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               PRBool aCompileEventHandlers);
 
   virtual PRInt32 IntrinsicState() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
+
   void MaybeLoadImage();
 protected:
   nsPoint GetXY();
   nsSize GetWidthHeight();
 };
 
 nsGenericHTMLElement*
 NS_NewHTMLImageElement(nsINodeInfo *aNodeInfo, PRBool aFromParser)
@@ -648,9 +650,26 @@ nsHTMLImageElement::GetNaturalWidth(PRIn
   if (!image) {
     return NS_OK;
   }
 
   image->GetWidth(aNaturalWidth);
   return NS_OK;
 }
 
-
+nsresult
+nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  if (aDest->GetOwnerDoc()->IsPrintDocument()) {
+    nsHTMLImageElement* dest = static_cast<nsHTMLImageElement*>(aDest);
+    dest->mCurrentRequest = mCurrentRequest;
+    dest->mForcedImageState = mForcedImageState;
+    dest->mImageBlockingStatus = mImageBlockingStatus;
+    dest->mLoadingEnabled = mLoadingEnabled;
+    dest->mStartingLoad = mStartingLoad;
+    dest->mIsImageStateForced = mIsImageStateForced;
+    dest->mLoading = mLoading;
+    dest->mBroken = mBroken;
+    dest->mUserDisabled = mUserDisabled;
+    dest->mSuppressed = mSuppressed;
+  }
+  return nsGenericHTMLElement::CopyInnerTo(aDest);
+}
diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -71,16 +71,18 @@
 #include "nsICategoryManager.h"
 #include "nsCommaSeparatedTokenizer.h"
 
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentErrors.h"
 #include "nsCrossSiteListenerProxy.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsLayoutUtils.h"
+#include "nsVideoFrame.h"
 
 #ifdef MOZ_OGG
 #include "nsOggDecoder.h"
 #endif
 #ifdef MOZ_WAVE
 #include "nsWaveDecoder.h"
 #endif
 
@@ -933,17 +935,17 @@ static PRBool IsAutoplayEnabled()
   return nsContentUtils::GetBoolPref("media.autoplay.enabled");
 }
 
 nsresult nsHTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                         nsIContent* aBindingParent,
                                         PRBool aCompileEventHandlers)
 {
   mIsBindingToTree = PR_TRUE;
-  mAutoplayEnabled = IsAutoplayEnabled();
+  mAutoplayEnabled = IsAutoplayEnabled() && !aDocument->IsPrintDocument();
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, 
                                                  aParent, 
                                                  aBindingParent, 
                                                  aCompileEventHandlers);
   if (NS_SUCCEEDED(rv) &&
       mIsDoneAddingChildren &&
       mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY)
   {
@@ -1484,17 +1486,33 @@ void nsHTMLMediaElement::NotifyAutoplayD
     DispatchAsyncSimpleEvent(NS_LITERAL_STRING("play"));
   }
 }
 
 void nsHTMLMediaElement::Paint(gfxContext* aContext,
                                gfxPattern::GraphicsFilter aFilter,
                                const gfxRect& aRect) 
 {
-  if (mDecoder)
+  if (mPrintSurface) {
+    printf("Print paint 1\n");
+    nsRefPtr<gfxPattern> pat = new gfxPattern(mPrintSurface);
+    if (!pat)
+      return;
+    // Make the source image fill the rectangle completely
+    pat->SetMatrix(gfxMatrix().Scale(mMediaSize.width/aRect.Width(), mMediaSize.height/aRect.Height()));
+
+    pat->SetFilter(aFilter);
+
+    /* Draw RGB surface onto frame */
+    aContext->NewPath();
+    aContext->PixelSnappedRectangleAndSetPattern(aRect, pat);
+    aContext->Fill();
+    
+    printf("Print paint 2\n");
+  } else if (mDecoder)
     mDecoder->Paint(aContext, aFilter, aRect);
 }
 
 nsresult nsHTMLMediaElement::DispatchSimpleEvent(const nsAString& aName)
 {
   return nsContentUtils::DispatchTrustedEvent(GetOwnerDoc(), 
                                               static_cast<nsIContent*>(this), 
                                               aName, 
@@ -1729,8 +1747,40 @@ void nsHTMLMediaElement::ChangeDelayLoad
   }
 }
 
 already_AddRefed<nsILoadGroup> nsHTMLMediaElement::GetDocumentLoadGroup()
 {
   nsIDocument* doc = GetOwnerDoc();
   return doc ? doc->GetDocumentLoadGroup() : nsnull;
 }
+
+nsresult
+nsHTMLMediaElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (aDest->GetOwnerDoc()->IsPrintDocument()) {
+    nsHTMLMediaElement* dest = static_cast<nsHTMLMediaElement*>(aDest);
+    if (mPrintSurface) {
+      dest->mPrintSurface = mPrintSurface;
+      dest->mMediaSize = mMediaSize;
+    } else {
+      nsIFrame* frame =
+        GetPrimaryFrameFor(const_cast<nsHTMLMediaElement*>(this),
+                           GetOwnerDoc());
+      nsCOMPtr<nsIDOMElement> elem;
+      if (frame && frame->GetType() == nsGkAtoms::HTMLVideoFrame &&
+          static_cast<nsVideoFrame*>(frame)->ShouldDisplayPoster()) {
+        elem = do_QueryInterface(static_cast<nsVideoFrame*>(frame)->
+                                 GetPosterImage());
+      } else {
+        elem = do_QueryInterface(const_cast<nsHTMLMediaElement*>(this));
+      }
+
+      nsLayoutUtils::SurfaceFromElementResult res =
+        nsLayoutUtils::SurfaceFromElement(elem, nsLayoutUtils::SFE_WANT_NEW_SURFACE);
+      dest->mPrintSurface = res.mSurface;
+      dest->mMediaSize = nsIntSize(res.mSize.width, res.mSize.height);
+    }
+  }
+  return rv;
+}
diff --git a/content/html/content/src/nsHTMLOptionElement.cpp b/content/html/content/src/nsHTMLOptionElement.cpp
--- a/content/html/content/src/nsHTMLOptionElement.cpp
+++ b/content/html/content/src/nsHTMLOptionElement.cpp
@@ -115,16 +115,18 @@ public:
   // nsIOptionElement
   NS_IMETHOD SetSelectedInternal(PRBool aValue, PRBool aNotify);
 
   // nsIContent
   virtual PRInt32 IntrinsicState() const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
+
 protected:
   /**
    * Get the select content element that contains this option, this
    * intentionally does not return nsresult, all we care about is if
    * there's a select associated with this option or not.
    * @param aSelectElement the select element (out param)
    */
   nsIContent* GetSelect();
@@ -527,8 +529,23 @@ nsHTMLOptionElement::Initialize(nsISuppo
           return SetSelected(selected);
         }
       }
     }
   }
 
   return result;
 }
+
+nsresult
+nsHTMLOptionElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aDest->GetOwnerDoc()->IsPrintDocument()) {
+    PRBool selected = PR_FALSE;
+    const_cast<nsHTMLOptionElement*>(this)->GetSelected(&selected);
+    static_cast<nsHTMLOptionElement*>(aDest)->SetSelected(selected);
+  }
+  return NS_OK;
+}
+
diff --git a/content/html/content/src/nsHTMLTextAreaElement.cpp b/content/html/content/src/nsHTMLTextAreaElement.cpp
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -145,16 +145,18 @@ public:
 
   virtual PRBool IsHTMLFocusable(PRBool *aIsFocusable, PRInt32 *aTabIndex);
 
   virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
   virtual PRBool IsDoneAddingChildren();
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
+
   /**
    * Called when an attribute is about to be changed
    */
   virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                                  const nsAString* aValue, PRBool aNotify);
 
   // nsIMutationObserver
   virtual void CharacterDataChanged(nsIDocument* aDocument,
@@ -970,8 +972,23 @@ nsHTMLTextAreaElement::AfterSetAttr(PRIn
       document->ContentStatesChanged(this, nsnull,
                                      NS_EVENT_STATE_MOZ_READONLY |
                                      NS_EVENT_STATE_MOZ_READWRITE);
     }
   }
   return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue,
                                                 aNotify);
 }
+
+nsresult
+nsHTMLTextAreaElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aDest->GetOwnerDoc()->IsPrintDocument()) {
+    nsAutoString value;
+    const_cast<nsHTMLTextAreaElement*>(this)->GetValue(value);
+    static_cast<nsHTMLTextAreaElement*>(aDest)->SetValue(value);
+  }
+  return NS_OK;
+}
+
diff --git a/embedding/browser/webBrowser/nsIWebBrowserPrint.idl b/embedding/browser/webBrowser/nsIWebBrowserPrint.idl
--- a/embedding/browser/webBrowser/nsIWebBrowserPrint.idl
+++ b/embedding/browser/webBrowser/nsIWebBrowserPrint.idl
@@ -139,17 +139,17 @@ interface nsIWebBrowserPrint : nsISuppor
   void print(in nsIPrintSettings aThePrintSettings,
              in nsIWebProgressListener aWPListener);
 
   /**
    * Print Preview the specified DOM window
    *
    * @param aThePrintSettings - Printer Settings for the print preview, if aThePrintSettings is null
    *                            then the global PS will be used.
-   * @param aChildDOMWin - DOM Window of the child document to be PP (FrameSet frames)
+   * @param aChildDOMWin - DOM Window to be print previewed.
    * @param aWPListener - is updated during the printpreview
    * @return void
    */
   void printPreview(in nsIPrintSettings aThePrintSettings,
                     in nsIDOMWindow aChildDOMWin,
                     in nsIWebProgressListener aWPListener);
 
   /**
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -11615,18 +11615,17 @@ nsCSSFrameConstructor::RebuildAllStyleDa
   NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
                "Should not reconstruct the root of the frame tree.  "
                "Use ReconstructDocElementHierarchy instead.");
 
   mRebuildAllStyleData = PR_FALSE;
   NS_UpdateHint(aExtraHint, mRebuildAllExtraHint);
   mRebuildAllExtraHint = nsChangeHint(0);
 
-  if (!mPresShell || !mPresShell->GetRootFrame() ||
-      !mPresShell->GetPresContext()->IsDynamic())
+  if (!mPresShell || !mPresShell->GetRootFrame())
     return;
 
   nsAutoScriptBlocker scriptBlocker;
 
   // Make sure that the viewmanager will outlive the presshell
   nsIViewManager::UpdateViewBatch batch(mPresShell->GetViewManager());
 
   // Processing the style changes could cause a flush that propagates to
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -684,16 +684,20 @@ DocumentViewerImpl::Init(nsIWidget* aPar
   NS_ENSURE_SUCCESS(rv, rv);
   
   return InitInternal(aParentWidget, nsnull, aBounds, PR_TRUE, PR_FALSE);
 }
 
 nsresult
 DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReenableRefresh)
 {
+  if (GetIsPrintPreview() ||
+      (mDocument && mDocument->IsPrintDocument()))
+    return NS_OK;
+
   NS_ASSERTION(!mPresShell,
                "Someone should have destroyed the presshell!");
 
   // Create the style set...
   nsStyleSet *styleSet;
   nsresult rv = CreateStyleSet(mDocument, &styleSet);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1625,24 +1629,26 @@ DocumentViewerImpl::SetDOMDocument(nsIDO
     // Set the script global object on the new document
     nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(container);
     if (window) {
       window->SetNewDocument(newDoc, nsnull, PR_TRUE);
     }
 
     // Clear the list of old child docshells. CChild docshells for the new
     // document will be constructed as frames are created.
-    nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(container);
-    if (node) {
-      PRInt32 count;
-      node->GetChildCount(&count);
-      for (PRInt32 i = 0; i < count; ++i) {
-        nsCOMPtr<nsIDocShellTreeItem> child;
-        node->GetChildAt(0, getter_AddRefs(child));
-        node->RemoveChild(child);
+    if (!newDoc->IsPrintDocument()) {
+      nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(container);
+      if (node) {
+        PRInt32 count;
+        node->GetChildCount(&count);
+        for (PRInt32 i = 0; i < count; ++i) {
+          nsCOMPtr<nsIDocShellTreeItem> child;
+          node->GetChildAt(0, getter_AddRefs(child));
+          node->RemoveChild(child);
+        }
       }
     }
   }
 
   rv = SyncParentSubDocMap();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Replace the current pres shell with a new shell for the new document
@@ -1690,47 +1696,29 @@ DocumentViewerImpl::GetDocument(nsIDocum
   NS_IF_ADDREF(*aResult = mDocument);
 
   return NS_OK;
 }
 
 nsIPresShell*
 DocumentViewerImpl::GetPresShell()
 {
-  if (!GetIsPrintPreview()) {
-    return mPresShell;
-  }
-  NS_ENSURE_TRUE(mDocument, nsnull);
-  nsCOMPtr<nsIPresShell> shell;
-  nsCOMPtr<nsIPresShell> currentShell;
-  nsPresShellIterator iter(mDocument);
-  while ((shell = iter.GetNextShell())) {
-    currentShell.swap(shell);
-  }
-  return currentShell.get();
+  return mPresShell;
 }
 
 nsPresContext*
 DocumentViewerImpl::GetPresContext()
 {
-  if (!GetIsPrintPreview()) {
-    return mPresContext;
-  }
-  nsIPresShell* shell = GetPresShell();
-  return shell ? shell->GetPresContext() : nsnull;
+  return mPresContext;
 }
 
 nsIViewManager*
 DocumentViewerImpl::GetViewManager()
 {
-  if (!GetIsPrintPreview()) {
-    return mViewManager;
-  }
-  nsIPresShell* shell = GetPresShell();
-  return shell ? shell->GetViewManager() : nsnull;
+  return mViewManager;
 }
 
 NS_IMETHODIMP
 DocumentViewerImpl::GetPresShell(nsIPresShell** aResult)
 {
   nsIPresShell* shell = GetPresShell();
   NS_IF_ADDREF(*aResult = shell);
   return NS_OK;
@@ -1936,27 +1924,28 @@ DocumentViewerImpl::Show(void)
       rv = InitPresentationStuff(mDocument->MayStartLayout(),
                                  mDocument->MayStartLayout());
     }
 
     // If we get here the document load has already started and the
     // window is shown because some JS on the page caused it to be
     // shown...
 
-    nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682
-    mPresShell->UnsuppressPainting();
+    if (mPresShell) {
+      nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682
+      mPresShell->UnsuppressPainting();
+    }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 DocumentViewerImpl::Hide(void)
 {
-  NS_PRECONDITION(mWindow, "null window");
   if (mWindow) {
     mWindow->Show(PR_FALSE);
   }
 
   if (!mPresShell)
     return NS_OK;
 
   NS_ASSERTION(mPresContext, "Can't have a presshell and no prescontext!");
@@ -2211,18 +2200,21 @@ DocumentViewerImpl::ClearHistoryEntry()
   return NS_OK;
 }
 
 //-------------------------------------------------------
 
 nsresult
 DocumentViewerImpl::MakeWindow(const nsSize& aSize)
 {
-  nsresult rv;
-
+  if (GetIsPrintPreview() ||
+      (mDocument && mDocument->IsPrintDocument()))
+    return NS_OK;
+
+  nsresult rv;
   mViewManager = do_CreateInstance(kViewManagerCID, &rv);
   if (NS_FAILED(rv))
     return rv;
 
   nsIDeviceContext *dx = mPresContext->DeviceContext();
 
   rv = mViewManager->Init(dx);
   if (NS_FAILED(rv))
@@ -3663,20 +3655,24 @@ DocumentViewerImpl::PrintPreview(nsIPrin
   nsCOMPtr<nsIPresShell> presShell;
   docShell->GetPresShell(getter_AddRefs(presShell));
   if (!presShell || !mDocument || !mDeviceContext || !mParentWidget) {
     PR_PL(("Can't Print Preview without pres shell, document etc"));
     return NS_ERROR_FAILURE;
   }
 
   if (!mPrintEngine) {
+    nsCOMPtr<nsIDOMDocument> domDoc;
+    aChildDOMWin->GetDocument(getter_AddRefs(domDoc));
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+
     mPrintEngine = new nsPrintEngine();
     NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY);
 
-    rv = mPrintEngine->Initialize(this, docShell, mDocument,
+    rv = mPrintEngine->Initialize(this, docShell, doc,
                                   mDeviceContext, mParentWidget,
 #ifdef NS_DEBUG
                                   mDebugFile
 #else
                                   nsnull
 #endif
                                   );
     if (NS_FAILED(rv)) {
@@ -4075,16 +4071,22 @@ DocumentViewerImpl::SetIsPrintPreview(PR
   // Set all the docShells in the docshell tree to be printing.
   // that way if anyone of them tries to "navigate" it can't
   if (mContainer) {
     nsCOMPtr<nsIDocShellTreeNode> docShellTreeNode(do_QueryReferent(mContainer));
     NS_ASSERTION(docShellTreeNode, "mContainer has to be a nsIDocShellTreeNode");
     SetIsPrintingInDocShellTree(docShellTreeNode, aIsPrintPreview, PR_TRUE);
   }
 #endif
+  if (!aIsPrintPreview) {
+    mWindow = nsnull;
+    mViewManager = nsnull;
+    mPresContext = nsnull;
+    mPresShell = nsnull;
+  }
 }
 
 //----------------------------------------------------------------------------------
 // nsIDocumentViewerPrint IFace
 //----------------------------------------------------------------------------------
 
 //------------------------------------------------------------
 void
@@ -4107,17 +4109,19 @@ DocumentViewerImpl::ReturnToGalleyPresen
   }
 
   SetIsPrintPreview(PR_FALSE);
 
   mPrintEngine->TurnScriptingOn(PR_TRUE);
   mPrintEngine->Destroy();
   mPrintEngine = nsnull;
 
-  mViewManager->EnableRefresh(NS_VMREFRESH_DEFERRED);
+  if (mViewManager) {
+    mViewManager->EnableRefresh(NS_VMREFRESH_DEFERRED);
+  }
 
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
   ResetFocusState(docShell);
 
   if (mPresContext)
     mPresContext->RestoreImageAnimationMode();
 
   SetTextZoom(mTextZoom);
@@ -4256,8 +4260,24 @@ DocumentViewerImpl::DestroyPresShell()
   nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(selection);
   if (selPrivate && mSelectionListener)
     selPrivate->RemoveSelectionListener(mSelectionListener);
 
   nsAutoScriptBlocker scriptBlocker;
   mPresShell->Destroy();
   mPresShell = nsnull;
 }
+
+void
+DocumentViewerImpl::SetPrintPreviewPresentation(nsIWidget* aWidget,
+                                                nsIViewManager* aViewManager,
+                                                nsPresContext* aPresContext,
+                                                nsIPresShell* aPresShell)
+{
+  if (mPresShell) {
+    DestroyPresShell();
+  }
+
+  mWindow = aWidget;
+  mViewManager = aViewManager;
+  mPresContext = aPresContext;
+  mPresShell = aPresShell;
+}
diff --git a/layout/base/nsIDocumentViewerPrint.h b/layout/base/nsIDocumentViewerPrint.h
--- a/layout/base/nsIDocumentViewerPrint.h
+++ b/layout/base/nsIDocumentViewerPrint.h
@@ -36,20 +36,25 @@
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsIDocumentViewerPrint_h___
 #define nsIDocumentViewerPrint_h___
 
 #include "nsISupports.h"
 
 class nsIDocument;
 class nsStyleSet;
+class nsIPresShell;
+class nsPresContext;
+class nsIWidget;
+class nsIViewManager;
 
-// {D0B7F354-D575-43fd-903D-5AA35A193EDA}
+// {b1c7bb4f-4739-4600-82cb-20e50ec86bb4}
 #define NS_IDOCUMENT_VIEWER_PRINT_IID \
- { 0xd0b7f354, 0xd575, 0x43fd, { 0x90, 0x3d, 0x5a, 0xa3, 0x5a, 0x19, 0x3e, 0xda } }
+{ 0xb1c7bb4f, 0x4739, 0x4600, \
+  { 0x82, 0xcb, 0x20, 0xe5, 0x0e, 0xc8, 0x6b, 0xb4 } }
 
 /**
  * A DocumentViewerPrint is an INTERNAL Interface used for interaction
  * between the DocumentViewer and the PrintEngine
  */
 class nsIDocumentViewerPrint : public nsISupports
 {
 public:
@@ -67,25 +72,33 @@ public:
   virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsStyleSet** aStyleSet) = 0;
 
   virtual void IncrementDestroyRefCount() = 0;
 
   virtual void ReturnToGalleyPresentation() = 0;
 
   virtual void OnDonePrinting() = 0;
 
+  virtual void SetPrintPreviewPresentation(nsIWidget* aWidget,
+                                           nsIViewManager* aViewManager,
+                                           nsPresContext* aPresContext,
+                                           nsIPresShell* aPresShell) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint,
                               NS_IDOCUMENT_VIEWER_PRINT_IID)
 
 /* Use this macro when declaring classes that implement this interface. */
 #define NS_DECL_NSIDOCUMENTVIEWERPRINT \
   virtual void     SetIsPrinting(PRBool aIsPrinting); \
   virtual PRBool   GetIsPrinting(); \
   virtual void     SetIsPrintPreview(PRBool aIsPrintPreview); \
   virtual PRBool   GetIsPrintPreview(); \
   virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsStyleSet** aStyleSet); \
   virtual void     IncrementDestroyRefCount(); \
   virtual void     ReturnToGalleyPresentation(); \
-  virtual void     OnDonePrinting();
+  virtual void     OnDonePrinting(); \
+  virtual void     SetPrintPreviewPresentation(nsIWidget* aWidget, \
+                                               nsIViewManager* aViewManager, \
+                                               nsPresContext* aPresContext, \
+                                               nsIPresShell* aPresShell);
 
 #endif /* nsIDocumentViewerPrint_h___ */
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -75,17 +75,16 @@
 #include "nsIBaseWindow.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIWidget.h"
 #include "gfxMatrix.h"
 #include "gfxTypes.h"
 #include "gfxUserFontSet.h"
 #include "nsTArray.h"
-#include "nsTextFragment.h"
 #include "nsICanvasElement.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "gfxPlatform.h"
 #ifdef MOZ_MEDIA
 #include "nsHTMLVideoElement.h"
 #endif
 #include "imgIRequest.h"
 #include "imgIContainer.h"
@@ -3244,58 +3243,16 @@ nsLayoutUtils::IsReallyFixedPos(nsIFrame
                     NS_STYLE_POSITION_FIXED,
                   "IsReallyFixedPos called on non-'position:fixed' frame");
 
   nsIAtom *parentType = aFrame->GetParent()->GetType();
   return parentType == nsGkAtoms::viewportFrame ||
          parentType == nsGkAtoms::pageContentFrame;
 }
 
-static void DeleteTextFragment(void* aObject, nsIAtom* aPropertyName,
-                               void* aPropertyValue, void* aData)
-{
-  delete static_cast<nsTextFragment*>(aPropertyValue);
-}
-
-/* static */ nsTextFragment*
-nsLayoutUtils::GetTextFragmentForPrinting(const nsIFrame* aFrame)
-{
-  nsPresContext* presContext = aFrame->PresContext();
-  NS_PRECONDITION(!presContext->IsDynamic(),
-                  "Shouldn't call this with dynamic PresContext");
-#ifdef MOZ_SVG
-  NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::textFrame ||
-                  aFrame->GetType() == nsGkAtoms::svgGlyphFrame,
-                  "Wrong frame type!");
-#else
-  NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::textFrame,
-                  "Wrong frame type!");
-#endif // MOZ_SVG
-
-  nsIContent* content = aFrame->GetContent();
-  nsTextFragment* frag =
-    static_cast<nsTextFragment*>(presContext->PropertyTable()->
-      GetProperty(content, nsGkAtoms::clonedTextForPrint));
-
-  if (!frag) {
-    frag = new nsTextFragment();
-    NS_ENSURE_TRUE(frag, nsnull);
-    *frag = *content->GetText();
-    nsresult rv = presContext->PropertyTable()->
-                    SetProperty(content, nsGkAtoms::clonedTextForPrint, frag,
-                                DeleteTextFragment, nsnull);
-    if (NS_FAILED(rv)) {
-      delete frag;
-      return nsnull;
-    }
-  }
-
-  return frag;
-}
-
 nsLayoutUtils::SurfaceFromElementResult
 nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
                                   PRUint32 aSurfaceFlags)
 {
   SurfaceFromElementResult result;
   nsresult rv;
 
   nsCOMPtr<nsINode> node = do_QueryInterface(aElement);
diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -59,17 +59,16 @@ class nsIFontMetrics;
 #include "nsIView.h"
 #include "nsIFrame.h"
 #include "nsThreadUtils.h"
 #include "nsIPresShell.h"
 #include "nsIPrincipal.h"
 #include "gfxPattern.h"
 
 class nsBlockFrame;
-class nsTextFragment;
 
 /**
  * nsLayoutUtils is a namespace class used for various helper
  * functions that are useful in multiple places in layout.  The goal
  * is not to define multiple copies of the same static helper.
  */
 class nsLayoutUtils
 {
@@ -999,22 +998,16 @@ public:
 
   /**
    * Indicates if the nsIFrame::GetUsedXXX assertions in nsFrame.cpp should
    * disabled.
    */
   static PRBool sDisableGetUsedXAssertions;
 
   /**
-   * Returns the text fragment, which aFrame should use for printing.
-   * @param aFrame The nsIFrame object, which uses text fragment data.
-   */
-  static nsTextFragment* GetTextFragmentForPrinting(const nsIFrame* aFrame);
-
-  /**
    * Return whether aFrame is an inline frame in the first part of an {ib}
    * split.
    */
   static PRBool FrameIsInFirstPartOfIBSplit(const nsIFrame* aFrame) {
     return (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
       !aFrame->GetFirstContinuation()->
         GetProperty(nsGkAtoms::IBSplitSpecialPrevSibling);
   }
diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1208,17 +1208,17 @@ nsPresContext::GetDefaultFont(PRUint8 aF
       break;
   }
   return font;
 }
 
 void
 nsPresContext::SetFullZoom(float aZoom)
 {
-  if (!mShell || mFullZoom == aZoom || !IsDynamic()) {
+  if (!mShell || mFullZoom == aZoom) {
     return;
   }
   // Re-fetch the view manager's window dimensions in case there's a deferred
   // resize which hasn't affected our mVisibleArea yet
   nscoord oldWidthAppUnits, oldHeightAppUnits;
   mShell->GetViewManager()->GetWindowDimensions(&oldWidthAppUnits, &oldHeightAppUnits);
   float oldWidthDevPixels = oldWidthAppUnits / float(mCurAppUnitsPerDevPixel);
   float oldHeightDevPixels = oldHeightAppUnits / float(mCurAppUnitsPerDevPixel);
diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1332,19 +1332,16 @@ protected:
   MOZ_TIMER_DECLARE(mFrameCreationWatch)  // Used for measuring time spent in frame creation 
 
 #ifdef MOZ_REFLOW_PERF
   ReflowCountMgr * mReflowCountMgr;
 #endif
 
   static PRBool sDisableNonTestMouseEvents;
 
-
-  nsCOMPtr<nsIDocumentObserver> mDocumentObserverForNonDynamicContext;
-
   // false if a check should be done for key/ime events that should be
   // retargeted to the currently focused presshell
   static PRBool sDontRetargetEvents;
 
 private:
 
   PRBool InZombieDocument(nsIContent *aContent);
   nsresult RetargetEventToParent(nsGUIEvent* aEvent,
@@ -1445,133 +1442,16 @@ public:
                            &aVisitor.mEventStatus);
       }
     }
   }
 
   nsRefPtr<PresShell> mPresShell;
 };
 
-class nsDocumentObserverForNonDynamicPresContext : public nsStubDocumentObserver
-{
-public:
-  nsDocumentObserverForNonDynamicPresContext(PresShell* aBaseObserver)
-  : mBaseObserver(aBaseObserver)
-  {
-    NS_ASSERTION(aBaseObserver, "Null document observer!");
-  }
-
-  NS_DECL_ISUPPORTS
-
-  virtual void BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
-  {
-    mBaseObserver->BeginUpdate(aDocument, aUpdateType);
-  }
-  virtual void EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType)
-  {
-    mBaseObserver->EndUpdate(aDocument, aUpdateType);
-  }
-  virtual void BeginLoad(nsIDocument* aDocument)
-  {
-    mBaseObserver->BeginLoad(aDocument);
-  }
-  virtual void EndLoad(nsIDocument* aDocument)
-  {
-    mBaseObserver->EndLoad(aDocument);
-  }
-  virtual void ContentStatesChanged(nsIDocument* aDocument,
-                                    nsIContent* aContent1,
-                                    nsIContent* aContent2,
-                                    PRInt32 aStateMask)
-  {
-    if ((!aContent1 || AllowMutation(aContent1)) &&
-        (!aContent2 || AllowMutation(aContent2))) {
-      mBaseObserver->ContentStatesChanged(aDocument, aContent1, aContent2,
-                                          aStateMask);
-    }
-  }
-
-  // nsIMutationObserver
-  virtual void CharacterDataChanged(nsIDocument* aDocument,
-                                    nsIContent* aContent,
-                                    CharacterDataChangeInfo* aInfo)
-  {
-    if (AllowMutation(aContent)) {
-      mBaseObserver->CharacterDataChanged(aDocument, aContent, aInfo);
-    }
-  }
-  virtual void AttributeChanged(nsIDocument* aDocument,
-                                nsIContent* aContent,
-                                PRInt32 aNameSpaceID,
-                                nsIAtom* aAttribute,
-                                PRInt32 aModType,
-                                PRUint32 aStateMask)
-  {
-    if (AllowMutation(aContent)) {
-      mBaseObserver->AttributeChanged(aDocument, aContent, aNameSpaceID,
-                                      aAttribute, aModType, aStateMask);
-    }
-  }
-  virtual void ContentAppended(nsIDocument* aDocument,
-                               nsIContent* aContainer,
-                               PRInt32 aNewIndexInContainer)
-  {
-    if (AllowMutation(aContainer)) {
-      mBaseObserver->ContentAppended(aDocument, aContainer,
-                                     aNewIndexInContainer);
-    }
-  }
-  virtual void ContentInserted(nsIDocument* aDocument,
-                               nsIContent* aContainer,
-                               nsIContent* aChild,
-                               PRInt32 aIndexInContainer)
-  {
-    if (AllowMutation(aContainer)) {
-      mBaseObserver->ContentInserted(aDocument, aContainer, aChild,
-                                     aIndexInContainer);
-    }
-  }
-  virtual void ContentRemoved(nsIDocument* aDocument,
-                              nsIContent* aContainer,
-                              nsIContent* aChild,
-                              PRInt32 aIndexInContainer)
-  {
-    if (AllowMutation(aContainer)) {
-      mBaseObserver->ContentRemoved(aDocument, aContainer, aChild, 
-                                    aIndexInContainer);
-    }
-  }
-
-  PRBool AllowMutation(nsIContent* aContent) {
-    if(aContent && aContent->IsInDoc()) {
-       if (mBaseObserver->ObservesNativeAnonMutationsForPrint() &&
-           aContent->IsInNativeAnonymousSubtree()) {
-         return PR_TRUE;
-       }
-       // Changes to scrollbar are always ok.
-       nsIContent* root = aContent->GetCurrentDoc()->GetRootContent();
-       while (aContent && aContent->IsInNativeAnonymousSubtree()) {
-         nsIContent* parent = aContent->GetParent();
-         if (parent == root && aContent->IsNodeOfType(nsINode::eXUL)) {
-           nsIAtom* tag = aContent->Tag();
-           return tag == nsGkAtoms::scrollbar || tag == nsGkAtoms::scrollcorner;
-         }
-         aContent = parent;
-       }
-    }
-    return PR_FALSE;
-  }
-protected:
-  nsRefPtr<PresShell> mBaseObserver;
-};
-
-NS_IMPL_ISUPPORTS2(nsDocumentObserverForNonDynamicPresContext,
-                   nsIDocumentObserver,
-                   nsIMutationObserver)
-
 PRBool PresShell::sDisableNonTestMouseEvents = PR_FALSE;
 PRBool PresShell::sDontRetargetEvents = PR_FALSE;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* PresShell::gLog;
 #endif
 
 #ifdef NS_DEBUG
@@ -2573,24 +2453,17 @@ PresShell::RepaintSelection(SelectionTyp
   return mSelection->RepaintSelection(aType);
 }
 
 // Make shell be a document observer
 NS_IMETHODIMP
 PresShell::BeginObservingDocument()
 {
   if (mDocument && !mIsDestroying) {
-    if (mPresContext->IsDynamic()) {
-      mDocument->AddObserver(this);
-    } else {
-      mDocumentObserverForNonDynamicContext =
-        new nsDocumentObserverForNonDynamicPresContext(this);
-      NS_ENSURE_TRUE(mDocumentObserverForNonDynamicContext, NS_ERROR_OUT_OF_MEMORY);
-      mDocument->AddObserver(mDocumentObserverForNonDynamicContext);
-    }
+    mDocument->AddObserver(this);
     if (mIsDocumentGone) {
       NS_WARNING("Adding a presshell that was disconnected from the document "
                  "as a document observer?  Sounds wrong...");
       mIsDocumentGone = PR_FALSE;
     }
   }
   return NS_OK;
 }
@@ -2598,20 +2471,17 @@ PresShell::BeginObservingDocument()
 // Make shell stop being a document observer
 NS_IMETHODIMP
 PresShell::EndObservingDocument()
 {
   // XXXbz do we need to tell the frame constructor that the document
   // is gone, perhaps?  Except for printing it's NOT gone, sometimes.
   mIsDocumentGone = PR_TRUE;
   if (mDocument) {
-    mDocument->RemoveObserver(mDocumentObserverForNonDynamicContext ?
-                              mDocumentObserverForNonDynamicContext.get() :
-                              this);
-    mDocumentObserverForNonDynamicContext = nsnull;
+    mDocument->RemoveObserver(this);
   }
   return NS_OK;
 }
 
 #ifdef DEBUG_kipp
 char* nsPresShell_ReflowStackPointerTop;
 #endif
 
@@ -3643,20 +3513,16 @@ PresShell::RecreateFramesFor(nsIContent*
 {
   NS_ENSURE_TRUE(mPresContext, NS_ERROR_FAILURE);
   if (!mDidInitialReflow) {
     // Nothing to do here.  In fact, if we proceed and aContent is the
     // root we will crash.
     return NS_OK;
   }
 
-  if (!mPresContext->IsDynamic()) {
-    return NS_OK;
-  }
-
   // Don't call RecreateFramesForContent since that is not exported and we want
   // to keep the number of entrypoints down.
 
   NS_ASSERTION(mViewManager, "Should have view manager");
   nsIViewManager::UpdateViewBatch batch(mViewManager);
 
   // Have to make sure that the content notifications are flushed before we
   // start messing with the frame model; otherwise we can get content doubling.
@@ -5069,19 +4935,16 @@ PresShell::ContentRemoved(nsIDocument *a
                                     &didReconstruct);
 
   VERIFY_STYLE_TREE;
 }
 
 nsresult
 PresShell::ReconstructFrames(void)
 {
-  if (!mPresContext || !mPresContext->IsDynamic()) {
-    return NS_OK;
-  }
   nsAutoCauseReflowNotifier crNotifier(this);
   mFrameConstructor->BeginUpdate();
   nsresult rv = mFrameConstructor->ReconstructDocElementHierarchy();
   VERIFY_STYLE_TREE;
   mFrameConstructor->EndUpdate();
 
   return rv;
 }
diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -54,20 +54,16 @@
 #include "nsLineBox.h"
 #include "gfxFont.h"
 #include "gfxSkipChars.h"
 #include "gfxContext.h"
 
 class nsTextPaintStyle;
 class PropertyProvider;
 
-// This bit is set while the frame is registered as a blinking frame or if
-// frame is within a non-dynamic PresContext.
-#define TEXT_BLINK_ON_OR_PRINTING  0x20000000
-
 // This state bit is set on frames that have some non-collapsed characters after
 // reflow
 #define TEXT_HAS_NONCOLLAPSED_CHARACTERS 0x80000000
 
 class nsTextFrame : public nsFrame {
 public:
   friend class nsContinuingTextFrame;
 
@@ -353,27 +349,19 @@ public:
   struct TrimmedOffsets {
     PRInt32 mStart;
     PRInt32 mLength;
     PRInt32 GetEnd() { return mStart + mLength; }
   };
   TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag,
                                    PRBool aTrimAfter);
 
-  const nsTextFragment* GetFragment() const
-  {
-    return !(GetStateBits() & TEXT_BLINK_ON_OR_PRINTING) ?
-      mContent->GetText() : GetFragmentInternal();
-  }
-
 protected:
   virtual ~nsTextFrame();
 
-  const nsTextFragment* GetFragmentInternal() const;
-
   nsIFrame*   mNextContinuation;
   // The key invariant here is that mContentOffset never decreases along
   // a next-continuation chain. And of course mContentOffset is always <= the
   // the text node's content length, and the mContentOffset for the first frame
   // is always 0. Furthermore the text mapped by a frame is determined by
   // GetContentOffset() and GetContentLength()/GetContentEnd(), which get
   // the length from the difference between this frame's offset and the next
   // frame's offset, or the text length if there is no next frame. This means
diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -159,19 +159,18 @@
 
 // Cache bits for IsEmpty().
 // Set this bit if the textframe is known to be only collapsible whitespace.
 #define TEXT_IS_ONLY_WHITESPACE    0x08000000
 // Set this bit if the textframe is known to be not only collapsible whitespace.
 #define TEXT_ISNOT_ONLY_WHITESPACE 0x10000000
 
 #define TEXT_WHITESPACE_FLAGS      0x18000000
-
-// nsTextFrame.h has
-// #define TEXT_BLINK_ON_OR_PRINTING  0x20000000
+// This bit is set while the frame is registered as a blinking frame.
+#define TEXT_BLINK_ON              0x20000000
 
 // Set when this text frame is mentioned in the userdata for a textrun
 #define TEXT_IN_TEXTRUN_USER_DATA  0x40000000
 
 // nsTextFrame.h has
 // #define TEXT_HAS_NONCOLLAPSED_CHARACTERS 0x80000000
 
 /*
@@ -478,33 +477,33 @@ nsTextFrameTextRunCache::Init() {
 void
 nsTextFrameTextRunCache::Shutdown() {
     delete gTextRuns;
     gTextRuns = nsnull;
 }
 
 PRInt32 nsTextFrame::GetContentEnd() const {
   nsTextFrame* next = static_cast<nsTextFrame*>(GetNextContinuation());
-  return next ? next->GetContentOffset() : GetFragment()->GetLength();
+  return next ? next->GetContentOffset() : mContent->GetText()->GetLength();
 }
 
 PRInt32 nsTextFrame::GetInFlowContentLength() {
 #ifdef IBMBIDI
   nsTextFrame* nextBidi = nsnull;
   PRInt32      start = -1, end;
 
   if (mState & NS_FRAME_IS_BIDI) {
     nextBidi = static_cast<nsTextFrame*>(GetLastInFlow()->GetNextContinuation());
     if (nextBidi) {
       nextBidi->GetOffsets(start, end);
       return start - mContentOffset;
     }
   }
 #endif //IBMBIDI
-  return GetFragment()->GetLength() - mContentOffset;
+  return mContent->TextLength() - mContentOffset;
 }
 
 // Smarter versions of XP_IS_SPACE.
 // Unicode is really annoying; sometimes a space character isn't whitespace ---
 // when it combines with another character
 // So we have several versions of IsSpace for use in different contexts.
 
 static PRBool IsSpaceCombiningSequenceTail(const nsTextFragment* aFrag, PRUint32 aPos)
@@ -723,17 +722,17 @@ public:
     // ancestor of the elements containing the characters is the one whose
     // CSS 'white-space' property governs. So this records the nearest common
     // ancestor of mStartFrame and the previous text frame, or null if there
     // was no previous text frame on this line.
     nsIFrame*    mAncestorControllingInitialBreak;
     
     PRInt32 GetContentEnd() {
       return mEndFrame ? mEndFrame->GetContentOffset()
-          : mStartFrame->GetFragment()->GetLength();
+          : mStartFrame->GetContent()->GetText()->GetLength();
     }
   };
 
   class BreakSink : public nsILineBreakSink {
   public:
     BreakSink(gfxTextRun* aTextRun, gfxContext* aContext, PRUint32 aOffsetIntoTextRun,
               PRBool aExistingTextRun) :
                 mTextRun(aTextRun), mContext(aContext),
@@ -929,17 +928,17 @@ BuildTextRunsScanner::FindBoundaries(nsI
     aState->mLastTextFrame = textFrame;
   }
   
   if (aFrame == aState->mStopAtFrame)
     return FB_STOPPED_AT_STOP_FRAME;
 
   if (textFrame) {
     if (!aState->mSeenSpaceForLineBreakingOnThisLine) {
-      const nsTextFragment* frag = textFrame->GetFragment();
+      const nsTextFragment* frag = textFrame->GetContent()->GetText();
       PRUint32 start = textFrame->GetContentOffset();
       const void* text = frag->Is2b()
           ? static_cast<const void*>(frag->Get2b() + start)
           : static_cast<const void*>(frag->Get1b() + start);
       if (TextContainsLineBreakerWhiteSpace(text, textFrame->GetContentLength(),
                                             frag->Is2b())) {
         aState->mSeenSpaceForLineBreakingOnThisLine = PR_TRUE;
         if (aState->mSeenTextRunBoundaryOnLaterLine)
@@ -1254,17 +1253,17 @@ void BuildTextRunsScanner::FlushLineBrea
   }
   mTextRunsToDelete.Clear();
 }
 
 void BuildTextRunsScanner::AccumulateRunInfo(nsTextFrame* aFrame)
 {
   NS_ASSERTION(mMaxTextLength <= mMaxTextLength + aFrame->GetContentLength(), "integer overflow");
   mMaxTextLength += aFrame->GetContentLength();
-  mDoubleByteText |= aFrame->GetFragment()->Is2b();
+  mDoubleByteText |= aFrame->GetContent()->GetText()->Is2b();
   mLastFrame = aFrame;
   mCommonAncestorWithLastFrame = aFrame->GetParent();
 
   MappedFlow* mappedFlow = &mMappedFlows[mMappedFlows.Length() - 1];
   NS_ASSERTION(mappedFlow->mStartFrame == aFrame ||
                mappedFlow->GetContentEnd() == aFrame->GetContentOffset(),
                "Overlapping or discontiguous frames => BAD");
   mappedFlow->mEndFrame = static_cast<nsTextFrame*>(aFrame->GetNextContinuation());
@@ -1287,17 +1286,17 @@ static nscoord StyleToCoord(const nsStyl
   }
 }
 
 static PRBool
 HasTerminalNewline(const nsTextFrame* aFrame)
 {
   if (aFrame->GetContentLength() == 0)
     return PR_FALSE;
-  const nsTextFragment* frag = aFrame->GetFragment();
+  const nsTextFragment* frag = aFrame->GetContent()->GetText();
   return frag->CharAt(aFrame->GetContentEnd() - 1) == '\n';
 }
 
 PRBool
 BuildTextRunsScanner::ContinueTextRunAcrossFrames(nsTextFrame* aFrame1, nsTextFrame* aFrame2)
 {
   if (mBidiEnabled &&
       NS_GET_EMBEDDING_LEVEL(aFrame1) != NS_GET_EMBEDDING_LEVEL(aFrame2))
@@ -1614,17 +1613,17 @@ BuildTextRunsScanner::BuildTextRunForFra
     }
     fontStyle = f->GetStyleFont();
     if (NS_STYLE_FONT_VARIANT_SMALL_CAPS == fontStyle->mFont.variant) {
       anySmallcapsStyle = PR_TRUE;
     }
 
     // Figure out what content is included in this flow.
     nsIContent* content = f->GetContent();
-    const nsTextFragment* frag = f->GetFragment();
+    const nsTextFragment* frag = content->GetText();
     PRInt32 contentStart = mappedFlow->mStartFrame->GetContentOffset();
     PRInt32 contentEnd = mappedFlow->GetContentEnd();
     PRInt32 contentLength = contentEnd - contentStart;
 
     TextRunMappedFlow* newFlow = &userData->mMappedFlows[i];
     newFlow->mStartFrame = mappedFlow->mStartFrame;
     newFlow->mDOMOffsetToBeforeTransformOffset = builder.GetCharCount() -
       mappedFlow->mStartFrame->GetContentOffset();
@@ -1860,17 +1859,17 @@ HasCompressedLeadingWhitespace(nsTextFra
                                PRInt32 aContentEndOffset,
                                const gfxSkipCharsIterator& aIterator)
 {
   if (!aIterator.IsOriginalCharSkipped())
     return PR_FALSE;
 
   gfxSkipCharsIterator iter = aIterator;
   PRInt32 frameContentOffset = aFrame->GetContentOffset();
-  const nsTextFragment* frag = aFrame->GetFragment();
+  const nsTextFragment* frag = aFrame->GetContent()->GetText();
   while (frameContentOffset < aContentEndOffset && iter.IsOriginalCharSkipped()) {
     if (IsTrimmableSpace(frag, frameContentOffset, aStyleText))
       return PR_TRUE;
     ++frameContentOffset;
     iter.AdvanceOriginal(1);
   }
   return PR_FALSE;
 }
@@ -2232,17 +2231,17 @@ public:
   /**
    * Use this constructor after the frame has been reflowed and we don't
    * have other data around. Gets everything from the frame. EnsureTextRun
    * *must* be called before this!!!
    */
   PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart)
     : mTextRun(aFrame->GetTextRun()), mFontGroup(nsnull),
       mTextStyle(aFrame->GetStyleText()),
-      mFrag(aFrame->GetFragment()),
+      mFrag(aFrame->GetContent()->GetText()),
       mLineContainer(nsnull),
       mFrame(aFrame), mStart(aStart), mTempIterator(aStart),
       mTabWidths(nsnull),
       mLength(aFrame->GetContentLength()),
       mWordSpacing(mTextStyle->mWordSpacing),
       mLetterSpacing(StyleToCoord(mTextStyle->mLetterSpacing)),
       mJustificationSpacing(0),
       mHyphenWidth(-1),
@@ -3405,21 +3404,16 @@ NS_IMETHODIMP nsTextFrame::GetAccessible
 NS_IMETHODIMP
 nsTextFrame::Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow)
 {
   NS_ASSERTION(!aPrevInFlow, "Can't be a continuation!");
   NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eTEXT),
                   "Bogus content!");
-
-  if (!PresContext()->IsDynamic()) {
-    AddStateBits(TEXT_BLINK_ON_OR_PRINTING);
-  }
-
   // Since our content has a frame now, this flag is no longer needed.
   aContent->UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE);
   // We're not a continuing frame.
   // mContentOffset = 0; not necessary since we get zeroed out at init
   return nsFrame::Init(aContent, aParent, aPrevInFlow);
 }
 
 void
@@ -3492,34 +3486,29 @@ protected:
 };
 
 NS_IMETHODIMP
 nsContinuingTextFrame::Init(nsIContent* aContent,
                             nsIFrame*   aParent,
                             nsIFrame*   aPrevInFlow)
 {
   NS_ASSERTION(aPrevInFlow, "Must be a continuation!");
-
-  if (!PresContext()->IsDynamic()) {
-    AddStateBits(TEXT_BLINK_ON_OR_PRINTING);
-  }
-
   // NOTE: bypassing nsTextFrame::Init!!!
   nsresult rv = nsFrame::Init(aContent, aParent, aPrevInFlow);
 
 #ifdef IBMBIDI
   nsTextFrame* nextContinuation =
     static_cast<nsTextFrame*>(aPrevInFlow->GetNextContinuation());
 #endif // IBMBIDI
   // Hook the frame into the flow
   SetPrevInFlow(aPrevInFlow);
   aPrevInFlow->SetNextInFlow(this);
   nsTextFrame* prev = static_cast<nsTextFrame*>(aPrevInFlow);
   mContentOffset = prev->GetContentOffset() + prev->GetContentLengthHint();
-  NS_ASSERTION(mContentOffset < PRInt32(GetFragment()->GetLength()),
+  NS_ASSERTION(mContentOffset < PRInt32(aContent->GetText()->GetLength()),
                "Creating ContinuingTextFrame, but there is no more content");
   if (prev->GetStyleContext() != GetStyleContext()) {
     // We're taking part of prev's text, and its style may be different
     // so clear its textrun which may no longer be valid (and don't set ours)
     prev->ClearTextRun();
   } else {
     mTextRun = prev->GetTextRun();
   }
@@ -3694,17 +3683,17 @@ NS_NewTextFrame(nsIPresShell* aPresShell
 nsIFrame*
 NS_NewContinuingTextFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsContinuingTextFrame(aContext);
 }
 
 nsTextFrame::~nsTextFrame()
 {
-  if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic())
+  if (0 != (mState & TEXT_BLINK_ON))
   {
     nsBlinkTimer::RemoveBlinkFrame(this);
   }
 }
 
 NS_IMETHODIMP
 nsTextFrame::GetCursor(const nsPoint& aPoint,
                        nsIFrame::Cursor& aCursor)
@@ -3878,17 +3867,17 @@ nsTextFrame::BuildDisplayList(nsDisplayL
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
     return NS_OK;
   
   DO_GLOBAL_REFLOW_COUNT_DSP("nsTextFrame");
 
-  if ((0 != (mState & TEXT_BLINK_ON_OR_PRINTING)) && nsBlinkTimer::GetBlinkIsOff() &&
+  if ((0 != (mState & TEXT_BLINK_ON)) && nsBlinkTimer::GetBlinkIsOff() &&
       PresContext()->IsDynamic() && !aBuilder->IsForEventDelivery())
     return NS_OK;
     
   return aLists.Content()->AppendNewToTop(new (aBuilder) nsDisplayText(this));
 }
 
 static nsIFrame*
 GetGeneratedContentOwner(nsIFrame* aFrame, PRBool* aIsBefore)
@@ -5202,17 +5191,17 @@ PRBool
 nsTextFrame::PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset)
 {
   NS_ASSERTION(aOffset && *aOffset <= GetContentLength(), "aOffset out of range");
 
   gfxSkipCharsIterator iter = EnsureTextRun();
   if (!mTextRun)
     return PR_FALSE;
 
-  TrimmedOffsets trimmed = GetTrimmedOffsets(GetFragment(), PR_TRUE);
+  TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_TRUE);
   // Check whether there are nonskipped characters in the trimmmed range
   return iter.ConvertOriginalToSkipped(trimmed.GetEnd()) >
          iter.ConvertOriginalToSkipped(trimmed.mStart);
 }
 
 /**
  * This class iterates through the clusters before or after the given
  * aPosition (which is a content offset). You can test each cluster
@@ -5269,17 +5258,17 @@ nsTextFrame::PeekOffsetCharacter(PRBool 
   IsSelectable(&selectable, &selectStyle);
   if (selectStyle == NS_STYLE_USER_SELECT_ALL)
     return PR_FALSE;
 
   gfxSkipCharsIterator iter = EnsureTextRun();
   if (!mTextRun)
     return PR_FALSE;
 
-  TrimmedOffsets trimmed = GetTrimmedOffsets(GetFragment(), PR_FALSE);
+  TrimmedOffsets trimmed = GetTrimmedOffsets(mContent->GetText(), PR_FALSE);
 
   // A negative offset means "end of frame".
   PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
 
   if (!aForward) {
     PRInt32 i;
     for (i = PR_MIN(trimmed.GetEnd(), startOffset) - 1;
          i >= trimmed.mStart; --i) {
@@ -5384,17 +5373,17 @@ ClusterIterator::ClusterIterator(nsTextF
   if (!aTextFrame->GetTextRun()) {
     mDirection = 0; // signal failure
     return;
   }
   mIterator.SetOriginalOffset(aPosition);
 
   mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID);
   
-  mFrag = aTextFrame->GetFragment();
+  mFrag = aTextFrame->GetContent()->GetText();
   mTrimmed = aTextFrame->GetTrimmedOffsets(mFrag, PR_TRUE);
 
   PRInt32 textOffset = aTextFrame->GetContentOffset();
   PRInt32 textLen = aTextFrame->GetContentLength();
   if (!mWordBreaks.AppendElements(textLen + 1)) {
     mDirection = 0; // signal failure
     return;
   }
@@ -5625,17 +5614,17 @@ nsTextFrame::AddInlineMinWidthForFlow(ns
   gfxSkipCharsIterator iter =
     EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun);
   if (!mTextRun)
     return;
 
   // Pass null for the line container. This will disable tab spacing, but that's
   // OK since we can't really handle tabs for intrinsic sizing anyway.
   const nsStyleText* textStyle = GetStyleText();
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
   PropertyProvider provider(mTextRun, textStyle, frag, this,
                             iter, PR_INT32_MAX, nsnull, 0);
 
   PRBool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant();
   PRBool preformatNewlines = textStyle->NewlineIsSignificant();
   PRBool preformatTabs = textStyle->WhiteSpaceIsSignificant();
   gfxFloat tabWidth = -1;
   PRUint32 start =
@@ -5753,17 +5742,17 @@ nsTextFrame::AddInlinePrefWidthForFlow(n
     EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun);
   if (!mTextRun)
     return;
 
   // Pass null for the line container. This will disable tab spacing, but that's
   // OK since we can't really handle tabs for intrinsic sizing anyway.
   
   const nsStyleText* textStyle = GetStyleText();
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
   PropertyProvider provider(mTextRun, textStyle, frag, this,
                             iter, PR_INT32_MAX, nsnull, 0);
 
   PRBool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant();
   PRBool preformatNewlines = textStyle->NewlineIsSignificant();
   PRBool preformatTabs = textStyle->WhiteSpaceIsSignificant();
   gfxFloat tabWidth = -1;
   PRUint32 start =
@@ -5991,18 +5980,18 @@ nsTextFrame::Reflow(nsPresContext*      
          aReflowState.availableWidth, aReflowState.availableHeight);
 #endif
 
   /////////////////////////////////////////////////////////////////////
   // Set up flags and clear out state
   /////////////////////////////////////////////////////////////////////
 
   // Clear out the reflow state flags in mState (without destroying
-  // the TEXT_BLINK_ON_OR_PRINTING bit). We also clear the whitespace flags
-  // because this can change whether the frame maps whitespace-only text or not.
+  // the TEXT_BLINK_ON bit). We also clear the whitespace flags because this
+  // can change whether the frame maps whitespace-only text or not.
   RemoveStateBits(TEXT_REFLOW_FLAGS | TEXT_WHITESPACE_FLAGS);
 
   // Temporarily map all possible content while we construct our new textrun.
   // so that when doing reflow our styles prevail over any part of the
   // textrun we look at. Note that next-in-flows may be mapping the same
   // content; gfxTextRun construction logic will ensure that we take priority.
   PRInt32 maxContentLength = GetInFlowContentLength();
 
@@ -6014,39 +6003,39 @@ nsTextFrame::Reflow(nsPresContext*      
     ClearMetrics(aMetrics);
     aStatus = NS_FRAME_COMPLETE;
     return NS_OK;
   }
 
   nsLineLayout& lineLayout = *aReflowState.mLineLayout;
 
   if (aReflowState.mFlags.mBlinks) {
-    if (0 == (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
-      mState |= TEXT_BLINK_ON_OR_PRINTING;
+    if (0 == (mState & TEXT_BLINK_ON)) {
+      mState |= TEXT_BLINK_ON;
       nsBlinkTimer::AddBlinkFrame(aPresContext, this);
     }
   }
   else {
-    if (0 != (mState & TEXT_BLINK_ON_OR_PRINTING) && PresContext()->IsDynamic()) {
-      mState &= ~TEXT_BLINK_ON_OR_PRINTING;
+    if (0 != (mState & TEXT_BLINK_ON)) {
+      mState &= ~TEXT_BLINK_ON;
       nsBlinkTimer::RemoveBlinkFrame(this);
     }
   }
 
   const nsStyleText* textStyle = GetStyleText();
 
   PRBool atStartOfLine = lineLayout.LineIsEmpty();
   if (atStartOfLine) {
     AddStateBits(TEXT_START_OF_LINE);
   }
 
   PRUint32 flowEndInTextRun;
   nsIFrame* lineContainer = lineLayout.GetLineContainerFrame();
   gfxContext* ctx = aReflowState.rendContext->ThebesContext();
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
 
   // DOM offsets of the text range we need to measure, after trimming
   // whitespace, restricting to first-letter, and restricting preformatted text
   // to nearest newline
   PRInt32 length = maxContentLength;
   PRInt32 offset = GetContentOffset();
 
   // Restrict preformatted text to the nearest newline
@@ -6446,17 +6435,17 @@ nsTextFrame::TrimTrailingWhiteSpace(nsIR
     return result;
 
   gfxContext* ctx = aRC->ThebesContext();
   gfxSkipCharsIterator start = EnsureTextRun(ctx);
   NS_ENSURE_TRUE(mTextRun, result);
 
   PRUint32 trimmedStart = start.GetSkippedOffset();
 
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
   TrimmedOffsets trimmed = GetTrimmedOffsets(frag, PR_TRUE);
   gfxSkipCharsIterator trimmedEndIter = start;
   const nsStyleText* textStyle = GetStyleText();
   gfxFloat delta = 0;
   PRUint32 trimmedEnd = trimmedEndIter.ConvertOriginalToSkipped(trimmed.GetEnd());
   
   if (GetStateBits() & TEXT_TRIMMED_TRAILING_WHITESPACE) {
     // We pre-trimmed this frame, so the last character is justifiable
@@ -6583,17 +6572,17 @@ nsresult nsTextFrame::GetRenderedText(ns
                                       gfxSkipChars* aSkipChars,
                                       gfxSkipCharsIterator* aSkipIter,
                                       PRUint32 aSkippedStartOffset,
                                       PRUint32 aSkippedMaxLength)
 {
   // The handling of aSkippedStartOffset and aSkippedMaxLength could be more efficient...
   gfxSkipCharsBuilder skipCharsBuilder;
   nsTextFrame* textFrame;
-  const nsTextFragment* textFrag = GetFragment();
+  const nsTextFragment* textFrag = mContent->GetText();
   PRUint32 keptCharsLength = 0;
   PRUint32 validCharsLength = 0;
 
   // Build skipChars and copy text, for each text frame in this continuation block
   for (textFrame = this; textFrame;
        textFrame = static_cast<nsTextFrame*>(textFrame->GetNextContinuation())) {
     // For each text frame continuation in this block ...
 
@@ -6649,17 +6638,17 @@ nsresult nsTextFrame::GetRenderedText(ns
 }
 
 #ifdef DEBUG
 // Translate the mapped content into a string that's printable
 void
 nsTextFrame::ToCString(nsCString& aBuf, PRInt32* aTotalContentLength) const
 {
   // Get the frames text content
-  const nsTextFragment* frag = GetFragment();
+  const nsTextFragment* frag = mContent->GetText();
   if (!frag) {
     return;
   }
 
   // Compute the total length of the text content.
   *aTotalContentLength = frag->GetLength();
 
   PRInt32 contentLength = GetContentLength();
@@ -6709,17 +6698,17 @@ nsTextFrame::IsEmpty()
   if (mState & TEXT_ISNOT_ONLY_WHITESPACE) {
     return PR_FALSE;
   }
 
   if (mState & TEXT_IS_ONLY_WHITESPACE) {
     return PR_TRUE;
   }
   
-  PRBool isEmpty = IsAllWhitespace(GetFragment(),
+  PRBool isEmpty = IsAllWhitespace(mContent->GetText(),
           textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE);
   mState |= (isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE);
   return isEmpty;
 }
 
 #ifdef DEBUG
 NS_IMETHODIMP
 nsTextFrame::GetFrameName(nsAString& aResult) const
@@ -6846,15 +6835,8 @@ nsTextFrame::HasTerminalNewline() const
   return ::HasTerminalNewline(this);
 }
 
 PRBool
 nsTextFrame::IsAtEndOfLine() const
 {
   return (GetStateBits() & TEXT_END_OF_LINE) != 0;
 }
-
-const nsTextFragment*
-nsTextFrame::GetFragmentInternal() const
-{
-  return PresContext()->IsDynamic() ? mContent->GetText() :
-    nsLayoutUtils::GetTextFragmentForPrinting(this);
-}
diff --git a/layout/generic/nsVideoFrame.cpp b/layout/generic/nsVideoFrame.cpp
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -215,37 +215,37 @@ nsVideoFrame::Reflow(nsPresContext*     
   // Reflow the child frames. We may have up to two, an image frame
   // which is the poster, and a box frame, which is the video controls.
   for (nsIFrame *child = mFrames.FirstChild();
        child;
        child = child->GetNextSibling()) {
     if (child->GetType() == nsGkAtoms::imageFrame) {
       // Reflow the poster frame.
       nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
-      nsHTMLReflowMetrics kidDesiredSize;
-      nsSize availableSize = nsSize(aReflowState.availableWidth,
-                                    aReflowState.availableHeight);
-      nsHTMLReflowState kidReflowState(aPresContext,
-                                       aReflowState,
-                                       imageFrame,
-                                       availableSize,
-                                       aMetrics.width,
-                                       aMetrics.height);
-      if (ShouldDisplayPoster()) {
-        kidReflowState.SetComputedWidth(aReflowState.ComputedWidth());
-        kidReflowState.SetComputedHeight(aReflowState.ComputedHeight());
-      } else {
-        kidReflowState.SetComputedWidth(0);
-        kidReflowState.SetComputedHeight(0);      
-      }
-      ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowState,
-                  mBorderPadding.left, mBorderPadding.top, 0, aStatus);
-      FinishReflowChild(imageFrame, aPresContext,
-                        &kidReflowState, kidDesiredSize,
-                        mBorderPadding.left, mBorderPadding.top, 0);
+      nsHTMLReflowMetrics kidDesiredSize;
+      nsSize availableSize = nsSize(aReflowState.availableWidth,
+                                    aReflowState.availableHeight);
+      nsHTMLReflowState kidReflowState(aPresContext,
+                                       aReflowState,
+                                       imageFrame,
+                                       availableSize,
+                                       aMetrics.width,
+                                       aMetrics.height);
+      if (ShouldDisplayPoster()) {
+        kidReflowState.SetComputedWidth(aReflowState.ComputedWidth());
+        kidReflowState.SetComputedHeight(aReflowState.ComputedHeight());
+      } else {
+        kidReflowState.SetComputedWidth(0);
+        kidReflowState.SetComputedHeight(0);      
+      }
+      ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowState,
+                  mBorderPadding.left, mBorderPadding.top, 0, aStatus);
+      FinishReflowChild(imageFrame, aPresContext,
+                        &kidReflowState, kidDesiredSize,
+                        mBorderPadding.left, mBorderPadding.top, 0);
     } else if (child->GetType() == nsGkAtoms::boxFrame) {
       // Reflow the video controls frame.
       nsBoxLayoutState boxState(PresContext(), aReflowState.rendContext);
       nsBoxFrame::LayoutChildAt(boxState,
                                 child,
                                 nsRect(mBorderPadding.left,
                                        mBorderPadding.top,
                                        aReflowState.ComputedWidth(),
@@ -427,19 +427,19 @@ nsSize nsVideoFrame::GetIntrinsicSize(ns
   nsIntSize size(300,150);
 
   if (ShouldDisplayPoster()) {
     // Use the poster image frame's size.
     nsIFrame *child = mFrames.FirstChild();
     if (child && child->GetType() == nsGkAtoms::imageFrame) {
       nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
       nsSize imgsize;
-      imageFrame->GetIntrinsicImageSize(imgsize);
-      return imgsize;
-    }
+      imageFrame->GetIntrinsicImageSize(imgsize);
+      return imgsize;
+    }
   }
 
   if (!HasVideoData()) {
     if (!aRenderingContext || !mFrames.FirstChild()) {
       // We just want our intrinsic ratio, but audio elements need no
       // intrinsic ratio, so just return "no ratio". Also, if there's
       // no controls frame, we prefer to be zero-sized.
       return nsSize(0, 0);
diff --git a/layout/generic/nsVideoFrame.h b/layout/generic/nsVideoFrame.h
--- a/layout/generic/nsVideoFrame.h
+++ b/layout/generic/nsVideoFrame.h
@@ -95,34 +95,36 @@ public:
 
   virtual PRBool IsFrameOfType(PRUint32 aFlags) const
   {
     return nsSplittableFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced));
   }
   
   virtual nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
 
+  nsIContent* GetPosterImage() { return mPosterImage; }
+
+  // Returns PR_TRUE if we should display the poster. Note that once we show
+  // a video frame, the poster will never be displayed again.
+  PRBool ShouldDisplayPoster();
+
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
 protected:
 
   // Returns PR_TRUE if we're rendering for a video element. We still create
   // nsVideoFrame to render controls for an audio element.
   PRBool HasVideoElement();
 
   // Returns PR_TRUE if there is video data to render. Can return false
   // when we're the frame for an audio element, or we've created a video
   // element for a media which is audio-only.
   PRBool HasVideoData();
-  
-  // Returns PR_TRUE if we should display the poster. Note that once we show
-  // a video frame, the poster will never be displayed again.
-  PRBool ShouldDisplayPoster();
 
   // Sets the mPosterImage's src attribute to be the video's poster attribute,
   // if we're the frame for a video element. Only call on frames for video
   // elements, not for frames for audio elements.
   nsresult UpdatePosterSource(PRBool aNotify);
 
   virtual ~nsVideoFrame();
 
diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -154,17 +154,17 @@ static const char kPrintingPromptService
 #include "nsIDOMHTMLLinkElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIContentViewerContainer.h"
 #include "nsIContentViewer.h"
 #include "nsIDocumentViewerPrint.h"
 
 #include "nsPIDOMWindow.h"
 #include "nsFocusManager.h"
-
+#include "nsRange.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIURIFixup.h"
 
 //-----------------------------------------------------
 // PR LOGGING
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG /* Allow logging in the release build */
 #endif
@@ -437,19 +437,20 @@ static void DumpLayoutData(char* aTitleS
                            nsIDocShell * aDocShell, FILE* aFD);
 #endif
 
 //--------------------------------------------------------------------------------
 
 nsresult
 nsPrintEngine::CommonPrint(PRBool                  aIsPrintPreview,
                            nsIPrintSettings*       aPrintSettings,
-                           nsIWebProgressListener* aWebProgressListener) {
+                           nsIWebProgressListener* aWebProgressListener,
+                           nsIDOMDocument* aDoc) {
   nsresult rv = DoCommonPrint(aIsPrintPreview, aPrintSettings,
-                              aWebProgressListener);
+                              aWebProgressListener, aDoc);
   if (NS_FAILED(rv)) {
     if (aIsPrintPreview) {
       SetIsCreatingPrintPreview(PR_FALSE);
       SetIsPrintPreview(PR_FALSE);
     } else {
       SetIsPrinting(PR_FALSE);
     }
     if (mProgressDialogIsShown)
@@ -461,17 +462,18 @@ nsPrintEngine::CommonPrint(PRBool       
   }
 
   return rv;
 }
 
 nsresult
 nsPrintEngine::DoCommonPrint(PRBool                  aIsPrintPreview,
                              nsIPrintSettings*       aPrintSettings,
-                             nsIWebProgressListener* aWebProgressListener)
+                             nsIWebProgressListener* aWebProgressListener,
+                             nsIDOMDocument*         aDoc)
 {
   nsresult rv;
 
   if (aIsPrintPreview) {
     // The WebProgressListener can be QI'ed to nsIPrintingPromptService
     // then that means the progress dialog is already being shown.
     nsCOMPtr<nsIPrintingPromptService> pps(do_QueryInterface(aWebProgressListener));
     mProgressDialogIsShown = pps != nsnull;
@@ -538,27 +540,28 @@ nsPrintEngine::DoCommonPrint(PRBool     
   PRBool isSelection = IsThereARangeSelection(mPrt->mCurrentFocusWin);
 
   // Get the docshell for this documentviewer
   nsCOMPtr<nsIDocShell> webContainer(do_QueryInterface(mContainer, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mPrt->mPrintObject = new nsPrintObject();
   NS_ENSURE_TRUE(mPrt->mPrintObject, NS_ERROR_OUT_OF_MEMORY);
-  rv = mPrt->mPrintObject->Init(webContainer);
+  rv = mPrt->mPrintObject->Init(webContainer, aDoc, aIsPrintPreview);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ENSURE_TRUE(mPrt->mPrintDocList.AppendElement(mPrt->mPrintObject),
                  NS_ERROR_OUT_OF_MEMORY);
 
   mPrt->mIsParentAFrameSet = IsParentAFrameSet(webContainer);
   mPrt->mPrintObject->mFrameType = mPrt->mIsParentAFrameSet ? eFrameSet : eDoc;
 
   // Build the "tree" of PrintObjects
-  nsCOMPtr<nsIDocShellTreeNode>  parentAsNode(do_QueryInterface(webContainer));
+  nsCOMPtr<nsIDocShellTreeNode> parentAsNode =
+    do_QueryInterface(mPrt->mPrintObject->mDocShell);
   BuildDocTree(parentAsNode, &mPrt->mPrintDocList, mPrt->mPrintObject);
 
   // XXX This isn't really correct...
   if (!mPrt->mPrintObject->mDocument->GetRootContent())
     return NS_ERROR_GFX_PRINTER_STARTDOC;
 
   // Create the linkage from the sub-docs back to the content element
   // in the parent document
@@ -747,17 +750,18 @@ nsPrintEngine::DoCommonPrint(PRBool     
   return NS_OK;
 }
 
 //---------------------------------------------------------------------------------
 NS_IMETHODIMP
 nsPrintEngine::Print(nsIPrintSettings*       aPrintSettings,
                      nsIWebProgressListener* aWebProgressListener)
 {
-  return CommonPrint(PR_FALSE, aPrintSettings, aWebProgressListener);
+  nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(mDocument);
+  return CommonPrint(PR_FALSE, aPrintSettings, aWebProgressListener, doc);
 }
 
 NS_IMETHODIMP
 nsPrintEngine::PrintPreview(nsIPrintSettings* aPrintSettings, 
                                  nsIDOMWindow *aChildDOMWin, 
                                  nsIWebProgressListener* aWebProgressListener)
 {
   // Get the DocShell and see if it is busy
@@ -768,18 +772,23 @@ nsPrintEngine::PrintPreview(nsIPrintSett
   PRUint32 busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
   if (NS_FAILED(docShell->GetBusyFlags(&busyFlags)) ||
       busyFlags != nsIDocShell::BUSY_FLAGS_NONE) {
     CloseProgressDialog(aWebProgressListener);
     ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP, PR_FALSE);
     return NS_ERROR_FAILURE;
   }
 
+  NS_ENSURE_STATE(aChildDOMWin);
+  nsCOMPtr<nsIDOMDocument> doc;
+  aChildDOMWin->GetDocument(getter_AddRefs(doc));
+  NS_ENSURE_STATE(doc);
+
   // Document is not busy -- go ahead with the Print Preview
-  return CommonPrint(PR_TRUE, aPrintSettings, aWebProgressListener);
+  return CommonPrint(PR_TRUE, aPrintSettings, aWebProgressListener, doc);
 }
 
 //----------------------------------------------------------------------------------
 /* readonly attribute boolean isFramesetDocument; */
 NS_IMETHODIMP
 nsPrintEngine::GetIsFramesetDocument(PRBool *aIsFramesetDocument)
 {
   nsCOMPtr<nsIDocShell> webContainer(do_QueryInterface(mContainer));
@@ -1087,22 +1096,16 @@ nsPrintEngine::IsThereARangeSelection(ns
   }
   return PR_FALSE;
 }
 
 //---------------------------------------------------------------------
 PRBool
 nsPrintEngine::IsParentAFrameSet(nsIDocShell * aParent)
 {
-  NS_ASSERTION(aParent, "Pointer is null!");
-
-  nsCOMPtr<nsIPresShell> shell;
-  aParent->GetPresShell(getter_AddRefs(shell));
-  NS_ASSERTION(shell, "shell can't be null");
-
   // See if the incoming doc is the root document
   nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(aParent));
   if (!parentAsItem) return PR_FALSE;
 
   // When it is the top level document we need to check
   // to see if it contains a frameset. If it does, then
   // we only want to print the doc's children and not the document itself
   // For anything else we always print all the children and the document
@@ -1112,23 +1115,22 @@ nsPrintEngine::IsParentAFrameSet(nsIDocS
   // XXX we really need to search the frame tree, and not the content
   // but there is no way to distinguish between IFRAMEs and FRAMEs
   // with the GetFrameType call.
   // Bug 53459 has been files so we can eventually distinguish
   // between IFRAME frames and FRAME frames
   PRBool isFrameSet = PR_FALSE;
   // only check to see if there is a frameset if there is
   // NO parent doc for this doc. meaning this parent is the root doc
-  if (shell) {
-    nsIDocument *doc = shell->GetDocument();
-    if (doc) {
-      nsIContent *rootContent = doc->GetRootContent();
-      if (rootContent) {
-        isFrameSet = HasFramesetChild(rootContent);
-      }
+  nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(aParent);
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+  if (doc) {
+    nsIContent *rootContent = doc->GetRootContent();
+    if (rootContent) {
+      isFrameSet = HasFramesetChild(rootContent);
     }
   }
   return isFrameSet;
 }
 
 
 //---------------------------------------------------------------------
 // Recursively build a list of sub documents to be printed
@@ -1152,21 +1154,22 @@ nsPrintEngine::BuildDocTree(nsIDocShellT
 
       nsCOMPtr<nsIContentViewer>  viewer;
       childAsShell->GetContentViewer(getter_AddRefs(viewer));
       if (viewer) {
         nsCOMPtr<nsIContentViewerFile> viewerFile(do_QueryInterface(viewer));
         if (viewerFile) {
           nsCOMPtr<nsIDocShell> childDocShell(do_QueryInterface(child));
           nsCOMPtr<nsIDocShellTreeNode> childNode(do_QueryInterface(child));
+          nsCOMPtr<nsIDOMDocument> doc = do_GetInterface(childDocShell);
           nsPrintObject * po = new nsPrintObject();
-          nsresult rv = po->Init(childDocShell);
+          po->mParent = aPO;
+          nsresult rv = po->Init(childDocShell, doc, aPO->mPrintPreview);
           if (NS_FAILED(rv))
             NS_NOTREACHED("Init failed?");
-          po->mParent = aPO;
           aPO->mKids.AppendElement(po);
           aDocList->AppendElement(po);
           BuildDocTree(childNode, aDocList, po);
         }
       }
     }
   }
 }
@@ -1218,17 +1221,26 @@ nsPrintEngine::MapContentToWebShells(nsP
                                      nsPrintObject* aPO)
 {
   NS_ASSERTION(aRootPO, "Pointer is null!");
   NS_ASSERTION(aPO, "Pointer is null!");
 
   // Recursively walk the content from the root item
   // XXX Would be faster to enumerate the subdocuments, although right now
   //     nsIDocument doesn't expose quite what would be needed.
-  nsIContent *rootContent = aPO->mDocument->GetRootContent();
+  nsCOMPtr<nsIContentViewer> viewer;
+  aPO->mDocShell->GetContentViewer(getter_AddRefs(viewer));
+  if (!viewer) return;
+
+  nsCOMPtr<nsIDOMDocument> domDoc;
+  viewer->GetDOMDocument(getter_AddRefs(domDoc));
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+  if (!doc) return;
+
+  nsIContent *rootContent = doc->GetRootContent();
   if (rootContent) {
     MapContentForPO(aPO, rootContent);
   } else {
     NS_WARNING("Null root content on (sub)document.");
   }
 
   // Continue recursively walking the chilren of this PO
   for (PRUint32 i=0;i<aPO->mKids.Length();i++) {
@@ -1311,17 +1323,16 @@ nsPrintEngine::MapContentForPO(nsPrintOb
           po = kid;
           break;
         }
       }
 
       // XXX If a subdocument has no onscreen presentation, there will be no PO
       //     This is even if there should be a print presentation
       if (po) {
-        po->mContent  = aContent;
 
         nsCOMPtr<nsIDOMHTMLFrameElement> frame(do_QueryInterface(aContent));
         // "frame" elements not in a frameset context should be treated
         // as iframes
         if (frame && po->mParent->mFrameType == eFrameSet) {
           po->mFrameType = eFrame;
         } else {
           // Assume something iframe-like, i.e. iframe, object, or embed
@@ -1909,16 +1920,18 @@ nsPrintEngine::ReflowPrintObject(nsPrint
     nsIView* view = frame->GetView();
     NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
     view = view->GetFirstChild();
     NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
     parentView = view;
     canCreateScrollbars = PR_FALSE;
   }
 
+  NS_ASSERTION(!aPO->mPresContext, "Recreating prescontext");
+
   // create the PresContext
   aPO->mPresContext = new nsPresContext(aPO->mDocument,
                                         mIsCreatingPrintPreview ?
                                          nsPresContext::eContext_PrintPreview:
                                          nsPresContext::eContext_Print);
   NS_ENSURE_TRUE(aPO->mPresContext, NS_ERROR_OUT_OF_MEMORY);
   aPO->mPresContext->SetPrintSettings(mPrt->mPrintSettings);
 
@@ -1992,16 +2005,23 @@ nsPrintEngine::ReflowPrintObject(nsPrint
   aPO->mPresContext->SetPageScale(aPO->mZoomRatio);
   // Calculate scale factor from printer to screen
   float printDPI = float(mPrt->mPrintDC->AppUnitsPerInch()) /
                    float(mPrt->mPrintDC->AppUnitsPerDevPixel());
   float screenDPI = float(mDeviceContext->AppUnitsPerInch()) /
                     float(mDeviceContext->AppUnitsPerDevPixel());
   aPO->mPresContext->SetPrintPreviewScale(screenDPI / printDPI);
 
+  if (mIsCreatingPrintPreview && documentIsTopLevel) {
+    mDocViewerPrint->SetPrintPreviewPresentation(aPO->mWindow,
+                                                 aPO->mViewManager,
+                                                 aPO->mPresContext,
+                                                 aPO->mPresShell);
+  }
+
   rv = aPO->mPresShell->InitialReflow(adjSize.width, adjSize.height);
 
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ASSERTION(aPO->mPresShell, "Presshell should still be here");
 
   // Process the reflow event InitialReflow posted
   aPO->mPresShell->FlushPendingNotifications(Flush_Layout);
 
@@ -2133,16 +2153,110 @@ nsPrintEngine::PrintDocContent(nsPrintOb
       if (printed || NS_FAILED(aStatus)) {
         return PR_TRUE;
       }
     }
   }
   return PR_FALSE;
 }
 
+static already_AddRefed<nsIDOMNode>
+GetEqualNodeInCloneTree(nsIDOMNode* aNode, nsIDocument* aDoc)
+{
+  nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
+  // Selections in anonymous subtrees aren't supported.
+  if (content && content->IsInAnonymousSubtree()) {
+    return nsnull;
+  }
+
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+  NS_ENSURE_TRUE(node, nsnull);
+
+  nsTArray<PRInt32> indexArray;
+  nsINode* current = node;
+  NS_ENSURE_TRUE(current, nsnull);
+  while (current) {
+    nsINode* parent = current->GetNodeParent();
+    if (!parent) {
+     break;
+    }
+    PRInt32 index = parent->IndexOf(current);
+    NS_ENSURE_TRUE(index >= 0, nsnull);
+    indexArray.AppendElement(index);
+    current = parent;
+  }
+  NS_ENSURE_TRUE(current->IsNodeOfType(nsINode::eDOCUMENT), nsnull);
+
+  current = aDoc;
+  for (PRInt32 i = indexArray.Length() - 1; i >= 0; --i) {
+    current = current->GetChildAt(indexArray[i]);
+    NS_ENSURE_TRUE(current, nsnull);
+  }
+  nsCOMPtr<nsIDOMNode> result = do_QueryInterface(current);
+  return result.forget();
+}
+
+static nsresult CloneRangeToSelection(nsIDOMRange* aRange,
+                                      nsIDocument* aDoc,
+                                      nsISelection* aSelection)
+{
+  PRBool collapsed = PR_FALSE;
+  aRange->GetCollapsed(&collapsed);
+  if (collapsed) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIDOMNode> startContainer, endContainer;
+  PRInt32 startOffset = -1, endOffset = -1;
+  aRange->GetStartContainer(getter_AddRefs(startContainer));
+  aRange->GetStartOffset(&startOffset);
+  aRange->GetEndContainer(getter_AddRefs(endContainer));
+  aRange->GetEndOffset(&endOffset);
+  NS_ENSURE_STATE(startContainer && endContainer);
+
+  nsCOMPtr<nsIDOMNode> newStart = GetEqualNodeInCloneTree(startContainer, aDoc);
+  nsCOMPtr<nsIDOMNode> newEnd = GetEqualNodeInCloneTree(endContainer, aDoc);
+  NS_ENSURE_STATE(newStart && newEnd);
+
+  nsCOMPtr<nsIDOMRange> range;
+  NS_NewRange(getter_AddRefs(range));
+  NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
+
+  nsresult rv = range->SetStart(newStart, startOffset);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = range->SetEnd(newEnd, endOffset);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return aSelection->AddRange(range);
+}
+
+static nsresult CloneSelection(nsIDocument* aOrigDoc, nsIDocument* aDoc)
+{
+  nsIPresShell* origShell = aOrigDoc->GetPrimaryShell();
+  nsIPresShell* shell = aDoc->GetPrimaryShell();
+  NS_ENSURE_STATE(origShell && shell);
+
+  nsCOMPtr<nsISelection> origSelection =
+    origShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
+  nsCOMPtr<nsISelection> selection =
+    shell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
+  NS_ENSURE_STATE(origSelection && selection);
+
+  PRInt32 rangeCount = 0;
+  origSelection->GetRangeCount(&rangeCount);
+  for (PRInt32 i = 0; i < rangeCount; ++i) {
+    nsCOMPtr<nsIDOMRange> range;
+    origSelection->GetRangeAt(i, getter_AddRefs(range));
+    if (range) {
+      CloneRangeToSelection(range, aDoc, selection);
+    }
+  }
+  return NS_OK;
+}
+
 //-------------------------------------------------------
 nsresult
 nsPrintEngine::DoPrint(nsPrintObject * aPO)
 {
   PR_PL(("\n"));
   PR_PL(("**************************** %s ****************************\n", gFrameTypesStr[aPO->mFrameType]));
   PR_PL(("****** In DV::DoPrint   PO: %p \n", aPO));
 
@@ -2199,16 +2313,18 @@ nsPrintEngine::DoPrint(nsPrintObject * a
 
       if (mPrt->mPrintSettings) {
         PRUnichar * docTitleStr = nsnull;
         PRUnichar * docURLStr   = nsnull;
 
         GetDisplayTitleAndURL(aPO, &docTitleStr, &docURLStr, eDocTitleDefBlank); 
 
         if (nsIPrintSettings::kRangeSelection == printRangeType) {
+          CloneSelection(aPO->mDocument->GetOriginalDocument(), aPO->mDocument);
+
           poPresContext->SetIsRenderingOnlySelection(PR_TRUE);
           // temporarily creating rendering context
           // which is needed to dinf the selection frames
           nsCOMPtr<nsIRenderingContext> rc;
           mPrt->mPrintDC->CreateRenderingContext(*getter_AddRefs(rc));
 
           // find the starting and ending page numbers
           // via the selection
@@ -2800,18 +2916,20 @@ nsPrintEngine::FindPrintObjectByDOMWin(n
   NS_ASSERTION(aPO, "Pointer is null!");
 
   // Often the CurFocused DOMWindow is passed in
   // andit is valid for it to be null, so short circut
   if (!aDOMWin) {
     return nsnull;
   }
 
-  nsCOMPtr<nsIDOMWindow> domWin(do_GetInterface(aPO->mDocShell));
-  if (domWin && domWin == aDOMWin) {
+  nsCOMPtr<nsIDOMDocument> domDoc;
+  aDOMWin->GetDocument(getter_AddRefs(domDoc));
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+  if (aPO->mDocument && aPO->mDocument->GetOriginalDocument() == doc) {
     return aPO;
   }
 
   PRInt32 cnt = aPO->mKids.Length();
   for (PRInt32 i = 0; i < cnt; ++i) {
     nsPrintObject* po = FindPrintObjectByDOMWin(aPO->mKids[i], aDOMWin);
     if (po) {
       return po;
@@ -2905,17 +3023,18 @@ nsPrintEngine::EnablePOsForPrinting()
 
           // check to see if we have a range selection,
           // as oppose to a insert selection
           // this means if the user just clicked on the IFrame then
           // there will not be a selection so we want the entire page to print
           //
           // XXX this is sort of a hack right here to make the page
           // not try to reposition itself when printing selection
-          nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(po->mDocShell);
+          nsCOMPtr<nsIDOMWindow> domWin =
+            do_QueryInterface(po->mDocument->GetOriginalDocument()->GetWindow());
           if (!IsThereARangeSelection(domWin)) {
             printRangeType = nsIPrintSettings::kRangeAllPages;
             mPrt->mPrintSettings->SetPrintRange(printRangeType);
           }
           PR_PL(("PrintFrameType:     %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType]));
           PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable]));
           PR_PL(("PrintRange:         %s \n", gPrintRangeStr[printRangeType]));
           return NS_OK;
@@ -2952,17 +3071,18 @@ nsPrintEngine::EnablePOsForPrinting()
 
         // check to see if we have a range selection,
         // as oppose to a insert selection
         // this means if the user just clicked on the IFrame then
         // there will not be a selection so we want the entire page to print
         //
         // XXX this is sort of a hack right here to make the page
         // not try to reposition itself when printing selection
-        nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(po->mDocShell);
+        nsCOMPtr<nsIDOMWindow> domWin =
+          do_QueryInterface(po->mDocument->GetOriginalDocument()->GetWindow());
         if (!IsThereARangeSelection(domWin)) {
           printRangeType = nsIPrintSettings::kRangeAllPages;
           mPrt->mPrintSettings->SetPrintRange(printRangeType);
         }
         PR_PL(("PrintFrameType:     %s \n", gPrintFrameTypeStr[mPrt->mPrintFrameType]));
         PR_PL(("HowToEnableFrameUI: %s \n", gFrameHowToEnableStr[printHowEnable]));
         PR_PL(("PrintRange:         %s \n", gPrintRangeStr[printRangeType]));
         return NS_OK;
diff --git a/layout/printing/nsPrintEngine.h b/layout/printing/nsPrintEngine.h
--- a/layout/printing/nsPrintEngine.h
+++ b/layout/printing/nsPrintEngine.h
@@ -222,20 +222,22 @@ public:
   PRBool GetIsCreatingPrintPreview()
   {
     return mIsCreatingPrintPreview;
   }
 
 protected:
 
   nsresult CommonPrint(PRBool aIsPrintPreview, nsIPrintSettings* aPrintSettings,
-              nsIWebProgressListener* aWebProgressListener);
+                       nsIWebProgressListener* aWebProgressListener,
+                       nsIDOMDocument* aDoc);
 
   nsresult DoCommonPrint(PRBool aIsPrintPreview, nsIPrintSettings* aPrintSettings,
-                         nsIWebProgressListener* aWebProgressListener);
+                         nsIWebProgressListener* aWebProgressListener,
+                         nsIDOMDocument* aDoc);
 
   void FirePrintCompletionEvent();
   static nsresult GetSeqFrameAndCountPagesInternal(nsPrintObject*  aPO,
                                                    nsIFrame*&      aSeqFrame,
                                                    PRInt32&        aCount);
 
   static nsresult FindSelectionBoundsWithList(nsPresContext* aPresContext,
                                               nsIRenderingContext& aRC,
diff --git a/layout/printing/nsPrintObject.cpp b/layout/printing/nsPrintObject.cpp
--- a/layout/printing/nsPrintObject.cpp
+++ b/layout/printing/nsPrintObject.cpp
@@ -34,16 +34,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsPrintObject.h"
 #include "nsIContentViewer.h"
 #include "nsIDOMDocument.h"
 #include "nsContentUtils.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsPIDOMWindow.h"
+#include "nsGkAtoms.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIDocShellTreeItem.h"
 
 //---------------------------------------------------
 //-- nsPrintObject Class Impl
 //---------------------------------------------------
 nsPrintObject::nsPrintObject() :
   mContent(nsnull), mFrameType(eFrame), mParent(nsnull),
   mHasBeenPrinted(PR_FALSE), mDontPrint(PR_TRUE), mPrintAsIs(PR_FALSE),
   mSharedPresShell(PR_FALSE), mInvisible(PR_FALSE),
@@ -60,33 +66,59 @@ nsPrintObject::~nsPrintObject()
   }
 
   DestroyPresentation();
 }
 
 //------------------------------------------------------------------
 // Resets PO by destroying the presentation
 nsresult 
-nsPrintObject::Init(nsIDocShell* aDocShell)
+nsPrintObject::Init(nsIDocShell* aDocShell, nsIDOMDocument* aDoc,
+                    PRBool aPrintPreview)
 {
-  mDocShell = aDocShell;
+  mPrintPreview = aPrintPreview;
+
+  if (mPrintPreview || mParent) {
+    mDocShell = aDocShell;
+  } else {
+    nsCOMPtr<nsIDocShellTreeOwner> owner = do_GetInterface(aDocShell);
+    nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(aDocShell);
+    PRInt32 itemType = 0;
+    item->GetItemType(&itemType);
+    // Create a container docshell for printing.
+    mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
+    NS_ENSURE_TRUE(mDocShell, NS_ERROR_OUT_OF_MEMORY);
+    nsCOMPtr<nsIDocShellTreeItem> newItem = do_QueryInterface(mDocShell);
+    newItem->SetItemType(itemType);
+    newItem->SetTreeOwner(owner);
+  }
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
-  
-  nsresult rv;
+
+  nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(mDocShell);
   nsCOMPtr<nsIContentViewer> viewer;
-  rv = mDocShell->GetContentViewer(getter_AddRefs(viewer));
-  NS_ENSURE_SUCCESS(rv, rv);
-  
-  nsCOMPtr<nsIDOMDocument> doc;
-  viewer->GetDOMDocument(getter_AddRefs(doc));
-  NS_ENSURE_SUCCESS(rv, rv);
-  
-  mDocument = do_QueryInterface(doc);
-  NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
+  mDocShell->GetContentViewer(getter_AddRefs(viewer));
+  NS_ENSURE_STATE(viewer);
 
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
+  NS_ENSURE_STATE(doc);
+
+  if (mParent) {
+    nsCOMPtr<nsPIDOMWindow> window = doc->GetWindow();
+    if (window) {
+      mContent = do_QueryInterface(window->GetFrameElementInternal());
+    }
+    mDocument = doc;
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIDocument> clonedDoc = doc->CloneForPrint(mDocShell);
+  nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
+
+  mDocument = clonedDoc;
+  viewer->SetDOMDocument(clonedDOMDoc);
   return NS_OK;
 }
 
 //------------------------------------------------------------------
 // Resets PO by destroying the presentation
 void 
 nsPrintObject::DestroyPresentation()
 {
diff --git a/layout/printing/nsPrintObject.h b/layout/printing/nsPrintObject.h
--- a/layout/printing/nsPrintObject.h
+++ b/layout/printing/nsPrintObject.h
@@ -57,41 +57,42 @@ enum PrintObjectType  {eDoc = 0, eFrame 
 class nsPrintObject
 {
 
 public:
   nsPrintObject();
   ~nsPrintObject(); // non-virtual
 
   // Methods
-  nsresult Init(nsIDocShell* aDocShell);
+  nsresult Init(nsIDocShell* aDocShell, nsIDOMDocument* aDoc,
+                PRBool aPrintPreview);
 
   PRBool IsPrintable()  { return !mDontPrint; }
   void   DestroyPresentation();
 
   // Data Members
   nsCOMPtr<nsIDocShell>    mDocShell;
   nsCOMPtr<nsIDocument>    mDocument;
 
   nsCOMPtr<nsPresContext>  mPresContext;
   nsCOMPtr<nsIPresShell>   mPresShell;
   nsCOMPtr<nsIViewManager> mViewManager;
   nsCOMPtr<nsIWidget>      mWindow;
 
-  nsIContent*      mContent;
+  nsCOMPtr<nsIContent>     mContent;
   PrintObjectType  mFrameType;
   
   nsTArray<nsPrintObject*> mKids;
   nsPrintObject*   mParent;
   PRPackedBool     mHasBeenPrinted;
   PRPackedBool     mDontPrint;
   PRPackedBool     mPrintAsIs;
   PRPackedBool     mSharedPresShell;
   PRPackedBool     mInvisible;        // Indicates PO is set to not visible by CSS
-
+  PRPackedBool     mPrintPreview;
   float            mShrinkRatio;
   float            mZoomRatio;
 
 private:
   nsPrintObject& operator=(const nsPrintObject& aOther); // not implemented
 
 };
 
diff --git a/layout/svg/base/src/nsSVGGlyphFrame.cpp b/layout/svg/base/src/nsSVGGlyphFrame.cpp
--- a/layout/svg/base/src/nsSVGGlyphFrame.cpp
+++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp
@@ -49,17 +49,16 @@
 #include "nsSVGPathElement.h"
 #include "nsSVGPoint.h"
 #include "nsSVGRect.h"
 #include "nsDOMError.h"
 #include "gfxContext.h"
 #include "gfxMatrix.h"
 #include "gfxPlatform.h"
 #include "gfxTextRunWordCache.h"
-#include "nsTextFrame.h"
 
 struct CharacterPosition {
   gfxPoint pos;
   gfxFloat angle;
   PRBool draw;
 };
   
 /**
@@ -295,20 +294,16 @@ nsSVGGlyphFrame::Init(nsIContent* aConte
   nsSVGTextContainerFrame *metrics = do_QueryFrame(ancestorFrame);
   NS_ASSERTION(metrics,
                "trying to construct an SVGGlyphFrame for an invalid container");
 
   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
                "trying to construct an SVGGlyphFrame for wrong content element");
 #endif /* DEBUG */
 
-  if (!PresContext()->IsDynamic()) {
-    AddStateBits(NS_STATE_SVG_PRINTING);
-  }
-
   return nsSVGGlyphFrameBase::Init(aContent, aParent, aPrevInFlow);
 }
 
 nsIAtom *
 nsSVGGlyphFrame::GetType() const
 {
   return nsGkAtoms::svgGlyphFrame;
 }
@@ -635,17 +630,17 @@ nsSVGGlyphFrame::GetCanvasTM()
 
 //----------------------------------------------------------------------
 // nsSVGGlyphFrame methods:
 
 PRBool
 nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
 {
   nsAutoString characterData;
-  GetFragment()->AppendTo(characterData);
+  mContent->AppendTextTo(characterData);
 
   if (mWhitespaceHandling & COMPRESS_WHITESPACE) {
     PRBool trimLeadingWhitespace, trimTrailingWhitespace;
     trimLeadingWhitespace = ((mWhitespaceHandling & TRIM_LEADING_WHITESPACE) != 0);
     trimTrailingWhitespace = ((mWhitespaceHandling & TRIM_TRAILING_WHITESPACE) != 0);
     characterData.CompressWhitespace(trimLeadingWhitespace, 
                                      trimTrailingWhitespace);
   } else {
@@ -839,17 +834,17 @@ nsSVGGlyphFrame::GetHighlight(PRUint32 *
     NS_ERROR("nsSVGGlyphFrame::GetHighlight() called by renderer when there is no highlight");
     return NS_ERROR_FAILURE;
   }
 
   nsPresContext *presContext = PresContext();
 
   // The selection ranges are relative to the uncompressed text in
   // the content element. We'll need the text fragment:
-  const nsTextFragment* fragment = GetFragment();
+  const nsTextFragment *fragment = mContent->GetText();
   NS_ASSERTION(fragment, "no text");
   
   // get the selection details 
   SelectionDetails *details = nsnull;
   {
     nsCOMPtr<nsFrameSelection> frameSelection;
     {
       nsCOMPtr<nsISelectionController> controller;
@@ -1120,17 +1115,17 @@ nsSVGGlyphFrame::IsAbsolutelyPositioned(
 
 //----------------------------------------------------------------------
 // nsISVGGlyphFragmentNode interface:
 
 PRUint32
 nsSVGGlyphFrame::GetNumberOfChars()
 {
   if (mWhitespaceHandling == PRESERVE_WHITESPACE)
-    return GetFragment()->GetLength();
+    return mContent->TextLength();
 
   nsAutoString text;
   GetCharacterData(text);
   return text.Length();
 }
 
 float
 nsSVGGlyphFrame::GetComputedTextLength()
diff --git a/layout/svg/base/src/nsSVGGlyphFrame.h b/layout/svg/base/src/nsSVGGlyphFrame.h
--- a/layout/svg/base/src/nsSVGGlyphFrame.h
+++ b/layout/svg/base/src/nsSVGGlyphFrame.h
@@ -207,21 +207,16 @@ protected:
   void NotifyGlyphMetricsChange();
   PRBool ContainsPoint(const nsPoint &aPoint);
   PRBool GetGlobalTransform(gfxMatrix *aMatrix);
   void SetupGlobalTransform(gfxContext *aContext);
   nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
                         nscolor *foreground, nscolor *background);
   float GetSubStringAdvance(PRUint32 charnum, PRUint32 fragmentChars);
   gfxFloat GetBaselineOffset(PRBool aForceGlobalTransform);
-  const nsTextFragment* GetFragment() const
-  {
-    return !(GetStateBits() & NS_STATE_SVG_PRINTING) ?
-      mContent->GetText() : nsLayoutUtils::GetTextFragmentForPrinting(this);
-  }
 
   // Used to support GetBBoxContribution by making GetConvasTM use this as the
   // parent transform instead of the real CanvasTM.
   nsCOMPtr<nsIDOMSVGMatrix> mOverrideCanvasTM;
 
   // Owning pointer, must call gfxTextRunWordCache::RemoveTextRun before deleting
   gfxTextRun *mTextRun;
   gfxPoint mPosition;
diff --git a/layout/svg/base/src/nsSVGUtils.h b/layout/svg/base/src/nsSVGUtils.h
--- a/layout/svg/base/src/nsSVGUtils.h
+++ b/layout/svg/base/src/nsSVGUtils.h
@@ -89,19 +89,16 @@ class nsSVGDisplayContainerFrame;
 
 #define NS_STATE_SVG_DIRTY            0x00200000
 
 /* are we the child of a non-display container? */
 #define NS_STATE_SVG_NONDISPLAY_CHILD 0x00400000
 
 #define NS_STATE_SVG_PROPAGATE_TRANSFORM 0x00800000
 
-// nsSVGGlyphFrame uses this when the frame is within a non-dynamic PresContext.
-#define NS_STATE_SVG_PRINTING 0x01000000
-
 /**
  * Byte offsets of channels in a native packed gfxColor or cairo image surface.
  */
 #ifdef IS_BIG_ENDIAN
 #define GFX_ARGB32_OFFSET_A 0
 #define GFX_ARGB32_OFFSET_R 1
 #define GFX_ARGB32_OFFSET_G 2
 #define GFX_ARGB32_OFFSET_B 3
diff --git a/toolkit/components/printing/content/printPreviewBindings.xml b/toolkit/components/printing/content/printPreviewBindings.xml
--- a/toolkit/components/printing/content/printPreviewBindings.xml
+++ b/toolkit/components/printing/content/printPreviewBindings.xml
@@ -158,17 +158,17 @@
       </field>
       <field name="mPrintPreviewObs">
       </field>
       <field name="mWebProgress">
       </field>
      
       <constructor>
       <![CDATA[
-        var print = PrintUtils.getWebBrowserPrint();
+        var print = PrintUtils.getPrintPreview();
         this.mTotalPages.value = print.printPreviewNumPages;
 
         this.updateToolbar();
 
         // Hide the ``Print...'' button when the underlying gfx code does not
         // support multiple devicecontext to be used concurrently
         // (e.g. printing and printpreview at the same time; required as 
         // legacy support for unices.'s PostScript module
@@ -232,17 +232,17 @@
       </method>
 
       <method name="navigate">
         <parameter name="aDirection"/>
         <parameter name="aPageNum"/>
         <parameter name="aHomeOrEnd"/>
         <body>
         <![CDATA[          
-          var print = PrintUtils.getWebBrowserPrint();
+          var print = PrintUtils.getPrintPreview();
           var validInput = false;
           var total;
 
           // we use only one of aHomeOrEnd, aDirection, or aPageNum
           if (aHomeOrEnd)
           {
             var homeOrEnd;
             if (aHomeOrEnd == "home")
@@ -395,17 +395,17 @@
           }
         ]]>
         </body>
       </method>
 
       <method name="updateToolbar">
         <body>
         <![CDATA[
-          var print = PrintUtils.getWebBrowserPrint();
+          var print = PrintUtils.getPrintPreview();
           var settings = PrintUtils.getPrintSettings();
 
           var isPortrait = settings.orientation == Components.interfaces.nsIPrintSettings.kPortraitOrientation;
 
           this.mPortaitButton.checked = isPortrait;
           this.mLandscapeButton.checked = !isPortrait;
 
           if (settings.shrinkToFit) {
diff --git a/toolkit/components/printing/content/printUtils.js b/toolkit/components/printing/content/printUtils.js
--- a/toolkit/components/printing/content/printUtils.js
+++ b/toolkit/components/printing/content/printUtils.js
@@ -132,29 +132,38 @@ var PrintUtils = {
         var webNav = getWebNavigation();
         ppParams.value.docTitle = webNav.document.title;
         ppParams.value.docURL   = webNav.currentURI.spec;
       }
 
       // this tells us whether we should continue on with PP or 
       // wait for the callback via the observer
       if (!notifyOnOpen.value.valueOf() || this._webProgressPP.value == null)
-        this.enterPrintPreview();
+        this.enterPrintPreview(aWindow);
     } catch (e) {
-      this.enterPrintPreview();
+      this.enterPrintPreview(aWindow);
     }
   },
 
   getWebBrowserPrint: function (aWindow)
   {
     var contentWindow = aWindow || window.content;
     return contentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                         .getInterface(Components.interfaces.nsIWebBrowserPrint);
   },
 
+  getPrintPreview: function() {
+    if (this._printPreviewTab) {
+      var ppWindow =
+        getPPBrowser().getBrowserForTab(this._printPreviewTab).contentWindow;
+      return this.getWebBrowserPrint(ppWindow);
+    }
+    return null;
+  },
+
   ////////////////////////////////////////
   // "private" methods. Don't use them. //
   ////////////////////////////////////////
 
   setPrinterDefaultsForSelectedPrinter: function (aPSSVC, aPrintSettings)
   {
     if (!aPrintSettings.printerName)
       aPrintSettings.printerName = aPSSVC.defaultPrinterName;
@@ -209,38 +218,67 @@ var PrintUtils = {
       if (iid.equals(Components.interfaces.nsIObserver) ||
           iid.equals(Components.interfaces.nsISupportsWeakReference) ||
           iid.equals(Components.interfaces.nsISupports))
         return this;   
       throw Components.results.NS_NOINTERFACE;
     }
   },
 
+  _originalTab: null,
+  _printPreviewTab: null,
+
   enterPrintPreview: function (aWindow)
   {
     gFocusedElement = document.commandDispatcher.focusedElement;
 
-    var webBrowserPrint = this.getWebBrowserPrint(aWindow);
-    var printSettings   = this.getPrintSettings();
+    var webBrowserPrint;
+    var printSettings  = this.getPrintSettings();
+    var tabbrowser = getPPBrowser();
+    var targetWindow = null;
+    var contentWindow = null;
+    if (tabbrowser) {
+      if (this._printPreviewTab) {
+        targetWindow =
+          tabbrowser.getBrowserForTab(this._printPreviewTab).contentWindow;
+        contentWindow = targetWindow;
+      } else {
+        this._originalTab = tabbrowser.mCurrentTab;
+        contentWindow = aWindow || window.content
+        this._printPreviewTab = tabbrowser.loadOneTab("about:blank", null, null,
+                                                      null, true, false);
+        var targetBrowser = tabbrowser.getBrowserForTab(this._printPreviewTab);
+        targetBrowser.stop();
+        targetWindow = targetBrowser.contentWindow;
+      }
+    }
+
     try {
-      webBrowserPrint.printPreview(printSettings, null, this._webProgressPP.value);
+      webBrowserPrint = this.getWebBrowserPrint(targetWindow);
+      webBrowserPrint.printPreview(printSettings, contentWindow,
+                                  this._webProgressPP.value);
     } catch (e) {
+      this._printPreviewTab = null;
+      this._originalTab = null;
       // Pressing cancel is expressed as an NS_ERROR_ABORT return value,
       // causing an exception to be thrown which we catch here.
       // Unfortunately this will also consume helpful failures, so add a
       // dump(e); // if you need to debug
       return;
     }
 
     var printPreviewTB = document.getElementById("print-preview-toolbar");
     if (printPreviewTB) {
       printPreviewTB.updateToolbar();
       var browser = getPPBrowser();
       if (browser)
         browser.collapsed = false;
+
+      tabbrowser.getBrowserForTab(this._printPreviewTab).contentWindow.focus();
+      tabbrowser.selectedTab = this._printPreviewTab;
       return;
     }
 
     // show the toolbar after we go into print preview mode so
     // that we can initialize the toolbar with total num pages
     var XUL_NS =
       "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
     printPreviewTB = document.createElementNS(XUL_NS, "toolbar");
@@ -254,19 +292,19 @@ var PrintUtils = {
     if (document.documentElement.hasAttribute("onclose"))
       this._closeHandlerPP = document.documentElement.getAttribute("onclose");
     else
       this._closeHandlerPP = null;
     document.documentElement.setAttribute("onclose", "PrintUtils.exitPrintPreview(); return false;");
 
     // disable chrome shortcuts...
     window.addEventListener("keypress", this.onKeyPressPP, true);
- 
-    var contentWindow = aWindow || window.content;
-    contentWindow.focus();
+
+    tabbrowser.getBrowserForTab(this._printPreviewTab).contentWindow.focus();
+    tabbrowser.selectedTab = this._printPreviewTab;
 
     // on Enter PP Call back
     if (this._onEnterPP) {
       this._onEnterPP();
       this._onEnterPP = null;
     }
   },
 
@@ -276,16 +314,24 @@ var PrintUtils = {
 
     // restore the old close handler
     document.documentElement.setAttribute("onclose", this._closeHandlerPP);
     this._closeHandlerPP = null;
 
     var webBrowserPrint = this.getWebBrowserPrint(aWindow);
     webBrowserPrint.exitPrintPreview(); 
 
+    var tabbrowser = getPPBrowser();
+    if (tabbrowser) {
+      tabbrowser.removeTab(this._printPreviewTab);
+      tabbrowser.selectedTab = this._originalTab;
+      this._originalTab = null;
+      this._printPreviewTab = null;
+    }
+
     // remove the print preview toolbar
     var printPreviewTB = document.getElementById("print-preview-toolbar");
     getNavToolbox().parentNode.removeChild(printPreviewTB);
 
     var fm = Components.classes["@mozilla.org/focus-manager;1"]
                        .getService(Components.interfaces.nsIFocusManager);
     if (gFocusedElement)
       fm.setFocus(gFocusedElement, fm.FLAG_NOSCROLL);
