Bug 449363 - Support media attribute of <source> elements. r=cpearce,bz
authorPaul Adenot <paul@paul.cx>
Tue, 15 May 2012 08:56:51 -0400
changeset 93981 b15a3c5dd0e6abab3098e1134f827aaae2a6a74b
parent 93980 975f2617b6392812e8d05e0b92433001c894ccf7
child 93982 7da36f8c159a1c7eab74063c0c620863c4ed9580
push id9404
push userryanvm@gmail.com
push dateTue, 15 May 2012 13:02:31 +0000
treeherdermozilla-inbound@e1fcace4621d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, bz
bugs449363
milestone15.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 449363 - Support media attribute of <source> elements. r=cpearce,bz
content/html/content/src/nsHTMLMediaElement.cpp
content/html/content/src/nsHTMLSourceElement.cpp
content/media/test/Makefile.in
content/media/test/test_source_media.html
dom/interfaces/html/nsIDOMHTMLSourceElement.idl
dom/locales/en-US/chrome/dom/dom.properties
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -93,16 +93,19 @@
 #include "nsIDOMNotifyAudioAvailableEvent.h"
 #include "nsMediaFragmentURIParser.h"
 #include "nsURIHashKey.h"
 #include "nsJSUtils.h"
 #include "MediaStreamGraph.h"
 #include "nsDOMMediaStream.h"
 #include "nsIScriptError.h"
 
+#include "nsCSSParser.h"
+#include "nsIMediaList.h"
+
 #ifdef MOZ_OGG
 #include "nsOggDecoder.h"
 #endif
 #ifdef MOZ_WAVE
 #include "nsWaveDecoder.h"
 #endif
 #ifdef MOZ_WEBM
 #include "nsWebMDecoder.h"
@@ -845,16 +848,22 @@ void nsHTMLMediaElement::NotifyAudioAvai
 }
 
 void nsHTMLMediaElement::LoadFromSourceChildren()
 {
   NS_ASSERTION(mDelayingLoadEvent,
                "Should delay load event (if in document) during load");
   NS_ASSERTION(mIsLoadingFromSourceChildren,
                "Must remember we're loading from source children");
+
+  nsIDocument* parentDoc = OwnerDoc()->GetParentDocument();
+  if (parentDoc) {
+    parentDoc->FlushPendingNotifications(Flush_Layout);
+  }
+
   while (true) {
     nsIContent* child = GetNextSource();
     if (!child) {
       // Exhausted candidates, wait for more candidates to be appended to
       // the media element.
       mLoadWaitStatus = WAITING_FOR_SOURCE;
       mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE;
       ChangeDelayLoadStatus(false);
@@ -871,21 +880,35 @@ void nsHTMLMediaElement::LoadFromSourceC
     }
 
     // If we have a type attribute, it must be a supported type.
     nsAutoString type;
     if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) &&
         GetCanPlay(type) == CANPLAY_NO) {
       DispatchAsyncSourceError(child);
       const PRUnichar* params[] = { type.get(), src.get() };
-      ReportLoadError("MediaLoadUnsupportedType", params, ArrayLength(params));
+      ReportLoadError("MediaLoadUnsupportedTypeAttribute", params, ArrayLength(params));
       continue;
     }
-    LOG(PR_LOG_DEBUG, ("%p Trying load from <source>=%s type=%s", this,
-      NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get()));
+    nsAutoString media;
+    if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::media, media) && !media.IsEmpty()) {
+      nsCSSParser cssParser;
+      nsRefPtr<nsMediaList> mediaList(new nsMediaList());
+      cssParser.ParseMediaList(media, NULL, 0, mediaList, false);
+      nsIPresShell* presShell = OwnerDoc()->GetShell();
+      if (presShell && !mediaList->Matches(presShell->GetPresContext(), NULL)) {
+        DispatchAsyncSourceError(child);
+        const PRUnichar* params[] = { media.get(), src.get() };
+        ReportLoadError("MediaLoadSourceMediaNotMatched", params, ArrayLength(params));
+        continue;
+      }
+    }
+    LOG(PR_LOG_DEBUG, ("%p Trying load from <source>=%s type=%s media=%s", this,
+      NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get(),
+      NS_ConvertUTF16toUTF8(media).get()));
 
     nsCOMPtr<nsIURI> uri;
     NewURIFromString(src, getter_AddRefs(uri));
     if (!uri) {
       DispatchAsyncSourceError(child);
       const PRUnichar* params[] = { src.get() };
       ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
       continue;
--- a/content/html/content/src/nsHTMLSourceElement.cpp
+++ b/content/html/content/src/nsHTMLSourceElement.cpp
@@ -109,16 +109,17 @@ NS_INTERFACE_TABLE_HEAD(nsHTMLSourceElem
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLSourceElement)
 
 
 NS_IMPL_ELEMENT_CLONE(nsHTMLSourceElement)
 
 
 NS_IMPL_URI_ATTR(nsHTMLSourceElement, Src, src)
 NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Type, type)
