Bug 1406278: Part 5b - Use subject principal as triggering principal in <source> "src" attribute for <audio>/<video>. r=bz
authorKris Maglione <maglione.k@gmail.com>
Thu, 05 Oct 2017 15:28:22 -0700
changeset 427840 ac4afd1e97b7856b0ff604fb7b867d555cecd40c
parent 427839 e894f7b9168b33eebda126c7b4b431a833807710
child 427841 19b365ebc32cd5895080ab0a572fc0cacdbcaefe
push id97
push userfmarier@mozilla.com
push dateSat, 14 Oct 2017 01:12:59 +0000
reviewersbz
bugs1406278
milestone58.0a1
Bug 1406278: Part 5b - Use subject principal as triggering principal in <source> "src" attribute for <audio>/<video>. r=bz MozReview-Commit-ID: zZCXpvs719
dom/html/HTMLMediaElement.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/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2372,17 +2372,17 @@ void HTMLMediaElement::LoadFromSourceChi
       const char16_t* params[] = { src.get() };
       ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
       DealWithFailedElement(child);
       return;
     }
 
     RemoveMediaElementFromURITable();
     mLoadingSrc = uri;
-    mLoadingSrcTriggeringPrincipal = nullptr;
+    mLoadingSrcTriggeringPrincipal = childSrc->GetSrcTriggeringPrincipal();
     mMediaSource = childSrc->GetSrcMediaSource();
     NS_ASSERTION(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING,
                  "Network state should be loading");
 
     if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
         !IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
       // preload:none media, suspend the load here before we make any
       // network requests.
--- a/dom/html/HTMLSourceElement.cpp
+++ b/dom/html/HTMLSourceElement.cpp
@@ -126,16 +126,19 @@ HTMLSourceElement::AfterSetAttr(int32_t 
           img->PictureSourceMediaOrTypeChanged(AsContent(), aNotify);
         }
       }
     }
 
   } else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::media) {
     UpdateMediaList(aValue);
   } else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
+    mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+        this, aValue ? aValue->GetStringValue() : EmptyString(),
+        aMaybeScriptedPrincipal);
     mSrcMediaSource = nullptr;
     if (aValue) {
       nsString srcStr = aValue->GetStringValue();
       nsCOMPtr<nsIURI> uri;
       NewURIFromString(srcStr, getter_AddRefs(uri));
       if (uri && IsMediaSourceURI(uri)) {
         NS_GetSourceForMediaSourceURI(uri, getter_AddRefs(mSrcMediaSource));
       }
--- a/dom/html/HTMLSourceElement.h
+++ b/dom/html/HTMLSourceElement.h
@@ -54,23 +54,28 @@ public:
   static bool WouldMatchMediaForDocument(const nsAString& aMediaStr,
                                          const nsIDocument *aDocument);
 
   // Return the MediaSource object if any associated with the src attribute
   // when it was set.
   MediaSource* GetSrcMediaSource() { return mSrcMediaSource; };
 
   // WebIDL
-  void GetSrc(nsString& aSrc)
+  void GetSrc(nsString& aSrc, nsIPrincipal&)
   {
     GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
   }
-  void SetSrc(const nsAString& aSrc, mozilla::ErrorResult& rv)
+  void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, mozilla::ErrorResult& rv)
   {
-    SetHTMLAttr(nsGkAtoms::src, aSrc, rv);
+    SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, rv);
+  }
+
+  nsIPrincipal* GetSrcTriggeringPrincipal() const
+  {
+    return mSrcTriggeringPrincipal;
   }
 
   void GetType(DOMString& aType)
   {
     GetHTMLAttr(nsGkAtoms::type, aType);
   }
   void SetType(const nsAString& aType, ErrorResult& rv)
   {
@@ -115,16 +120,19 @@ protected:
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
 
 private:
   RefPtr<MediaList> mMediaList;
   RefPtr<MediaSource> mSrcMediaSource;
 
+  // The triggering principal for the src attribute.
+  nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
+
   // 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
@@ -8,17 +8,17 @@
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 [HTMLConstructor]
 interface HTMLSourceElement : HTMLElement {
-           [CEReactions, SetterThrows]
+           [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString src;
            [CEReactions, SetterThrows]
            attribute DOMString type;
 };
 
 partial interface HTMLSourceElement {
            [CEReactions, SetterThrows]
            attribute DOMString srcset;
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
@@ -39,17 +39,17 @@ function registerStaticPage(path, conten
 }
 
 const BASE_URL = `http://localhost:${server.identity.primaryPort}`;
 
 /**
  * A set of tags which are automatically closed in HTML documents, and
  * do not require an explicit closing tag.
  */
-const AUTOCLOSE_TAGS = new Set(["img"]);
+const AUTOCLOSE_TAGS = new Set(["img", "source"]);
 
 /**
  * An object describing the elements to create for a specific test.
  *
  * @typedef {object} ElementTestCase
  * @property {Array} element
  *        A recursive array, describing the element to create, in the
  *        following format:
@@ -432,16 +432,20 @@ add_task(async function test_contentscri
    * A list of tests to run in each context, as understood by
    * {@see getElementData}.
    */
   const TESTS = [
     {
       element: ["audio", {}],
       src: "audio.webm",
     },
+    {
+      element: ["audio", {}, ["source", {}]],
+      src: "audio-source.webm",
+    },
     // TODO: <frame> element, which requires a frameset document.
     {
       element: ["iframe", {}],
       src: "iframe.html",
     },
     {
       element: ["img", {}],
       src: "img.png",
@@ -455,16 +459,20 @@ add_task(async function test_contentscri
       element: ["script", {}],
       src: "script.js",
       liveSrc: false,
     },
     {
       element: ["video", {}],
       src: "video.webm",
     },
+    {
+      element: ["video", {}, ["source", {}]],
+      src: "video-source.webm",
+    },
   ];
 
   /**
    * A set of sources for which each of the above tests is expected to
    * generate one request, if each of the properties in the value object
    * matches the value of the same property in the test object.
    */
   const SOURCES = {