Bug 966591 - Part 2: Validate input to AddHitRegion. Provide partial implementation. r=roc
authorRik Cabanier <cabanier@adobe.com>
Fri, 21 Feb 2014 08:35:36 -0500
changeset 170707 a1e64b0a72712e40cd98151be2889aa46ac56839
parent 170706 24f3ddfd7c48d75c26b3ba656a4f9bc3dac5ed28
child 170708 5692dd63d785836d564e1a628258630d9a648333
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersroc
bugs966591
milestone30.0a1
Bug 966591 - Part 2: Validate input to AddHitRegion. Provide partial implementation. r=roc
content/canvas/src/CanvasRenderingContext2D.cpp
content/canvas/src/CanvasRenderingContext2D.h
dom/webidl/CanvasRenderingContext2D.webidl
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -2350,22 +2350,46 @@ CanvasRenderingContext2D::MeasureText(co
   error = DrawOrMeasureText(rawText, 0, 0, maxWidth, TEXT_DRAW_OPERATION_MEASURE, &width);
   if (error.Failed()) {
     return nullptr;
   }
 
   return new TextMetrics(width);
 }
 
-void CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& )
-{}
-
-void CanvasRenderingContext2D::RemoveHitRegion(const nsAString&)
-{}
-
+void
+CanvasRenderingContext2D::AddHitRegion(const HitRegionOptions& options, ErrorResult& error)
+{
+  // remove old hit region first
+  RemoveHitRegion(options.mId);
+
+  // for now, we require a fallback element
+  if (options.mControl == NULL) {
+    error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+    return;
+  }
+
+  // check if the control is a descendant of our canvas
+  HTMLCanvasElement* canvas = GetCanvas();
+  if (!canvas || !nsContentUtils::ContentIsDescendantOf(options.mControl, canvas)) {
+    error.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+    return;
+  }
+
+  // finally, add the region to the list if it has an ID
+  if (options.mId.Length() != 0) {
+    mHitRegionsOptions.PutEntry(options.mId)->mElement = options.mControl;
+  }
+}
+
+void
+CanvasRenderingContext2D::RemoveHitRegion(const nsAString& id)
+{
+  mHitRegionsOptions.RemoveEntry(id);
+}
 
 /**
  * Used for nsBidiPresUtils::ProcessText
  */
 struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcessor
 {
   typedef CanvasRenderingContext2D::ContextState ContextState;
 
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -181,17 +181,17 @@ public:
                 const Optional<double>& maxWidth,
                 mozilla::ErrorResult& error);
   void StrokeText(const nsAString& text, double x, double y,
                   const Optional<double>& maxWidth,
                   mozilla::ErrorResult& error);
   TextMetrics*
     MeasureText(const nsAString& rawText, mozilla::ErrorResult& error);
 
-  void AddHitRegion(const HitRegionOptions& options);
+  void AddHitRegion(const HitRegionOptions& options, mozilla::ErrorResult& error);
   void RemoveHitRegion(const nsAString& id);
 
   void DrawImage(const HTMLImageOrCanvasOrVideoElement& image,
                  double dx, double dy, mozilla::ErrorResult& error)
   {
     DrawImage(image, 0.0, 0.0, 0.0, 0.0, dx, dy, 0.0, 0.0, 0, error);
   }
 
@@ -680,16 +680,36 @@ protected:
 
   /**
     * Number of times we've invalidated before calling redraw
     */
   uint32_t mInvalidateCount;
   static const uint32_t kCanvasMaxInvalidateCount = 100;
 
   /**
+    * State information for hit regions
+    */
+
+  struct RegionInfo : public nsStringHashKey
+  {
+    RegionInfo(const nsAString& aKey) :
+      nsStringHashKey(&aKey)
+    {
+    }
+    RegionInfo(const nsAString *aKey) :
+      nsStringHashKey(aKey)
+    {
+    }
+
+    nsRefPtr<Element> mElement;
+  };
+
+  nsTHashtable<RegionInfo> mHitRegionsOptions;
+
+  /**
     * Returns true if a shadow should be drawn along with a
     * drawing operation.
     */
   bool NeedToDrawShadow()
   {
     const ContextState& state = CurrentState();
 
     // The spec says we should not draw shadows if the operator is OVER.
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -111,17 +111,17 @@ interface CanvasRenderingContext2D {
   [Throws, LenientFloat]
   void drawImage((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, double dx, double dy);
   [Throws, LenientFloat]
   void drawImage((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, double dx, double dy, double dw, double dh);
   [Throws, LenientFloat]
   void drawImage((HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) image, double sx, double sy, double sw, double sh, double dx, double dy, double dw, double dh);
 
   // hit regions
-  [Pref="canvas.hitregions.enabled"] void addHitRegion(optional HitRegionOptions options);
+  [Pref="canvas.hitregions.enabled", Throws] void addHitRegion(optional HitRegionOptions options);
   [Pref="canvas.hitregions.enabled"] void removeHitRegion(DOMString id);
 
   // pixel manipulation
   [NewObject, Throws]
   ImageData createImageData(double sw, double sh);
   [NewObject, Throws]
   ImageData createImageData(ImageData imagedata);
   [NewObject, Throws]