Bug 1310879 - Remove EME persistent-license sessions. r=gerald
authorChris Pearce <cpearce@mozilla.com>
Tue, 18 Oct 2016 15:42:02 +1300
changeset 319905 a0c11c1c08c34cada800dc86cb2f78c65a4852ef
parent 319904 22007e69f30a9d47b44154576bba03ffd955fa70
child 319906 de41e684fb55d7e64a3eecf8ee0e4279f37e0724
push id20749
push userryanvm@gmail.com
push dateSat, 29 Oct 2016 13:21:21 +0000
treeherderfx-team@1b170b39ed6b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald
bugs1310879
milestone52.0a1
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'}],
       }