Bug 505847 - Implement asyncDrawXULElement in 2D canvas. r=bz,bsmedberg
authorJoe Drew <joe@drew.ca>
Wed, 28 Oct 2009 16:55:49 -0400
changeset 36021 9e1daa4eaa0967515cf91f2b9b08d6d2c1739f6a
parent 36020 5f19b649bbb0b1b17980d10bea59f71a9fbc2948
child 36022 873798f6dcdc92f8a5babda59e4825459256ab5d
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbz, bsmedberg
bugs505847
milestone1.9.3a1pre
Bug 505847 - Implement asyncDrawXULElement in 2D canvas. r=bz,bsmedberg
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/canvas/public/DocumentRendererChild.h
content/canvas/public/DocumentRendererParent.h
content/canvas/public/Makefile.in
content/canvas/public/nsICanvasRenderingContextInternal.h
content/canvas/src/DocumentRendererChild.cpp
content/canvas/src/DocumentRendererParent.cpp
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.h
content/canvas/src/nsCanvasRenderingContext2D.cpp
dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl
dom/ipc/PDocumentRenderer.ipdl
dom/ipc/PIFrameEmbedding.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/ipc/ipdl.mk
toolkit/content/tests/fennec-tile-testapp/application.ini
toolkit/content/tests/fennec-tile-testapp/chrome/content/BrowserView.js
toolkit/content/tests/fennec-tile-testapp/chrome/content/TileManager.js
toolkit/content/tests/fennec-tile-testapp/chrome/content/foo.xul
toolkit/content/tests/fennec-tile-testapp/defaults/preferences/prefs.js
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -1431,8 +1431,19 @@ nsFrameLoader::TryNewProcess()
 
 #else
 #error TODO for this platform
 #endif
 
   return PR_TRUE;
 }
 #endif
