Bug 1493798. Update the MediaCapabilities dictionaries to follow the spec more closely. r=jya
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 26 Sep 2018 19:19:47 +0000
changeset 438361 a4c0087797d6752c7f18563c8d2ead7e87eb2e9c
parent 438327 6e4da634fab4c1e70046fb6a6111cc2575667d62
child 438362 7856d822921f3133aab589ad96e98d2eabd98eec
push id34718
push usershindli@mozilla.com
push dateThu, 27 Sep 2018 03:13:23 +0000
treeherdermozilla-central@fa1831cceeae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya
bugs1493798, 1471165
milestone64.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 1493798. Update the MediaCapabilities dictionaries to follow the spec more closely. r=jya This partially backs out bug 1471165 now that we don't enforce a default value for dictionary-typed members of dictionaries. Differential Revision: https://phabricator.services.mozilla.com/D6876
dom/media/MediaMIMETypes.cpp
dom/media/mediacapabilities/MediaCapabilities.cpp
dom/webidl/MediaCapabilities.webidl
testing/web-platform/meta/media-capabilities/encodingInfo.html.ini
testing/web-platform/tests/media-capabilities/decodingInfo.html
testing/web-platform/tests/media-capabilities/encodingInfo.html
--- a/dom/media/MediaMIMETypes.cpp
+++ b/dom/media/MediaMIMETypes.cpp
@@ -257,66 +257,59 @@ MakeMediaExtendedMIMEType(const nsAStrin
                                     haveCodecs, codecs,
                                     width, height,
                                     framerate, bitrate));
 }
 
 Maybe<MediaExtendedMIMEType>
 MakeMediaExtendedMIMEType(const dom::VideoConfiguration& aConfig)
 {
-  MOZ_ASSERT(aConfig.mContentType.WasPassed() &&
-             aConfig.mFramerate.WasPassed() &&
-             aConfig.mWidth.WasPassed() &&
-             aConfig.mHeight.WasPassed() &&
-             aConfig.mBitrate.WasPassed(),
-             "All dictionary members must be present");
-  if (aConfig.mContentType.Value().IsEmpty()) {
+  if (aConfig.mContentType.IsEmpty()) {
     return Nothing();
   }
-  nsContentTypeParser parser(aConfig.mContentType.Value());
+  nsContentTypeParser parser(aConfig.mContentType);
   nsAutoString mime;
   nsresult rv = parser.GetType(mime);
   if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
     return Nothing();
   }
 
   NS_ConvertUTF16toUTF8 mime8{ mime };
   if (!IsMediaMIMEType(mime8)) {
     return Nothing();
   }
 
   nsAutoString codecs;
   rv = parser.GetParameter("codecs", codecs);
   bool haveCodecs = NS_SUCCEEDED(rv);
 
   auto framerate =
-    MediaExtendedMIMEType::ComputeFractionalString(aConfig.mFramerate.Value());
+    MediaExtendedMIMEType::ComputeFractionalString(aConfig.mFramerate);
   if (!framerate) {
     return Nothing();
   }
 
   return Some(
-    MediaExtendedMIMEType(NS_ConvertUTF16toUTF8(aConfig.mContentType.Value()),
+    MediaExtendedMIMEType(NS_ConvertUTF16toUTF8(aConfig.mContentType),
                           mime8,
                           haveCodecs,
                           codecs,
-                          aConfig.mWidth.Value(),
-                          aConfig.mHeight.Value(),
+                          aConfig.mWidth,
+                          aConfig.mHeight,
                           framerate.ref(),
-                          aConfig.mBitrate.Value()));
+                          aConfig.mBitrate));
 }
 
 Maybe<MediaExtendedMIMEType>
 MakeMediaExtendedMIMEType(const dom::AudioConfiguration& aConfig)
 {
-  if (!aConfig.mContentType.WasPassed() ||
-      aConfig.mContentType.Value().IsEmpty()) {
+  if (aConfig.mContentType.IsEmpty()) {
     return Nothing();
   }
-  nsContentTypeParser parser(aConfig.mContentType.Value());
+  nsContentTypeParser parser(aConfig.mContentType);
   nsAutoString mime;
   nsresult rv = parser.GetType(mime);
   if (!NS_SUCCEEDED(rv) || mime.IsEmpty()) {
     return Nothing();
   }
 
   NS_ConvertUTF16toUTF8 mime8{ mime };
   if (!IsMediaMIMEType(mime8)) {
@@ -338,17 +331,17 @@ MakeMediaExtendedMIMEType(const dom::Aud
     // Value is a channel configuration such as 5.1. We want to treat this as 6.
     channels = value;
     double fp = value - channels;
      // round up as .1 and .2 aren't exactly expressible in binary.
     channels += (fp * 10) + .5;
   }
 
   return Some(MediaExtendedMIMEType(
-    NS_ConvertUTF16toUTF8(aConfig.mContentType.Value()),
+    NS_ConvertUTF16toUTF8(aConfig.mContentType),
     mime8,
     haveCodecs,
     codecs,
     channels,
     aConfig.mSamplerate.WasPassed() ? aConfig.mSamplerate.Value() : 48000,
     aConfig.mBitrate.WasPassed() ? aConfig.mBitrate.Value() : 131072));
 }
 
--- a/dom/media/mediacapabilities/MediaCapabilities.cpp
+++ b/dom/media/mediacapabilities/MediaCapabilities.cpp
@@ -38,33 +38,33 @@ namespace dom {
 static nsCString
 VideoConfigurationToStr(const VideoConfiguration* aConfig)
 {
   if (!aConfig) {
     return nsCString();
   }
   auto str = nsPrintfCString(
     "[contentType:%s width:%d height:%d bitrate:%" PRIu64 " framerate:%s]",
-    NS_ConvertUTF16toUTF8(aConfig->mContentType.Value()).get(),
-    aConfig->mWidth.Value(),
-    aConfig->mHeight.Value(),
-    aConfig->mBitrate.Value(),
-    NS_ConvertUTF16toUTF8(aConfig->mFramerate.Value()).get());
+    NS_ConvertUTF16toUTF8(aConfig->mContentType).get(),
+    aConfig->mWidth,
+    aConfig->mHeight,
+    aConfig->mBitrate,
+    NS_ConvertUTF16toUTF8(aConfig->mFramerate).get());
   return std::move(str);
 }
 
 static nsCString
 AudioConfigurationToStr(const AudioConfiguration* aConfig)
 {
   if (!aConfig) {
     return nsCString();
   }
   auto str = nsPrintfCString(
     "[contentType:%s channels:%s bitrate:%" PRIu64 " samplerate:%d]",
-    NS_ConvertUTF16toUTF8(aConfig->mContentType.Value()).get(),
+    NS_ConvertUTF16toUTF8(aConfig->mContentType).get(),
     aConfig->mChannels.WasPassed()
       ? NS_ConvertUTF16toUTF8(aConfig->mChannels.Value()).get()
       : "?",
     aConfig->mBitrate.WasPassed() ? aConfig->mBitrate.Value() : 0,
     aConfig->mSamplerate.WasPassed() ? aConfig->mSamplerate.Value() : 0);
   return std::move(str);
 }
 
@@ -81,184 +81,116 @@ MediaCapabilitiesInfoToStr(const MediaCa
   return std::move(str);
 }
 
 static nsCString
 MediaDecodingConfigurationToStr(const MediaDecodingConfiguration& aConfig)
 {
   nsCString str;
   str += NS_LITERAL_CSTRING("[");
-  if (aConfig.mVideo.IsAnyMemberPresent()) {
+  if (aConfig.mVideo.WasPassed()) {
     str +=
-      NS_LITERAL_CSTRING("video:") + VideoConfigurationToStr(&aConfig.mVideo);
-    if (aConfig.mAudio.IsAnyMemberPresent()) {
+      NS_LITERAL_CSTRING("video:") + VideoConfigurationToStr(&aConfig.mVideo.Value());
+    if (aConfig.mAudio.WasPassed()) {
       str += NS_LITERAL_CSTRING(" ");
     }
   }
-  if (aConfig.mAudio.IsAnyMemberPresent()) {
+  if (aConfig.mAudio.WasPassed()) {
     str +=
-      NS_LITERAL_CSTRING("audio:") + AudioConfigurationToStr(&aConfig.mAudio);
+      NS_LITERAL_CSTRING("audio:") + AudioConfigurationToStr(&aConfig.mAudio.Value());
   }
   str += NS_LITERAL_CSTRING("]");
   return str;
 }
 
 MediaCapabilities::MediaCapabilities(nsIGlobalObject* aParent)
   : mParent(aParent)
 {
 }
 
-static void
-ThrowWithMemberName(ErrorResult& aRv,
-                    const char* aCategory,
-                    const char* aMember)
-{
-  auto str = nsPrintfCString("'%s' member of %s", aMember, aCategory);
-  aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(
-    NS_ConvertUTF8toUTF16(str));
-}
-
-static void
-CheckVideoConfigurationSanity(const VideoConfiguration& aConfig,
-                              const char* aCategory,
-                              ErrorResult& aRv)
-{
-  if (!aConfig.mContentType.WasPassed()) {
-    ThrowWithMemberName(aRv, "contentType", aCategory);
-    return;
-  }
-  if (!aConfig.mWidth.WasPassed()) {
-    ThrowWithMemberName(aRv, "width", aCategory);
-    return;
-  }
-  if (!aConfig.mHeight.WasPassed()) {
-    ThrowWithMemberName(aRv, "height", aCategory);
-    return;
-  }
-  if (!aConfig.mBitrate.WasPassed()) {
-    ThrowWithMemberName(aRv, "bitrate", aCategory);
-    return;
-  }
-  if (!aConfig.mFramerate.WasPassed()) {
-    ThrowWithMemberName(aRv, "framerate", aCategory);
-    return;
-  }
-}
-
-static void
-CheckAudioConfigurationSanity(const AudioConfiguration& aConfig,
-                              const char* aCategory,
-                              ErrorResult& aRv)
-{
-  if (!aConfig.mContentType.WasPassed()) {
-    ThrowWithMemberName(aRv, "contentType", aCategory);
-    return;
-  }
-}
-
 already_AddRefed<Promise>
 MediaCapabilities::DecodingInfo(
   const MediaDecodingConfiguration& aConfiguration,
   ErrorResult& aRv)
 {
   RefPtr<Promise> promise = Promise::Create(mParent, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   // If configuration is not a valid MediaConfiguration, return a Promise
   // rejected with a TypeError.
-  if (!aConfiguration.IsAnyMemberPresent() ||
-      (!aConfiguration.mVideo.IsAnyMemberPresent() &&
-       !aConfiguration.mAudio.IsAnyMemberPresent())) {
+  if (!aConfiguration.mVideo.WasPassed() &&
+      !aConfiguration.mAudio.WasPassed()) {
     aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(
       NS_LITERAL_STRING("'audio' or 'video'"));
     return nullptr;
   }
 
-  // Here we will throw rather than rejecting a promise in order to simulate
-  // optional dictionaries with required members (see bug 1368949)
-  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
-    // Check that all VideoConfiguration required members are present.
-    CheckVideoConfigurationSanity(
-      aConfiguration.mVideo, "MediaDecodingConfiguration", aRv);
-    if (aRv.Failed()) {
-      return nullptr;
-    }
-  }
-  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
-    // Check that all AudioConfiguration required members are present.
-    CheckAudioConfigurationSanity(
-      aConfiguration.mAudio, "MediaDecodingConfiguration", aRv);
-    if (aRv.Failed()) {
-      return nullptr;
-    }
-  }
-
   LOG("Processing %s", MediaDecodingConfigurationToStr(aConfiguration).get());
 
   bool supported = true;
   Maybe<MediaContainerType> videoContainer;
   Maybe<MediaContainerType> audioContainer;
 
   // If configuration.video is present and is not a valid video configuration,
   // return a Promise rejected with a TypeError.
-  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
-    videoContainer = CheckVideoConfiguration(aConfiguration.mVideo);
+  if (aConfiguration.mVideo.WasPassed()) {
+    videoContainer = CheckVideoConfiguration(aConfiguration.mVideo.Value());
     if (!videoContainer) {
       aRv.ThrowTypeError<MSG_INVALID_MEDIA_VIDEO_CONFIGURATION>();
       return nullptr;
     }
 
     // We have a video configuration and it is valid. Check if it is supported.
     supported &=
       aConfiguration.mType == MediaDecodingType::File
-        ? CheckTypeForFile(aConfiguration.mVideo.mContentType.Value())
-        : CheckTypeForMediaSource(aConfiguration.mVideo.mContentType.Value());
+        ? CheckTypeForFile(aConfiguration.mVideo.Value().mContentType)
+        : CheckTypeForMediaSource(aConfiguration.mVideo.Value().mContentType);
   }
-  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
-    audioContainer = CheckAudioConfiguration(aConfiguration.mAudio);
+  if (aConfiguration.mAudio.WasPassed()) {
+    audioContainer = CheckAudioConfiguration(aConfiguration.mAudio.Value());
     if (!audioContainer) {
       aRv.ThrowTypeError<MSG_INVALID_MEDIA_AUDIO_CONFIGURATION>();
       return nullptr;
     }
     // We have an audio configuration and it is valid. Check if it is supported.
     supported &=
       aConfiguration.mType == MediaDecodingType::File
-        ? CheckTypeForFile(aConfiguration.mAudio.mContentType.Value())
-        : CheckTypeForMediaSource(aConfiguration.mAudio.mContentType.Value());
+        ? CheckTypeForFile(aConfiguration.mAudio.Value().mContentType)
+        : CheckTypeForMediaSource(aConfiguration.mAudio.Value().mContentType);
   }
 
   if (!supported) {
     auto info = MakeUnique<MediaCapabilitiesInfo>(
       false /* supported */, false /* smooth */, false /* power efficient */);
     LOG("%s -> %s",
         MediaDecodingConfigurationToStr(aConfiguration).get(),
         MediaCapabilitiesInfoToStr(info.get()).get());
     promise->MaybeResolve(std::move(info));
     return promise.forget();
   }
 
   nsTArray<UniquePtr<TrackInfo>> tracks;
-  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
+  if (aConfiguration.mVideo.WasPassed()) {
     MOZ_ASSERT(videoContainer.isSome(), "configuration is valid and supported");
     auto videoTracks = DecoderTraits::GetTracksInfo(*videoContainer);
     // If the MIME type does not imply a codec, the string MUST
     // also have one and only one parameter that is named codecs with a value
     // describing a single media codec. Otherwise, it MUST contain no
     // parameters.
     if (videoTracks.Length() != 1) {
       promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
       return promise.forget();
     }
     MOZ_DIAGNOSTIC_ASSERT(videoTracks.ElementAt(0),
                           "must contain a valid trackinfo");
     tracks.AppendElements(std::move(videoTracks));
   }
-  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
+  if (aConfiguration.mAudio.WasPassed()) {
     MOZ_ASSERT(audioContainer.isSome(), "configuration is valid and supported");
     auto audioTracks = DecoderTraits::GetTracksInfo(*audioContainer);
     // If the MIME type does not imply a codec, the string MUST
     // also have one and only one parameter that is named codecs with a value
     // describing a single media codec. Otherwise, it MUST contain no
     // parameters.
     if (audioTracks.Length() != 1) {
       promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
@@ -481,64 +413,44 @@ MediaCapabilities::EncodingInfo(
 {
   RefPtr<Promise> promise = Promise::Create(mParent, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   // If configuration is not a valid MediaConfiguration, return a Promise
   // rejected with a TypeError.
-  if (!aConfiguration.IsAnyMemberPresent() ||
-      (!aConfiguration.mVideo.IsAnyMemberPresent() &&
-       !aConfiguration.mAudio.IsAnyMemberPresent())) {
+  if (!aConfiguration.mVideo.WasPassed() &&
+      !aConfiguration.mAudio.WasPassed()) {
     aRv.ThrowTypeError<MSG_MISSING_REQUIRED_DICTIONARY_MEMBER>(
       NS_LITERAL_STRING("'audio' or 'video'"));
     return nullptr;
   }
 
-  // Here we will throw rather than rejecting a promise in order to simulate
-  // optional dictionaries with required members (see bug 1368949)
-  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
-    // Check that all VideoConfiguration required members are present.
-    CheckVideoConfigurationSanity(
-      aConfiguration.mVideo, "MediaDecodingConfiguration", aRv);
-    if (aRv.Failed()) {
-      return nullptr;
-    }
-  }
-  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
-    // Check that all AudioConfiguration required members are present.
-    CheckAudioConfigurationSanity(
-      aConfiguration.mAudio, "MediaDecodingConfiguration", aRv);
-    if (aRv.Failed()) {
-      return nullptr;
-    }
-  }
-
   bool supported = true;
 
   // If configuration.video is present and is not a valid video configuration,
   // return a Promise rejected with a TypeError.
-  if (aConfiguration.mVideo.IsAnyMemberPresent()) {
-    if (!CheckVideoConfiguration(aConfiguration.mVideo)) {
+  if (aConfiguration.mVideo.WasPassed()) {
+    if (!CheckVideoConfiguration(aConfiguration.mVideo.Value())) {
       aRv.ThrowTypeError<MSG_INVALID_MEDIA_VIDEO_CONFIGURATION>();
       return nullptr;
     }
     // We have a video configuration and it is valid. Check if it is supported.
     supported &=
-      CheckTypeForEncoder(aConfiguration.mVideo.mContentType.Value());
+      CheckTypeForEncoder(aConfiguration.mVideo.Value().mContentType);
   }
-  if (aConfiguration.mAudio.IsAnyMemberPresent()) {
-    if (!CheckAudioConfiguration(aConfiguration.mAudio)) {
+  if (aConfiguration.mAudio.WasPassed()) {
+    if (!CheckAudioConfiguration(aConfiguration.mAudio.Value())) {
       aRv.ThrowTypeError<MSG_INVALID_MEDIA_AUDIO_CONFIGURATION>();
       return nullptr;
     }
     // We have an audio configuration and it is valid. Check if it is supported.
     supported &=
-      CheckTypeForEncoder(aConfiguration.mAudio.mContentType.Value());
+      CheckTypeForEncoder(aConfiguration.mAudio.Value().mContentType);
   }
 
   auto info = MakeUnique<MediaCapabilitiesInfo>(supported, supported, false);
   promise->MaybeResolve(std::move(info));
 
   return promise.forget();
 }
 
--- a/dom/webidl/MediaCapabilities.webidl
+++ b/dom/webidl/MediaCapabilities.webidl
@@ -5,20 +5,18 @@
  *
  * The origin of this IDL file is
  * https://wicg.github.io/media-capabilities/
  *
  * Copyright © 2018 the Contributors to the Media Capabilities Specification
  */
 
 dictionary MediaConfiguration {
-  // Bug 1493798: This should actually be optional and its members required.
-  VideoConfiguration video = null;
-  // Bug 1493798: This should actually be optional and its members required.
-  AudioConfiguration audio = null;
+  VideoConfiguration video;
+  AudioConfiguration audio;
 };
 
 dictionary MediaDecodingConfiguration : MediaConfiguration {
   required MediaDecodingType type;
 };
 
 dictionary MediaEncodingConfiguration : MediaConfiguration {
   required MediaEncodingType type;
@@ -29,32 +27,26 @@ enum MediaDecodingType {
   "media-source",
 };
 
 enum MediaEncodingType {
   "record",
   "transmission"
 };
 
-// all members are specified as required in the spec.
-// We enforce that requirement in the MediaCapabilities code instead
-// See https://github.com/heycam/webidl/issues/76
 dictionary VideoConfiguration {
-  DOMString contentType;
-  unsigned long width;
-  unsigned long height;
-  unsigned long long bitrate;
-  DOMString framerate;
+  required DOMString contentType;
+  required unsigned long width;
+  required unsigned long height;
+  required unsigned long long bitrate;
+  required DOMString framerate;
 };
 
-// contentType member is specified as required in the spec.
-// We enforce that requirement in the MediaCapabilities code instead
-// See https://github.com/heycam/webidl/issues/76
 dictionary AudioConfiguration {
-  DOMString contentType;
+  required DOMString contentType;
   DOMString channels;
   unsigned long long bitrate;
   unsigned long samplerate;
 };
 
 [Exposed=(Window, Worker), Func="mozilla::dom::MediaCapabilities::Enabled",
  HeaderFile="mozilla/dom/MediaCapabilities.h"]
 interface MediaCapabilitiesInfo {
copy from testing/web-platform/meta/media-capabilities/decodingInfo.html.ini
copy to testing/web-platform/meta/media-capabilities/encodingInfo.html.ini
--- a/testing/web-platform/meta/media-capabilities/decodingInfo.html.ini
+++ b/testing/web-platform/meta/media-capabilities/encodingInfo.html.ini
@@ -1,7 +1,13 @@
-[decodingInfo.html]
-  [Test that decodingInfo rejects if the video configuration contentType has more than one parameter]
+[encodingInfo.html]
+  [Test that encodingInfo rejects if the video configuration contentType has more than one parameter]
+    expected: FAIL
+
+  [Test that encodingInfo rejects if the video configuration contentType has one parameter that isn't codecs]
     expected: FAIL
 
-  [Test that decodingInfo rejects if the audio configuration contentType has more than one parameters]
+  [Test that encodingInfo rejects if the audio configuration contentType has more than one parameters]
     expected: FAIL
 
+  [Test that encodingInfo rejects if the audio configuration contentType has one parameter that isn't codecs]
+    expected: FAIL
+
--- a/testing/web-platform/tests/media-capabilities/decodingInfo.html
+++ b/testing/web-platform/tests/media-capabilities/decodingInfo.html
@@ -286,17 +286,18 @@ promise_test(t => {
     assert_idl_attribute(ability, 'supported');
     assert_idl_attribute(ability, 'smooth');
     assert_idl_attribute(ability, 'powerEfficient');
   });
 }, "Test that decodingInfo returns a valid MediaCapabilitiesInfo objects");
 
 async_test(t => {
   var validTypes = [ 'file', 'media-source' ];
-  var invalidTypes = [ undefined, null, '', 'foobar', 'mse', 'MediaSource' ];
+  var invalidTypes = [ undefined, null, '', 'foobar', 'mse', 'MediaSource',
+                       'record', 'transmission' ];
 
   var validPromises = [];
   var invalidCaught = 0;
 
   validTypes.forEach(type => {
     validPromises.push(navigator.mediaCapabilities.decodingInfo({
       type: type,
       video: minimalVideoConfiguration,
copy from testing/web-platform/tests/media-capabilities/decodingInfo.html
copy to testing/web-platform/tests/media-capabilities/encodingInfo.html
--- a/testing/web-platform/tests/media-capabilities/decodingInfo.html
+++ b/testing/web-platform/tests/media-capabilities/encodingInfo.html
@@ -16,312 +16,313 @@ var minimalVideoConfiguration = {
 
 // Minimal AudioConfiguration that will be allowed per spec. All optional
 // properties are missing.
 var minimalAudioConfiguration = {
   contentType: 'audio/webm; codecs="opus"',
 };
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo());
-}, "Test that decodingInfo rejects if it doesn't get a configuration");
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo());
+}, "Test that encodingInfo rejects if it doesn't get a configuration");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({}));
-}, "Test that decodingInfo rejects if the MediaConfiguration isn't valid");
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({}));
+}, "Test that encodingInfo rejects if the MediaConfiguration isn't valid");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
     video: minimalVideoConfiguration,
     audio: minimalAudioConfiguration,
   }));
-}, "Test that decodingInfo rejects if the MediaConfiguration does not have a type");
+}, "Test that encodingInfo rejects if the MediaConfiguration does not have a type");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
   }));
-}, "Test that decodingInfo rejects if the configuration doesn't have an audio or video field");
+}, "Test that encodingInfo rejects if the configuration doesn't have an audio or video field");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: -1,
     },
   }));
