Bug 1416328 - Part 2. Expose decoding attribute for img elements. r=bz,tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Wed, 08 Aug 2018 07:56:01 -0400
changeset 430539 630049a9ac3b
parent 430538 1f426c672aab
child 430540 bc7ac43b0e13
push id106197
push useraosmond@gmail.com
push dateWed, 08 Aug 2018 12:05:25 +0000
treeherdermozilla-inbound@bc7ac43b0e13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, tnikkel
bugs1416328
milestone63.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 1416328 - Part 2. Expose decoding attribute for img elements. r=bz,tnikkel This adds support for HTMLImageElement's decoding attribute, as described by: https://github.com/whatwg/html/pull/3221 https://whatpr.org/html/3221/images.html#decoding-images It also exposes the same attribute on SVGImageElement, just as Blink has chosen to do so.
dom/base/nsImageLoadingContent.cpp
dom/base/nsImageLoadingContent.h
dom/html/HTMLImageElement.cpp
dom/html/HTMLImageElement.h
dom/svg/SVGImageElement.cpp
dom/svg/SVGImageElement.h
dom/webidl/HTMLImageElement.webidl
dom/webidl/SVGImageElement.webidl
xpcom/ds/nsGkAtomList.h
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -76,16 +76,25 @@ static void PrintReqURL(imgIRequest* req
   }
 
   nsAutoCString spec;
   uri->GetSpec(spec);
   printf("spec='%s'\n", spec.get());
 }
 #endif /* DEBUG_chb */
 
+const nsAttrValue::EnumTable nsImageLoadingContent::kDecodingTable[] = {
+  { "auto",   nsImageLoadingContent::ImageDecodingType::Auto },
+  { "async",  nsImageLoadingContent::ImageDecodingType::Async },
+  { "sync",   nsImageLoadingContent::ImageDecodingType::Sync },
+  { nullptr,  0 }
+};
+
+const nsAttrValue::EnumTable* nsImageLoadingContent::kDecodingTableDefault =
+  &nsImageLoadingContent::kDecodingTable[0];
 
 nsImageLoadingContent::nsImageLoadingContent()
   : mCurrentRequestFlags(0),
     mPendingRequestFlags(0),
     mObserverList(nullptr),
     mImageBlockingStatus(nsIContentPolicy::ACCEPT),
     mLoadingEnabled(true),
     mIsImageStateForced(false),
--- a/dom/base/nsImageLoadingContent.h
+++ b/dom/base/nsImageLoadingContent.h
@@ -19,16 +19,17 @@
 #include "mozilla/TimeStamp.h"
 #include "nsCOMPtr.h"
 #include "nsIImageLoadingContent.h"
 #include "nsIRequest.h"
 #include "mozilla/ErrorResult.h"
 #include "nsIContentPolicy.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/net/ReferrerPolicy.h"
+#include "nsAttrValue.h"
 
 class nsIURI;
 class nsIDocument;
 class nsPresContext;
 class nsIContent;
 class imgRequestProxy;
 
 namespace mozilla {
@@ -228,16 +229,25 @@ protected:
   static nsContentPolicyType PolicyTypeForLoad(ImageLoadType aImageLoadType);
 
   void AsyncEventRunning(mozilla::AsyncEventDispatcher* aEvent);
 
   // Get ourselves as an nsIContent*.  Not const because some of the callers
   // want a non-const nsIContent.
   virtual nsIContent* AsContent() = 0;
 
+  enum class ImageDecodingType : uint8_t {
+    Auto,
+    Async,
+    Sync,
+  };
+
+  static const nsAttrValue::EnumTable kDecodingTable[];
+  static const nsAttrValue::EnumTable* kDecodingTableDefault;
+
 private:
   /**
    * Struct used to manage the native image observers.
    */
   struct ImageObserver {
     explicit ImageObserver(imgINotificationObserver* aObserver);
     ~ImageObserver();
 
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -217,31 +217,41 @@ HTMLImageElement::X()
 }
 
 int32_t
 HTMLImageElement::Y()
 {
   return GetXY().y;
 }
 
+void
+HTMLImageElement::GetDecoding(nsAString& aValue)
+{
+  GetEnumAttr(nsGkAtoms::decoding, kDecodingTableDefault->tag, aValue);
+}
+
 bool
 HTMLImageElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom* aAttribute,
                                  const nsAString& aValue,
                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::align) {
       return ParseAlignValue(aValue, aResult);
     }
     if (aAttribute == nsGkAtoms::crossorigin) {
       ParseCORSValue(aValue, aResult);
       return true;
     }