+
+mozilla::dom::PIFrameEmbeddingParent*
+nsFrameLoader::GetChildProcess()
+{
+#ifdef MOZ_IPC
+  return mChildProcess;
+#else
+  return nsnull;
+#endif
+}
+
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -54,16 +54,17 @@
 class nsIContent;
 class nsIURI;
 class nsIFrameFrame;
 
 #ifdef MOZ_IPC
 namespace mozilla {
   namespace dom {
     class TabParent;
+    class PIFrameEmbeddingParent;
   }
 }
 #endif
 
 class nsFrameLoader : public nsIFrameLoader
 {
 protected:
   nsFrameLoader(nsIContent *aOwner) :
@@ -111,16 +112,21 @@ public:
   void Hide();
 
   // 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);
+
+#ifdef MOZ_IPC
+  mozilla::dom::PIFrameEmbeddingParent* GetChildProcess();
+#endif
+
 private:
 
 #ifdef MOZ_IPC
   bool ShouldUseRemoteProcess();
 #endif
 
   /**
    * If we are an IPC frame, set mRemoteFrame. Otherwise, create and
new file mode 100644
--- /dev/null
+++ b/content/canvas/public/DocumentRendererChild.h
@@ -0,0 +1,68 @@
+/* ***** 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 Fennec Electrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 mozilla_dom_DocumentRendererChild
+#define mozilla_dom_DocumentRendererChild
+
+#include "mozilla/ipc/PDocumentRendererChild.h"
+#include "nsICanvasRenderingContextInternal.h"
+#include "nsString.h"
+#include "gfxContext.h"
+
+class nsIDOMWindow;
+
+namespace mozilla {
+namespace ipc {
+
+class DocumentRendererChild : public PDocumentRendererChild
+{
+public:
+    DocumentRendererChild();
+    virtual ~DocumentRendererChild();
+    
+    bool RenderDocument(nsIDOMWindow *window, const PRInt32& x, const PRInt32& y, const PRInt32& w, const PRInt32& h,
+			    const nsString& bgcolor, const PRUint32& flags, const PRBool& flush, 
+			    PRUint32& _width, PRUint32& _height, nsCString& data);
+
+private:
+
+    DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererChild);
+};
+
+}
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/canvas/public/DocumentRendererParent.h
@@ -0,0 +1,70 @@
+/* ***** 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 Fennec Electrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 mozilla_dom_DocumentRendererParent
+#define mozilla_dom_DocumentRendererParent
+
+#include "mozilla/ipc/PDocumentRendererParent.h"
+#include "nsICanvasRenderingContextInternal.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "gfxContext.h"
+
+namespace mozilla {
+namespace ipc {
+
+class DocumentRendererParent : public PDocumentRendererParent
+{
+public:
+    DocumentRendererParent();
+    virtual ~DocumentRendererParent();
+
+    void SetCanvasContext(nsICanvasRenderingContextInternal* aCanvas,
+			  gfxContext* ctx);
+    void DrawToCanvas(PRUint32 aWidth, PRUint32 aHeight,
+		      const nsCString& aData);
+
+private:
+    nsCOMPtr<nsICanvasRenderingContextInternal> mCanvas;
+    nsRefPtr<gfxContext> mCanvasContext;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererParent);
+};
+
+}
+}
+
+#endif
--- a/content/canvas/public/Makefile.in
+++ b/content/canvas/public/Makefile.in
@@ -40,19 +40,26 @@ topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 XPIDL_MODULE = content_canvas
 
+EXPORTS_NAMESPACES = mozilla/ipc
+
 EXPORTS		= \
 		nsICanvasRenderingContextInternal.h \
 		nsICanvasElement.h \
 		WebGLArray.h \
 		$(NULL)
 
+EXPORTS_mozilla/ipc = \
+		DocumentRendererChild.h \
+		DocumentRendererParent.h \
+		$(NULL)
+
 XPIDLSRCS	= \
 		nsICanvasGLPrivate.idl \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/content/canvas/public/nsICanvasRenderingContextInternal.h
+++ b/content/canvas/public/nsICanvasRenderingContextInternal.h
@@ -82,14 +82,17 @@ public:
   // return the surface.  Otherwise returns an error.
   NS_IMETHOD GetThebesSurface(gfxASurface **surface) = 0;
 
   // If this context is opaque, the backing store of the canvas should
   // be created as opaque; all compositing operators should assume the
   // dst alpha is always 1.0.  If this is never called, the context
   // defaults to false (not opaque).
   NS_IMETHOD SetIsOpaque(PRBool isOpaque) = 0;
+
+  // Redraw the dirty rectangle of this canvas.
+  NS_IMETHOD Redraw(const gfxRect &dirty) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
                               NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
 
 #endif /* nsICanvasRenderingContextInternal_h___ */
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/DocumentRendererChild.cpp
@@ -0,0 +1,144 @@
+/* ***** 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 Fennec Electrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 "mozilla/ipc/DocumentRendererChild.h"
+#include "gfxImageSurface.h"
+#include "gfxPattern.h"
+#include "nsPIDOMWindow.h"
+#include "nsIDOMWindow.h"
+#include "nsIDOMDocument.h"
+#include "nsIDocShellTreeNode.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIDocument.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsICSSParser.h"
+#include "nsPresContext.h"
+#include "nsCOMPtr.h"
+#include "nsColor.h"
+#include "gfxContext.h"
+#include "gfxImageSurface.h"
+#include "nsLayoutUtils.h"
+
+using namespace mozilla::ipc;
+
+DocumentRendererChild::DocumentRendererChild()
+{}
+
+DocumentRendererChild::~DocumentRendererChild()
+{}
+
+static void
+FlushLayoutForTree(nsIDOMWindow* aWindow)
+{
+    nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
+    if (!piWin)
+        return;
+
+    // Note that because FlushPendingNotifications flushes parents, this
+    // is O(N^2) in docshell tree depth.  However, the docshell tree is
+    // usually pretty shallow.
+
+    nsCOMPtr<nsIDOMDocument> domDoc;
+    aWindow->GetDocument(getter_AddRefs(domDoc));
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+    if (doc) {
+        doc->FlushPendingNotifications(Flush_Layout);
+    }
+
+    nsCOMPtr<nsIDocShellTreeNode> node =
+        do_QueryInterface(piWin->GetDocShell());
+    if (node) {
+        PRInt32 i = 0, i_end;
+        node->GetChildCount(&i_end);
+        for (; i < i_end; ++i) {
+            nsCOMPtr<nsIDocShellTreeItem> item;
+            node->GetChildAt(i, getter_AddRefs(item));
+            nsCOMPtr<nsIDOMWindow> win = do_GetInterface(item);
+            if (win) {
+                FlushLayoutForTree(win);
+            }
+        }
+    }
+}
+
+bool
+DocumentRendererChild::RenderDocument(nsIDOMWindow *window, const PRInt32& x, const PRInt32& y, const PRInt32& w, const PRInt32& h,
+                                      const nsString& aBGColor, const PRUint32& flags, const PRBool& flush, 
+                                      PRUint32& _width, PRUint32& _height, nsCString& data)
+{
+    if (flush)
+        FlushLayoutForTree(window);
+
+    nsCOMPtr<nsPresContext> presContext;
+    nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
+    if (win) {
+        nsIDocShell* docshell = win->GetDocShell();
+        if (docshell) {
+            docshell->GetPresContext(getter_AddRefs(presContext));
+        }
+    }
+    if (!presContext)
+        return NS_ERROR_FAILURE;
+
+    nscolor bgColor;
+    nsCOMPtr<nsICSSParser> parser = do_CreateInstance("@mozilla.org/content/css-parser;1");
+    nsresult rv = parser->ParseColorString(PromiseFlatString(aBGColor),
+                                           nsnull, 0, &bgColor);
+    if (NS_FAILED(rv))
+        return false;
+
+    nsIPresShell* presShell = presContext->PresShell();
+
+    nsRect r(x, y, w, h);
+
+    _width = nsPresContext::AppUnitsToIntCSSPixels(w);
+    _height = nsPresContext::AppUnitsToIntCSSPixels(h);
+
+    // Draw directly into the output array.
+    data.SetLength(_width * _height * 4);
+    nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(reinterpret_cast<PRUint8*>(const_cast<char*>(data.get())),
+                                                         gfxIntSize(_width, _height),
+                                                         4 * _width, gfxASurface::ImageFormatARGB32);
+    nsRefPtr<gfxContext> ctx = new gfxContext(surf);
+
+    PRBool oldDisableValue = nsLayoutUtils::sDisableGetUsedXAssertions;
+    nsLayoutUtils::sDisableGetUsedXAssertions = oldDisableValue || !flush;
+    presShell->RenderDocument(r, flags, bgColor, ctx);
+    nsLayoutUtils::sDisableGetUsedXAssertions = oldDisableValue;
+
+    return true;
+}
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/DocumentRendererParent.cpp
@@ -0,0 +1,77 @@
+/* ***** 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 Fennec Electrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 "mozilla/ipc/DocumentRendererParent.h"
+#include "gfxImageSurface.h"
+#include "gfxPattern.h"
+
+using namespace mozilla::ipc;
+
+DocumentRendererParent::DocumentRendererParent()
+{}
+
+DocumentRendererParent::~DocumentRendererParent()
+{}
+
+void DocumentRendererParent::SetCanvasContext(nsICanvasRenderingContextInternal* aCanvas,
+                                              gfxContext* ctx)
+{
+    mCanvas = aCanvas;
+    mCanvasContext = ctx;
+}
+
+void DocumentRendererParent::DrawToCanvas(PRUint32 aWidth, PRUint32 aHeight,
+                                          const nsCString& aData)
+{
+    if (!mCanvas || !mCanvasContext)
+        return;
+
+    nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(reinterpret_cast<PRUint8*>(const_cast<char*>(aData.Data())),
+                                                         gfxIntSize(aWidth, aHeight),
+                                                         aWidth * 4,
+                                                         gfxASurface::ImageFormatARGB32);
+    nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
+
+    mCanvasContext->NewPath();
+    mCanvasContext->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, aWidth, aHeight), pat);
+    mCanvasContext->Fill();
+
+    // get rid of the pattern surface ref, because aData is very likely to go away shortly
+    mCanvasContext->SetColor(gfxRGBA(1,1,1,1));
+
+    gfxRect damageRect = mCanvasContext->UserToDevice(gfxRect(0, 0, aWidth, aHeight));
+    mCanvas->Redraw(damageRect);
+}
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -48,16 +48,23 @@ LIBXUL_LIBRARY  = 1
 
 
 
 CPPSRCS	= \
 	CanvasUtils.cpp \
 	nsCanvasRenderingContext2D.cpp \
 	$(NULL)
 
+ifdef MOZ_IPC
+CPPSRCS += \
+	DocumentRendererParent.cpp \
+	DocumentRendererChild.cpp \
+	$(NULL)
+endif
+
 # Canvas 3D Pieces
 
 ifdef MOZ_WEBGL
 
 CPPSRCS += \
 	WebGLContext.cpp \
 	WebGLContextGL.cpp \
 	WebGLContextUtils.cpp \
@@ -95,16 +102,17 @@ else
 CPPSRCS += WebGLContextNotSupported.cpp
 
 endif
 
 # 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
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 CXXFLAGS	+= $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
 
 INCLUDES	+= \
 		-I$(srcdir)/../../../layout/xul/base/src \
 		-I$(srcdir)/../../../layout/style \
 		-I$(srcdir)/../../../layout/generic \
 		-I$(srcdir)/../../base/src \
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -238,16 +238,17 @@ public:
     NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height)
         { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter f);
     NS_IMETHOD GetInputStream(const char* aMimeType,
                               const PRUnichar* aEncoderOptions,
                               nsIInputStream **aStream);
     NS_IMETHOD GetThebesSurface(gfxASurface **surface);
     NS_IMETHOD SetIsOpaque(PRBool b) { return NS_OK; };
+    NS_IMETHOD Redraw(const gfxRect&) { return NS_ERROR_NOT_IMPLEMENTED; }
 
 protected:
     GLES20Wrap *gl;
 
     nsICanvasElement* mCanvasElement;
 
     nsGLPbuffer *mGLPbuffer;
     PRInt32 mWidth, mHeight;
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -32,16 +32,23 @@
  * 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 ***** */
 
+#ifdef MOZ_IPC
+#include "mozilla/ipc/PDocumentRendererParent.h"
+#include "mozilla/dom/PIFrameEmbeddingParent.h"
+#include "mozilla/ipc/DocumentRendererParent.h"
+#endif
+#include "nsIDOMXULElement.h"
+
 #ifdef _MSC_VER
 #define _USE_MATH_DEFINES
 #endif
 #include <math.h>
 
 #include "prmem.h"
 
 #include "nsIServiceManager.h"
@@ -98,16 +105,18 @@
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "gfxFont.h"
 #include "gfxTextRunCache.h"
 #include "gfxBlur.h"
 
 #include "nsFrameManager.h"
 
+#include "nsFrameLoader.h"
+
 #include "nsBidiPresUtils.h"
 
 #include "CanvasUtils.h"
 
 using namespace mozilla;
 
 #ifndef M_PI
 #define M_PI		3.14159265358979323846
@@ -306,29 +315,29 @@ class nsCanvasRenderingContext2D :
     public nsIDOMCanvasRenderingContext2D,
     public nsICanvasRenderingContextInternal
 {
 public:
     nsCanvasRenderingContext2D();
     virtual ~nsCanvasRenderingContext2D();
 
     nsresult Redraw();
-    // this rect is in CSS pixels
-    nsresult Redraw(const gfxRect& r);
 
     // nsICanvasRenderingContextInternal
     NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
     NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
     NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height);
     NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter);
     NS_IMETHOD GetInputStream(const char* aMimeType,
                               const PRUnichar* aEncoderOptions,
                               nsIInputStream **aStream);
     NS_IMETHOD GetThebesSurface(gfxASurface **surface);
     NS_IMETHOD SetIsOpaque(PRBool isOpaque);