-}, "Test that decodingInfo rejects if the video configuration has a negative framerate");
+}, "Test that encodingInfo rejects if the video configuration has a negative framerate");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: 0,
     },
   }));
-}, "Test that decodingInfo rejects if the video configuration has a framerate set to 0");
+}, "Test that encodingInfo rejects if the video configuration has a framerate set to 0");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: Infinity,
     },
   }));
-}, "Test that decodingInfo rejects if the video configuration has a framerate set to Infinity");
+}, "Test that encodingInfo rejects if the video configuration has a framerate set to Infinity");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'fgeoa',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: 24,
     },
   }));
-}, "Test that decodingInfo rejects if the video configuration contentType doesn't parse");
+}, "Test that encodingInfo rejects if the video configuration contentType doesn't parse");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'audio/fgeoa',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: 24,
     },
   }));
-}, "Test that decodingInfo rejects if the video configuration contentType isn't of type video");
+}, "Test that encodingInfo rejects if the video configuration contentType isn't of type video");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"; foo="bar"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: 24,
     },
   }));
-}, "Test that decodingInfo rejects if the video configuration contentType has more than one parameter");
+}, "Test that encodingInfo rejects if the video configuration contentType has more than one parameter");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; foo="bar"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: 24,
     },
   }));
-}, "Test that decodingInfo rejects if the video configuration contentType has one parameter that isn't codecs");
+}, "Test that encodingInfo rejects if the video configuration contentType has one parameter that isn't codecs");
 
 promise_test(t => {
-  return navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: '24000/1001',
     }
   });