+    if (aAttribute == nsGkAtoms::decoding) {
+      return aResult.ParseEnumValue(aValue, kDecodingTable, false,
+                                    kDecodingTableDefault);
+    }
     if (ParseImageAttribute(aAttribute, aValue, aResult)) {
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
@@ -373,16 +383,22 @@ HTMLImageElement::AfterSetAttr(int32_t a
     PictureSourceSrcsetChanged(this, attrVal.String(), aNotify);
   } else if (aName == nsGkAtoms::sizes &&
              aNameSpaceID == kNameSpaceID_None) {
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
     mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     PictureSourceSizesChanged(this, attrVal.String(), aNotify);
+  } else if (aName == nsGkAtoms::decoding &&
+             aNameSpaceID == kNameSpaceID_None) {
+    // Request sync or async image decoding.
+    SetSyncDecodingHint(aValue &&
+                        static_cast<ImageDecodingType>(aValue->GetEnumValue()) ==
+                          ImageDecodingType::Sync);
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
                                             aValue, aOldValue,
                                             aMaybeScriptedPrincipal,
                                             aNotify);
 }
 
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -228,16 +228,21 @@ public:
   void SetReferrerPolicy(const nsAString& aReferrer, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrer, aError);
   }
   void GetReferrerPolicy(nsAString& aReferrer)
   {
     GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aReferrer);
   }
+  void SetDecoding(const nsAString& aDecoding, ErrorResult& aError)
+  {
+    SetHTMLAttr(nsGkAtoms::decoding, aDecoding, aError);
+  }
+  void GetDecoding(nsAString& aValue);
 
   net::ReferrerPolicy
   GetImageReferrerPolicy() override
   {
     return GetReferrerPolicyAsEnum();
   }
 
   MOZ_CAN_RUN_SCRIPT int32_t X();
--- a/dom/svg/SVGImageElement.cpp
+++ b/dom/svg/SVGImageElement.cpp
@@ -109,16 +109,22 @@ SVGImageElement::PreserveAspectRatio()
 already_AddRefed<SVGAnimatedString>
 SVGImageElement::Href()
 {
   return mStringAttributes[HREF].IsExplicitlySet()
          ? mStringAttributes[HREF].ToDOMAnimatedString(this)
          : mStringAttributes[XLINK_HREF].ToDOMAnimatedString(this);
 }
 
+void
+SVGImageElement::GetDecoding(nsAString& aValue)
+{
+  GetEnumAttr(nsGkAtoms::decoding, kDecodingTableDefault->tag, aValue);
+}
+
 //----------------------------------------------------------------------
 
 nsresult
 SVGImageElement::LoadSVGImage(bool aForce, bool aNotify)
 {
   // resolve href attribute
   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
 
@@ -147,32 +153,56 @@ void
 SVGImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
 {
   nsImageLoadingContent::AsyncEventRunning(aEvent);
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods:
 
+bool
+SVGImageElement::ParseAttribute(int32_t aNamespaceID,
+                                 nsAtom* aAttribute,
+                                 const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
+                                 nsAttrValue& aResult)
+{
+  if (aNamespaceID == kNameSpaceID_None) {
+    if (aAttribute == nsGkAtoms::decoding) {
+      return aResult.ParseEnumValue(aValue, kDecodingTable, false,
+                                    kDecodingTableDefault);
+    }
+  }
+
+  return SVGImageElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
+                                             aMaybeScriptedPrincipal, aResult);
+}
+
 nsresult
 SVGImageElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
                               const nsAttrValue* aOldValue,
                               nsIPrincipal* aSubjectPrincipal,
                               bool aNotify)
 {
   if (aName == nsGkAtoms::href &&
       (aNamespaceID == kNameSpaceID_None ||
        aNamespaceID == kNameSpaceID_XLink)) {
 
     if (aValue) {
       LoadSVGImage(true, aNotify);
     } else {
       CancelImageRequests(aNotify);
     }
+  } else if (aName == nsGkAtoms::decoding &&
+             aNamespaceID == kNameSpaceID_None) {
+    // Request sync or async image decoding.
+    SetSyncDecodingHint(aValue &&
+                        static_cast<ImageDecodingType>(aValue->GetEnumValue())
+                          == ImageDecodingType::Sync);
   }
   return SVGImageElementBase::AfterSetAttr(aNamespaceID, aName,
                                            aValue, aOldValue,
                                            aSubjectPrincipal, aNotify);
 }
 
 void
 SVGImageElement::MaybeLoadSVGImage()