+    // this rect is in CSS pixels
+    NS_IMETHOD Redraw(const gfxRect &r);
 
     // nsISupports interface
     NS_DECL_ISUPPORTS
 
     // nsIDOMCanvasRenderingContext2D interface
     NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D
 
     enum Style {
@@ -843,17 +852,17 @@ nsCanvasRenderingContext2D::Redraw()
 
     if (mIsEntireFrameInvalid)
         return NS_OK;
 
     mIsEntireFrameInvalid = PR_TRUE;
     return mCanvasElement->InvalidateFrame();
 }
 
-nsresult
+NS_IMETHODIMP
 nsCanvasRenderingContext2D::Redraw(const gfxRect& r)
 {
     if (!mCanvasElement)
         return NS_OK;
 
     if (mIsEntireFrameInvalid)
         return NS_OK;
 
@@ -3300,16 +3309,78 @@ nsCanvasRenderingContext2D::DrawWindow(n
     // space.
     gfxRect damageRect = mThebes->UserToDevice(gfxRect(0, 0, aW, aH));
 
     Redraw(damageRect);
 
     return rv;
 }
 
+NS_IMETHODIMP
+nsCanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* aElem, float aX, float aY,
+                                                float aW, float aH,
+                                                const nsAString& aBGColor,
+                                                PRUint32 flags)
+{
+    NS_ENSURE_ARG(aElem != nsnull);
+
+    // We can't allow web apps to call this until we fix at least the
+    // following potential security issues:
+    // -- rendering cross-domain IFRAMEs and then extracting the results
+    // -- rendering the user's theme and then extracting the results
+    // -- rendering native anonymous content (e.g., file input paths;
+    // scrollbars should be allowed)
+    if (!nsContentUtils::IsCallerTrustedForRead()) {
+        // not permitted to use DrawWindow
+        // XXX ERRMSG we need to report an error to developers here! (bug 329026)
+        return NS_ERROR_DOM_SECURITY_ERR;
+    }
+
+    nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(aElem);
+    if (!loaderOwner)
+        return NS_ERROR_FAILURE;
+
+    nsCOMPtr<nsFrameLoader> frameloader = loaderOwner->GetFrameLoader();
+    if (!frameloader)
+        return NS_ERROR_FAILURE;
+
+    mozilla::dom::PIFrameEmbeddingParent *child = frameloader->GetChildProcess();
+    if (!child)
+        return NS_ERROR_FAILURE;
+
+    // protect against too-large surfaces that will cause allocation
+    // or overflow issues
+    if (!gfxASurface::CheckSurfaceSize(gfxIntSize(aW, aH), 0xffff))
+        return NS_ERROR_FAILURE;
+
+    PRBool flush =
+        (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH) == 0;
+
+    PRUint32 renderDocFlags = nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
+    if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_CARET) {
+        renderDocFlags |= nsIPresShell::RENDER_CARET;
+    }
+    if (flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_VIEW) {
+        renderDocFlags &= ~nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
+    }
+
+    PRInt32 x = nsPresContext::CSSPixelsToAppUnits(aX),
+            y = nsPresContext::CSSPixelsToAppUnits(aY),
+            w = nsPresContext::CSSPixelsToAppUnits(aW),
+            h = nsPresContext::CSSPixelsToAppUnits(aH);
+
+    mozilla::ipc::PDocumentRendererParent *pdocrender =
+        child->SendPDocumentRendererConstructor(x, y, w, h, nsString(aBGColor), renderDocFlags, flush);
+    mozilla::ipc::DocumentRendererParent *docrender = static_cast<mozilla::ipc::DocumentRendererParent *>(pdocrender);
+
+    docrender->SetCanvasContext(this, mThebes);
+
+    return NS_OK;
+}
+
 //
 // device pixel getting/setting
 //
 extern "C" {
 #include "jstypes.h"
 JS_FRIEND_API(JSBool)
 js_CoerceArrayToCanvasImageData(JSObject *obj, jsuint offset, jsuint count,
                                 JSUint8 *dest);
--- a/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl
+++ b/dom/interfaces/canvas/nsIDOMCanvasRenderingContext2D.idl
@@ -38,16 +38,17 @@
 #include "nsISupports.idl"
 #include "nsIVariant.idl"
 
 interface nsIDOMWindow;
 interface nsIDOMElement;
 interface nsIDOMHTMLElement;
 interface nsIDOMHTMLImageElement;
 interface nsIDOMHTMLCanvasElement;
+interface nsIDOMXULElement;
 
 [scriptable, uuid(bbb20a59-524e-4662-981e-5e142814b20c)]
 interface nsIDOMCanvasGradient : nsISupports
 {
   void addColorStop(in float offset, in DOMString color);
 };
 
 [scriptable, uuid(21dea65c-5c08-4eb1-ac82-81fe95be77b8)]
@@ -56,17 +57,17 @@ interface nsIDOMCanvasPattern : nsISuppo
 };
 
 [scriptable, uuid(2d01715c-ec7d-424a-ab85-e0fd70c8665c)]
 interface nsIDOMTextMetrics : nsISupports
 {
   readonly attribute float width;
 };
 
