Bug 1310879 - Remove EME persistent-license sessions. r=gerald
authorChris Pearce <cpearce@mozilla.com>
Tue, 18 Oct 2016 15:42:02 +1300
changeset 319793 a0c11c1c08c34cada800dc86cb2f78c65a4852ef
parent 319792 22007e69f30a9d47b44154576bba03ffd955fa70
child 319794 de41e684fb55d7e64a3eecf8ee0e4279f37e0724
push id83254
push usercpearce@mozilla.com
push dateFri, 28 Oct 2016 02:25:15 +0000
treeherdermozilla-inbound@a0c11c1c08c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald
bugs1310879
milestone52.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 1310879 - Remove EME persistent-license sessions. r=gerald This removes the ability for ClearKey to instantiate persistent-license sessions using the EME APIs. MozReview-Commit-ID: FXj5YORxpas
browser/components/contextualidentity/test/browser/browser_eme.js
browser/components/contextualidentity/test/browser/browser_forgetAPI_EME_forgetThisSite.js
dom/media/MediaPrefs.h
dom/media/eme/MediaKeySession.cpp
dom/media/eme/MediaKeySystemAccess.cpp
dom/media/test/mochitest.ini
dom/media/test/test_eme_persistent_sessions.html
dom/media/test/test_eme_requestKeySystemAccess.html
--- a/browser/components/contextualidentity/test/browser/browser_eme.js
+++ b/browser/components/contextualidentity/test/browser/browser_eme.js
@@ -86,16 +86,17 @@ function generateKeyInfo(aData) {
 add_task(function* setup() {
   // Make sure userContext is enabled.
   yield new Promise(resolve => {
     SpecialPowers.pushPrefEnv({"set": [
       [ "privacy.userContext.enabled", true ],
       [ "media.mediasource.enabled", true ],
       [ "media.eme.apiVisible", true ],
       [ "media.mediasource.webm.enabled", true ],
+      [ "media.clearkey.persistent-license.enabled", true ],
     ]}, resolve);
   });
 });
 
 add_task(function* test() {
   // Open a tab with the default container.
   let defaultContainer = yield openTabInUserContext(TEST_URL + "empty_file.html", USER_ID_DEFAULT);
 
--- a/browser/components/contextualidentity/test/browser/browser_forgetAPI_EME_forgetThisSite.js
+++ b/browser/components/contextualidentity/test/browser/browser_forgetAPI_EME_forgetThisSite.js
@@ -176,16 +176,17 @@ function* checkEMEKey(browser, emeSessio
 
 add_task(function* setup() {
   // Make sure userContext is enabled.
   yield SpecialPowers.pushPrefEnv({"set": [
       [ "privacy.userContext.enabled", true ],
       [ "media.mediasource.enabled", true ],
       [ "media.eme.apiVisible", true ],
       [ "media.mediasource.webm.enabled", true ],
+      [ "media.clearkey.persistent-license.enabled", true ],
   ]});
 });
 
 add_task(function* test_EME_forgetThisSite() {
   let tabs = [];
   let emeSessionIds = [];
 
   for (let userContextId of Object.keys(USER_CONTEXTS)) {
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -90,16 +90,19 @@ private:
   DECL_MEDIA_PREF("accessibility.monoaudio.enable",           MonoAudio, bool, false);
   DECL_MEDIA_PREF("media.resampling.enabled",                 AudioSinkResampling, bool, false);
   DECL_MEDIA_PREF("media.resampling.rate",                    AudioSinkResampleRate, uint32_t, 48000);
   DECL_MEDIA_PREF("media.forcestereo.enabled",                AudioSinkForceStereo, bool, true);
 
   // VideoSink
   DECL_MEDIA_PREF("media.ruin-av-sync.enabled",               RuinAvSync, bool, false);
 
+  // Encrypted Media Extensions
+  DECL_MEDIA_PREF("media.clearkey.persistent-license.enabled", ClearKeyPersistentLicenseEnabled, bool, false);
+
   // PlatformDecoderModule
   DECL_MEDIA_PREF("media.apple.forcevda",                     AppleForceVDA, bool, false);
   DECL_MEDIA_PREF("media.gmp.insecure.allow",                 GMPAllowInsecure, bool, false);
   DECL_MEDIA_PREF("media.gmp.async-shutdown-timeout",         GMPAsyncShutdownTimeout, uint32_t, GMP_DEFAULT_ASYNC_SHUTDOWN_TIMEOUT);
   DECL_MEDIA_PREF("media.eme.enabled",                        EMEEnabled, bool, false);
   DECL_MEDIA_PREF("media.use-blank-decoder",                  PDMUseBlankDecoder, bool, false);
   DECL_MEDIA_PREF("media.gpu-process-decoder",                PDMUseGPUDecoder, bool, false);
 #ifdef MOZ_GONK_MEDIACODEC
--- a/dom/media/eme/MediaKeySession.cpp
+++ b/dom/media/eme/MediaKeySession.cpp
@@ -498,17 +498,17 @@ MediaKeySession::Close(ErrorResult& aRv)
             this, NS_ConvertUTF16toUTF8(mSessionId).get());
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
       NS_LITERAL_CSTRING("MediaKeySession.Close() lost reference to CDM"));
     return promise.forget();
   }
   // 4. Let promise be a new promise.
   PromiseId pid = mKeys->StorePromise(promise);
   // 5. Run the following steps in parallel:
-  // 5.1 Let cdm be the CDM instance represented by session's cdm instance value.
+  // 5.1 Let cdm be the CDM instance represented by session's cdm instance value.
   // 5.2 Use cdm to close the session associated with session.
   mKeys->GetCDMProxy()->CloseSession(mSessionId, pid);
 
   EME_LOG("MediaKeySession[%p,'%s'] Close() sent to CDM, promiseId=%d",
           this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid);
 
   // Session Closed algorithm is run when CDM causes us to run OnSessionClosed().
 
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -427,17 +427,19 @@ GetSupportedKeySystems()
       KeySystemConfig clearkey;
       clearkey.mKeySystem = NS_ConvertUTF8toUTF16(kEMEKeySystemClearkey);
       clearkey.mInitDataTypes.AppendElement(NS_LITERAL_STRING("cenc"));
       clearkey.mInitDataTypes.AppendElement(NS_LITERAL_STRING("keyids"));
       clearkey.mInitDataTypes.AppendElement(NS_LITERAL_STRING("webm"));
       clearkey.mPersistentState = KeySystemFeatureSupport::Requestable;
       clearkey.mDistinctiveIdentifier = KeySystemFeatureSupport::Prohibited;
       clearkey.mSessionTypes.AppendElement(MediaKeySessionType::Temporary);
-      clearkey.mSessionTypes.AppendElement(MediaKeySessionType::Persistent_license);
+      if (MediaPrefs::ClearKeyPersistentLicenseEnabled()) {
+        clearkey.mSessionTypes.AppendElement(MediaKeySessionType::Persistent_license);
+      }
 #if defined(XP_WIN)
       // Clearkey CDM uses WMF decoders on Windows.
       if (WMFDecoderModule::HasAAC()) {
         clearkey.mMP4.SetCanDecryptAndDecode(GMP_CODEC_AAC);
       } else {
         clearkey.mMP4.SetCanDecrypt(GMP_CODEC_AAC);
       }
       if (WMFDecoderModule::HasH264()) {
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -692,18 +692,16 @@ skip-if = toolkit == 'android' # bug 114
 [test_eme_initDataTypes.html]
 skip-if = toolkit == 'android' # bug 1149374
 [test_eme_missing_pssh.html]
 skip-if = toolkit == 'android' # bug 1149374
 [test_eme_non_mse_fails.html]
 skip-if = toolkit == 'android' # bug 1149374
 [test_eme_request_notifications.html]
 skip-if = toolkit == 'android' # bug 1149374
-[test_eme_persistent_sessions.html]
-skip-if = toolkit == 'android' # bug 1149374
 [test_eme_playback.html]
 skip-if = toolkit == 'android' || toolkit == 'gonk' # android: bug 1149374; gonk: bug 1193351
 [test_eme_requestKeySystemAccess.html]
 skip-if = toolkit == 'android' # bug 1149374
 [test_eme_setMediaKeys_before_attach_MediaSource.html]
 skip-if = toolkit == 'android' # bug 1149374
 [test_eme_stream_capture_blocked_case1.html]
 tags=msg capturestream
deleted file mode 100644
--- a/dom/media/test/test_eme_persistent_sessions.html
+++ /dev/null
@@ -1,166 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test Encrypted Media Extensions</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="eme.js"></script>
-</head>
-<body>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-var manager = new MediaTestManager;
-
-function UsableKeyIdsMatch(usableKeyIds, expectedKeyIds) {
-  var hexKeyIds = usableKeyIds.map(function(keyId) {
-    return Base64ToHex(window.btoa(ArrayBufferToString(keyId)));
-  }).sort();
-  var expected = Object.keys(expectedKeyIds).sort();
-  if (expected.length != hexKeyIds.length) {
-    return false;
-  }
-  for (var i = 0; i < hexKeyIds.length; i++) {
-    if (hexKeyIds[i] != expected[i]){
-      return false;
-    }
-  }
-  return true;
-}
-
-function AwaitAllKeysUsable(session, keys, token) {
-  return new Promise(function(resolve, reject) {
-    function check() {
-      var map = session.keyStatuses;
-      var usableKeyIds = [];
-      for (var [key, val] of map.entries()) {
-        is(val, "usable", token + ": key status should be usable");
-        usableKeyIds.push(key);
-      }
-      if (UsableKeyIdsMatch(usableKeyIds, keys)) {
-        session.removeEventListener("keystatuseschange", check);
-        resolve();
-      }
-    }
-    session.addEventListener("keystatuseschange", check);
-    check(); // in case all keys are already usable
-  });
-}
-
-function AwaitAllKeysNotUsable(session, token) {
-  return new Promise(function(resolve, reject) {
-    function check() {
-      var map = session.keyStatuses;
-      if (map.size == 0) {
-        session.removeEventListener("keystatuseschange", check);
-        resolve();
-      }
-    }
-    session.addEventListener("keystatuseschange", check);
-    check(); // in case all keys are already removed
-  });
-}
-
-function startTest(test, token)
-{
-  manager.started(token);
-
-  var recreatedSession; // will have remove() called on it.
-
-  var keySystemAccess;
-
-  var v = SetupEME(test, token,
-    {
-      onsessionupdated: function(session) {
-        Log(token, "Session created");
-        var sessionId;
-
-        // Once the session has loaded and has all its keys usable, close
-        // all sessions without calling remove() on them.
-        AwaitAllKeysUsable(session, test.keys, token)
-        .then(function() {
-          sessionId = session.sessionId;
-          Log(token, "Closing session with id=" + sessionId);
-          return session.close();
-        })
-
-        // Once the session is closed, reload the MediaKeys and reload the session
-        .then(function() {
-          return navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, gCencMediaKeySystemConfig);
-        })
-
-        .then(function(requestedKeySystemAccess) {
-          keySystemAccess = requestedKeySystemAccess;
-          return keySystemAccess.createMediaKeys();
-        })
-
-        .then(function(mediaKeys) {
-          Log(token, "re-created MediaKeys object ok");
-          recreatedSession = mediaKeys.createSession("persistent-license");
-          Log(token, "Created recreatedSession, loading sessionId=" + sessionId);
-          return recreatedSession.load(sessionId);
-        })
-
-        .then(function(suceeded) {
-          if (suceeded) {
-            return Promise.resolve();
-          } else {
-            return Promise.reject("Fail to load recreatedSession, sessionId=" + sessionId);
-          }
-        })
-
-        .then(function() {
-          return AwaitAllKeysUsable(recreatedSession, test.keys, token);
-        })
-
-        .then(function() {
-          Log(token, "re-loaded persistent session, all keys still usable");
-          return Promise.all([AwaitAllKeysNotUsable(recreatedSession, token), recreatedSession.remove()]);
-        })
-
-        .then(function() {
-          Log(token, "removed session, all keys unusable.");
-          // Attempt to recreate the session, the attempt should fail.
-          return keySystemAccess.createMediaKeys();
-        })
-
-        .then(function(mediaKeys) {
-          Log(token, "re-re-created MediaKeys object ok");
-          // Trying to load the removed persistent session should fail.
-          return mediaKeys.createSession("persistent-license").load(sessionId);
-        })
-
-        .then(function(suceeded) {
-          is(suceeded, false, token + " we expect the third session creation to fail, as the session should have been removed.");
-          manager.finished(token);
-        })
-
-        .catch(function(reason) {
-          // Catch rejections if any.
-          ok(false, token + " rejected, reason=" + reason);
-          manager.finished(token);
-        });
-
-      },
-      sessionType: "persistent-license",
-    }
-  );
-
-  LoadTestWithManagedLoadToken(test, v, manager, token,
-                               { onlyLoadFirstFragments:2, noEndOfStream:false });
-}
-
-function beginTest() {
-  manager.runTests(gEMETests.filter(t => t.sessionCount === 1), startTest);
-}
-
-if (!IsMacOSSnowLeopardOrEarlier()) {
-  SimpleTest.waitForExplicitFinish();
-  SetupEMEPref(beginTest);
-} else {
-  todo(false, "Test disabled on this platform.");
-}
-</script>
-</pre>
-</body>
-</html>
--- a/dom/media/test/test_eme_requestKeySystemAccess.html
+++ b/dom/media/test/test_eme_requestKeySystemAccess.html
@@ -233,79 +233,39 @@ var tests = [
     expectedConfig: {
       label: SUPPORTED_LABEL,
       initDataTypes: ['cenc'],
       videoCapabilities: [{contentType: 'video/mp4'}],
     },
     shouldPass: true,
   },
   {
-    name: 'Persistent sessions; persistence required',
-    options: [
-      {
-        label: SUPPORTED_LABEL,
-        initDataTypes: ['cenc'],
-        videoCapabilities: [{contentType: 'video/mp4'}],
-        sessionTypes: ['temporary','persistent-license'],
-        persistentState: 'required',
-      }
-    ],
-    expectedConfig: {
-      label: SUPPORTED_LABEL,
-      initDataTypes: ['cenc'],
-      videoCapabilities: [{contentType: 'video/mp4'}],
-      sessionTypes: ['temporary','persistent-license'],
-      persistentState: 'required',
-    },
-    shouldPass: true,
-  },
-  {
-    name: 'Persistent sessions not allowed when persistentState prohibited',
+    name: 'Persistent-license should not be supported by ClearKey',
     options: [
       {
         initDataTypes: ['cenc'],
         videoCapabilities: [{contentType: 'video/mp4'}],
-        sessionTypes: ['temporary','persistent-license'],
-        persistentState: 'not-allowed',
+        sessionTypes: ['persistent-license'],
+        persistentState: 'optional',
       }
     ],
     shouldPass: false,
-  },
-  {
-    name: 'Persistent sessions; should bump optional persistState to required',
-    options: [
-      {
-        label: SUPPORTED_LABEL,
-        initDataTypes: ['cenc'],
-        videoCapabilities: [{contentType: 'video/mp4'}],
-        sessionTypes: ['temporary','persistent-license'],
-        persistentState: 'optional',
-      }
-    ],
-    expectedConfig: {
-      label: SUPPORTED_LABEL,
-      initDataTypes: ['cenc'],
-      videoCapabilities: [{contentType: 'video/mp4'}],
-      sessionTypes: ['temporary','persistent-license'],
-      persistentState: 'required',
-    },
-    shouldPass: true,
-  },
+  },  
   {
     name: 'Persistent-usage-record should not be supported by ClearKey',
     options: [
       {
         initDataTypes: ['cenc'],
         videoCapabilities: [{contentType: 'video/mp4'}],
         sessionTypes: ['persistent-usage-record'],
-        persistentState: 'required',
+        persistentState: 'optional',
       }
     ],
     shouldPass: false,
-  },  
+  },
   {
     name: 'MP4 audio container',
     options: [
       {
         label: SUPPORTED_LABEL,
         initDataTypes: ['cenc'],
         audioCapabilities: [{contentType: 'audio/mp4'}],
       }