Bug 487667 - Clone documents for printing, r=roc+jst+joe+dbaron
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Thu, 10 Dec 2009 20:02:13 -0800
changeset 35581 180966423a3c8f87a1af9ff894a4c22d5d35e106
parent 35580 b06d6479f8a4d7be44d715795a2859a7dc41d830
child 35582 5fc28d369d566df854d3f5bfcf164962e8d40301
push idunknown
push userunknown
push dateunknown
reviewersroc
bugs487667
milestone1.9.3a1pre
Bug 487667 - Clone documents for printing, r=roc+jst+joe+dbaron
content/base/public/nsContentUtils.h
content/base/public/nsIDocument.h
content/base/public/nsIObjectLoadingContent.idl
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsGkAtomList.h
content/base/src/nsImageLoadingContent.cpp
content/base/src/nsImageLoadingContent.h
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsObjectLoadingContent.h
content/base/src/nsStyledElement.cpp
content/html/content/public/nsHTMLMediaElement.h
content/html/content/src/Makefile.in
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsHTMLCanvasElement.cpp
content/html/content/src/nsHTMLImageElement.cpp
content/html/content/src/nsHTMLInputElement.cpp
content/html/content/src/nsHTMLMediaElement.cpp
content/html/content/src/nsHTMLObjectElement.cpp
content/html/content/src/nsHTMLOptionElement.cpp
content/html/content/src/nsHTMLSharedObjectElement.cpp
content/html/content/src/nsHTMLTextAreaElement.cpp
content/svg/content/src/nsSVGImageElement.cpp
content/svg/content/src/nsSVGImageElement.h
content/svg/document/src/nsSVGDocument.cpp
content/svg/document/src/nsSVGDocument.h
docshell/base/Makefile.in
docshell/base/nsDocShell.cpp
docshell/base/nsIDocShell.idl
embedding/browser/webBrowser/nsIWebBrowserPrint.idl
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsDocumentViewer.cpp
layout/base/nsIDocumentViewerPrint.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsPresShell.cpp
layout/base/tests/chrome/bug396024_helper.xul
layout/base/tests/chrome/bug482976_helper.xul
layout/base/tests/chrome/printpreview_helper.xul
layout/generic/nsBlockFrame.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsTextFrame.h
layout/generic/nsTextFrameThebes.cpp
layout/generic/nsVideoFrame.h
layout/printing/nsPrintEngine.cpp
layout/printing/nsPrintEngine.h
layout/printing/nsPrintObject.cpp
layout/printing/nsPrintObject.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.h
layout/svg/base/src/nsSVGGlyphFrame.cpp
layout/svg/base/src/nsSVGGlyphFrame.h
layout/svg/base/src/nsSVGUtils.h
layout/xul/base/src/nsImageBoxFrame.cpp
layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
modules/libpr0n/public/imgIRequest.idl
modules/libpr0n/src/Makefile.in
modules/libpr0n/src/imgContainerRequest.cpp
modules/libpr0n/src/imgContainerRequest.h
modules/libpr0n/src/imgRequest.cpp
modules/libpr0n/src/imgRequest.h
modules/libpr0n/src/imgRequestProxy.cpp
toolkit/components/printing/content/printPreviewBindings.xml
toolkit/components/printing/content/printUtils.js
widget/src/windows/nsDeviceContextSpecWin.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -666,16 +666,21 @@ public:
    *
    * @param aContent The image loading content.  Must not be null.
    * @param aRequest The image request [out]
    * @return the imgIContainer corresponding to the first frame of the image
    */
   static already_AddRefed<imgIContainer> GetImageFromContent(nsIImageLoadingContent* aContent, imgIRequest **aRequest = nsnull);
 
   /**
+   * Helper method to call imgIRequest::GetStaticRequest.
+   */
+  static already_AddRefed<imgIRequest> GetStaticRequest(imgIRequest* aRequest);
+
+  /**
    * Method that decides whether a content node is draggable
    *
    * @param aContent The content node to test.
    * @return whether it's draggable
    */
   static PRBool ContentIsDraggable(nsIContent* aContent);
 
   /**
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1155,16 +1155,35 @@ public:
    */
   virtual void UnsuppressEventHandlingAndFireEvents(PRBool aFireEvents) = 0;
 
   PRUint32 EventHandlingSuppressed() const { return mEventsSuppressed; }
 
   PRBool IsDNSPrefetchAllowed() const { return mAllowDNSPrefetch; }
 
   /**
+   * PR_TRUE when this document is a static clone of a normal document.
+   * For example print preview and printing use static documents.
+   */
+  PRBool IsStaticDocument() { return mIsStaticDocument; }
+
+  /**
+   * Clones the document and subdocuments and stylesheet etc.
+   * @param aCloneContainer The container for the clone document.
+   */
+  virtual already_AddRefed<nsIDocument>
+  CreateStaticClone(nsISupports* aCloneContainer);
+
+  /**
+   * If this document is a static clone, this returns the original
+   * document.
+   */
+  nsIDocument* GetOriginalDocument() { return mOriginalDocument; }
+
+  /**
    * Called by nsParser to preload images. Can be removed and code moved
    * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
    * parser-module is linked with gklayout-module.
    */
   virtual void MaybePreLoadImage(nsIURI* uri) = 0;
 
   /**
    * Returns true if the locale used for the document specifies a direction of
@@ -1303,16 +1322,26 @@ protected:
   // (it may still be displayed, but in zombie state). Form control data
   // has been saved.
   PRPackedBool mRemovedFromDocShell;
 
   // 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;
   
+  // True when this document is a static clone of a normal document
+  PRPackedBool mIsStaticDocument;
+
+  // True while this document is being cloned to a static document.
+  PRPackedBool mCreatingStaticClone;
+
+  // If mIsStaticDocument is true, mOriginalDocument points to the original
+  // document.
+  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
--- a/content/base/public/nsIObjectLoadingContent.idl
+++ b/content/base/public/nsIObjectLoadingContent.idl
@@ -32,25 +32,26 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
+interface nsIFrame;
 interface nsIObjectFrame;
 interface nsIPluginInstance;
 interface nsIDOMElement;
 interface nsIDOMClientRect;
 
 /**
  * This interface represents a content node that loads objects.
  */
-[scriptable, uuid(8afe3b08-293c-48bd-a997-321745478611)]
+[scriptable, uuid(7749d965-92f3-473e-b12d-de1e342acf1c)]
 interface nsIObjectLoadingContent : nsISupports
 {
   const unsigned long TYPE_LOADING  = 0;
   const unsigned long TYPE_IMAGE    = 1;
   const unsigned long TYPE_PLUGIN   = 2;
   const unsigned long TYPE_DOCUMENT = 3;
   const unsigned long TYPE_NULL     = 4;
 
@@ -110,9 +111,17 @@ interface nsIObjectLoadingContent : nsIS
 
   /**
    * Tells the object to paint directly in this location ignoring any
    * positioning information that may have been provided otherwise
    */
   void setAbsoluteScreenPosition(in nsIDOMElement element,
                                  in nsIDOMClientRect position,
                                  in nsIDOMClientRect clip);
+
+  /**
+   * If this object is in going to be printed, this method
+   * returns the nsIObjectFrame object which should be used when
+   * printing the plugin. The returned nsIFrame is in the original document,
+   * not in the static clone.
+   */
+  [noscript] nsIFrame getPrintFrame();
 };
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2499,16 +2499,26 @@ nsContentUtils::GetImageFromContent(nsII
 
   if (aRequest) {
     imgRequest.swap(*aRequest);
   }
 
   return imgContainer.forget();
 }
 
+//static
+already_AddRefed<imgIRequest>
+nsContentUtils::GetStaticRequest(imgIRequest* aRequest)
+{
+  NS_ENSURE_TRUE(aRequest, nsnull);
+  nsCOMPtr<imgIRequest> retval;
+  aRequest->GetStaticRequest(getter_AddRefs(retval));
+  return retval.forget();
+}
+
 // static
 PRBool
 nsContentUtils::ContentIsDraggable(nsIContent* aContent)
 {
   nsCOMPtr<nsIDOMNSHTMLElement> htmlElement = do_QueryInterface(aContent);
   if (htmlElement) {
     PRBool draggable = PR_FALSE;
     htmlElement->GetDraggable(&draggable);
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3055,16 +3055,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)
 {
@@ -7582,26 +7585,43 @@ nsDocument::QuerySelectorAll(const nsASt
                              nsIDOMNodeList **aReturn)
 {
   return nsGenericElement::doQuerySelectorAll(this, aSelector, aReturn);
 }
 
 nsresult
 nsDocument::CloneDocHelper(nsDocument* clone) const
 {
+  clone->mIsStaticDocument = mCreatingStaticClone;
+
   // 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 (mCreatingStaticClone) {
+    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
@@ -7816,8 +7836,72 @@ void
 nsIDocument::EnumerateFreezableElements(FreezableElementEnumerator aEnumerator,
                                         void* aData)
 {
   if (!mFreezableElements)
     return;
   EnumerateFreezablesData data = { aEnumerator, aData };
   mFreezableElements->EnumerateEntries(EnumerateFreezables, &data);
 }
+
+already_AddRefed<nsIDocument>
+nsIDocument::CreateStaticClone(nsISupports* aCloneContainer)
+{
+  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(this);
+  NS_ENSURE_TRUE(domDoc, nsnull);
+  mCreatingStaticClone = PR_TRUE;
+
+  // Make document 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);
+            }
+          }
+        }
+      }
+    }
+  }
+  mCreatingStaticClone = PR_FALSE;
+  return clonedDoc.forget();
+}
+
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -82,16 +82,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)
   {
   }
@@ -133,19 +135,21 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 nsFrameLoader*
 nsFrameLoader::Create(nsIContent* aOwner)
 {
   NS_ENSURE_TRUE(aOwner, nsnull);
-  nsIDocument* doc = aOwner->GetCurrentDoc();
+  nsIDocument* doc = aOwner->GetOwnerDoc();
   NS_ENSURE_TRUE(doc && !doc->GetDisplayDocument() &&
-                 !doc->IsLoadedAsData(), nsnull);
+                 ((!doc->IsLoadedAsData() && aOwner->GetCurrentDoc()) ||
+                   doc->IsStaticDocument()),
+                 nsnull);
 
   return new nsFrameLoader(aOwner);
 }
 
 NS_IMETHODIMP
 nsFrameLoader::LoadFrame()
 {
   NS_ENSURE_TRUE(mOwnerContent, NS_ERROR_NOT_INITIALIZED);
@@ -155,17 +159,17 @@ nsFrameLoader::LoadFrame()
 
   src.Trim(" \t\n\r");
 
   if (src.IsEmpty()) {
     src.AssignLiteral("about:blank");
   }
 
   nsIDocument* doc = mOwnerContent->GetOwnerDoc();
-  if (!doc) {
+  if (!doc || doc->IsStaticDocument()) {
     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;
@@ -905,28 +909,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->IsStaticDocument() || 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);
@@ -1118,8 +1123,33 @@ nsFrameLoader::CheckForRecursiveLoad(nsI
     }
     nsCOMPtr<nsIDocShellTreeItem> temp;
     temp.swap(parentAsItem);
     temp->GetSameTypeParent(getter_AddRefs(parentAsItem));
   }
 
   return NS_OK;
 }
+
+nsresult
+nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest)
+{
+  nsFrameLoader* dest = static_cast<nsFrameLoader*>(aDest);
+  dest->EnsureDocShell();
+  NS_ENSURE_STATE(dest->mDocShell);
+
+  nsCOMPtr<nsIDOMDocument> dummy = do_GetInterface(dest->mDocShell);
+  nsCOMPtr<nsIContentViewer> viewer;
+  dest->mDocShell->GetContentViewer(getter_AddRefs(viewer));
+  NS_ENSURE_STATE(viewer);
+
+  nsCOMPtr<nsIDocShell> origDocShell;
+  GetDocShell(getter_AddRefs(origDocShell));
+  nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(origDocShell);
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+  NS_ENSURE_STATE(doc);
+  nsCOMPtr<nsIDocument> clonedDoc = doc->CreateStaticClone(dest->mDocShell);
+  nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
+
+  viewer->SetDOMDocument(clonedDOMDoc);
+  return NS_OK;
+}
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -76,31 +76,35 @@ 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 CreateStaticClone(nsIFrameLoader* aDest);
+
   /**
    * Called from the layout frame associated with this frame loader;
    * this notifies us to hook up with the widget and view.
    */
   bool Show(PRInt32 marginWidth, PRInt32 marginHeight,
             PRInt32 scrollbarPrefX, PRInt32 scrollbarPrefY,
             nsIFrameFrame* frame);
 
   /**
    * Called from the layout frame associated with this frame loader, when
    * the frame is being torn down; this notifies us that out widget and view
    * are going away and we should unhook from them.
    */
   void Hide();
 
+  nsresult CloneForStatic(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:
 
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -196,17 +196,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")
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -982,8 +982,24 @@ nsImageLoadingContent::SetBlockingOnload
       doc->BlockOnload();
     else
       doc->UnblockOnload(PR_FALSE);
 
     // Update our state
     mBlockingOnload = aBlocking;
   }
 }