-[scriptable, uuid(72635fb6-0c1c-47d7-bf69-49388d5980fc)]
+[scriptable, uuid(408be1b9-4d75-4873-b50b-9b651626e41d)]
 interface nsIDOMCanvasRenderingContext2D : nsISupports
 {
   // back-reference to the canvas element for which
   // this context was created
   readonly attribute nsIDOMHTMLCanvasElement canvas;
 
   // state
   void save();
@@ -217,9 +218,12 @@ interface nsIDOMCanvasRenderingContext2D
    * transparency.
    *
    * This API cannot currently be used by Web content. It is chrome
    * only.
    */
   void drawWindow(in nsIDOMWindow window, in float x, in float y,
                   in float w, in float h, in DOMString bgColor,
                   [optional] in unsigned long flags);
+  void asyncDrawXULElement(in nsIDOMXULElement elem, in float x, in float y,
+                  in float w, in float h, in DOMString bgColor,
+                  [optional] in unsigned long flags);
 };
new file mode 100644
--- /dev/null
+++ b/dom/ipc/PDocumentRenderer.ipdl
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Fenntrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 protocol "PIFrameEmbedding.ipdl";
+
+namespace mozilla {
+namespace ipc {
+
+protocol PDocumentRenderer
+{
+  manager PIFrameEmbedding;
+};
+
+} // namespace ipc
+} // namespace mozilla
--- a/dom/ipc/PIFrameEmbedding.ipdl
+++ b/dom/ipc/PIFrameEmbedding.ipdl
@@ -33,29 +33,38 @@
  * 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 protocol "PContentProcess.ipdl";
