Bug 1304767 - Deprecate ImageBitmapRenderingContext.transferImageBitmap. r=ehsan, a=ritu
authorMorris Tseng <mtseng@mozilla.com>
Mon, 17 Oct 2016 10:03:00 -0400
changeset 428871 0616db3d38ab140ff3641e0b3eaa7aedecbcf893
parent 428870 f65f7378763e36b99436af60b0bb52242b28dfda
child 428872 2ae1db552424c583c8631429e06cab64a372d508
push id33416
push userpaul@paul.cx
push dateMon, 24 Oct 2016 16:26:20 +0000
reviewersehsan, ritu
bugs1304767
milestone50.0
Bug 1304767 - Deprecate ImageBitmapRenderingContext.transferImageBitmap. r=ehsan, a=ritu
dom/base/nsDeprecatedOperationList.h
dom/base/nsDocument.cpp
dom/base/nsIDocument.h
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/canvas/ImageBitmapRenderingContext.cpp
dom/canvas/ImageBitmapRenderingContext.h
dom/canvas/test/test_bitmaprenderer.html
dom/canvas/test/test_offscreencanvas_toimagebitmap.html
dom/webidl/ImageBitmapRenderingContext.webidl
--- a/dom/base/nsDeprecatedOperationList.h
+++ b/dom/base/nsDeprecatedOperationList.h
@@ -42,8 +42,9 @@ DEPRECATED_OPERATION(ImportXULIntoConten
 DEPRECATED_OPERATION(PannerNodeDoppler)
 DEPRECATED_OPERATION(NavigatorGetUserMedia)
 DEPRECATED_OPERATION(WebrtcDeprecatedPrefix)
 DEPRECATED_OPERATION(RTCPeerConnectionGetStreams)
 DEPRECATED_OPERATION(AppCache)
 DEPRECATED_OPERATION(PrefixedFullscreenAPI)
 DEPRECATED_OPERATION(LenientSetter)
 DEPRECATED_OPERATION(FileLastModifiedDate)
+DEPRECATED_OPERATION(ImageBitmapRenderingContext_TransferImageBitmap)
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -10533,16 +10533,33 @@ nsIDocument::WarnOnceAbout(DeprecatedOpe
   uint32_t flags = asError ? nsIScriptError::errorFlag
                            : nsIScriptError::warningFlag;
   nsContentUtils::ReportToConsole(flags,
                                   NS_LITERAL_CSTRING("DOM Core"), this,
                                   nsContentUtils::eDOM_PROPERTIES,
                                   kDeprecationWarnings[aOperation]);
 }
 
+void
+nsIDocument::WarnOnceAbout(DeprecatedOperations aOperation,
+                           const nsAString& aErrorText,
+                           bool asError /* = false */) const
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  if (HasWarnedAbout(aOperation)) {
+    return;
+  }
+  mDeprecationWarnedAbout[aOperation] = true;
+  const_cast<nsIDocument*>(this)->SetDocumentAndPageUseCounter(OperationToUseCounter(aOperation));
+  uint32_t flags = asError ? nsIScriptError::errorFlag
+                           : nsIScriptError::warningFlag;
+  nsContentUtils::ReportToConsoleNonLocalized(aErrorText, flags,
+                                              NS_LITERAL_CSTRING("DOM Core"), this);
+}
+
 bool
 nsIDocument::HasWarnedAbout(DocumentWarnings aWarning) const
 {
   return mDocWarningWarnedAbout[aWarning];
 }
 
 void
 nsIDocument::WarnOnceAbout(DocumentWarnings aWarning,
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2364,16 +2364,19 @@ public:
   enum DeprecatedOperations {
 #include "nsDeprecatedOperationList.h"
     eDeprecatedOperationCount
   };
 #undef DEPRECATED_OPERATION
   bool HasWarnedAbout(DeprecatedOperations aOperation) const;
   void WarnOnceAbout(DeprecatedOperations aOperation,
                      bool asError = false) const;
+  void WarnOnceAbout(DeprecatedOperations aOperation,
+                     const nsAString& aErrorText,
+                     bool asError = false) const;
 
 #define DOCUMENT_WARNING(_op) e##_op,
   enum DocumentWarnings {
 #include "nsDocumentWarningList.h"
     eDocumentWarningCount
   };
 #undef DOCUMENT_WARNING
   bool HasWarnedAbout(DocumentWarnings aWarning) const;
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -3281,22 +3281,25 @@ SetDocumentAndPageUseCounter(JSContext* 
 
 namespace {
 
 // This runnable is used to write a deprecation message from a worker to the
 // console running on the main-thread.
 class DeprecationWarningRunnable final : public WorkerProxyToMainThreadRunnable
 {
   nsIDocument::DeprecatedOperations mOperation;
+  nsString mErrorText;
 
 public:
   DeprecationWarningRunnable(WorkerPrivate* aWorkerPrivate,
-                             nsIDocument::DeprecatedOperations aOperation)
+                             nsIDocument::DeprecatedOperations aOperation,
+                             const nsAString& aErrorText)
     : WorkerProxyToMainThreadRunnable(aWorkerPrivate)
     , mOperation(aOperation)
+    , mErrorText(aErrorText)
   {
     MOZ_ASSERT(aWorkerPrivate);
     aWorkerPrivate->AssertIsOnWorkerThread();
   }
 
 private:
   void
   RunOnMainThread() override
@@ -3306,53 +3309,62 @@ private:
     // Walk up to our containing page
     WorkerPrivate* wp = mWorkerPrivate;
     while (wp->GetParent()) {
       wp = wp->GetParent();
     }
 
     nsPIDOMWindowInner* window = wp->GetWindow();
     if (window && window->GetExtantDoc()) {
-      window->GetExtantDoc()->WarnOnceAbout(mOperation);
+      if (mErrorText.IsEmpty()) {
+        window->GetExtantDoc()->WarnOnceAbout(mOperation);
+      } else {
+        window->GetExtantDoc()->WarnOnceAbout(mOperation, mErrorText);
+      }
     }
   }
 
   void
   RunBackOnWorkerThread() override
   {}
 };
 
 } // anonymous namespace
 
 void
 DeprecationWarning(JSContext* aCx, JSObject* aObject,
-                   nsIDocument::DeprecatedOperations aOperation)
+                   nsIDocument::DeprecatedOperations aOperation,
+                   const nsAString& aErrorText /* = EmptyString() */)
 {
   GlobalObject global(aCx, aObject);
   if (global.Failed()) {
     NS_ERROR("Could not create global for DeprecationWarning");
     return;
   }
 
   if (NS_IsMainThread()) {
     nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global.GetAsSupports());
     if (window && window->GetExtantDoc()) {
-      window->GetExtantDoc()->WarnOnceAbout(aOperation);
+      if (aErrorText.IsEmpty()) {
+        window->GetExtantDoc()->WarnOnceAbout(aOperation);
+      } else {
+        window->GetExtantDoc()->WarnOnceAbout(aOperation, aErrorText);
+      }
     }
 
     return;
   }
 
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
   if (!workerPrivate) {
     return;
   }
 
   RefPtr<DeprecationWarningRunnable> runnable =