+
+void
+nsImageLoadingContent::CreateStaticImageClone(nsImageLoadingContent* aDest) const
+{
+  aDest->mCurrentRequest = nsContentUtils::GetStaticRequest(mCurrentRequest);
+  aDest->mForcedImageState = mForcedImageState;
+  aDest->mImageBlockingStatus = mImageBlockingStatus;
+  aDest->mLoadingEnabled = mLoadingEnabled;
+  aDest->mStartingLoad = mStartingLoad;
+  aDest->mIsImageStateForced = mIsImageStateForced;
+  aDest->mLoading = mLoading;
+  aDest->mBroken = mBroken;
+  aDest->mUserDisabled = mUserDisabled;
+  aDest->mSuppressed = mSuppressed;
+}
+
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -242,19 +242,20 @@ private:
   /**
    * Method to fire an event once we know what's going on with the image load.
    *
    * @param aEventType "load" or "error" depending on how things went
    */
   nsresult FireEvent(const nsAString& aEventType);
   class Event;
   friend class Event;
+protected:
+  void CreateStaticImageClone(nsImageLoadingContent* aDest) const;
 
   /* 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
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -807,16 +807,24 @@ nsObjectLoadingContent::EnsureInstantiat
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
 {
   LOG(("OBJLC [%p]: Got frame %p (mInstantiating=%i)\n", this, aFrame,
        mInstantiating));
 
+  nsCOMPtr<nsIContent> thisContent = 
+    do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+  NS_ASSERTION(thisContent, "must be a content");
+  nsIDocument* doc = thisContent->GetOwnerDoc();
+  if (!doc || doc->IsStaticDocument()) {
+    return NS_OK;
+  }
+  
   // "revoke" any existing instantiate event as it likely has out of
   // date data (frame pointer etc).
   mPendingInstantiateEvent = nsnull;
 
   nsCOMPtr<nsIPluginInstance> instance;
   aFrame->GetPluginInstance(*getter_AddRefs(instance));
 
   if (instance) {
@@ -1093,17 +1101,19 @@ nsObjectLoadingContent::LoadObject(nsIUR
       mFinalListener->OnStopRequest(mChannel, nsnull, NS_BINDING_ABORTED);
       mFinalListener = nsnull;
     }
     mChannel = nsnull;
   }
 
   // Security checks
   if (doc->IsLoadedAsData()) {
-    Fallback(PR_FALSE);
+    if (!doc->IsStaticDocument()) {
+      Fallback(PR_FALSE);
+    }
     return NS_OK;
   }
 
   // Can't do security checks without a URI - hopefully the plugin will take
   // care of that
   // Null URIs happen when the URL to load is specified via other means than the
   // data/src attribute, for example via custom <param> elements.
   if (aURI) {
@@ -1871,16 +1881,50 @@ nsObjectLoadingContent::GetPluginDisable
   nsresult rv = host->IsPluginEnabledForType(aContentType.get());
   if (rv == NS_ERROR_PLUGIN_DISABLED)
     return ePluginDisabled;
   if (rv == NS_ERROR_PLUGIN_BLOCKLISTED)
     return ePluginBlocklisted;
   return ePluginUnsupported;
 }
 
+void
+nsObjectLoadingContent::CreateStaticClone(nsObjectLoadingContent* aDest) const
+{
+  nsImageLoadingContent::CreateStaticImageClone(aDest);
+
+  aDest->mType = mType;
+  nsObjectLoadingContent* thisObj = const_cast<nsObjectLoadingContent*>(this);
+  if (thisObj->mPrintFrame.IsAlive()) {
+    aDest->mPrintFrame = thisObj->mPrintFrame;
+  } else {
+    nsIObjectFrame* frame =
+      const_cast<nsObjectLoadingContent*>(this)->GetExistingFrame(eDontFlush);
+    nsIFrame* f = do_QueryFrame(frame);
+    aDest->mPrintFrame = f;
+  }
+
+  if (mFrameLoader) {
+    nsCOMPtr<nsIContent> content =
+      do_QueryInterface(static_cast<nsIImageLoadingContent*>((aDest)));
+    nsFrameLoader* fl = nsFrameLoader::Create(content);
+    if (fl) {
+      aDest->mFrameLoader = fl;
+      mFrameLoader->CreateStaticClone(fl);
+    }
+  }
+}
+
+NS_IMETHODIMP
+nsObjectLoadingContent::GetPrintFrame(nsIFrame** aFrame)
+{
+  *aFrame = mPrintFrame.GetFrame();
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsObjectLoadingContent::SetAbsoluteScreenPosition(nsIDOMElement* element,
                                                   nsIDOMClientRect* position,
                                                   nsIDOMClientRect* clip)
 {
   nsIObjectFrame* frame = GetExistingFrame(eFlushLayout);
   if (!frame)
     return NS_ERROR_NOT_AVAILABLE;
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -48,16 +48,17 @@
 #include "nsImageLoadingContent.h"
 #include "nsIStreamListener.h"
 #include "nsFrameLoader.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIChannelEventSink.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIRunnable.h"
 #include "nsIChannelClassifier.h"
+#include "nsIFrame.h"
 
 class nsAsyncInstantiateEvent;
 class AutoNotifier;
 class AutoFallback;
 class AutoSetInstantiatingToFalse;
 
 enum PluginSupportState {
   ePluginUnsupported,  // The plugin is not supported (not installed, say)
@@ -218,16 +219,17 @@ class nsObjectLoadingContent : public ns
      * document.
      *
      * XXX This is a temporary workaround for docshell suckyness
      */
     void RemovedFromDocument();
 
     void Traverse(nsCycleCollectionTraversalCallback &cb);
 
+    void CreateStaticClone(nsObjectLoadingContent* aDest) const;
   private:
     /**
      * Check whether the given request represents a successful load.
      */
     static PRBool IsSuccessfulRequest(nsIRequest* aRequest);
 
     /**
      * Check whether the URI can be handled internally.
@@ -417,13 +419,15 @@ class nsObjectLoadingContent : public ns
      */
     PRPackedBool                mInstantiating : 1;
     // Blocking status from content policy
     PRPackedBool                mUserDisabled  : 1;
     PRPackedBool                mSuppressed    : 1;
     // A specific state that caused us to fallback
     PluginSupportState          mPluginState;
 
+    nsWeakFrame                 mPrintFrame;
+
     friend class nsAsyncInstantiateEvent;
 };
 
 
 #endif
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -217,17 +217,19 @@ void
 nsStyledElement::ParseStyleAttribute(nsIContent* aContent,
                                      const nsAString& aValue,
                                      nsAttrValue& aResult,
                                      PRBool aForceInDataDoc)
 {
   nsresult result = NS_OK;
   nsIDocument* doc = aContent->GetOwnerDoc();
 
-  if (doc && (aForceInDataDoc || !doc->IsLoadedAsData())) {
+  if (doc && (aForceInDataDoc ||
+              !doc->IsLoadedAsData() ||
+              doc->IsStaticDocument())) {
     PRBool isCSS = PR_TRUE; // assume CSS until proven otherwise
 
     if (!aContent->IsInNativeAnonymousSubtree()) {  // native anonymous content
                                                     // always assumes CSS
       nsAutoString styleType;
       doc->GetHeaderData(nsGkAtoms::headerContentStyleType, styleType);
       if (!styleType.IsEmpty()) {
         static const char textCssStr[] = "text/css";
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -262,18 +262,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
@@ -514,9 +515,11 @@ protected:
   // PR_TRUE if we've played or completed a seek. We use this to determine
   // when the poster frame should be shown.
   PRPackedBool mHasPlayedOrSeeked;
 
   // PR_TRUE if we've added a reference to ourselves to keep the element
   // alive while no-one is referencing it but the element may still fire
   // events of its own accord.
   PRPackedBool mHasSelfReference;
+
+  nsRefPtr<gfxASurface> mPrintSurface;
 };
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -122,13 +122,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
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -2864,16 +2864,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->IsStaticDocument() && mFrameLoader) {
+    nsGenericHTMLFrameElement* dest =
+      static_cast<nsGenericHTMLFrameElement*>(aDest);
+    nsFrameLoader* fl = nsFrameLoader::Create(dest);
+    NS_ENSURE_STATE(fl);
+    dest->mFrameLoader = fl;
+    static_cast<nsFrameLoader*>(mFrameLoader.get())->CreateStaticClone(fl);
+  }
+
+  return rv;
+}
+
 //----------------------------------------------------------------------
 
 nsresult
 nsGenericHTMLElement::Blur()
 {
   if (!ShouldBlur(this))
     return NS_OK;
 
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -912,16 +912,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:
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -53,17 +53,17 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
 
 #include "nsICanvasElement.h"
 #include "nsIRenderingContext.h"
 
 #include "nsICanvasRenderingContextInternal.h"
-
+#include "nsIDOMCanvasRenderingContext2D.h"
 #include "nsLayoutUtils.h"
 
 #define DEFAULT_CANVAS_WIDTH 300
 #define DEFAULT_CANVAS_HEIGHT 150
 
 class nsHTMLCanvasElement : public nsGenericHTMLElement,
                             public nsIDOMHTMLCanvasElement,
                             public nsICanvasElement
@@ -113,17 +113,17 @@ public:
                    const nsAString& aValue, PRBool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
   }
   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            PRBool aNotify);
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
 protected:
   nsIntSize GetWidthHeight();
 
   nsresult UpdateContext();
   nsresult ToDataURLImpl(const nsAString& aMimeType,
                          const nsAString& aEncoderOptions,
                          nsAString& aDataURL);
 
@@ -213,16 +213,34 @@ nsHTMLCanvasElement::SetAttr(PRInt32 aNa
   {
     rv = UpdateContext();
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return rv;
 }
 
+nsresult
+nsHTMLCanvasElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (aDest->GetOwnerDoc()->IsStaticDocument()) {
+    nsHTMLCanvasElement* dest = static_cast<nsHTMLCanvasElement*>(aDest);
+    nsCOMPtr<nsISupports> cxt;
+    dest->GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(cxt));
+    nsCOMPtr<nsIDOMCanvasRenderingContext2D> context2d = do_QueryInterface(cxt);
+    if (context2d) {
+      context2d->DrawImage(const_cast<nsHTMLCanvasElement*>(this),
+                           0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0);
+    }
+  }
+  return rv;
+}
+
 nsChangeHint
 nsHTMLCanvasElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                             PRInt32 aModType) const
 {
   nsChangeHint retval =
     nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
   if (aAttribute == nsGkAtoms::width ||
       aAttribute == nsGkAtoms::height)
--- 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)
@@ -653,9 +655,16 @@ nsHTMLImageElement::GetNaturalWidth(PRIn
   if (!image) {
     return NS_OK;
   }
 
   image->GetWidth(aNaturalWidth);
   return NS_OK;
 }
 
-
+nsresult
+nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  if (aDest->GetOwnerDoc()->IsStaticDocument()) {
+    CreateStaticImageClone(static_cast<nsHTMLImageElement*>(aDest));
+  }
+  return nsGenericHTMLElement::CopyInnerTo(aDest);
+}
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -552,16 +552,21 @@ nsHTMLInputElement::Clone(nsINodeInfo *a
         // We no longer have our original checked state.  Set our
         // checked state on the clone.
         // XXX GetChecked should be const
         PRBool checked;
         const_cast<nsHTMLInputElement*>(this)->GetChecked(&checked);
         it->DoSetChecked(checked, PR_FALSE);
       }
       break;
+    case NS_FORM_INPUT_IMAGE:
+      if (it->GetOwnerDoc()->IsStaticDocument()) {
+        CreateStaticImageClone(it);
+      }
+      break;
     default:
       break;
   }
 
   kungFuDeathGrip.swap(*aResult);
 
   return NS_OK;
 }
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -73,16 +73,18 @@
 #include "nsCommaSeparatedTokenizer.h"
 #include "nsMediaStream.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
 
@@ -1079,17 +1081,18 @@ 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 || !aDocument->IsStaticDocument());
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
                                                  aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   if (NS_SUCCEEDED(rv) &&
       mIsDoneAddingChildren &&
       mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY)
   {
@@ -1706,18 +1709,32 @@ void nsHTMLMediaElement::NotifyAutoplayD
     DispatchAsyncSimpleEvent(NS_LITERAL_STRING("play"));
   }
 }
 
 void nsHTMLMediaElement::Paint(gfxContext* aContext,
                                gfxPattern::GraphicsFilter aFilter,
                                const gfxRect& aRect)
 {
-  if (mDecoder)
+  if (mPrintSurface) {
+    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);
+
+    aContext->NewPath();
+    aContext->PixelSnappedRectangleAndSetPattern(aRect, pat);
+    aContext->Fill();
+  } else if (mDecoder) {
     mDecoder->Paint(aContext, aFilter, aRect);
+  }
 }
 
 nsresult nsHTMLMediaElement::DispatchSimpleEvent(const nsAString& aName)
 {
   LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching simple event %s", this,
                           NS_ConvertUTF16toUTF8(aName).get()));
 
   return nsContentUtils::DispatchTrustedEvent(GetOwnerDoc(),
@@ -1990,8 +2007,41 @@ void nsHTMLMediaElement::ChangeDelayLoad
   AddRemoveSelfReference();
 }
 
 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()->IsStaticDocument()) {
+    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;
+}
--- a/content/html/content/src/nsHTMLObjectElement.cpp
+++ b/content/html/content/src/nsHTMLObjectElement.cpp
@@ -118,16 +118,18 @@ public:
   virtual PRInt32 IntrinsicState() const;
   virtual void DestroyContent();
 
   // nsObjectLoadingContent
   virtual PRUint32 GetCapabilities() const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