+include protocol "PDocumentRenderer.ipdl";
 
 using PRUint32;
+using PRInt32;
 
 namespace mozilla {
 namespace dom {
 
 async protocol PIFrameEmbedding
 {
     manager PContentProcess;
+    manages PDocumentRenderer;
 
 child:
     loadURL(nsCString uri);
 
     move(PRUint32 x,
          PRUint32 y,
          PRUint32 width,
          PRUint32 height);
+
+    PDocumentRenderer(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, nsString bgcolor, PRUint32 flags, bool flush);
+
+parent:
+
+    ~PDocumentRenderer(PRUint32 w, PRUint32 h, nsCString data);
 };
 
 }
 }
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -37,18 +37,21 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "TabChild.h"
 
 #include "nsIWebBrowser.h"
 #include "nsEmbedCID.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIBaseWindow.h"
+#include "nsIDOMWindow.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsThreadUtils.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "mozilla/ipc/DocumentRendererChild.h"
 
 #ifdef MOZ_WIDGET_GTK2
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #endif
 
 using namespace mozilla::dom;
 
@@ -110,8 +113,66 @@ TabChild::Recvmove(const PRUint32& x,
 {
     printf("[TabChild] MOVE to (x,y)=(%ud, %ud), (w,h)= (%ud, %ud)\n",
            x, y, width, height);
 
     nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mWebNav);
     baseWin->SetPositionAndSize(x, y, width, height, PR_TRUE);
     return true;
 }
