Bug 1280829 - Only block non-MSE content which is encrypted once it reaches load metadata. r=jya, a=ritu
authorChris Pearce <cpearce@mozilla.com>
Wed, 21 Sep 2016 13:04:01 +1200
changeset 355766 2d7f4fd136fa8d899070e3edf84e85709674f853
parent 355765 7a64ad6bb64d79fb18a976381c6d097db82b168e
child 355767 130a83f1c885540bf15a8f755ca968d3bba656b9
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, ritu
bugs1280829
milestone51.0a2
Bug 1280829 - Only block non-MSE content which is encrypted once it reaches load metadata. r=jya, a=ritu Previously, we'd block loading of non-MSE content when there was a MediaKeys attached, that is, we'd assume that all content was EME content if a MediaKeys was attached. But some sites attach a MediaKeys and then load non-MSE non-EME content, and that (despite being a bit silly) shouldn't fail. MozReview-Commit-ID: 9LupWaehXim
dom/html/HTMLMediaElement.cpp
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1632,30 +1632,16 @@ nsresult HTMLMediaElement::LoadResource(
   nsCOMPtr<nsIDocShell> docShell = OwnerDoc()->GetDocShell();
   if (docShell && !docShell->GetAllowMedia()) {
     return NS_ERROR_FAILURE;
   }
 
   // Set the media element's CORS mode only when loading a resource
   mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
 
-#ifdef MOZ_EME
-  bool isBlob = false;
-  if (mMediaKeys &&
-      Preferences::GetBool("media.eme.mse-only", true) &&
-      // We only want mediaSource URLs, but they are BlobURL, so we have to
-      // check the schema and if they are not MediaStream or real Blob.
-      (NS_FAILED(mLoadingSrc->SchemeIs(BLOBURI_SCHEME, &isBlob)) ||
-       !isBlob ||
-       IsMediaStreamURI(mLoadingSrc) ||
-       IsBlobURI(mLoadingSrc))) {
-    return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
-  }
-#endif
-
   HTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc);
   if (other && other->mDecoder) {
     // Clone it.
     nsresult rv = InitializeDecoderAsClone(other->mDecoder);
     if (NS_SUCCEEDED(rv))
       return rv;
   }
 
@@ -4335,18 +4321,20 @@ void HTMLMediaElement::MetadataLoaded(co
                 mMediaInfo.mVideo.mDisplay.height > 0),
                "Video resolution must be known on 'loadedmetadata'");
   DispatchAsyncEvent(NS_LITERAL_STRING("loadedmetadata"));
   if (mDecoder && mDecoder->IsTransportSeekable() && mDecoder->IsMediaSeekable()) {
     ProcessMediaFragmentURI();
     mDecoder->SetFragmentEndTime(mFragmentEnd);
   }
   if (mIsEncrypted) {
+    // We only support playback of encrypted content via MSE by default.
     if (!mMediaSource && Preferences::GetBool("media.eme.mse-only", true)) {
-      DecodeError(NS_ERROR_DOM_MEDIA_FATAL_ERR);
+      DecodeError(MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
+                              "Encrypted content not supported outside of MSE"));
       return;
     }
 
 #ifdef MOZ_EME
     // Dispatch a distinct 'encrypted' event for each initData we have.
     for (const auto& initData : mPendingEncryptedInitData.mInitDatas) {
       DispatchEncrypted(initData.mInitData, initData.mType);
     }
@@ -6111,26 +6099,16 @@ HTMLMediaElement::SetMediaKeys(mozilla::
     return nullptr;
   }
   RefPtr<DetailedPromise> promise = DetailedPromise::Create(global, aRv,
     NS_LITERAL_CSTRING("HTMLMediaElement.setMediaKeys"));
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  // We only support EME for MSE content by default.
-  if (mDecoder &&
-      !mMediaSource &&
-      Preferences::GetBool("media.eme.mse-only", true)) {
-    ShutdownDecoder();
-    promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
-                         NS_LITERAL_CSTRING("EME not supported on non-MSE streams"));
-    return promise.forget();
-  }
-
   // 1. If mediaKeys and the mediaKeys attribute are the same object,
   // return a resolved promise.
   if (mMediaKeys == aMediaKeys) {
     promise->MaybeResolveWithUndefined();
     return promise.forget();
   }
 
   // Note: Our attaching code is synchronous, so we can skip the following steps.