Bug 1101304 - Handle CORS in EME - r=cpearce a=lmandel
authorEdwin Flores <eflores@mozilla.com>
Thu, 29 Jan 2015 20:30:38 +1300
changeset 250180 7503ad43a7fd
parent 250179 6f83d3fe38da
child 250181 00ac75ab182f
push id4521
push usercpearce@mozilla.com
push date2015-03-04 01:22 +0000
treeherdermozilla-beta@8abdbdecd2d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, lmandel
bugs1101304
milestone37.0
Bug 1101304 - Handle CORS in EME - r=cpearce a=lmandel
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
dom/media/eme/MediaEncryptedEvent.cpp
dom/media/eme/MediaEncryptedEvent.h
dom/media/eme/MediaKeys.cpp
dom/media/eme/MediaKeys.h
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3318,16 +3318,25 @@ void HTMLMediaElement::DownloadProgresse
   CheckProgress(true);
 }
 
 bool HTMLMediaElement::ShouldCheckAllowOrigin()
 {
   return mCORSMode != CORS_NONE;
 }
 
+bool HTMLMediaElement::IsCORSSameOrigin()
+{
+  bool subsumes;
+  nsRefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
+  return
+    (NS_SUCCEEDED(NodePrincipal()->Subsumes(principal, &subsumes)) && subsumes) ||
+    ShouldCheckAllowOrigin();
+}
+
 void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatus aNextFrame)
 {
   mLastNextFrameStatus = aNextFrame;
 
   if (mDecoder && mReadyState < nsIDOMHTMLMediaElement::HAVE_METADATA) {
     // aNextFrame might have a next frame because the decoder can advance
     // on its own thread before MetadataLoaded gets a chance to run.
     // The arrival of more data can't change us out of this readyState.
@@ -3663,32 +3672,23 @@ already_AddRefed<nsIPrincipal> HTMLMedia
   }
   return nullptr;
 }
 
 void HTMLMediaElement::NotifyDecoderPrincipalChanged()
 {
   nsRefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
 
-  bool subsumes;
-  mDecoder->UpdateSameOriginStatus(
-    !principal ||
-    (NS_SUCCEEDED(NodePrincipal()->Subsumes(principal, &subsumes)) && subsumes) ||
-    mCORSMode != CORS_NONE);
+  mDecoder->UpdateSameOriginStatus(!principal || IsCORSSameOrigin());
 
   for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) {
     OutputMediaStream* ms = &mOutputStreams[i];
     ms->mStream->SetCORSMode(mCORSMode);
     ms->mStream->CombineWithPrincipal(principal);
   }
-#ifdef MOZ_EME
-  if (mMediaKeys && NS_FAILED(mMediaKeys->CheckPrincipals())) {
-    mMediaKeys->Shutdown();
-  }
-#endif
 }
 
 void HTMLMediaElement::UpdateMediaSize(nsIntSize size)
 {
   mMediaSize = size;
   UpdateReadyStateForData(mLastNextFrameStatus);
 }
 