+
+mozilla::ipc::PDocumentRendererChild*
+TabChild::AllocPDocumentRenderer(
+        const PRInt32& x,
+        const PRInt32& y,
+        const PRInt32& w,
+        const PRInt32& h,
+        const nsString& bgcolor,
+        const PRUint32& flags,
+        const bool& flush)
+{
+    return new mozilla::ipc::DocumentRendererChild();
+}
+
+bool
+TabChild::DeallocPDocumentRenderer(
+        mozilla::ipc::PDocumentRendererChild* __a,
+        const PRUint32& w,
+        const PRUint32& h,
+        const nsCString& data)
+{
+    delete __a;
+    return true;
+}
+
+bool
+TabChild::RecvPDocumentRendererConstructor(
+        mozilla::ipc::PDocumentRendererChild *__a,
+        const PRInt32& aX,
+        const PRInt32& aY,
+        const PRInt32& aW,
+        const PRInt32& aH,
+        const nsString& bgcolor,
+        const PRUint32& flags,
+        const bool& flush)
+{
+    mozilla::ipc::DocumentRendererChild *render = 
+        static_cast<mozilla::ipc::DocumentRendererChild *>(__a);
+
+    nsCOMPtr<nsIWebBrowser> browser = do_QueryInterface(mWebNav);
+    if (!browser)
+        return true; // silently ignore
+    nsCOMPtr<nsIDOMWindow> window;
+    if (NS_FAILED(browser->GetContentDOMWindow(getter_AddRefs(window))) ||
+        !window)
+    {
+        return true; // silently ignore
+    }
+
+    PRUint32 width, height;
+    nsCString data;
+    nsresult rv = render->RenderDocument(window, aX, aY, aW, aH, bgcolor, flags, flush,
+                                         width, height, data);
+    if (NS_FAILED(rv))
+        return true; // silently ignore
+
+    return SendPDocumentRendererDestructor(__a, width, height, data);
+}
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -52,16 +52,38 @@ public:
     TabChild(const MagicWindowHandle& parentWidget);
     virtual ~TabChild();
 
     virtual bool RecvloadURL(const nsCString& uri);
     virtual bool Recvmove(const PRUint32& x,
                           const PRUint32& y,
                           const PRUint32& width,
                           const PRUint32& height);