+NS_IMPL_STRING_ATTR(nsHTMLSourceElement, Media, media)
 
 nsresult
 nsHTMLSourceElement::BindToTree(nsIDocument *aDocument,
                                 nsIContent *aParent,
                                 nsIContent *aBindingParent,
                                 bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument,
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -156,16 +156,17 @@ include $(topsrcdir)/config/rules.mk
 		test_streams_element_capture_reset.html \
 		test_timeupdate_small_files.html \
 		test_too_many_elements.html \
 		test_volume.html \
 		test_video_to_canvas.html \
 		use_large_cache.js \
 		test_audiowrite.html \
 		test_mozHasAudio.html \
+		test_source_media.html \
 		$(NULL)
 
 # Don't run in suite
 ifndef MOZ_SUITE
 _TEST_FILES += test_play_twice.html
 else
 $(warning test_play_twice.html is disabled pending investigation. Bug 598252)
 endif
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_source_media.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Media test: media attribute for the source element.</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script type="text/javascript" src="manifest.js"></script>
+<script type="text/javascript" src="../../html/content/test/reflect.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="text/javascript">
+  var testCount = 0;
+  function notifyFinished() {
+    testCount++;
+    if (testCount == 2) {
+      SimpleTest.finish();
+    }
+  }
+  SimpleTest.waitForExplicitFinish();
+
+  reflectString({
+    element: document.createElement("source"),
+    attribute: "media",
+  });
+
+  var media = getPlayableVideo(gSmallTests);
+
+  if (media == null) {
+    todo(false, "No media supported.");
+    SimpleTest.finish();
+  } else {
+    var v = document.createElement('video');
+    v.innerHTML = "<source src=\"" + media.name + "?fail\" media=\"not all\">" +
+                  "<source src=\""+ media.name + "?pass\" media=\"all\">";
+    var v2 = document.createElement("video");
+    v2.innerHTML = "<source src=\""+ media.name +"?pass\">" +
+                   "<source src=\""+ media.name + "?fail\" media=\"all\">";
+    document.body.appendChild(v);
+    document.body.appendChild(v2);
+
+    v.addEventListener("loadedmetadata", function(e) {
+        ok(/pass/.test(e.target.currentSrc),
+          "The source has been chosen according to the media attribute.");
+        notifyFinished();
+        });
+    v2.addEventListener("loadedmetadata", function(e) {
+        ok(/pass/.test(e.target.currentSrc),
+          "If no media attribute is specified, it defaults to \'all\'.")
+        notifyFinished();
+    });
+  }
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/interfaces/html/nsIDOMHTMLSourceElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLSourceElement.idl
@@ -43,14 +43,15 @@
  * <source> element.
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#source
  *
  * @status UNDER_DEVELOPMENT
  */
 
-[scriptable, uuid(4BF58085-9986-47B5-BB03-62BAA0451497)]
+[scriptable, uuid(af4b7ca2-2694-4672-a182-8a63be79c826)]
 interface nsIDOMHTMLSourceElement : nsIDOMHTMLElement
 {
            attribute DOMString src;
            attribute DOMString type;
+           attribute DOMString media;
 };
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -139,17 +139,19 @@ TimeoutSyncXHRWarning=Use of XMLHttpRequ
 JSONCharsetWarning=An attempt was made to declare a non-UTF-8 encoding for JSON retrieved using XMLHttpRequest. Only UTF-8 is supported for decoding JSON.
 MediaLoadExhaustedCandidates=All candidate resources failed to load. Media load paused.
 MediaLoadSourceMissingSrc=<source> element has no "src" attribute. Media resource load failed.
 # LOCALIZATION NOTE: %1$S is the Http error code the server returned (e.g. 404, 500, etc), %2$S is the URL of the media resource which failed to load.
 MediaLoadHttpError=HTTP load failed with status %1$S. Load of media resource %2$S failed.
 # LOCALIZATION NOTE: %S is the URL of the media resource which failed to load.
 MediaLoadInvalidURI=Invalid URI. Load of media resource %S failed.
 # LOCALIZATION NOTE: %1$S is the media resource's format/codec type (basically equivalent to the file type, e.g. MP4,AVI,WMV,MOV etc), %2$S is the URL of the media resource which failed to load.
-MediaLoadUnsupportedType=Specified "type" of "%1$S" is not supported. Load of media resource %2$S failed.
+MediaLoadUnsupportedTypeAttribute=Specified "type" attribute of "%1$S" is not supported. Load of media resource %2$S failed.
+# LOCALIZATION NOTE: %1$S is the "media" attribute value of the <source> element. It is a media query. %2$S is the URL of the media resource which failed to load.
+MediaLoadSourceMediaNotMatched=Specified "media" attribute of "%1$S" does not match the environment. Load of media resource %2$S failed.
 # LOCALIZATION NOTE: %1$S is the MIME type HTTP header being sent by the web server, %2$S is the URL of the media resource which failed to load.
 MediaLoadUnsupportedMimeType=HTTP "Content-Type" of "%1$S" is not supported. Load of media resource %2$S failed.
 # LOCALIZATION NOTE: %S is the URL of the media resource which failed to load because of error in decoding.
 MediaLoadDecodeError=Media resource %S could not be decoded.
 # LOCALIZATION NOTE: Do not translate "MozBlobBuilder" and "Blob"
 MozBlobBuilderWarning=Use of MozBlobBuilder is deprecated. Use Blob constructor instead.
 # LOCALIZATION NOTE: Do not translate "DOMException", "code" and "name"
 DOMExceptionCodeWarning=Use of DOMException's code attribute is deprecated. Use name instead.