-}, "Test that decodingInfo() accepts framerate in the form of x/y");
+}, "Test that encodingInfo() accepts framerate in the form of x/y");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: '24000/0',
     }
   }));
-}, "Test that decodingInfo() rejects framerate in the form of x/0");
+}, "Test that encodingInfo() rejects framerate in the form of x/0");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: '0/10001',
     }
   }));
-}, "Test that decodingInfo() rejects framerate in the form of 0/y");
+}, "Test that encodingInfo() rejects framerate in the form of 0/y");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: '-24000/10001',
     }
   }));
-}, "Test that decodingInfo() rejects framerate in the form of -x/y");
+}, "Test that encodingInfo() rejects framerate in the form of -x/y");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: '24000/-10001',
     }
   }));
-}, "Test that decodingInfo() rejects framerate in the form of x/-y");
+}, "Test that encodingInfo() rejects framerate in the form of x/-y");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: '24000/',
     }
   }));
-}, "Test that decodingInfo() rejects framerate in the form of x/");
+}, "Test that encodingInfo() rejects framerate in the form of x/");
 
 promise_test(t => {
-  return navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: '24000/1e4',
     }
   });
-}, "Test that decodingInfo() accepts framerate with 'e'");
+}, "Test that encodingInfo() accepts framerate with 'e'");
 
 promise_test(t => {
-  return navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: '24/1.0001',
     }
   });