+    virtual mozilla::ipc::PDocumentRendererChild* AllocPDocumentRenderer(
+            const PRInt32& x,
+            const PRInt32& y,
+            const PRInt32& w,
+            const PRInt32& h,
+            const nsString& bgcolor,
+            const PRUint32& flags,
+            const bool& flush);
+    virtual bool DeallocPDocumentRenderer(
+            mozilla::ipc::PDocumentRendererChild* __a,
+            const PRUint32& w,
+            const PRUint32& h,
+            const nsCString& data);
+    virtual bool RecvPDocumentRendererConstructor(
+            mozilla::ipc::PDocumentRendererChild *__a,
+            const PRInt32& x,
+            const PRInt32& y,
+            const PRInt32& w,
+            const PRInt32& h,
+            const nsString& bgcolor,
+            const PRUint32& flags,
+            const bool& flush);
 
 private:
     nsCOMPtr<nsIWebNavigation> mWebNav;
 
     DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 }
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -34,20 +34,22 @@
  * 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 "TabParent.h"
 
 #include "mozilla/ipc/GeckoThread.h"
+#include "mozilla/ipc/DocumentRendererParent.h"
 
 #include "nsIURI.h"
 
 using mozilla::ipc::BrowserProcessSubThread;
+using mozilla::ipc::DocumentRendererParent;
 
 namespace mozilla {
 namespace dom {
 
 TabParent::TabParent()
 {
 }
 
@@ -65,10 +67,38 @@ TabParent::LoadURL(nsIURI* aURI)
 }
 
 void
 TabParent::Move(PRUint32 x, PRUint32 y, PRUint32 width, PRUint32 height)
 {
     Sendmove(x, y, width, height);
 }
 
+mozilla::ipc::PDocumentRendererParent*
+TabParent::AllocPDocumentRenderer(const PRInt32& x,
+        const PRInt32& y, const PRInt32& w, const PRInt32& h, const nsString& bgcolor,
+        const PRUint32& flags, const bool& flush)
+{
+    return new DocumentRendererParent();
+}
+
+bool
+TabParent::DeallocPDocumentRenderer(mozilla::ipc::PDocumentRendererParent* __a,
+        const PRUint32& w, const PRUint32& h, const nsCString& data)
+{
+    NS_ENSURE_ARG_POINTER(__a);
+    delete __a;
+    return true;
+}
+
+bool
+TabParent::RecvPDocumentRendererDestructor(PDocumentRendererParent* __a,
+        const PRUint32& w, const PRUint32& h, const nsCString& data)
+{
+    NS_ENSURE_ARG_POINTER(__a);
+    DocumentRendererParent *renderer = static_cast<DocumentRendererParent *>(__a);
+    renderer->DrawToCanvas(w, h, data);
+
+    return true;
+}
+
 } // namespace tabs
 } // namespace mozilla
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -51,14 +51,33 @@ namespace dom {
 class TabParent : public PIFrameEmbeddingParent
 {
 public:
     TabParent();
     virtual ~TabParent();
 
     void LoadURL(nsIURI* aURI);
     void Move(PRUint32 x, PRUint32 y, PRUint32 width, PRUint32 height);
+
+    virtual mozilla::ipc::PDocumentRendererParent* AllocPDocumentRenderer(
+            const PRInt32& x,
+            const PRInt32& y,
+            const PRInt32& w,
+            const PRInt32& h,
+            const nsString& bgcolor,
+            const PRUint32& flags,
+            const bool& flush);
+    virtual bool DeallocPDocumentRenderer(
+            mozilla::ipc::PDocumentRendererParent* __a,
+            const PRUint32& w,
+            const PRUint32& h,
+            const nsCString& data);
+    virtual bool RecvPDocumentRendererDestructor(
+            mozilla::ipc::PDocumentRendererParent* __a,
+            const PRUint32& w,
+            const PRUint32& h,
+            const nsCString& data);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/ipc/ipdl.mk
+++ b/dom/ipc/ipdl.mk
@@ -32,9 +32,10 @@
 # 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 *****
 
 IPDLSRCS = \
   PContentProcess.ipdl \
   PIFrameEmbedding.ipdl \
+  PDocumentRenderer.ipdl \
   $(NULL)
--- a/toolkit/content/tests/fennec-tile-testapp/application.ini
+++ b/toolkit/content/tests/fennec-tile-testapp/application.ini
@@ -3,9 +3,9 @@ Vendor=venderr
 Name=tile
 Version=1.0
 BuildID=20060101
 Copyright=Copyright (c) 2006 Mark Finkle
 ID=xulapp@starkravingfinkle.org
 
 [Gecko]
 MinVersion=1.8
-MaxVersion=1.9.2.*
+MaxVersion=2.0
--- a/toolkit/content/tests/fennec-tile-testapp/chrome/content/BrowserView.js
+++ b/toolkit/content/tests/fennec-tile-testapp/chrome/content/BrowserView.js
@@ -179,25 +179,17 @@ function() {
     dump('--------------------------' + endl);
   }
 
   function getViewportStateFromBrowser(browser) {
     return browser.__BrowserView__vps;
   }
 
   function getBrowserDimensions(browser) {
-    let cdoc = browser.contentDocument;
-
-    // These might not exist yet depending on page load state
-    let body = cdoc.body || {};
-    let html = cdoc.documentElement || {};
-    let w = Math.max(body.scrollWidth || 0, html.scrollWidth);
-    let h = Math.max(body.scrollHeight || 0, html.scrollHeight);
-
-    return [w, h];
+    return [browser.scrollWidth, browser.scrollHeight];
   }
 
   function getContentScrollValues(browser) {
     let cwu = getBrowserDOMWindowUtils(browser);
     let scrollX = {};
     let scrollY = {};
     cwu.getScrollXY(false, scrollX, scrollY);
 
--- a/toolkit/content/tests/fennec-tile-testapp/chrome/content/TileManager.js
+++ b/toolkit/content/tests/fennec-tile-testapp/chrome/content/TileManager.js
@@ -849,29 +849,30 @@ TileManager.Tile.prototype = {
     if (!this.isDirty())
       this.markDirty();
 
     let rect = this._dirtyTileCanvasRect;
 
     let x = rect.left - this.boundRect.left;
     let y = rect.top - this.boundRect.top;
 
-    browserView.viewportToBrowserRect(rect);
+    // content process is not being scaled, so don't scale our rect either
+    //browserView.viewportToBrowserRect(rect);
     //rect.round(); // snap outward to get whole "pixel" (in browser coords)
 
     let ctx = this._canvas.getContext("2d");
     ctx.save();
 
     browserView.browserToViewportCanvasContext(ctx);
 
     ctx.translate(x, y);
 
     let cw = browserView._contentWindow;
     //let cw = browser.contentWindow;
-    ctx.drawWindow(cw,
+    ctx.asyncDrawXULElement(browserView._browser,
                    rect.left, rect.top,
                    rect.right - rect.left, rect.bottom - rect.top,
                    "grey",
                    (ctx.DRAWWINDOW_DO_NOT_FLUSH | ctx.DRAWWINDOW_DRAW_CARET));
 
     ctx.restore();
 
     this.unmarkDirty();
--- a/toolkit/content/tests/fennec-tile-testapp/chrome/content/foo.xul
+++ b/toolkit/content/tests/fennec-tile-testapp/chrome/content/foo.xul
@@ -456,14 +456,14 @@ function getVisibleRect() {
   <vbox id="right_sidebar" class="sidebar" style="background-color: blue"><button label="right sidebar"/></vbox>
   </hbox>
 </scrollbox>
 
   <box>
     <html:div style="position: relative; overflow: hidden; max-width: 0px; max-height: 0px; visibility: hidden;">
     <html:div id="browsers" style="position: absolute;">
         <!-- <browser id="googlenews" src="http://www.webhamster.com/" type="content" style="width: 1024px; height: 614px"/> -->
-	<browser id="googlenews" src="http://news.google.com/" type="content" style="width: 1024px; height: 614px"/>
+	<iframe id="googlenews" src="http://news.google.com/" type="content" style="width: 1024px; height: 614px"/>
     </html:div>
     </html:div>
   </box>
 
 </window>
--- a/toolkit/content/tests/fennec-tile-testapp/defaults/preferences/prefs.js
+++ b/toolkit/content/tests/fennec-tile-testapp/defaults/preferences/prefs.js
@@ -1,4 +1,5 @@
 pref("toolkit.defaultChromeURI", "chrome://tile/content/foo.xul");
 pref("javascript.options.jit.chrome",  true);
 pref("javascript.options.jit.content", false);
 pref("browser.dom.window.dump.enabled", true);
+pref("dom.ipc.tabs.enabled", true);