+
   void StartObjectLoad() { StartObjectLoad(PR_TRUE); }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLObjectElement,
                                                      nsGenericHTMLFormElement)
 
 private:
   /**
    * Calls LoadObject with the correct arguments to start the plugin load.
@@ -473,8 +475,21 @@ nsHTMLObjectElement::GetCapabilities() c
 }
 
 void
 nsHTMLObjectElement::DestroyContent()
 {
   RemovedFromDocument();
   nsGenericHTMLFormElement::DestroyContent();
 }
+
+nsresult
+nsHTMLObjectElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aDest->GetOwnerDoc()->IsStaticDocument()) {
+    CreateStaticClone(static_cast<nsHTMLObjectElement*>(aDest));
+  }
+
+  return rv;
+}
--- 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();
@@ -523,8 +525,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()->IsStaticDocument()) {
+    PRBool selected = PR_FALSE;
+    const_cast<nsHTMLOptionElement*>(this)->GetSelected(&selected);
+    static_cast<nsHTMLOptionElement*>(aDest)->SetSelected(selected);
+  }
+  return NS_OK;
+}
+
--- a/content/html/content/src/nsHTMLSharedObjectElement.cpp
+++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp
@@ -125,16 +125,18 @@ public:
   virtual PRInt32 IntrinsicState() const;
   virtual void DestroyContent();
 
   // nsObjectLoadingContent
   virtual PRUint32 GetCapabilities() const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
+
   void StartObjectLoad() { StartObjectLoad(PR_TRUE); }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLSharedObjectElement,
                                                      nsGenericHTMLElement)
 
 private:
   /**
    * Calls LoadObject with the correct arguments to start the plugin load.
@@ -455,8 +457,21 @@ nsHTMLSharedObjectElement::GetCapabiliti
 }
 
 void
 nsHTMLSharedObjectElement::DestroyContent()
 {
   RemovedFromDocument();
   nsGenericHTMLElement::DestroyContent();
 }
+
+nsresult
+nsHTMLSharedObjectElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aDest->GetOwnerDoc()->IsStaticDocument()) {
+    CreateStaticClone(static_cast<nsHTMLSharedObjectElement*>(aDest));
+  }
+
+  return rv;
+}
--- 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()->IsStaticDocument()) {
+    nsAutoString value;
+    const_cast<nsHTMLTextAreaElement*>(this)->GetValue(value);
+    static_cast<nsHTMLTextAreaElement*>(aDest)->SetValue(value);
+  }
+  return NS_OK;
+}
+
--- a/content/svg/content/src/nsSVGImageElement.cpp
+++ b/content/svg/content/src/nsSVGImageElement.cpp
@@ -264,8 +264,17 @@ nsSVGImageElement::GetPreserveAspectRati
 }
 
 nsSVGElement::StringAttributesInfo
 nsSVGImageElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               NS_ARRAY_LENGTH(sStringInfo));
 }
+
+nsresult
+nsSVGImageElement::CopyInnerTo(nsGenericElement* aDest) const
+{
+  if (aDest->GetOwnerDoc()->IsStaticDocument()) {
+    CreateStaticImageClone(static_cast<nsSVGImageElement*>(aDest));
+  }
+  return nsSVGImageElementBase::CopyInnerTo(aDest);
+}
--- a/content/svg/content/src/nsSVGImageElement.h
+++ b/content/svg/content/src/nsSVGImageElement.h
@@ -85,16 +85,18 @@ public:
 
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* name) const;
 
   // nsSVGPathGeometryElement methods:
   virtual void ConstructPath(gfxContext *aCtx);
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
+
   void MaybeLoadSVGImage();
 protected:
   nsresult LoadSVGImage(PRBool aForce, PRBool aNotify);
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual nsSVGPreserveAspectRatio *GetPreserveAspectRatio();
   virtual StringAttributesInfo GetStringInfo();
 
--- a/content/svg/document/src/nsSVGDocument.cpp
+++ b/content/svg/document/src/nsSVGDocument.cpp
@@ -124,16 +124,30 @@ NS_IMETHODIMP
 nsSVGDocument::GetRootElement(nsIDOMSVGSVGElement** aRootElement)
 {
   *aRootElement = nsnull;
   nsIContent* root = GetRootContent();
 
   return root ? CallQueryInterface(root, aRootElement) : NS_OK;
 }
 
+nsresult
+nsSVGDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
+{
+  NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
+               "Can't import this document into another document!");
+
+  nsRefPtr<nsSVGDocument> clone = new nsSVGDocument();
+  NS_ENSURE_TRUE(clone, NS_ERROR_OUT_OF_MEMORY);
+  nsresult rv = CloneDocHelper(clone.get());
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return CallQueryInterface(clone.get(), aResult);
+}
+
 ////////////////////////////////////////////////////////////////////////
 // Exported creation functions
 
 nsresult
 NS_NewSVGDocument(nsIDocument** aInstancePtrResult)
 {
   *aInstancePtrResult = nsnull;
   nsSVGDocument* doc = new nsSVGDocument();
--- a/content/svg/document/src/nsSVGDocument.h
+++ b/content/svg/document/src/nsSVGDocument.h
@@ -49,12 +49,12 @@ class nsSVGDocument : public nsXMLDocume
   nsSVGDocument();
   virtual ~nsSVGDocument();
 
   NS_DECL_NSIDOMSVGDOCUMENT
   NS_FORWARD_NSIDOMDOCUMENT(nsXMLDocument::)
   NS_FORWARD_NSIDOMNODE(nsXMLDocument::)
   NS_FORWARD_NSIDOMDOCUMENTEVENT(nsXMLDocument::)
   NS_DECL_ISUPPORTS_INHERITED
-
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 };
 
 #endif
--- a/docshell/base/Makefile.in
+++ b/docshell/base/Makefile.in
@@ -98,9 +98,11 @@ CPPSRCS		= \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
-LOCAL_INCLUDES += -I$(srcdir)/../shistory/src
+LOCAL_INCLUDES += -I$(srcdir)/../shistory/src \
+		-I$(srcdir)/../../layout/base \
+		$(NULL)
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -197,16 +197,21 @@
 #include "nsIEventStateManager.h"
 #endif
 
 #include "nsIFrame.h"
 
 // for embedding
 #include "nsIWebBrowserChromeFocus.h"
 
+#if NS_PRINT_PREVIEW
+#include "nsIDocumentViewerPrint.h"
+#include "nsIWebBrowserPrint.h"
+#endif
+
 #include "nsPluginError.h"
 
 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
                      NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #if defined(DEBUG_bryner) || defined(DEBUG_chb)
 //#define DEBUG_DOCSHELL_FOCUS
@@ -11067,11 +11072,37 @@ nsDocShell::SetRendering(PRBool aRender)
        mContentViewer->SetEnableRendering(aRender);
        return NS_OK;
     }
   }
   //return failer if this request is not accepted due to mCharsetReloadState
   return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
 }
 
+NS_IMETHODIMP
+nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
+{
+  *aPrintPreview = nsnull;
+#if NS_PRINT_PREVIEW
+  nsCOMPtr<nsIDocumentViewerPrint> print = do_QueryInterface(mContentViewer);
+  if (!print || !print->IsInitializedForPrintPreview()) {
+    Stop(nsIWebNavigation::STOP_ALL);
+    nsCOMPtr<nsIPrincipal> principal =
+      do_CreateInstance("@mozilla.org/nullprincipal;1");
+    NS_ENSURE_STATE(principal);
+    nsresult rv = CreateAboutBlankContentViewer(principal, nsnull);
+    NS_ENSURE_SUCCESS(rv, rv);
+    print = do_QueryInterface(mContentViewer);
+    NS_ENSURE_STATE(print);
+    print->InitializeForPrintPreview();
+  }
+  nsCOMPtr<nsIWebBrowserPrint> result = do_QueryInterface(print);
+  result.forget(aPrintPreview);
+  return NS_OK;
+#else
+  return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+
 #ifdef DEBUG
 unsigned long nsDocShell::gNumberOfDocShells = 0;
 #endif
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -63,18 +63,19 @@ interface nsIWebNavigation;
 interface nsISimpleEnumerator;
 interface nsIInputStream;
 interface nsIRequest;
 interface nsISHEntry;
 interface nsILayoutHistoryState;
 interface nsISecureBrowserUI;
 interface nsIDOMStorage;
 interface nsIPrincipal;
+interface nsIWebBrowserPrint;
 
-[scriptable, uuid(8ADFB831-1053-4A19-884D-BCDAD7277B4B)]
+[scriptable, uuid(1067ee1a-08e8-455d-9b12-19eeeee56b8e)]
 interface nsIDocShell : nsISupports
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -483,9 +484,16 @@ interface nsIDocShell : nsISupports
   [noscript, notxpcom] void DetachEditorFromWindow();
 
   /**
    * If true, this browser is not visible in the traditional sense, but
    * is actively being rendered to the screen (ex. painted on a canvas)
    * and should be treated accordingly.
    **/
   attribute boolean isOffScreenBrowser;    
+
+  /**
+   * If the current content viewer isn't initialized for print preview,
+   * it is replaced with one which is and to which an about:blank document
+   * is loaded.
+   */
+  readonly attribute nsIWebBrowserPrint printPreview;
 };