-}, "Test that decodingInfo() accepts framerate as fraction with decimals");
+}, "Test that encodingInfo() accepts framerate as fraction with decimals");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: {
       contentType: 'video/webm; codecs="vp09.00.10.08"',
       width: 800,
       height: 600,
       bitrate: 3000,
       framerate: '1/3x',
     }
   }));
-}, "Test that decodingInfo() rejects framerate with trailing unallowed characters");
+}, "Test that encodingInfo() rejects framerate with trailing unallowed characters");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     audio: { contentType: 'fgeoa' },
   }));
-}, "Test that decodingInfo rejects if the audio configuration contenType doesn't parse");
+}, "Test that encodingInfo rejects if the audio configuration contenType doesn't parse");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     audio: { contentType: 'video/fgeoa' },
   }));
-}, "Test that decodingInfo rejects if the audio configuration contentType isn't of type audio");
+}, "Test that encodingInfo rejects if the audio configuration contentType isn't of type audio");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     audio: { contentType: 'audio/webm; codecs="opus"; foo="bar"' },
   }));
-}, "Test that decodingInfo rejects if the audio configuration contentType has more than one parameters");
+}, "Test that encodingInfo rejects if the audio configuration contentType has more than one parameters");
 
 promise_test(t => {
-  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     audio: { contentType: 'audio/webm; foo="bar"' },
   }));
