Bug 1406278: Part 6 - Use subject principal as triggering principal in <source> "srcset" attribute for <picture>. r=bz
authorKris Maglione <maglione.k@gmail.com>
Thu, 05 Oct 2017 15:59:15 -0700
changeset 385282 19b365ebc32cd5895080ab0a572fc0cacdbcaefe
parent 385281 ac4afd1e97b7856b0ff604fb7b867d555cecd40c
child 385283 1784e206cc103a87b366b83f7ce6bf9c1d4ade9f
push id32650
push userarchaeopteryx@coole-files.de
push dateTue, 10 Oct 2017 09:13:16 +0000
treeherdermozilla-central@77a4c52e9987 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1406278
milestone58.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 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
@@ -1039,16 +1039,18 @@ 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 (auto* source = HTMLSourceElement::FromContent(aSourceNode)) {
+      principal = source->GetSrcsetTriggeringPrincipal();
     }
     mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue, principal);
   }
 
   if (!mInDocResponsiveContent && IsInComposedDoc()) {
     nsIDocument* doc = GetOurOwnerDoc();
     if (doc) {
       doc->AddResponsiveContent(this);
@@ -1233,16 +1235,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, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify)
 {
+  if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::srcset) {
+    mSrcsetTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+        this, aValue ? aValue->GetStringValue() : EmptyString(),
+        aMaybeScriptedPrincipal);
+  }
   // 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, aTriggeringPrincipal, 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& aTriggeringPrincipal, mozilla::ErrorResult& rv)
   {
-    SetHTMLAttr(nsGkAtoms::srcset, aSrcset, rv);
+    SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aTriggeringPrincipal, 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
@@ -451,16 +451,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",
     },