Bug 1475139 part 12 - Expose drawSnapshot API to <browser>. r=nika
authorRyan Hunt <rhunt@eqrion.net>
Mon, 24 Sep 2018 21:48:30 -0500
changeset 495738 4de4f6aaef1056ec2d7f3555f7afb1595fb0e4ed
parent 495737 d393cf125c13a93eb22e353da552377bb57eeb9e
child 495739 c6e6514203c9172dd1cbc99c505d42ae84e8b32a
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1475139
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1475139 part 12 - Expose drawSnapshot API to <browser>. r=nika This commit initially exposes the drawSnapshot API off of <browser>. This is done by adding a WebIDL binding to FrameLoader and wrapping it in browser.xml. Differential Revision: https://phabricator.services.mozilla.com/D6791
dom/base/nsFrameLoader.cpp
dom/base/nsFrameLoader.h
dom/webidl/FrameLoader.webidl
toolkit/content/widgets/browser.xml
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -75,18 +75,21 @@
 #include "mozilla/GuardObjects.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/NullPrincipal.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/ChromeMessageSender.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FrameLoaderBinding.h"
+#include "mozilla/gfx/CrossProcessPaint.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layout/RenderFrameParent.h"
+#include "mozilla/ServoCSSParser.h"
+#include "mozilla/ServoStyleSet.h"
 #include "nsGenericHTMLFrameElement.h"
 #include "GeckoProfiler.h"
 
 #include "jsapi.h"
 #include "mozilla/dom/HTMLIFrameElement.h"
 #include "nsSandboxFlags.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/dom/CustomEvent.h"
@@ -3098,16 +3101,74 @@ nsFrameLoader::Print(uint64_t aOuterWind
   nsresult rv = webBrowserPrint->Print(aPrintSettings, aProgressListener);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 #endif
 }
 
+already_AddRefed<mozilla::dom::Promise>
+nsFrameLoader::DrawSnapshot(double aX,
+                            double aY,
+                            double aW,
+                            double aH,
+                            double aScale,
+                            const nsAString& aBackgroundColor,
+                            mozilla::ErrorResult& aRv)
+{
+  RefPtr<nsIGlobalObject> global = GetOwnerContent()->GetOwnerGlobal();
+  RefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return nullptr;
+  }
+
+  RefPtr<nsIDocument> document = GetOwnerContent()->GetOwnerDocument();
+  if (NS_WARN_IF(!document)) {
+    aRv = NS_ERROR_FAILURE;
+    return nullptr;
+  }
+  nsIPresShell* presShell = document->GetShell();
+  if (NS_WARN_IF(!presShell)) {
+    aRv = NS_ERROR_FAILURE;
+    return nullptr;
+  }
+
+  nscolor color;
+  css::Loader* loader = document->CSSLoader();
+  ServoStyleSet* set = presShell->StyleSet();
+  if (NS_WARN_IF(!ServoCSSParser::ComputeColor(set,
+                                               NS_RGB(0, 0, 0),
+                                               aBackgroundColor,
+                                               &color,
+                                               nullptr,
+                                               loader))) {
+    aRv = NS_ERROR_FAILURE;
+    return nullptr;
+  }
+
+  gfx::IntRect rect = gfx::IntRect::RoundOut(gfx::Rect(aX, aY, aW, aH));
+
+  if (IsRemoteFrame()) {
+    gfx::CrossProcessPaint::StartRemote(mRemoteBrowser->GetTabId(),
+                                        rect,
+                                        aScale,
+                                        color,
+                                        promise);
+  } else {
+    gfx::CrossProcessPaint::StartLocal(mDocShell,
+                                       rect,
+                                       aScale,
+                                       color,
+                                       promise);
+  }
+
+  return promise.forget();
+}
+
 already_AddRefed<nsITabParent>
 nsFrameLoader::GetTabParent()
 {
   return do_AddRef(mRemoteBrowser);
 }
 
 already_AddRefed<nsILoadContext>
 nsFrameLoader::LoadContext()
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -166,16 +166,25 @@ public:
 
   void RequestUpdatePosition(mozilla::ErrorResult& aRv);
 
   void Print(uint64_t aOuterWindowID,
              nsIPrintSettings* aPrintSettings,
              nsIWebProgressListener* aProgressListener,
              mozilla::ErrorResult& aRv);
 
+  already_AddRefed<mozilla::dom::Promise>
+  DrawSnapshot(double aX,
+               double aY,
+               double aW,
+               double aH,
+               double aScale,
+               const nsAString& aBackgroundColor,
+               mozilla::ErrorResult& aRv);
+
   void StartPersistence(uint64_t aOuterWindowID,
                         nsIWebBrowserPersistDocumentReceiver* aRecv,
                         mozilla::ErrorResult& aRv);
 
   // WebIDL getters
 
   already_AddRefed<mozilla::dom::MessageSender> GetMessageManager();
 
--- a/dom/webidl/FrameLoader.webidl
+++ b/dom/webidl/FrameLoader.webidl
@@ -104,16 +104,40 @@ interface FrameLoader {
    * @param aProgressListener optional print progress listener.
    */
   [Throws]
   void print(unsigned long long aOuterWindowID,
              nsIPrintSettings aPrintSettings,
              optional nsIWebProgressListener? aProgressListener = null);
 
   /**
+   * Renders a region of the frame into an image bitmap.
+   *
+   * @param x
+   * @param y
+   * @param w
+   * @param h Specify the area of the window to render, in CSS
+   * pixels. This is relative to the current scroll position.
+   * @param scale The scale to render the window at. Use devicePixelRatio
+   * to have comparable rendering to the OS.
+   * @param backgroundColor The background color to use.
+   *
+   * This API can only be used in the parent process, as content processes
+   * cannot access the rendering of out of process iframes. This API works
+   * with remote and local frames.
+   */
+  [Throws]
+  Promise<ImageBitmap> drawSnapshot(double x,
+                                    double y,
+                                    double w,
+                                    double h,
+                                    double scale,
+                                    DOMString backgroundColor);
+
+  /**
    * If false, then the subdocument is not clipped to its CSS viewport, and the
    * subdocument's viewport scrollbar(s) are not rendered.
    * Defaults to true.
    */
   attribute boolean clipSubdocument;
 
   /**
    * The element which owns this frame loader.
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -1899,16 +1899,34 @@
             }
 
             this.frameLoader.print(aOuterWindowID, aPrintSettings,
                                    aPrintProgressListener);
           ]]>
         </body>
       </method>
 
+      <method name="drawSnapshot">
+        <parameter name="x"/>
+        <parameter name="y"/>
+        <parameter name="w"/>
+        <parameter name="h"/>
+        <parameter name="scale"/>
+        <parameter name="backgroundColor"/>
+        <body>
+          <![CDATA[
+            if (!this.frameLoader) {
+              throw Components.Exception("No frame loader.",
+                                         Cr.NS_ERROR_FAILURE);
+            }
+            return this.frameLoader.drawSnapshot(x, y, w, h, scale, backgroundColor);
+          ]]>
+        </body>
+      </method>
+
       <method name="dropLinks">
         <parameter name="aLinksCount"/>
         <parameter name="aLinks"/>
         <parameter name="aTriggeringPrincipal"/>
         <body><![CDATA[
           if (!this.droppedLinkHandler) {
             return false;
           }