-}, "Test that decodingInfo rejects if the audio configuration contentType has one parameter that isn't codecs");
+}, "Test that encodingInfo rejects if the audio configuration contentType has one parameter that isn't codecs");
 
 promise_test(t => {
-  return navigator.mediaCapabilities.decodingInfo({
-    type: 'file',
+  return navigator.mediaCapabilities.encodingInfo({
+    type: 'record',
     video: minimalVideoConfiguration,
     audio: minimalAudioConfiguration,
   }).then(ability => {
     assert_idl_attribute(ability, 'supported');
     assert_idl_attribute(ability, 'smooth');
     assert_idl_attribute(ability, 'powerEfficient');
   });
-}, "Test that decodingInfo returns a valid MediaCapabilitiesInfo objects");
+}, "Test that encodingInfo returns a valid MediaCapabilitiesInfo objects");
 
 async_test(t => {
-  var validTypes = [ 'file', 'media-source' ];
-  var invalidTypes = [ undefined, null, '', 'foobar', 'mse', 'MediaSource' ];
+  var validTypes = [ 'record', 'transmission' ];
+  var invalidTypes = [ undefined, null, '', 'foobar', 'mse', 'MediaSource',
+                       'file', 'media-source', ];
 
   var validPromises = [];
   var invalidCaught = 0;
 
   validTypes.forEach(type => {
-    validPromises.push(navigator.mediaCapabilities.decodingInfo({
+    validPromises.push(navigator.mediaCapabilities.encodingInfo({
       type: type,
       video: minimalVideoConfiguration,
       audio: minimalAudioConfiguration,
     }));
   });
 
   // validTypes are tested via Promise.all(validPromises) because if one of the
   // promises fail, Promise.all() will reject. This mechanism can't be used for
   // invalid types which will be tested individually and increment invalidCaught
   // when rejected until the amount of rejection matches the expectation.
   Promise.all(validPromises).then(t.step_func(() => {
     for (var i = 0; i < invalidTypes.length; ++i) {
-      navigator.mediaCapabilities.decodingInfo({
+      navigator.mediaCapabilities.encodingInfo({
         type: invalidTypes[i],
         video: minimalVideoConfiguration,
         audio: minimalAudioConfiguration,
       }).then(t.unreached_func(), t.step_func(e => {
         assert_equals(e.name, 'TypeError');
         ++invalidCaught;
         if (invalidCaught == invalidTypes.length)
           t.done();
       }));
     }
   }), t.unreached_func('Promise.all should not reject for valid types'));
-}, "Test that decodingInfo rejects if the MediaConfiguration does not have a valid type");
+}, "Test that encodingInfo rejects if the MediaConfiguration does not have a valid type");
 
 </script>