-    new DeprecationWarningRunnable(workerPrivate, aOperation);
+    new DeprecationWarningRunnable(workerPrivate, aOperation, aErrorText);
   runnable->Dispatch();
 }
 
 namespace binding_detail {
 JSObject*
 UnprivilegedJunkScopeOrWorkerGlobal()
 {
   if (NS_IsMainThread()) {
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -3182,17 +3182,18 @@ GetDesiredProto(JSContext* aCx, const JS
 
 void
 SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
                              UseCounter aUseCounter);
 
 // Warnings
 void
 DeprecationWarning(JSContext* aCx, JSObject* aObject,
-                   nsIDocument::DeprecatedOperations aOperation);
+                   nsIDocument::DeprecatedOperations aOperation,
+                   const nsAString& aErrorText = EmptyString());
 
 // A callback to perform funToString on an interface object
 JSString*
 InterfaceObjectToString(JSContext* aCx, JS::Handle<JSObject*> aObject,
                         unsigned /* indent */);
 
 namespace binding_detail {
 // Get a JS global object that can be used for some temporary allocations.  The
--- a/dom/canvas/ImageBitmapRenderingContext.cpp
+++ b/dom/canvas/ImageBitmapRenderingContext.cpp
@@ -46,16 +46,32 @@ ImageBitmapRenderingContext::ClipToIntri
   }
   result = new layers::SourceSurfaceImage(gfx::IntSize(mWidth, mHeight), surface);
   return result.forget();
 }
 
 void
 ImageBitmapRenderingContext::TransferImageBitmap(ImageBitmap& aImageBitmap)
 {
+  JSContext* cx = nsContentUtils::GetCurrentJSContext();
+  if (cx) {
+    JSObject* obj = JS::CurrentGlobalOrNull(cx);
+    DeprecationWarning(cx, obj,
+                       nsIDocument::eImageBitmapRenderingContext_TransferImageBitmap,
+                       NS_LITERAL_STRING("ImageBitmapRenderingContext.transferImageBitmap "
+                                         "is deprecated and will be removed soon. "
+                                         "Use ImageBitmapRenderingContext."
+                                         "transferFromImageBitmap instead."));
+  }
+  TransferFromImageBitmap(aImageBitmap);
+}
+
+void
+ImageBitmapRenderingContext::TransferFromImageBitmap(ImageBitmap& aImageBitmap)
+{
   Reset();
   mImage = aImageBitmap.TransferAsImage();
 
   if (!mImage) {
     return;
   }
 
   Redraw(gfxRect(0, 0, mWidth, mHeight));
--- a/dom/canvas/ImageBitmapRenderingContext.h
+++ b/dom/canvas/ImageBitmapRenderingContext.h
@@ -20,17 +20,17 @@ namespace layers {
 class Image;
 class ImageContainer;
 }
 
 namespace dom {
 
 /**
  * The purpose of ImageBitmapRenderingContext is to provide a faster and efficient
- * way to display ImageBitmap. Simply call TransferImageBitmap() then we'll transfer
+ * way to display ImageBitmap. Simply call TransferFromImageBitmap() then we'll transfer
  * the surface of ImageBitmap to this context and then to use it to display.
  *
  * See more details in spec: https://wiki.whatwg.org/wiki/OffscreenCanvas
  */
 class ImageBitmapRenderingContext final :
   public nsICanvasRenderingContextInternal,
   public nsWrapperCache
 {
@@ -42,16 +42,17 @@ public:
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // nsISupports interface + CC
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ImageBitmapRenderingContext)
 
   void TransferImageBitmap(ImageBitmap& aImageBitmap);
+  void TransferFromImageBitmap(ImageBitmap& aImageBitmap);
 
   // nsICanvasRenderingContextInternal
   virtual int32_t GetWidth() const override;
   virtual int32_t GetHeight() const override;
 
   NS_IMETHOD SetDimensions(int32_t aWidth, int32_t aHeight) override;
 
   NS_IMETHOD InitializeWithDrawTarget(nsIDocShell* aDocShell,
--- a/dom/canvas/test/test_bitmaprenderer.html
+++ b/dom/canvas/test/test_bitmaprenderer.html
@@ -15,17 +15,17 @@ function ok(expect, msg) {
 onmessage = function(event) {
   var bitmap = event.data.bitmap;
   ok(!!bitmap, "Get the ImageBitmap from the main script.");
 
   var offscreenCanvas = new OffscreenCanvas(64, 64);
   var ctx = offscreenCanvas.getContext('bitmaprenderer');
   ok(!!ctx, "Get bitmaprenderer context on worker.");
 
-  ctx.transferImageBitmap(bitmap);
+  ctx.transferFromImageBitmap(bitmap);
   var resultBitmap = offscreenCanvas.transferToImageBitmap();
   postMessage({"type": "bitmap", bitmap: resultBitmap}, [resultBitmap]);
 }
 </script>
 <script>
 
 SimpleTest.waitForExplicitFinish();
 
@@ -52,17 +52,17 @@ function runTest(canvasWidth, canvasHeig
   ctx.fillStyle = "#00FF00";
   ctx.fillRect(0, 0, canvasWidth, canvasHeight);
 
   createImageBitmap(canvas1).then(function(bmp) {
     document.body.removeChild(canvas1);
 
     var canvas2 = createCanvas(90, 90);
     var ctx2 = canvas2.getContext("bitmaprenderer");
-    ctx2.transferImageBitmap(bmp);
+    ctx2.transferFromImageBitmap(bmp);
 
     ok(canvasRef.toDataURL() == canvas2.toDataURL(), "toDataURL should return same result.");
 
     // Exam render result
     canvasRef.style.display = "none";
     canvas2.style.display = "block";
     var snapshot = snapshotWindow(window);
 
@@ -95,28 +95,28 @@ function scaleTest() {
   var p2 = createImageBitmap(canvas2);
   Promise.all([p1, p2]).then(function(bitmaps) {
     document.body.removeChild(canvas1);
     document.body.removeChild(canvas2);
 
     // Create a large canvas then shrink.
     var canvas3 = createCanvas(128, 128);
     var ctx3 = canvas3.getContext("bitmaprenderer");
-    ctx3.transferImageBitmap(bitmaps[0]);
+    ctx3.transferFromImageBitmap(bitmaps[0]);
     var snapshotLargeRef = snapshotWindow(window);
 
     canvas3.width = 32;
     canvas3.height = 32;
     var snapshotSmall = snapshotWindow(window);
     document.body.removeChild(canvas3);
 
     // Create a small canvas then grow.
     var canvas4 = createCanvas(32, 32);
     var ctx4 = canvas4.getContext("bitmaprenderer");
-    ctx4.transferImageBitmap(bitmaps[1]);
+    ctx4.transferFromImageBitmap(bitmaps[1]);
     var snapshotSmallRef = snapshotWindow(window);
 
     canvas4.width = 128;
     canvas4.height = 128;
     var snapshotLarge = snapshotWindow(window);
     document.body.removeChild(canvas4);
 
     var resultsLarge = compareSnapshots(snapshotLarge, snapshotLargeRef, true);
@@ -141,17 +141,17 @@ function runTestOnWorker() {
   createImageBitmap(canvas1).then(function(bmp) {
     worker.postMessage({bitmap: bmp}, [bmp]);
     worker.onmessage = function(event) {
       if (event.data.type == "status") {
         ok(event.data.status, event.data.msg);
       } else if (event.data.type == "bitmap") {
         var canvas2 = createCanvas(64, 64);
         var ctx2 = canvas2.getContext('bitmaprenderer');
-        ctx2.transferImageBitmap(event.data.bitmap);
+        ctx2.transferFromImageBitmap(event.data.bitmap);
         ok(canvas1.toDataURL() == canvas2.toDataURL(), 'toDataURL should be the same');
         SimpleTest.finish();
       }
     }
   });
 }
 
 SpecialPowers.pushPrefEnv({'set': [
--- a/dom/canvas/test/test_offscreencanvas_toimagebitmap.html
+++ b/dom/canvas/test/test_offscreencanvas_toimagebitmap.html
@@ -30,27 +30,27 @@ function runTest() {
       var c = document.getElementById("c-ref");
       var ctx = c.getContext("2d");
       ctx.rect(0, 0, 64, 64);
       ctx.fillStyle = "#00FF00";
       ctx.fill();
 
       var htmlCanvas = document.getElementById("c");
       var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
-      bitmapRenderer.transferImageBitmap(msg.bitmap);
+      bitmapRenderer.transferFromImageBitmap(msg.bitmap);
 
       ok(c.toDataURL() == htmlCanvas.toDataURL(),
          "imagebitmap should return a 64x64 green square");
 
       // The ownership of msg.bitmap should be transferred to canvas "c" when
-      // we called transferImageBitmap. So we test if the ownership is actually
+      // we called transferFromImageBitmap. So we test if the ownership is actually
       // transferred here.
       var htmlCanvas = document.getElementById("c2");
       var bitmapRenderer = htmlCanvas.getContext("bitmaprenderer");
-      bitmapRenderer.transferImageBitmap(msg.bitmap);
+      bitmapRenderer.transferFromImageBitmap(msg.bitmap);
 
       SimpleTest.doesThrow(
         function() { c2.toDataURL(); },
         "ImageBitmap has been transferred, toDataURL will throw.");
 
       worker.terminate();
       SimpleTest.finish();
     }
--- a/dom/webidl/ImageBitmapRenderingContext.webidl
+++ b/dom/webidl/ImageBitmapRenderingContext.webidl
@@ -27,10 +27,13 @@ interface ImageBitmapRenderingContext {
   // The ImageBitmap conceptually replaces the canvas's bitmap, but
   // it does not change the canvas's intrinsic width or height.
   //
   // The ImageBitmap, when displayed, is clipped to the rectangle
   // defined by the canvas's instrinsic width and height. Pixels that
   // would be covered by the canvas's bitmap which are not covered by
   // the supplied ImageBitmap are rendered transparent black. Any CSS
   // styles affecting the display of the canvas are applied as usual.
+  void transferFromImageBitmap(ImageBitmap bitmap);
+
+  // Deprecated version of transferFromImageBitmap
   void transferImageBitmap(ImageBitmap bitmap);
 };