--- a/dom/svg/SVGImageElement.h
+++ b/dom/svg/SVGImageElement.h
@@ -40,16 +40,21 @@ public:
   // interfaces:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // EventTarget
   virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
 
   // nsIContent interface
+  bool ParseAttribute(int32_t aNamespaceID,
+                      nsAtom* aAttribute,
+                      const nsAString& aValue,
+                      nsIPrincipal* aMaybeScriptedPrincipal,
+                      nsAttrValue& aResult) override;
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
@@ -77,16 +82,22 @@ public:
   // WebIDL
   already_AddRefed<SVGAnimatedLength> X();
   already_AddRefed<SVGAnimatedLength> Y();
   already_AddRefed<SVGAnimatedLength> Width();
   already_AddRefed<SVGAnimatedLength> Height();
   already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
   already_AddRefed<SVGAnimatedString> Href();
 
+  void SetDecoding(const nsAString& aDecoding, ErrorResult& aError)
+  {
+    SetAttr(nsGkAtoms::decoding, aDecoding, aError);
+  }
+  void GetDecoding(nsAString& aValue);
+
 protected:
   nsresult LoadSVGImage(bool aForce, bool aNotify);
 
   virtual LengthAttributesInfo GetLengthInfo() override;
   virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio() override;
   virtual StringAttributesInfo GetStringInfo() override;
 
   // Override for nsImageLoadingContent.
--- a/dom/webidl/HTMLImageElement.webidl
+++ b/dom/webidl/HTMLImageElement.webidl
@@ -32,16 +32,18 @@ interface HTMLImageElement : HTMLElement
            [CEReactions, SetterThrows]
            attribute DOMString referrerPolicy;
            [CEReactions, SetterThrows]
            attribute boolean isMap;
            [CEReactions, SetterThrows]
            attribute unsigned long width;
            [CEReactions, SetterThrows]
            attribute unsigned long height;
+           [CEReactions, SetterThrows]
+           attribute DOMString decoding;
   readonly attribute unsigned long naturalWidth;
   readonly attribute unsigned long naturalHeight;
   readonly attribute boolean complete;
 };
 
 // http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
 partial interface HTMLImageElement {
            [CEReactions, SetterThrows]
--- a/dom/webidl/SVGImageElement.webidl
+++ b/dom/webidl/SVGImageElement.webidl
@@ -16,13 +16,15 @@ interface SVGImageElement : SVGGraphicsE
   [Constant]
   readonly attribute SVGAnimatedLength y;
   [Constant]
   readonly attribute SVGAnimatedLength width;
   [Constant]
   readonly attribute SVGAnimatedLength height;
   [Constant]
   readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio;
+  [CEReactions, SetterThrows]
+  attribute DOMString decoding;
 };
 
 SVGImageElement implements MozImageLoadingContent;
 SVGImageElement implements SVGURIReference;
 
--- a/xpcom/ds/nsGkAtomList.h
+++ b/xpcom/ds/nsGkAtomList.h
@@ -274,16 +274,17 @@ GK_ATOM(date, "date")
 GK_ATOM(datetime, "datetime")
 GK_ATOM(datetimebox, "datetimebox")
 GK_ATOM(dd, "dd")
 GK_ATOM(decimal, "decimal")
 GK_ATOM(decimalFormat, "decimal-format")
 GK_ATOM(decimalSeparator, "decimal-separator")
 GK_ATOM(declare, "declare")
 GK_ATOM(decoderDoctor, "decoder-doctor")
+GK_ATOM(decoding, "decoding")
 GK_ATOM(decrement, "decrement")
 GK_ATOM(_default, "default")
 GK_ATOM(headerDefaultStyle, "default-style")
 GK_ATOM(defer, "defer")
 GK_ATOM(del, "del")
 GK_ATOM(descendant, "descendant")
 GK_ATOM(descendantOrSelf, "descendant-or-self")
 GK_ATOM(descending, "descending")