@@ -4332,18 +4332,16 @@ HTMLMediaElement::SetMediaKeys(mozilla::
     if (NS_FAILED(mMediaKeys->Bind(this))) {
       promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
       mMediaKeys = nullptr;
       return promise.forget();
     }
     if (mDecoder) {
       mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
     }
-    // Update the same-origin status.
-    NotifyDecoderPrincipalChanged();
   }
   promise->MaybeResolve(JS::UndefinedHandleValue);
   return promise.forget();
 }
 
 MediaWaitingFor
 HTMLMediaElement::WaitingFor() const
 {
@@ -4366,18 +4364,23 @@ HTMLMediaElement::SetOnencrypted(EventHa
     elm->SetEventHandler(nsGkAtoms::onencrypted, EmptyString(), handler);
   }
 }
 
 void
 HTMLMediaElement::DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
                                     const nsAString& aInitDataType)
 {
-  nsRefPtr<MediaEncryptedEvent> event(
-    MediaEncryptedEvent::Constructor(this, aInitDataType, aInitData));
+  nsRefPtr<MediaEncryptedEvent> event;
+  if (IsCORSSameOrigin()) {
+    event = MediaEncryptedEvent::Constructor(this, aInitDataType, aInitData);
+  } else {
+    event = MediaEncryptedEvent::Constructor(this);
+  }
+
   nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
     new AsyncEventDispatcher(this, event);
   asyncDispatcher->PostDOMEvent();
 }
 
 bool
 HTMLMediaElement::IsEventAttributeName(nsIAtom* aName)
 {
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -240,16 +240,20 @@ public:
   // start playing.
   // If the element is 'autoplay' and is ready to play back (not paused,
   // autoplay pref enabled, etc), it should start playing back.
   void CheckAutoplayDataReady();
 
   // Check if the media element had crossorigin set when loading started
   bool ShouldCheckAllowOrigin();
 
+  // Returns true if the currently loaded resource is CORS same-origin with
+  // respect to the document.
+  bool IsCORSSameOrigin();
+
   // Is the media element potentially playing as defined by the HTML 5 specification.
   // http://www.whatwg.org/specs/web-apps/current-work/#potentially-playing
   bool IsPotentiallyPlaying() const;
 
   // Has playback ended as defined by the HTML 5 specification.
   // http://www.whatwg.org/specs/web-apps/current-work/#ended
   bool IsPlaybackEnded() const;
 
--- a/dom/media/eme/MediaEncryptedEvent.cpp
+++ b/dom/media/eme/MediaEncryptedEvent.cpp
@@ -47,16 +47,25 @@ MediaEncryptedEvent::~MediaEncryptedEven
 
 JSObject*
 MediaEncryptedEvent::WrapObjectInternal(JSContext* aCx)
 {
   return MediaEncryptedEventBinding::Wrap(aCx, this);
 }
 
 already_AddRefed<MediaEncryptedEvent>
+MediaEncryptedEvent::Constructor(EventTarget* aOwner)
+{
+  nsRefPtr<MediaEncryptedEvent> e = new MediaEncryptedEvent(aOwner);
+  e->InitEvent(NS_LITERAL_STRING("encrypted"), false, false);
+  e->SetTrusted(true);
+  return e.forget();
+}
+
+already_AddRefed<MediaEncryptedEvent>
 MediaEncryptedEvent::Constructor(EventTarget* aOwner,
                                  const nsAString& aInitDataType,
                                  const nsTArray<uint8_t>& aInitData)
 {
   nsRefPtr<MediaEncryptedEvent> e = new MediaEncryptedEvent(aOwner);
   e->InitEvent(NS_LITERAL_STRING("encrypted"), false, false);
   e->mInitDataType = aInitDataType;
   e->mRawInitData = aInitData;
--- a/dom/media/eme/MediaEncryptedEvent.h
+++ b/dom/media/eme/MediaEncryptedEvent.h
@@ -34,16 +34,19 @@ protected:
   nsString mInitDataType;
   JS::Heap<JSObject*> mInitData;
 
 public:
 
   virtual JSObject* WrapObjectInternal(JSContext* aCx) MOZ_OVERRIDE;
 
   static already_AddRefed<MediaEncryptedEvent>
+  Constructor(EventTarget* aOwner);
+
+  static already_AddRefed<MediaEncryptedEvent>
   Constructor(EventTarget* aOwner,
               const nsAString& aInitDataType,
               const nsTArray<uint8_t>& aInitData);
 
   static already_AddRefed<MediaEncryptedEvent>
   Constructor(const GlobalObject& aGlobal,
               const nsAString& aType,
               const MediaKeyNeededEventInit& aEventInitDict,
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -428,43 +428,16 @@ nsresult
 MediaKeys::Bind(HTMLMediaElement* aElement)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (IsBoundToMediaElement()) {
     return NS_ERROR_FAILURE;
   }
 
   mElement = aElement;
-  nsresult rv = CheckPrincipals();
-  if (NS_FAILED(rv)) {
-    mElement = nullptr;
-    return rv;
-  }
-
-  return NS_OK;
-}
-
-nsresult
-MediaKeys::CheckPrincipals()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  if (!IsBoundToMediaElement()) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsRefPtr<nsIPrincipal> elementPrincipal(mElement->GetCurrentPrincipal());
-  nsRefPtr<nsIPrincipal> elementTopLevelPrincipal(mElement->GetTopLevelPrincipal());
-  if (!elementPrincipal ||
-      !mPrincipal ||
-      !elementPrincipal->Equals(mPrincipal) ||
-      !elementTopLevelPrincipal ||
-      !mTopLevelPrincipal ||
-      !elementTopLevelPrincipal->Equals(mTopLevelPrincipal)) {
-    return NS_ERROR_FAILURE;
-  }
 
   return NS_OK;
 }
 
 bool
 CopyArrayBufferViewOrArrayBufferData(const ArrayBufferViewOrArrayBuffer& aBufferOrView,
                                      nsTArray<uint8_t>& aOutData)
 {
--- a/dom/media/eme/MediaKeys.h
+++ b/dom/media/eme/MediaKeys.h
@@ -112,20 +112,16 @@ public:
 
   // Called by CDMProxy when CDM crashes or shuts down. It is different from
   // Shutdown which is called from the script/dom side.
   void Terminated();
 
   // Returns true if this MediaKeys has been bound to a media element.
   bool IsBoundToMediaElement() const;
 
-  // Return NS_OK if the principals are the same as when the MediaKeys
-  // was created, failure otherwise.
-  nsresult CheckPrincipals();
-
 private:
 
   bool IsInPrivateBrowsing();
 
   // Removes promise from mPromises, and returns it.
   already_AddRefed<Promise> RetrievePromise(PromiseId aId);
 
   // Owning ref to proxy. The proxy has a weak reference back to the MediaKeys,