--- 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);
 
   /**
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -11609,18 +11609,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
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -493,17 +493,17 @@ protected:
   PRInt32 mHintCharsetSource;
   nsCString mHintCharset;
   nsCString mDefaultCharacterSet;
   nsCString mForceCharacterSet;
   nsCString mPrevDocCharacterSet;
   
   PRPackedBool mIsPageMode;
   PRPackedBool mCallerIsClosingWindow;
-
+  PRPackedBool mInitializedForPrintPreview;
 };
 
 //------------------------------------------------------------------
 // DocumentViewerImpl
 //------------------------------------------------------------------
 // Class IDs
 static NS_DEFINE_CID(kViewManagerCID,       NS_VIEW_MANAGER_CID);
 static NS_DEFINE_CID(kWidgetCID,            NS_CHILD_CID);
@@ -535,37 +535,37 @@ void DocumentViewerImpl::PrepareToStartL
   mPrintIsPending        = PR_FALSE;
   mPrintDocIsFullyLoaded = PR_FALSE;
   mClosingWhilePrinting  = PR_FALSE;
 
   // Make sure we have destroyed it and cleared the data member
   if (mPrintEngine) {
     mPrintEngine->Destroy();
     mPrintEngine = nsnull;
+#ifdef NS_PRINT_PREVIEW
+    SetIsPrintPreview(PR_FALSE);
+#endif
   }
 
-#ifdef NS_PRINT_PREVIEW
-  SetIsPrintPreview(PR_FALSE);
-#endif
-
 #ifdef NS_DEBUG
   mDebugFile = nsnull;
 #endif
 
 #endif // NS_PRINTING
 }
 
 // Note: operator new zeros our memory, so no need to init things to null.
 DocumentViewerImpl::DocumentViewerImpl()
   : mTextZoom(1.0), mPageZoom(1.0),
     mIsSticky(PR_TRUE),
 #ifdef NS_PRINT_PREVIEW
     mPrintPreviewZoom(1.0),
 #endif
-    mHintCharsetSource(kCharsetUninitialized)
+    mHintCharsetSource(kCharsetUninitialized),
+    mInitializedForPrintPreview(PR_FALSE)
 {
   PrepareToStartLoad();
 }
 
 NS_IMPL_ADDREF(DocumentViewerImpl)
 NS_IMPL_RELEASE(DocumentViewerImpl)
 
 NS_INTERFACE_MAP_BEGIN(DocumentViewerImpl)
@@ -695,16 +695,19 @@ DocumentViewerImpl::Init(nsIWidget* aPar
                          const nsIntRect& aBounds)
 {
   return InitInternal(aParentWidget, nsnull, aBounds, PR_TRUE, PR_FALSE);
 }
 
 nsresult
 DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow, PRBool aReenableRefresh)
 {
+  if (GetIsPrintPreview())
+    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);
 
@@ -1695,24 +1698,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->IsStaticDocument()) {
+      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
@@ -1762,47 +1767,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;
@@ -2006,18 +1993,20 @@ 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)
 {
@@ -2280,18 +2269,20 @@ DocumentViewerImpl::ClearHistoryEntry()
   return NS_OK;
 }
 
 //-------------------------------------------------------
 
 nsresult
 DocumentViewerImpl::MakeWindow(const nsSize& aSize, nsIView* aContainerView)
 {
+  if (GetIsPrintPreview())
+    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))
@@ -3769,16 +3760,20 @@ DocumentViewerImpl::Print(nsIPrintSettin
 }
 
 NS_IMETHODIMP
 DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, 
                                  nsIDOMWindow *aChildDOMWin, 
                                  nsIWebProgressListener* aWebProgressListener)
 {
 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
+  NS_WARN_IF_FALSE(IsInitializedForPrintPreview(),
+                   "Using docshell.printPreview is the preferred way for print previewing!");
+
+  NS_ENSURE_ARG_POINTER(aChildDOMWin);
   nsresult rv = NS_OK;
 
   if (GetIsPrinting()) {
     nsPrintEngine::CloseProgressDialog(aWebProgressListener);
     return NS_ERROR_FAILURE;
   }
 
 #ifdef MOZ_XUL
@@ -3786,35 +3781,33 @@ DocumentViewerImpl::PrintPreview(nsIPrin
   nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
   if (xulDoc) {
     nsPrintEngine::CloseProgressDialog(aWebProgressListener);
     nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL, PR_FALSE);
     return NS_ERROR_FAILURE;
   }
 #endif
 
-  if (!mContainer) {
-    PR_PL(("Container was destroyed yet we are still trying to use it!"));
-    return NS_ERROR_FAILURE;
-  }
-
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mContainer));
   NS_ASSERTION(docShell, "This has to be a docshell");
-  nsCOMPtr<nsIPresShell> presShell;
-  docShell->GetPresShell(getter_AddRefs(presShell));
-  if (!presShell || !mDocument || !mDeviceContext || !mParentWidget) {
-    PR_PL(("Can't Print Preview without pres shell, document etc"));
+  if (!docShell ||! mDeviceContext || !mParentWidget) {
+    PR_PL(("Can't Print Preview without device context, docshell etc"));
     return NS_ERROR_FAILURE;
   }
 
   if (!mPrintEngine) {
+    nsCOMPtr<nsIDOMDocument> domDoc;
+    aChildDOMWin->GetDocument(getter_AddRefs(domDoc));
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+    NS_ENSURE_STATE(doc);
+
     mPrintEngine = new nsPrintEngine();
     NS_ENSURE_TRUE(mPrintEngine, NS_ERROR_OUT_OF_MEMORY);
 
-    rv = mPrintEngine->Initialize(this, docShell, mDocument,
+    rv = mPrintEngine->Initialize(this, docShell, doc,
                                   float(mDeviceContext->AppUnitsPerInch()) /
                                   float(mDeviceContext->AppUnitsPerDevPixel()) /
                                   mPageZoom,
                                   mParentWidget,
 #ifdef NS_DEBUG
                                   mDebugFile
 #else
                                   nsnull
@@ -4219,16 +4212,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
@@ -4251,24 +4250,23 @@ 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);
   SetFullZoom(mPageZoom);
   Show();
 
 #endif // NS_PRINTING && NS_PRINT_PREVIEW
 }
 
 //------------------------------------------------------------
@@ -4330,18 +4328,16 @@ DocumentViewerImpl::OnDonePrinting()
     } else if (mClosingWhilePrinting) {
       if (mDocument) {
         mDocument->SetScriptGlobalObject(nsnull);
         mDocument->Destroy();
         mDocument = nsnull;
       }
       mClosingWhilePrinting = PR_FALSE;
     }
-    if (mPresContext)
-      mPresContext->RestoreImageAnimationMode();
   }
 #endif // NS_PRINTING && NS_PRINT_PREVIEW
 }
 
 NS_IMETHODIMP DocumentViewerImpl::SetPageMode(PRBool aPageMode, nsIPrintSettings* aPrintSettings)
 {
   // XXX Page mode is only partially working; it's currently used for
   // reftests that require a paginated context
@@ -4397,8 +4393,36 @@ DocumentViewerImpl::DestroyPresShell()
   nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(selection);
   if (selPrivate && mSelectionListener)
     selPrivate->RemoveSelectionListener(mSelectionListener);
 
   nsAutoScriptBlocker scriptBlocker;
   mPresShell->Destroy();
   mPresShell = nsnull;
 }
+
+PRBool
+DocumentViewerImpl::IsInitializedForPrintPreview()
+{
+  return mInitializedForPrintPreview;
+}
+
+void
+DocumentViewerImpl::InitializeForPrintPreview()
+{
+  mInitializedForPrintPreview = PR_TRUE;
+}
+
+void
+DocumentViewerImpl::SetPrintPreviewPresentation(nsIWidget* aWidget,
+                                                nsIViewManager* aViewManager,
+                                                nsPresContext* aPresContext,
+                                                nsIPresShell* aPresShell)
+{
+  if (mPresShell) {
+    DestroyPresShell();
+  }
+
+  mWindow = aWidget;
+  mViewManager = aViewManager;
+  mPresContext = aPresContext;
+  mPresShell = aPresShell;
+}
--- 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}
+// {c6f255cf-cadd-4382-b57f-cd2a9874169b}
 #define NS_IDOCUMENT_VIEWER_PRINT_IID \
- { 0xd0b7f354, 0xd575, 0x43fd, { 0x90, 0x3d, 0x5a, 0xa3, 0x5a, 0x19, 0x3e, 0xda } }
+{ 0xc6f255cf, 0xcadd, 0x4382, \
+  { 0xb5, 0x7f, 0xcd, 0x2a, 0x98, 0x74, 0x16, 0x9b } }
 
 /**
  * A DocumentViewerPrint is an INTERNAL Interface used for interaction
  * between the DocumentViewer and the PrintEngine
  */
 class nsIDocumentViewerPrint : public nsISupports
 {
 public:
@@ -67,25 +72,48 @@ public:
   virtual nsresult CreateStyleSet(nsIDocument* aDocument, nsStyleSet** aStyleSet) = 0;
 
   virtual void IncrementDestroyRefCount() = 0;
 
   virtual void ReturnToGalleyPresentation() = 0;
 
   virtual void OnDonePrinting() = 0;
 
+  /**
+   * Returns PR_TRUE is InitializeForPrintPreview() has been called.
+   */
+  virtual PRBool IsInitializedForPrintPreview() = 0;
+
+  /**
+   * Marks this viewer to be used for print preview.
+   */
+  virtual void InitializeForPrintPreview() = 0;
+
+  /**
+   * Replaces the current presentation with print preview presentation.
+   */
+  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 PRBool   IsInitializedForPrintPreview(); \
+  virtual void     InitializeForPrintPreview(); \
+  virtual void     SetPrintPreviewPresentation(nsIWidget* aWidget, \
+                                               nsIViewManager* aViewManager, \
+                                               nsPresContext* aPresContext, \
+                                               nsIPresShell* aPresShell);
 
 #endif /* nsIDocumentViewerPrint_h___ */
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -73,17 +73,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"
 #include "nsClientRect.h"
 #ifdef MOZ_MEDIA
 #include "nsHTMLVideoElement.h"
 #endif
 #include "imgIRequest.h"
@@ -3270,58 +3269,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);
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -62,17 +62,16 @@ class nsClientRectList;
 #include "nsThreadUtils.h"
 #include "nsIPresShell.h"
 #include "nsIPrincipal.h"
 #include "gfxPattern.h"
 #include "imgIContainer.h"
 #include "nsCSSPseudoElements.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
 {
@@ -1059,22 +1058,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 true if aFrame is in an {ib} split and is NOT one of the
    * continuations of the first inline in it.
    */
   static PRBool FrameIsNonFirstInIBSplit(const nsIFrame* aFrame) {
     return (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
       aFrame->GetFirstContinuation()->
         GetProperty(nsGkAtoms::IBSplitSpecialPrevSibling);
   }
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1224,17 +1224,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);
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -98,16 +98,17 @@ class nsIAtom;
 struct nsStyleBackground;
 struct nsStyleBorder;
 class nsIRunnable;
 class gfxUserFontSet;
 class nsUserFontSet;
 struct nsFontFaceRuleContainer;
 class nsObjectFrame;
 class nsTransitionManager;
+class imgIContainer;
 
 #ifdef MOZ_REFLOW_PERF
 class nsIRenderingContext;
 #endif
 
 enum nsWidgetType {
   eWidgetType_Button  	= 1,
   eWidgetType_Checkbox	= 2,
@@ -273,17 +274,16 @@ public:
    * Notify the context that the document's compatibility mode has changed
    */
   NS_HIDDEN_(void) CompatibilityModeChanged();
 
   /**
    * Access the image animation mode for this context
    */
   PRUint16     ImageAnimationMode() const { return mImageAnimationMode; }
-  void RestoreImageAnimationMode() { SetImageAnimationMode(mImageAnimationModePref); }
   virtual NS_HIDDEN_(void) SetImageAnimationModeExternal(PRUint16 aMode);
   NS_HIDDEN_(void) SetImageAnimationModeInternal(PRUint16 aMode);
 #ifdef _IMPL_NS_LAYOUT
   void SetImageAnimationMode(PRUint16 aMode)
   { SetImageAnimationModeInternal(aMode); }
 #else
   void SetImageAnimationMode(PRUint16 aMode)
   { SetImageAnimationModeExternal(aMode); }
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1218,19 +1218,16 @@ protected:
   PRBool PostReflowEventOffTimer();
   
 #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,
@@ -1335,132 +1332,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)
-  {
-    if (AllowMutation(aContent)) {
-      mBaseObserver->AttributeChanged(aDocument, aContent, aNameSpaceID,
-                                      aAttribute, aModType);
-    }
-  }
-  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->IsXUL()) {
-           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
@@ -2527,24 +2408,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;
 }
@@ -2552,20 +2426,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
 
@@ -3619,20 +3490,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.
@@ -5154,19 +5021,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;
 }
--- a/layout/base/tests/chrome/bug396024_helper.xul
+++ b/layout/base/tests/chrome/bug396024_helper.xul
@@ -3,24 +3,25 @@
 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
                  type="text/css"?>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=396024
 -->
 <window title="Mozilla Bug 396024" onload="run()"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 <iframe src="data:text/html;charset=utf-8,&lt;body onload='window.parent.loadedChild()'&gt;"></iframe>
