Bug 1406278: Part 6 - Use subject principal as triggering principal in <source> "srcset" attribute for <picture>. r?bz draft
authorKris Maglione <maglione.k@gmail.com>
Thu, 05 Oct 2017 15:59:15 -0700
changeset 676488 9c5b314c7504ef3fc04e69c861cc93e6314303fb
parent 676487 f2374dc831cf58fe53f020dfca762301d4bc1eb9
child 676489 06d29a3b66de5eb169c6b688d147d21d3b3dfef9
push id83505
push usermaglione.k@gmail.com
push dateSat, 07 Oct 2017 18:18:04 +0000
reviewersbz
bugs1406278
milestone58.0a1
Bug 1406278: Part 6 - Use subject principal as triggering principal in <source> "srcset" attribute for <picture>. r?bz MozReview-Commit-ID: DFq3k9PSOgA
dom/html/HTMLImageElement.cpp
dom/html/HTMLSourceElement.cpp
dom/html/HTMLSourceElement.h
dom/webidl/HTMLSourceElement.webidl
toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -1037,16 +1037,19 @@ HTMLImageElement::PictureSourceSrcsetCha
     mResponsiveSelector ? mResponsiveSelector->Content() : nullptr;
 
   if (aSourceNode == currentSrc) {
     // We're currently using this node as our responsive selector
     // source.
     nsCOMPtr<nsIPrincipal> principal;
     if (aSourceNode == this) {
       principal = mSrcsetTriggeringPrincipal;
+    } else if (aSourceNode->IsHTMLElement(nsGkAtoms::source)) {
+      auto* source = HTMLSourceElement::FromContent(aSourceNode);
+      principal = source->GetSrcsetTriggeringPrincipal();
     }
     mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue, principal);
   }
 
   if (!mInDocResponsiveContent && IsInComposedDoc()) {
     nsIDocument* doc = GetOurOwnerDoc();
     if (doc) {
       doc->AddResponsiveContent(this);
@@ -1231,16 +1234,18 @@ HTMLImageElement::TryCreateResponsiveSel
   nsCOMPtr<nsIPrincipal> principal;
 
   // Skip if this is not a <source> with matching media query
   bool isSourceTag = aSourceNode->IsHTMLElement(nsGkAtoms::source);
   if (isSourceTag) {
     if (!SourceElementMatches(aSourceNode)) {
       return false;
     }
+    auto* source = HTMLSourceElement::FromContent(aSourceNode);
+    principal = source->GetSrcsetTriggeringPrincipal();
   } else if (aSourceNode->IsHTMLElement(nsGkAtoms::img)) {
     // Otherwise this is the <img> tag itself
     MOZ_ASSERT(aSourceNode == this);
     principal = mSrcsetTriggeringPrincipal;
   }
 
   // Skip if has no srcset or an empty srcset
   nsString srcset;
--- a/dom/html/HTMLSourceElement.cpp
+++ b/dom/html/HTMLSourceElement.cpp
@@ -95,16 +95,21 @@ HTMLSourceElement::UpdateMediaList(const
 
 nsresult
 HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify)
 {
+  if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::srcset) {
+    mSrcsetTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+        this, aValue ? aValue->GetStringValue() : EmptyString(),
+        aSubjectPrincipal);
+  }
   // If we are associated with a <picture> with a valid <img>, notify it of
   // responsive parameter changes
   Element *parent = nsINode::GetParentElement();
   if (aNameSpaceID == kNameSpaceID_None &&
       (aName == nsGkAtoms::srcset ||
        aName == nsGkAtoms::sizes ||
        aName == nsGkAtoms::media ||
        aName == nsGkAtoms::type) &&
--- a/dom/html/HTMLSourceElement.h
+++ b/dom/html/HTMLSourceElement.h
@@ -68,32 +68,37 @@ public:
     SetHTMLAttr(nsGkAtoms::src, aSrc, aPrincipal, rv);
   }
 
   nsIPrincipal* GetSrcTriggeringPrincipal() const
   {
     return mSrcTriggeringPrincipal;
   }
 
+  nsIPrincipal* GetSrcsetTriggeringPrincipal() const
+  {
+    return mSrcsetTriggeringPrincipal;
+  }
+
   void GetType(DOMString& aType)
   {
     GetHTMLAttr(nsGkAtoms::type, aType);
   }
   void SetType(const nsAString& aType, ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::type, aType, rv);
   }
 
-  void GetSrcset(DOMString& aSrcset)
+  void GetSrcset(DOMString& aSrcset, nsIPrincipal&)
   {
     GetHTMLAttr(nsGkAtoms::srcset, aSrcset);
   }
-  void SetSrcset(const nsAString& aSrcset, mozilla::ErrorResult& rv)
+  void SetSrcset(const nsAString& aSrcset, nsIPrincipal& aPrincipal, mozilla::ErrorResult& rv)
   {
-    SetHTMLAttr(nsGkAtoms::srcset, aSrcset, rv);
+    SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aPrincipal, rv);
   }
 
   void GetSizes(DOMString& aSizes)
   {
     GetHTMLAttr(nsGkAtoms::sizes, aSizes);
   }
   void SetSizes(const nsAString& aSizes, mozilla::ErrorResult& rv)
   {
@@ -123,16 +128,19 @@ protected:
 
 private:
   RefPtr<MediaList> mMediaList;
   RefPtr<MediaSource> mSrcMediaSource;
 
   // The triggering principal for the src attribute.
   nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
 
+  // The triggering principal for the srcset attribute.
+  nsCOMPtr<nsIPrincipal> mSrcsetTriggeringPrincipal;
+
   // Generates a new MediaList using the given input
   void UpdateMediaList(const nsAttrValue* aValue);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSourceElement_h
--- a/dom/webidl/HTMLSourceElement.webidl
+++ b/dom/webidl/HTMLSourceElement.webidl
@@ -15,15 +15,15 @@
 interface HTMLSourceElement : HTMLElement {
            [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString src;
            [CEReactions, SetterThrows]
            attribute DOMString type;
 };
 
 partial interface HTMLSourceElement {
-           [CEReactions, SetterThrows]
+           [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString srcset;
            [CEReactions, SetterThrows]
            attribute DOMString sizes;
            [CEReactions, SetterThrows]
            attribute DOMString media;
 };
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
@@ -444,16 +444,21 @@ add_task(async function test_contentscri
       src: "img.png",
     },
     {
       element: ["img", {}],
       src: "imgset.png",
       srcAttr: "srcset",
     },
     {
+      element: ["picture", {}, ["source", {}], ["img", {}]],
+      src: "picture.png",
+      srcAttr: "srcset",
+    },
+    {
       element: ["script", {}],
       src: "script.js",
       liveSrc: false,
     },
     {
       element: ["video", {}],
       src: "video.webm",
     },