+<iframe src="about:blank"/>
 <script type="application/javascript">
 <![CDATA[
 var is = window.opener.wrappedJSObject.is;
 var ok = window.opener.wrappedJSObject.ok;
 var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
 var gWbp;
 function printpreview() {
-  gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+  gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
              .getInterface(Components.interfaces.nsIWebBrowserPrint);
   var listener = {
     onLocationChange: function(webProgress, request, location) { },
     onProgressChange: function(webProgress, request, curSelfProgress, 
                                maxSelfProgress, curTotalProgress,
                                maxTotalProgress) { },
     onSecurityChange: function(webProgress, request, state) { },
     onStateChange: function(webProgress, request, stateFlags, status) { },
@@ -32,22 +33,22 @@ function printpreview() {
       throw Components.results.NS_NOINTERFACE;
     }
   }
   var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                             .getService(Components.interfaces.nsIPrefBranch);
   prefs.setBoolPref('print.show_print_progress', false);
   //XXX I would have thought this would work, instead I'm forced to use prefs service
   gWbp.globalPrintSettings.showPrintProgress = false; 
-  gWbp.printPreview(gWbp.globalPrintSettings, null, listener);
+  gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
   prefs.clearUserPref('print.show_print_progress');
 }
 
 function exitprintpreview() {
-  window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+  window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
    .getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview(); 
 }
 
 function run()
 {
 /** Test for Bug 396024 **/
   var printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
                                .getService(Components.interfaces.nsIPrintSettingsService);
@@ -75,32 +76,32 @@ function run()
 }
 
 function run2() {
   window.loadedChild = function() { setTimeout(run3, 0); };
   window.frames[0].location.reload();
 }
 
 function run3() {
-  gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+  gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
              .getInterface(Components.interfaces.nsIWebBrowserPrint);
-  ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore2");
+  ok(gWbp.doingPrintPreview, "Should be doing print preview");
   window.loadedChild = null;
-  printpreview();
+  exitprintpreview();
   setTimeout(run4, 0);
 }
 
 function run4() {
   var x = window.frames[0].frameElement.parentNode.removeChild(window.frames[0].frameElement);
   window.loadedChild = function() { setTimeout(run5, 0); };
   document.documentElement.getBoundingClientRect();
   document.documentElement.appendChild(x);
-  gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+  gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
              .getInterface(Components.interfaces.nsIWebBrowserPrint);
-  ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore3");
+  ok(!gWbp.doingPrintPreview, "Should not be doing print preview anymore2");
 }
 
 function run5() {
   //XXX this shouldn't be necessary, see bug 405555
   printpreview();
   exitprintpreview();
   SimpleTest.finish(); //should not have crashed after all of this
   window.close();
--- a/layout/base/tests/chrome/bug482976_helper.xul
+++ b/layout/base/tests/chrome/bug482976_helper.xul
@@ -3,24 +3,25 @@
 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
                  type="text/css"?>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=482976
 -->
 <window title="Mozilla Bug 482976" onload="run1()"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 <iframe src="data:text/html;charset=utf-8,&lt;body onload='window.parent.loadedChild()'&gt;&lt;q&gt;"></iframe>
+<iframe src="about:blank"/>
 <script type="application/javascript">
 <![CDATA[
 var is = window.opener.wrappedJSObject.is;
 var ok = window.opener.wrappedJSObject.ok;
 var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
 var gWbp;
 function printpreview() {
-  gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+  gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
              .getInterface(Components.interfaces.nsIWebBrowserPrint);
   var listener = {
     onLocationChange: function(webProgress, request, location) { },
     onProgressChange: function(webProgress, request, curSelfProgress, 
                                maxSelfProgress, curTotalProgress,
                                maxTotalProgress) { },
     onSecurityChange: function(webProgress, request, state) { },
     onStateChange: function(webProgress, request, stateFlags, status) { },
@@ -32,22 +33,22 @@ function printpreview() {
       throw Components.results.NS_NOINTERFACE;
     }
   }
   var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                             .getService(Components.interfaces.nsIPrefBranch);
   prefs.setBoolPref('print.show_print_progress', false);
   //XXX I would have thought this would work, instead I'm forced to use prefs service
   gWbp.globalPrintSettings.showPrintProgress = false; 
-  gWbp.printPreview(gWbp.globalPrintSettings, null, listener);
+  gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
   prefs.clearUserPref('print.show_print_progress');
 }
 
 function exitprintpreview() {
-  window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+  window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
    .getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview(); 
 }
 
 function run1()
 {
 /** Test for Bug 482976 **/
   var printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
                                .getService(Components.interfaces.nsIPrintSettingsService);
--- a/layout/base/tests/chrome/printpreview_helper.xul
+++ b/layout/base/tests/chrome/printpreview_helper.xul
@@ -1,28 +1,29 @@
 <?xml version="1.0"?>
 <?xml-stylesheet type="text/css" href="chrome://global/skin"?>
 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
                  type="text/css"?>
 <window onload="runTests()"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 <iframe height="200" width="600"></iframe>
+<iframe height="200" width="600"></iframe>
 <script type="application/javascript">
 <![CDATA[
 var is = window.opener.wrappedJSObject.is;
 var isnot = window.opener.wrappedJSObject.isnot;
 var ok = window.opener.wrappedJSObject.ok;
 var SimpleTest = window.opener.wrappedJSObject.SimpleTest;
 var gWbp;
 var ctx1;
 var ctx2;
 var counter = 0;
 
 function printpreview() {
-  gWbp = window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+  gWbp = window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
              .getInterface(Components.interfaces.nsIWebBrowserPrint);
   var listener = {
     onLocationChange: function(webProgress, request, location) { },
     onProgressChange: function(webProgress, request, curSelfProgress, 
                                maxSelfProgress, curTotalProgress,
                                maxTotalProgress) { },
     onSecurityChange: function(webProgress, request, state) { },
     onStateChange: function(webProgress, request, stateFlags, status) { },
@@ -33,23 +34,23 @@ function printpreview() {
             return this;
       throw Components.results.NS_NOINTERFACE;
     }
   }
   var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                             .getService(Components.interfaces.nsIPrefBranch);
   prefs.setBoolPref('print.show_print_progress', false);
   //XXX I would have thought this would work, instead I'm forced to use prefs service
-  gWbp.globalPrintSettings.showPrintProgress = false; 
-  gWbp.printPreview(gWbp.globalPrintSettings, null, listener);
+  gWbp.globalPrintSettings.showPrintProgress = false;
+  gWbp.printPreview(gWbp.globalPrintSettings, window.frames[0], listener);
   prefs.clearUserPref('print.show_print_progress');
 }
 
 function exitprintpreview() {
-  window.frames[0].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+  window.frames[1].QueryInterface(Components.interfaces.nsIInterfaceRequestor)
    .getInterface(Components.interfaces.nsIWebBrowserPrint).exitPrintPreview(); 
 }
 
 function runTests()
 {
   var printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
                                .getService(Components.interfaces.nsIPrintSettingsService);
 
@@ -99,38 +100,33 @@ function startTest1() {
   // after print preview, but not during it.
   window.frames[0].counter = counter;
   window.frames[0].counterTimeout = "document.body.firstChild.nextSibling.innerHTML = ++counter + ' timers';" +
                                     "window.setTimeout(counterTimeout, 0);";
   window.frames[0].setTimeout(window.frames[0].counterTimeout, 0);
   window.frames[0].document.body.firstChild.innerHTML = "Print preview";
 
   printpreview();
-  ctx1.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
+  ctx1.drawWindow(window.frames[1], 0, 0, 300, 300, "rgb(256,256,256)");
   window.frames[0].document.body.firstChild.innerHTML = "Galley presentation";
-  window.frames[0].document.body.firstChild.innerHTML +=
-    "<div style='color: red;'>This is not for print preview!</div>";
-  window.frames[0].document.body.firstChild.lastChild.firstChild.data += " Really!";
 
   // Add some elements.
   addHTMLContent(window.frames[0].document.body.lastChild);
   // Delete them.
   window.frames[0].document.body.lastChild.innerHTML = "";
   // And readd.
   addHTMLContent(window.frames[0].document.body.lastChild);
 
   setTimeout(finalizeTest1, 1000);
 }
 
 function finalizeTest1() {
-  ctx2.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
+  ctx2.drawWindow(window.frames[1], 0, 0, 300, 300, "rgb(256,256,256)");
   exitprintpreview();
   ok(compareCanvases(), "Canvas should be the same!");
-  is(window.frames[0].document.body.firstChild.nextSibling.textContent, "0 timers", "Timers shouldn't have run yet!");
-  is(window.frames[0].counter, 0, "Timers shouldn't have run yet!");
   counter = window.frames[0].counter;
   // This timeout is needed so that we can check that timers do run after
   // print preview.
   setTimeout(runTest2, 1000);
 }
 
 function runTest2() {
   isnot(window.frames[0].document.body.firstChild.nextSibling.textContent, "0 timers", "Timers should have run!");
@@ -189,23 +185,23 @@ function runTest3() {
   window.close();
 }
 
 function compareFormElementPrint(el1, el2, equals) {
   window.frames[0].document.body.innerHTML = el1;
   window.frames[0].document.body.firstChild.value =
     window.frames[0].document.body.firstChild.getAttribute('value');
   printpreview();
-  ctx1.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
+  ctx1.drawWindow(window.frames[1], 0, 0, 300, 300, "rgb(256,256,256)");
   exitprintpreview();
   window.frames[0].document.body.innerHTML = el2;
   window.frames[0].document.body.firstChild.value =
     window.frames[0].document.body.firstChild.getAttribute('value');
   printpreview();
-  ctx2.drawWindow(window.frames[0], 0, 0, 300, 300, "rgb(256,256,256)");
+  ctx2.drawWindow(window.frames[1], 0, 0, 300, 300, "rgb(256,256,256)");
   exitprintpreview();
   is(compareCanvases(), equals,
      "Comparing print preview didn't succeed [" + el1 + " : " + el2 + "]");
   setTimeout(runTest3, 100);
 }
 ]]></script>
 <table style="border: 1px solid black;" xmlns="http://www.w3.org/1999/xhtml">
 <tr><th>Print preview canvas 1</th><th>Print preview canvas 2</th></tr>
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -6182,17 +6182,18 @@ NS_IMETHODIMP nsBlockFrame::GetAccessibl
 
     // Not a bullet, treat as normal HTML container
     return accService->CreateHyperTextAccessible(static_cast<nsIFrame*>(this), aAccessible);
   }
 
   // Create special list bullet accessible
   const nsStyleList* myList = GetStyleList();
   nsAutoString bulletText;
-  if (myList->mListStyleImage || myList->mListStyleType == NS_STYLE_LIST_STYLE_DISC ||
+  if (myList->GetListStyleImage() ||
+      myList->mListStyleType == NS_STYLE_LIST_STYLE_DISC ||
       myList->mListStyleType == NS_STYLE_LIST_STYLE_CIRCLE ||
       myList->mListStyleType == NS_STYLE_LIST_STYLE_SQUARE) {
     bulletText.Assign(PRUnichar(0x2022));; // Unicode bullet character
   }
   else if (myList->mListStyleType != NS_STYLE_LIST_STYLE_NONE) {
     mBullet->GetListItemText(*myList, bulletText);
   }
 
@@ -6414,17 +6415,17 @@ nsBlockFrame::SetInitialChildList(nsIAto
 PRBool
 nsBlockFrame::BulletIsEmpty() const
 {
   NS_ASSERTION(GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_LIST_ITEM &&
                HaveOutsideBullet(),
                "should only care when we have an outside bullet");
   const nsStyleList* list = GetStyleList();
   return list->mListStyleType == NS_STYLE_LIST_STYLE_NONE &&
-         !list->mListStyleImage;
+         !list->GetListStyleImage();
 }
 
 // static
 PRBool
 nsBlockFrame::FrameStartsCounterScope(nsIFrame* aFrame)
 {
   nsIContent* content = aFrame->GetContent();
   if (!content || !content->IsHTML())
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -132,17 +132,17 @@ nsBulletFrame::IsSelfEmpty()
   return GetStyleList()->mListStyleType == NS_STYLE_LIST_STYLE_NONE;
 }
 
 /* virtual */ void
 nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   nsFrame::DidSetStyleContext(aOldStyleContext);
 
-  imgIRequest *newRequest = GetStyleList()->mListStyleImage;
+  imgIRequest *newRequest = GetStyleList()->GetListStyleImage();
 
   if (newRequest) {
 
     if (!mListener) {
       nsBulletListener *listener;
       NS_NEWXPCOM(listener, nsBulletListener);
       NS_ADDREF(listener);
       listener->SetFrame(this);
@@ -223,17 +223,17 @@ nsBulletFrame::BuildDisplayList(nsDispla
 
 void
 nsBulletFrame::PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt,
                            const nsRect& aDirtyRect)
 {
   const nsStyleList* myList = GetStyleList();
   PRUint8 listStyleType = myList->mListStyleType;
 
-  if (myList->mListStyleImage && mImageRequest) {
+  if (myList->GetListStyleImage() && mImageRequest) {
     PRUint32 status;
     mImageRequest->GetImageStatus(&status);
     if (status & imgIRequest::STATUS_LOAD_COMPLETE &&
         !(status & imgIRequest::STATUS_ERROR)) {
       nsCOMPtr<imgIContainer> imageCon;
       mImageRequest->GetImage(getter_AddRefs(imageCon));
       if (imageCon) {
         nsRect dest(mPadding.left, mPadding.top,
@@ -1253,17 +1253,17 @@ nsBulletFrame::GetDesiredSize(nsPresCont
                               nsHTMLReflowMetrics& aMetrics)
 {
   // Reset our padding.  If we need it, we'll set it below.
   mPadding.SizeTo(0, 0, 0, 0);
   
   const nsStyleList* myList = GetStyleList();
   nscoord ascent;
 
-  if (myList->mListStyleImage && mImageRequest) {
+  if (myList->GetListStyleImage() && mImageRequest) {
     PRUint32 status;
     mImageRequest->GetImageStatus(&status);
     if (status & imgIRequest::STATUS_SIZE_AVAILABLE &&
         !(status & imgIRequest::STATUS_ERROR)) {
       // auto size the image
       mComputedSize.width = mIntrinsicSize.width;
       mComputedSize.height = mIntrinsicSize.height;
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -116,17 +116,17 @@
 #include "nsWidgetsCID.h"     // for NS_LOOKANDFEEL_CID
 #include "nsUnicharUtils.h"
 #include "nsLayoutErrors.h"
 #include "nsContentErrors.h"
 #include "nsHTMLContainerFrame.h"
 #include "nsBoxLayoutState.h"
 #include "nsBlockFrame.h"
 #include "nsDisplayList.h"
-
+#include "nsIObjectLoadingContent.h"
 #ifdef MOZ_SVG
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGEffects.h"
 #endif
 
 #include "gfxContext.h"
 
 static NS_DEFINE_CID(kLookAndFeelCID,  NS_LOOKANDFEEL_CID);
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1317,32 +1317,22 @@ nsObjectFrame::BuildDisplayList(nsDispla
   return aLists.Content()->AppendNewToTop(new (aBuilder)
       nsDisplayPlugin(this));
 }
 
 void
 nsObjectFrame::PrintPlugin(nsIRenderingContext& aRenderingContext,
                            const nsRect& aDirtyRect)
 {
-  // if we are printing, we need to get the correct nsIPluginInstance
-  // for THIS content node in order to call ->Print() on the right plugin
-
-  // first, we need to get the document
-  nsIDocument* doc = mContent->GetCurrentDoc();
-  if (!doc)
+  nsCOMPtr<nsIObjectLoadingContent> obj(do_QueryInterface(mContent));
+  if (!obj)
     return;
 
-  // now we need to get the shell for the screen
-  // XXX assuming that the shell at zero will always be the screen one
-  nsIPresShell *shell = doc->GetPrimaryShell();
-  if (!shell)
-    return;
-
-  // then the shell can give us the screen frame for this content node
-  nsIFrame* frame = shell->GetPrimaryFrameFor(mContent);
+  nsIFrame* frame = nsnull;
+  obj->GetPrintFrame(&frame);
   if (!frame)
     return;
 
   nsPresContext* presContext = PresContext();
   // make sure this is REALLY an nsIObjectFrame
   // we may need to go through the children to get it
   nsIObjectFrame* objectFrame = do_QueryFrame(frame);
   if (!objectFrame)
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -55,20 +55,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:
   NS_DECL_FRAMEARENA_HELPERS
 
@@ -364,27 +360,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
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -160,19 +160,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
 
 /*
@@ -479,33 +478,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)
@@ -724,17 +723,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),
@@ -942,17 +941,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)
@@ -1267,17 +1266,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());
@@ -1300,17 +1299,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))
@@ -1621,17 +1620,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();
@@ -1850,17 +1849,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;
 }
@@ -2218,17 +2217,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),
@@ -3404,21 +3403,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
@@ -3493,34 +3487,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();
   }
@@ -3699,17 +3688,17 @@ NS_NewContinuingTextFrame(nsIPresShell* 
 {
   return new (aPresShell) nsContinuingTextFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsContinuingTextFrame)
 
 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)
@@ -3907,17 +3896,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)
@@ -5241,17 +5230,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
@@ -5308,17 +5297,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 = NS_MIN(trimmed.GetEnd(), startOffset) - 1;
          i >= trimmed.mStart; --i) {
@@ -5423,17 +5412,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;
   }
@@ -5664,17 +5653,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 =
@@ -5792,17 +5781,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 =
@@ -6057,18 +6046,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();
 
@@ -6080,39 +6069,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
@@ -6522,17 +6511,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
@@ -6659,17 +6648,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 ...
 
@@ -6725,17 +6714,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();
@@ -6785,17 +6774,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
@@ -6922,15 +6911,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);
-}
--- a/layout/generic/nsVideoFrame.h
+++ b/layout/generic/nsVideoFrame.h
@@ -96,34 +96,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();
 
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -153,17 +153,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
@@ -434,19 +434,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)
@@ -458,17 +459,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;
@@ -535,31 +537,33 @@ 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())
+  if (!mPrt->mPrintObject->mDocument ||
+      !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
   MapContentToWebShells(mPrt->mPrintObject, mPrt->mPrintObject);
 
   mPrt->mIsIFrameSelected = IsThereAnIFrameSelected(webContainer, mPrt->mCurrentFocusWin, mPrt->mIsParentAFrameSet);
 
@@ -744,17 +748,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
@@ -765,18 +770,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));
@@ -1084,22 +1094,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
@@ -1109,23 +1113,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
@@ -1149,21 +1152,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);
         }
       }
     }
   }
 }
@@ -1215,17 +1219,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++) {
@@ -1308,17 +1321,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
@@ -1906,16 +1918,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 nsRootPresContext(aPO->mDocument,
     mIsCreatingPrintPreview ? nsPresContext::eContext_PrintPreview:
                               nsPresContext::eContext_Print);
   NS_ENSURE_TRUE(aPO->mPresContext, NS_ERROR_OUT_OF_MEMORY);
   aPO->mPresContext->SetPrintSettings(mPrt->mPrintSettings);
 
   // set the presentation context to the value in the print settings
@@ -1986,16 +2000,23 @@ nsPrintEngine::ReflowPrintObject(nsPrint
   aPO->mPresContext->SetPageSize(adjSize);
   aPO->mPresContext->SetIsRootPaginatedDocument(documentIsTopLevel);
   aPO->mPresContext->SetPageScale(aPO->mZoomRatio);
   // Calculate scale factor from printer to screen
   float printDPI = float(mPrt->mPrintDC->AppUnitsPerInch()) /
                    float(mPrt->mPrintDC->AppUnitsPerDevPixel());
   aPO->mPresContext->SetPrintPreviewScale(mScreenDPI / 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);
 
@@ -2127,16 +2148,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));
 
@@ -2190,16 +2305,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
@@ -2791,18 +2908,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;
@@ -2896,17 +3015,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;
@@ -2943,17 +3063,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;
--- 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,
--- 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;
+  }
+
+  mDocument = doc->CreateStaticClone(mDocShell);
+  nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(mDocument);
+  NS_ENSURE_STATE(clonedDOMDoc);
+
+  viewer->SetDOMDocument(clonedDOMDoc);
   return NS_OK;
 }
 
 //------------------------------------------------------------------
 // Resets PO by destroying the presentation
 void 
 nsPrintObject::DestroyPresentation()
 {
--- 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
 
 };
 
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2264,22 +2264,22 @@ nsComputedDOMStyle::GetZIndex(nsIDOMCSSV
 nsresult
 nsComputedDOMStyle::GetListStyleImage(nsIDOMCSSValue** aValue)
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
   NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
 
   const nsStyleList* list = GetStyleList();
 
-  if (!list->mListStyleImage) {
+  if (!list->GetListStyleImage()) {
     val->SetIdent(eCSSKeyword_none);
   } else {
     nsCOMPtr<nsIURI> uri;
-    if (list->mListStyleImage) {
-      list->mListStyleImage->GetURI(getter_AddRefs(uri));
+    if (list->GetListStyleImage()) {
+      list->GetListStyleImage()->GetURI(getter_AddRefs(uri));
     }
     val->SetURI(uri);
   }
     
   return CallQueryInterface(val, aValue);
 }
 
 nsresult
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -71,16 +71,25 @@
 #include "nsILanguageAtomService.h"
 #include "nsIStyleRule.h"
 #include "nsBidiUtils.h"
 #include "nsStyleStructInlines.h"
 #include "nsStyleTransformMatrix.h"
 #include "nsCSSKeywords.h"
 #include "nsCSSProps.h"
 #include "nsTArray.h"
+#include "nsContentUtils.h"
+
+#define NS_SET_IMAGE_REQUEST(method_, context_, request_)                   \
+  if ((context_)->PresContext()->IsDynamic()) {                               \
+    method_(request_);                                                      \
+  } else {                                                                  \
+    nsCOMPtr<imgIRequest> req = nsContentUtils::GetStaticRequest(request_); \
+    method_(req);                                                           \
+  }
 
 /*
  * For storage of an |nsRuleNode|'s children in a PLDHashTable.
  */
 
 struct ChildrenHashEntry : public PLDHashEntryHdr {
   // key is |mRuleNode->GetKey()|
   nsRuleNode *mRuleNode;
@@ -602,29 +611,32 @@ static void SetGradient(const nsCSSValue
     SetColor(valueStop.mColor, NS_RGB(0, 0, 0), aPresContext,
              aContext, stop.mColor, aCanStoreInRuleTree);
 
     aResult.mStops.AppendElement(stop);
   }
 }
 
 // -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
-static void SetStyleImageToImageRect(const nsCSSValue& aValue,
+static void SetStyleImageToImageRect(nsStyleContext* aStyleContext,
+                                     const nsCSSValue& aValue,
                                      nsStyleImage& aResult)
 {
   NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Function &&
                     aValue.EqualsFunction(eCSSKeyword__moz_image_rect),
                     "the value is not valid -moz-image-rect()");
 
   nsCSSValue::Array* arr = aValue.GetArrayValue();
   NS_ABORT_IF_FALSE(arr && arr->Count() == 6, "invalid number of arguments");
 
   // <uri>
   if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
-    aResult.SetImageData(arr->Item(1).GetImageValue());
+    NS_SET_IMAGE_REQUEST(aResult.SetImageData,
+                         aStyleContext,
+                         arr->Item(1).GetImageValue())
   } else {
     NS_WARNING("nsCSSValue::Image::Image() failed?");
   }
 
   // <top>, <right>, <bottom>, <left>
   nsStyleSides cropRect;
   NS_FOR_CSS_SIDES(side) {
     nsStyleCoord coord;
@@ -640,21 +652,23 @@ static void SetStyleImage(nsStyleContext
                           const nsCSSValue& aValue,
                           nsStyleImage& aResult,
                           PRBool& aCanStoreInRuleTree)
 {
   aResult.SetNull();
 
   switch (aValue.GetUnit()) {
     case eCSSUnit_Image:
-      aResult.SetImageData(aValue.GetImageValue());
+      NS_SET_IMAGE_REQUEST(aResult.SetImageData,
+                           aStyleContext,
+                           aValue.GetImageValue())
       break;
     case eCSSUnit_Function:
       if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
-        SetStyleImageToImageRect(aValue, aResult);
+        SetStyleImageToImageRect(aStyleContext, aValue, aResult);
       } else {
         NS_NOTREACHED("-moz-image-rect() is the only expected function");
       }
       break;
     case eCSSUnit_Gradient:
     {
       nsStyleGradient* gradient = new nsStyleGradient();
       if (gradient) {
@@ -4869,17 +4883,19 @@ nsRuleNode::ComputeBorderData(void* aSta
               NS_STYLE_FLOAT_EDGE_CONTENT, 0, 0, 0, 0);
 
   // border-image
   if (eCSSUnit_Array == marginData.mBorderImage.GetUnit()) {
     nsCSSValue::Array *arr = marginData.mBorderImage.GetArrayValue();
 
     // the image
     if (eCSSUnit_Image == arr->Item(0).GetUnit()) {
-      border->SetBorderImage(arr->Item(0).GetImageValue());
+      NS_SET_IMAGE_REQUEST(border->SetBorderImage,
+                           aContext,
+                           arr->Item(0).GetImageValue())
     }
 
     // the numbers saying where to split the image
     NS_FOR_CSS_SIDES(side) {
       if (SetAbsCoord(arr->Item(1 + side), coord,
                       SETCOORD_FACTOR | SETCOORD_PERCENT)) {
         border->mBorderImageSplit.Set(side, coord);
       }
@@ -4932,17 +4948,18 @@ nsRuleNode::ComputeBorderData(void* aSta
     canStoreInRuleTree = PR_FALSE;
     NS_FOR_CSS_SIDES(side) {
       border->SetBorderImageWidthOverride(side, parentBorder->mBorderImageWidth.side(side));
     }
     border->mBorderImageSplit = parentBorder->mBorderImageSplit;
     border->mBorderImageHFill = parentBorder->mBorderImageHFill;
     border->mBorderImageVFill = parentBorder->mBorderImageVFill;
     border->mHaveBorderImageWidth = parentBorder->mHaveBorderImageWidth;
-    border->SetBorderImage(parentBorder->GetBorderImage());
+    NS_SET_IMAGE_REQUEST(border->SetBorderImage, aContext,
+                         parentBorder->GetBorderImage())
   }
 
   COMPUTE_END_RESET(Border, border)
 }
 
 const void*
 nsRuleNode::ComputePaddingData(void* aStartStruct,
                                const nsRuleDataStruct& aData,
@@ -5089,25 +5106,29 @@ nsRuleNode::ComputeListData(void* aStart
 
   // list-style-type: enum, inherit, initial
   SetDiscrete(listData.mType, list->mListStyleType, canStoreInRuleTree,
               SETDSC_ENUMERATED, parentList->mListStyleType,
               NS_STYLE_LIST_STYLE_DISC, 0, 0, 0, 0);
 
   // list-style-image: url, none, inherit
   if (eCSSUnit_Image == listData.mImage.GetUnit()) {
-    list->mListStyleImage = listData.mImage.GetImageValue();
+    NS_SET_IMAGE_REQUEST(list->SetListStyleImage,
+                         aContext,
+                         listData.mImage.GetImageValue())
   }
   else if (eCSSUnit_None == listData.mImage.GetUnit() ||
            eCSSUnit_Initial == listData.mImage.GetUnit()) {
-    list->mListStyleImage = nsnull;
+    list->SetListStyleImage(nsnull);
   }
   else if (eCSSUnit_Inherit == listData.mImage.GetUnit()) {
     canStoreInRuleTree = PR_FALSE;
-    list->mListStyleImage = parentList->mListStyleImage;
+    NS_SET_IMAGE_REQUEST(list->SetListStyleImage,
+                         aContext,
+                         parentList->GetListStyleImage())
   }
 
   // list-style-position: enum, inherit, initial
   SetDiscrete(listData.mPosition, list->mListStylePosition, canStoreInRuleTree,
               SETDSC_ENUMERATED, parentList->mListStylePosition,
               NS_STYLE_LIST_STYLE_POSITION_OUTSIDE, 0, 0, 0, 0);
 
   // image region property: length, auto, inherit
@@ -5377,18 +5398,17 @@ nsRuleNode::ComputeContentData(void* aSt
                   NS_ERROR("bad content value");
               }
               break;
             default:
               NS_ERROR("bad content type");
           }
           data.mType = type;
           if (type == eStyleContentType_Image) {
-            data.mContent.mImage = value.GetImageValue();
-            NS_IF_ADDREF(data.mContent.mImage);
+            NS_SET_IMAGE_REQUEST(data.SetImage, aContext, value.GetImageValue());
           }
           else if (type <= eStyleContentType_Attr) {
             value.GetStringValue(buffer);
             data.mContent.mString = NS_strdup(buffer.get());
           }
           else if (type <= eStyleContentType_Counters) {
             data.mContent.mCounters = value.GetArrayValue();
             data.mContent.mCounters->AddRef();
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -61,16 +61,17 @@
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsTArray.h"
 #include "nsIAtom.h"
 #include "nsIURI.h"
 #include "nsCSSValue.h"
 #include "nsStyleTransformMatrix.h"
 #include "nsAlgorithm.h"
+#include "imgIRequest.h"
 
 class nsIFrame;
 class imgIRequest;
 class imgIContainer;
 
 // Includes nsStyleStructID.
 #include "nsStyleStructFwd.h"
 
@@ -910,17 +911,17 @@ protected:
   // computed value either. The values are rounded to the nearest device pixel
   // We also use these values when we have a loaded border-image that
   // does not have width overrides.
   nsMargin      mBorder;
 
   PRUint8       mBorderStyle[4];  // [reset] See nsStyleConsts.h
   nscolor       mBorderColor[4];  // [reset] the colors to use for a simple border.  not used
                                   // if -moz-border-colors is specified
-
+private:
   nsCOMPtr<imgIRequest> mBorderImage; // [reset]
 
   // Cache used by callers for border-image painting
   nsCOMArray<imgIContainer> mSubImages;
 
   nscoord       mTwipsPerPixel;
 };
 
@@ -1028,19 +1029,27 @@ struct nsStyleList {
   }
 
   nsChangeHint CalcDifference(const nsStyleList& aOther) const;
 #ifdef DEBUG
   static nsChangeHint MaxDifference();
 #endif
   static PRBool ForceCompare() { return PR_FALSE; }
   
+  imgIRequest* GetListStyleImage() const { return mListStyleImage; }
+  void SetListStyleImage(imgIRequest* aReq)
+  {
+    mListStyleImage = aReq;
+  }
+
   PRUint8   mListStyleType;             // [inherited] See nsStyleConsts.h
-  PRUint8   mListStylePosition;         // [inherited] 
+  PRUint8   mListStylePosition;         // [inherited]
+private:
   nsCOMPtr<imgIRequest> mListStyleImage; // [inherited]
+public:
   nsRect        mImageRegion;           // [inherited] the rect to use within an image  
 };
 
 struct nsStylePosition {
   nsStylePosition(void);
   nsStylePosition(const nsStylePosition& aOther);
   ~nsStylePosition(void);
 
@@ -1447,16 +1456,22 @@ struct nsStyleContentData {
   nsStyleContentData() : mType(nsStyleContentType(0)) { mContent.mString = nsnull; }
   ~nsStyleContentData();
   nsStyleContentData& operator=(const nsStyleContentData& aOther);
   PRBool operator==(const nsStyleContentData& aOther) const;
 
   PRBool operator!=(const nsStyleContentData& aOther) const {
     return !(*this == aOther);
   }
+
+  void SetImage(imgIRequest* aRequest)
+  {
+    NS_ASSERTION(mType == eStyleContentType_Image, "Wrong type!");
+    NS_IF_ADDREF(mContent.mImage = aRequest);
+  }
 private:
   nsStyleContentData(const nsStyleContentData&); // not to be implemented
 };
 
 struct nsStyleCounterData {
   nsString  mCounter;
   PRInt32   mValue;
 };
--- 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;
 };
   
 /**
@@ -290,20 +289,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;
 }
@@ -632,17 +627,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 {
@@ -836,17 +831,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;
@@ -1117,17 +1112,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()
--- a/layout/svg/base/src/nsSVGGlyphFrame.h
+++ b/layout/svg/base/src/nsSVGGlyphFrame.h
@@ -203,21 +203,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;
--- a/layout/svg/base/src/nsSVGUtils.h
+++ b/layout/svg/base/src/nsSVGUtils.h
@@ -90,19 +90,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
--- a/layout/xul/base/src/nsImageBoxFrame.cpp
+++ b/layout/xul/base/src/nsImageBoxFrame.cpp
@@ -274,17 +274,17 @@ nsImageBoxFrame::UpdateImage()
     }
   } else {
     // Only get the list-style-image if we aren't being drawn
     // by a native theme.
     PRUint8 appearance = GetStyleDisplay()->mAppearance;
     if (!(appearance && nsBox::gTheme && 
           nsBox::gTheme->ThemeSupportsWidget(nsnull, this, appearance))) {
       // get the list-style-image
-      imgIRequest *styleRequest = GetStyleList()->mListStyleImage;
+      imgIRequest *styleRequest = GetStyleList()->GetListStyleImage();
       if (styleRequest) {
         styleRequest->Clone(mListener, getter_AddRefs(mImageRequest));
       }
     }
   }
 
   if (!mImageRequest) {
     // We have no image, so size to 0
@@ -412,18 +412,18 @@ nsImageBoxFrame::DidSetStyleContext(nsSt
   if (disp->mAppearance && nsBox::gTheme && 
       nsBox::gTheme->ThemeSupportsWidget(nsnull, this, disp->mAppearance))
     return;
 
   // If list-style-image changes, we have a new image.
   nsCOMPtr<nsIURI> oldURI, newURI;
   if (mImageRequest)
     mImageRequest->GetURI(getter_AddRefs(oldURI));
-  if (myList->mListStyleImage)
-    myList->mListStyleImage->GetURI(getter_AddRefs(newURI));
+  if (myList->GetListStyleImage())
+    myList->GetListStyleImage()->GetURI(getter_AddRefs(newURI));
   PRBool equal;
   if (newURI == oldURI ||   // handles null==null
       (newURI && oldURI &&
        NS_SUCCEEDED(newURI->Equals(oldURI, &equal)) && equal))
     return;
 
   UpdateImage();
 } // DidSetStyleContext
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -2152,17 +2152,17 @@ nsTreeBodyFrame::GetImage(PRInt32 aRowIn
   mView->GetImageSrc(aRowIndex, aCol, imageSrc);
   nsCOMPtr<imgIRequest> styleRequest;
   if (!aUseContext && !imageSrc.IsEmpty()) {
     aAllowImageRegions = PR_FALSE;
   }
   else {
     // Obtain the URL from the style context.
     aAllowImageRegions = PR_TRUE;
-    styleRequest = aStyleContext->GetStyleList()->mListStyleImage;
+    styleRequest = aStyleContext->GetStyleList()->GetListStyleImage();
     if (!styleRequest)
       return NS_OK;
     nsCOMPtr<nsIURI> uri;
     styleRequest->GetURI(getter_AddRefs(uri));
     nsCAutoString spec;
     uri->GetSpec(spec);
     CopyUTF8toUTF16(spec, imageSrc);
   }
--- a/modules/libpr0n/public/imgIRequest.idl
+++ b/modules/libpr0n/public/imgIRequest.idl
@@ -47,17 +47,17 @@ interface nsIPrincipal;
 
 /**
  * imgIRequest interface
  *
  * @author Stuart Parmenter <stuart@mozilla.com>
  * @version 0.1
  * @see imagelib2
  */
-[scriptable, uuid(c0c9f606-19d6-4ed1-8486-6cae2fe0a6a4)]
+[scriptable, uuid(ebde51c9-cc11-4b6a-99c3-d7f568c7481b)]
 interface imgIRequest : nsIRequest
 {
   /**
    * the image container...
    * @return the image object associated with the request.
    * @attention NEED DOCS
    */
   readonly attribute imgIContainer image;
@@ -168,10 +168,16 @@ interface imgIRequest : nsIRequest
 
   /**
    * Unlocks an image.
    *
    * @see imgIContainer::unlockImage for documentation of the underlying call.
    */
   void unlockImage();
 
+  /**
+   * If this request is for an animated image, the method creates a new
+   * request which contains the current frame of the image.
+   * Otherwise returns the same request.
+   */
+  imgIRequest getStaticRequest();
 };
 
--- a/modules/libpr0n/src/Makefile.in
+++ b/modules/libpr0n/src/Makefile.in
@@ -51,16 +51,18 @@ LIBXUL_LIBRARY  = 1
 
 
 CPPSRCS		= \
 			imgContainer.cpp \
 			imgFrame.cpp \
 			imgLoader.cpp    \
 			imgRequest.cpp   \
 			imgRequestProxy.cpp \
-			imgTools.cpp
+			imgTools.cpp \
+			imgContainerRequest.cpp \
+			$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 # Because imgFrame.cpp includes "cairo.h"
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS)
 
 
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/src/imgContainerRequest.cpp
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "imgContainerRequest.h"
+#include "ImageErrors.h"
+#include "imgRequest.h"
+
+NS_IMPL_ISUPPORTS2(imgContainerRequest, imgIRequest, nsIRequest)
+
+imgContainerRequest::imgContainerRequest(imgIContainer* aImage,
+                                         nsIURI* aURI,
+                                         PRUint32 aImageStatus,
+                                         PRUint32 aState,
+                                         nsIPrincipal* aPrincipal)
+: mImage(aImage), mURI(aURI), mPrincipal(aPrincipal), mImageStatus(aImageStatus),
+  mState(aState), mLocksHeld(0)
+{
+#ifdef DEBUG
+  PRUint32 numFrames = 0;
+  if (aImage) {
+    aImage->GetNumFrames(&numFrames);
+  }
+  NS_ABORT_IF_FALSE(!aImage || numFrames == 1,
+                    "Shouldn't have image with more than one frame!");
+#endif
+}
+
+imgContainerRequest::~imgContainerRequest()
+{
+  if (mImage) {
+    while (mLocksHeld) {
+      UnlockImage();
+    }
+  }
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetName(nsACString& aName)
+{
+  aName.Truncate();
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::IsPending(PRBool* _retval)
+{
+  *_retval = PR_FALSE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetStatus(nsresult* aStatus)
+{
+  *aStatus = NS_OK;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::Cancel(nsresult aStatus)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::Suspend()
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::Resume()
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetLoadGroup(nsILoadGroup** aLoadGroup)
+{
+  *aLoadGroup = nsnull;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::SetLoadGroup(nsILoadGroup* aLoadGroup)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetLoadFlags(nsLoadFlags* aLoadFlags)
+{
+  *aLoadFlags = LOAD_NORMAL;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::SetLoadFlags(nsLoadFlags aLoadFlags)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetImage(imgIContainer** aImage)
+{
+  NS_IF_ADDREF(*aImage = mImage);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetImageStatus(PRUint32* aImageStatus)
+{
+  *aImageStatus = mImageStatus;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetURI(nsIURI** aURI)
+{
+  NS_IF_ADDREF(*aURI = mURI);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetDecoderObserver(imgIDecoderObserver** aDecoderObserver)
+{
+  NS_IF_ADDREF(*aDecoderObserver = mObserver);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetMimeType(char** aMimeType)
+{
+  *aMimeType = nsnull;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::Clone(imgIDecoderObserver* aObserver, imgIRequest** _retval)
+{
+  imgContainerRequest* req =
+    new imgContainerRequest(mImage, mURI, mImageStatus, mState, mPrincipal);
+  if (!req) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  NS_ADDREF(*_retval = req);
+  req->mObserver = aObserver;
+
+  nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(aObserver);
+
+  // Keep these notifications in sync with imgRequest::NotifyProxyListener!
+
+  // OnStartRequest
+  if (req->mState & stateRequestStarted)
+    aObserver->OnStartRequest(req);
+
+  // OnStartContainer
+  if (req->mState & stateHasSize)
+    aObserver->OnStartContainer(req, req->mImage);
+
+  // OnStartDecode
+  if (req->mState & stateDecodeStarted)
+    aObserver->OnStartDecode(req);
+
+  // Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame)
+  PRUint32 nframes = 0;
+  if (req->mImage)
+    req->mImage->GetNumFrames(&nframes);
+
+  if (nframes > 0) {
+    PRUint32 frame;
+    req->mImage->GetCurrentFrameIndex(&frame);
+    aObserver->OnStartFrame(req, frame);
+
+    // OnDataAvailable
+    // XXX - Should only send partial rects here, but that needs to
+    // wait until we fix up the observer interface
+    nsIntRect r;
+    req->mImage->GetCurrentFrameRect(r);
+    aObserver->OnDataAvailable(req, frame, &r);
+
+    if (req->mState & stateRequestStopped)
+      aObserver->OnStopFrame(req, frame);
+  }
+
+  // Reseting image animation isn't needed here.
+
+  if (req->mState & stateRequestStopped) {
+    aObserver->OnStopContainer(req, req->mImage);
+    aObserver->OnStopDecode(req,
+                            imgRequest::GetResultFromImageStatus(req->mImageStatus),
+                            nsnull);
+    aObserver->OnStopRequest(req, PR_TRUE);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetImagePrincipal(nsIPrincipal** aImagePrincipal)
+{
+  NS_IF_ADDREF(*aImagePrincipal = mPrincipal);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::CancelAndForgetObserver(nsresult aStatus)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::RequestDecode()
+{
+  return mImage ? mImage->RequestDecode() : NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::LockImage()
+{
+  if (mImage) {
+    ++mLocksHeld;
+    return mImage->LockImage();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::UnlockImage()
+{
+  if (mImage) {
+    NS_ABORT_IF_FALSE(mLocksHeld > 0, "calling unlock but no locks!");
+    --mLocksHeld;
+    return mImage->UnlockImage();
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+imgContainerRequest::GetStaticRequest(imgIRequest** aReturn)
+{
+  NS_ADDREF(*aReturn = this);
+  return NS_OK;
+}
+
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/src/imgContainerRequest.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef imgContainerRequest_h__
+#define imgContainerRequest_h__
+
+#include "imgIRequest.h"
+#include "imgIContainer.h"
+#include "imgIDecoderObserver.h"
+#include "nsIPrincipal.h"
+#include "nsIURI.h"
+
+class imgContainerRequest : public imgIRequest
+{
+public:
+  imgContainerRequest(imgIContainer* aImage,
+                      nsIURI* aURI,
+                      PRUint32 aImageStatus,
+                      PRUint32 aState,
+                      nsIPrincipal* aPrincipal);
+  virtual ~imgContainerRequest();
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_IMGIREQUEST
+  NS_DECL_NSIREQUEST
+
+protected:
+  nsCOMPtr<imgIContainer>       mImage;
+  nsCOMPtr<nsIURI>              mURI;
+  nsCOMPtr<nsIPrincipal>        mPrincipal;
+  nsCOMPtr<imgIDecoderObserver> mObserver;
+  PRUint32                      mImageStatus;
+  PRUint32                      mState;
+  PRUint32                      mLocksHeld;
+};
+#endif
--- a/modules/libpr0n/src/imgRequest.cpp
+++ b/modules/libpr0n/src/imgRequest.cpp
@@ -40,17 +40,16 @@
 
 #include "imgRequest.h"
 
 #include "imgLoader.h"
 #include "imgRequestProxy.h"
 #include "imgContainer.h"
 
 #include "imgILoader.h"
-#include "ImageErrors.h"
 #include "ImageLogging.h"
 
 #include "netCore.h"
 
 #include "nsIChannel.h"
 #include "nsICachingChannel.h"
 #include "nsILoadGroup.h"
 #include "nsIInputStream.h"
@@ -250,16 +249,18 @@ nsresult imgRequest::RemoveProxy(imgRequ
 
   return NS_OK;
 }
 
 nsresult imgRequest::NotifyProxyListener(imgRequestProxy *proxy)
 {
   nsCOMPtr<imgIRequest> kungFuDeathGrip(proxy);
 
+  // Keep these notifications in sync with imgContainerRequest::Clone!
+
   // OnStartRequest
   if (mState & stateRequestStarted)
     proxy->OnStartRequest(nsnull, nsnull);
 
   // OnStartContainer
   if (mState & stateHasSize)
     proxy->OnStartContainer(mImage);
 
@@ -300,28 +301,16 @@ nsresult imgRequest::NotifyProxyListener
     proxy->OnStopRequest(nsnull, nsnull,
                          GetResultFromImageStatus(mImageStatus),
                          mHadLastPart);
   }
 
   return NS_OK;
 }
 
-nsresult imgRequest::GetResultFromImageStatus(PRUint32 aStatus) const
-{
-  nsresult rv = NS_OK;
-
-  if (aStatus & imgIRequest::STATUS_ERROR)
-    rv = NS_IMAGELIB_ERROR_FAILURE;
-  else if (aStatus & imgIRequest::STATUS_LOAD_COMPLETE)
-    rv = NS_IMAGELIB_SUCCESS_LOAD_FINISHED;
-
-  return rv;
-}
-
 void imgRequest::Cancel(nsresult aStatus)
 {
   /* The Cancel() method here should only be called by this class. */
 
   LOG_SCOPE(gImgLog, "imgRequest::Cancel");
 
   if (mImage) {
     LOG_MSG(gImgLog, "imgRequest::Cancel", "stopping animation");
--- a/modules/libpr0n/src/imgRequest.h
+++ b/modules/libpr0n/src/imgRequest.h
@@ -54,16 +54,18 @@
 #include "nsIURI.h"
 #include "nsIPrincipal.h"
 
 #include "nsCategoryCache.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsTObserverArray.h"
 #include "nsWeakReference.h"
+#include "ImageErrors.h"
+#include "imgIRequest.h"
 
 class imgCacheValidator;
 
 class imgRequestProxy;
 class imgCacheEntry;
 
 enum {
   stateRequestStarted    = PR_BIT(0),
@@ -113,30 +115,37 @@ public:
 
   nsresult GetImage(imgIContainer **aImage);
 
   // Methods that get forwarded to the imgContainer, or deferred until it's
   // instantiated.
   nsresult LockImage();
   nsresult UnlockImage();
   nsresult RequestDecode();
-
+  static nsresult GetResultFromImageStatus(PRUint32 aStatus)
+  {
+    if (aStatus & imgIRequest::STATUS_ERROR)
+      return NS_IMAGELIB_ERROR_FAILURE;
+    if (aStatus & imgIRequest::STATUS_LOAD_COMPLETE)
+      return NS_IMAGELIB_SUCCESS_LOAD_FINISHED;
+    return NS_OK;
+  }
 private:
   friend class imgCacheEntry;
   friend class imgRequestProxy;
   friend class imgLoader;
   friend class imgCacheValidator;
   friend class imgCacheExpirationTracker;
 
   inline void SetLoadId(void *aLoadId) {
     mLoadId = aLoadId;
     mLoadTime = PR_Now();
   }
   inline PRUint32 GetImageStatus() const { return mImageStatus; }
-  inline nsresult GetResultFromImageStatus(PRUint32 aStatus) const;
+  inline PRUint32 GetState() const { return mState; }
   void Cancel(nsresult aStatus);
   nsresult GetURI(nsIURI **aURI);
   nsresult GetKeyURI(nsIURI **aURI);
   nsresult GetPrincipal(nsIPrincipal **aPrincipal);
   nsresult GetSecurityInfo(nsISupports **aSecurityInfo);
   void RemoveFromCache();
   inline const char *GetMimeType() const {
     return mContentType.get();
--- a/modules/libpr0n/src/imgRequestProxy.cpp
+++ b/modules/libpr0n/src/imgRequestProxy.cpp
@@ -48,17 +48,17 @@
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
 
 #include "ImageErrors.h"
 #include "ImageLogging.h"
 
 #include "nspr.h"
-
+#include "imgContainerRequest.h"
 
 NS_IMPL_ISUPPORTS4(imgRequestProxy, imgIRequest, nsIRequest,
                    nsISupportsPriority, nsISecurityInfoProvider)
 
 imgRequestProxy::imgRequestProxy() :
   mOwner(nsnull),
   mListener(nsnull),
   mLoadFlags(nsIRequest::LOAD_NORMAL),
@@ -668,8 +668,52 @@ void imgRequestProxy::NullOutListener()
     // Releasing could do weird reentery stuff, so just play it super-safe
     nsCOMPtr<imgIDecoderObserver> obs;
     obs.swap(mListener);
     mListenerIsStrongRef = PR_FALSE;
   } else {
     mListener = nsnull;
   }
 }
+
+NS_IMETHODIMP
+imgRequestProxy::GetStaticRequest(imgIRequest** aReturn)
+{
+  *aReturn = nsnull;
+  nsCOMPtr<imgIContainer> img, currentFrame;
+  GetImage(getter_AddRefs(img));
+  if (img) {
+    PRBool animated = PR_FALSE;
+    nsresult rv = img->GetAnimated(&animated);
+    if (NS_SUCCEEDED(rv) && !animated) {
+      NS_ADDREF(*aReturn = this);
+      return NS_OK;
+    }
+
+    PRInt32 w = 0;
+    PRInt32 h = 0;
+    img->GetWidth(&w);
+    img->GetHeight(&h);
+    nsIntRect rect(0, 0, w, h);
+    img->ExtractFrame(imgIContainer::FRAME_CURRENT, rect,
+                      imgIContainer::FLAG_SYNC_DECODE,
+                      getter_AddRefs(currentFrame));
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  GetURI(getter_AddRefs(uri));
+  PRUint32 imageStatus = 0;
+  GetImageStatus(&imageStatus);
+  nsCOMPtr<nsIPrincipal> principal;
+  GetImagePrincipal(getter_AddRefs(principal));
+
+  imgContainerRequest* req =
+    new imgContainerRequest(currentFrame, uri, imageStatus,
+                            mOwner ? mOwner->GetState() : 0,
+                            principal);
+  if (!req) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  NS_ADDREF(*aReturn = req);
+  return NS_OK;
+}
+
--- a/toolkit/components/printing/content/printPreviewBindings.xml
+++ b/toolkit/components/printing/content/printPreviewBindings.xml
@@ -156,17 +156,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.mPageTextBox.max = 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 
@@ -231,17 +231,17 @@
       </method>
 
       <method name="navigate">
         <parameter name="aDirection"/>
         <parameter name="aPageNum"/>
         <parameter name="aHomeOrEnd"/>
         <body>
         <![CDATA[          
-          var print = PrintUtils.getWebBrowserPrint();
+          var print = PrintUtils.getPrintPreview();
 
           // we use only one of aHomeOrEnd, aDirection, or aPageNum
           if (aHomeOrEnd)
           {
             var homeOrEnd;
             if (aHomeOrEnd == "home")
             {
               homeOrEnd = print.PRINTPREVIEW_HOME;
@@ -362,17 +362,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) {
--- a/toolkit/components/printing/content/printUtils.js
+++ b/toolkit/components/printing/content/printUtils.js
@@ -136,29 +136,37 @@ 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 docShell = getPPBrowser().getBrowserForTab(this._printPreviewTab).docShell;
+      return docShell.printPreview;
+    }
+    return null;
+  },
+
   ////////////////////////////////////////
   // "private" methods. Don't use them. //
   ////////////////////////////////////////
 
   setPrinterDefaultsForSelectedPrinter: function (aPSSVC, aPrintSettings)
   {
     if (!aPrintSettings.printerName)
       aPrintSettings.printerName = aPSSVC.defaultPrinterName;
@@ -214,46 +222,70 @@ 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 ()
   {
     gFocusedElement = document.commandDispatcher.focusedElement;
 
     // Reset the zoom value and save it to be restored later.
     if (typeof ZoomManager == "object") {
       this._originalZoomValue = ZoomManager.zoom;
       ZoomManager.reset();
     }
 
-    var webBrowserPrint = this.getWebBrowserPrint();
-    var printSettings   = this.getPrintSettings();
+    var webBrowserPrint;
+    var printSettings  = this.getPrintSettings();
+    var tabbrowser = getPPBrowser();
+    var contentWindow = null;
+    if (tabbrowser) {
+      if (this._printPreviewTab) {
+        contentWindow =
+          tabbrowser.getBrowserForTab(this._printPreviewTab).contentWindow;
+      } else {
+        this._originalTab = tabbrowser.mCurrentTab;
+        contentWindow = window.content
+        this._printPreviewTab = tabbrowser.loadOneTab("about:blank", null, null,
+                                                      null, true, false);
+      }
+    }
+
     try {
-      webBrowserPrint.printPreview(printSettings, null, this._webProgressPP.value);
+      webBrowserPrint = this.getPrintPreview();
+      webBrowserPrint.printPreview(printSettings, contentWindow,
+                                   this._webProgressPP.value);
     } catch (e) {
+      this._printPreviewTab = null;
+      this._originalTab = null;
       if (typeof ZoomManager == "object")
         ZoomManager.zoom = this._originalZoomValue;
       // 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");
@@ -269,17 +301,18 @@ var PrintUtils = {
       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);
 
-    window.content.focus();
+    tabbrowser.getBrowserForTab(this._printPreviewTab).contentWindow.focus();
+    tabbrowser.selectedTab = this._printPreviewTab;
 
     // on Enter PP Call back
     if (this._onEnterPP) {
       this._onEnterPP();
       this._onEnterPP = null;
     }
   },
 
@@ -288,16 +321,25 @@ var PrintUtils = {
     window.removeEventListener("keypress", this.onKeyPressPP, true);
 
     // restore the old close handler
     document.documentElement.setAttribute("onclose", this._closeHandlerPP);
     this._closeHandlerPP = null;
 
     var webBrowserPrint = this.getWebBrowserPrint();
     webBrowserPrint.exitPrintPreview();
+
+    var tabbrowser = getPPBrowser();
+    if (tabbrowser) {
+      tabbrowser.removeTab(this._printPreviewTab);
+      tabbrowser.selectedTab = this._originalTab;
+      this._originalTab = null;
+      this._printPreviewTab = null;
+    }
+
     if (typeof ZoomManager == "object")
       ZoomManager.zoom = this._originalZoomValue;
 
     // 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"]
--- a/widget/src/windows/nsDeviceContextSpecWin.cpp
+++ b/widget/src/windows/nsDeviceContextSpecWin.cpp
@@ -463,18 +463,20 @@ NS_IMETHODIMP nsDeviceContextSpecWin::In
   } else {
     PR_PL(("***** nsDeviceContextSpecWin::Init - aPrintSettingswas NULL!\n"));
   }
 
   LPDEVMODEW pDevMode  = NULL;
   HGLOBAL   hDevNames = NULL;
 
   // Get the Print Name to be used
-  PRUnichar * printerName;
-  mPrintSettings->GetPrinterName(&printerName);
+  PRUnichar * printerName = nsnull;
+  if (mPrintSettings) {
+    mPrintSettings->GetPrinterName(&printerName);
+  }
 
   // If there is no name then use the default printer
   if (!printerName || (printerName && !*printerName)) {
     printerName = GetDefaultPrinterNameFromGlobalPrinters();
   }
 
   NS_ASSERTION(printerName, "We have to have a printer name");
   if (!printerName || !*printerName) return rv;
@@ -507,18 +509,20 @@ static void CleanAndCopyString(PRUnichar
 }
 
 NS_IMETHODIMP nsDeviceContextSpecWin::GetSurfaceForPrinter(gfxASurface **surface)
 {
   NS_ASSERTION(mDevMode, "DevMode can't be NULL here");
 
   nsRefPtr<gfxASurface> newSurface;
 
-  PRInt16 outputFormat;
-  mPrintSettings->GetOutputFormat(&outputFormat);
+  PRInt16 outputFormat = 0;
+  if (mPrintSettings) {
+    mPrintSettings->GetOutputFormat(&outputFormat);
+  }
 
   if (outputFormat == nsIPrintSettings::kOutputFormatPDF) {
     nsXPIDLString filename;
     mPrintSettings->GetToFileName(getter_Copies(filename));
 
     double width, height;
     mPrintSettings->GetEffectivePageSize(&width, &height);
     // convert twips to points
@@ -533,16 +537,17 @@ NS_IMETHODIMP nsDeviceContextSpecWin::Ge
     nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1");
     rv = stream->Init(file, -1, -1, 0);
     if (NS_FAILED(rv))
       return rv;
 
     newSurface = new gfxPDFSurface(stream, gfxSize(width, height));
   } else {
     if (mDevMode) {
+      NS_WARN_IF_FALSE(mDriverName, "No driver!");
       HDC dc = ::CreateDCW(mDriverName, mDeviceName, NULL, mDevMode);
 
       // have this surface take over ownership of this DC
       newSurface = new gfxWindowsSurface(dc, gfxWindowsSurface::FLAG_TAKE_DC | gfxWindowsSurface::FLAG_FOR_PRINTING);
     }
   }
 
   if (newSurface) {