| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>Test MediaKeySession lifetime without release()</title> |
| <script src="encrypted-media-utils.js"></script> |
| <script src="../../resources/testharness.js"></script> |
| <script src="../../resources/testharnessreport.js"></script> |
| </head> |
| <body> |
| <div id="log"></div> |
| <script> |
| // Since MediaKeySession (and MediaKeys) are ActiveDOMObjects, |
| // we can determine when they are garbage collected. |
| // MediaKeySessions remain as long as: |
| // JavaScript has a reference to it |
| // OR (MediaKeys is around |
| // AND the session has not received a close() event) |
| |
| async_test(function(test) |
| { |
| var mediaKeys; |
| var mediaKeySession1; |
| var mediaKeySession2; |
| var mediaKeySession3; |
| var initDataType; |
| var initData; |
| var startingActiveDOMObjectCount = window.internals.activeDOMObjectCount(document); |
| |
| function numActiveDOMObjectsCreated() |
| { |
| return window.internals.activeDOMObjectCount(document) - startingActiveDOMObjectCount; |
| } |
| |
| getSupportedInitDataType().then(function(type) { |
| initDataType = type; |
| initData = getInitData(initDataType); |
| return navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{}]); |
| }).then(function(access) { |
| assert_equals(access.keySystem, 'org.w3.clearkey'); |
| return access.createMediaKeys(); |
| }).then(function(result) { |
| mediaKeys = result; |
| assert_equals(typeof mediaKeys.createSession, 'function'); |
| |
| // Verify MediaKeys is an ActiveDOMObject. |
| // In non-Oilpan, numActiveDOMObjectsCreate() == 1. |
| // In Oilpan, numActiveDOMObjectsCreate() <= 4. |
| // (1 MediaKeys, |
| // 1 MediaKeysInitializer and |
| // 1 MediaKeySystemAccessInitializer (navigator.requestMediaKeySystemAccess() use above), |
| // 1 MediaKeySystemAccessInitializer (isInitDataSupported() (via getSupportedInitDataType()))) |
| assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 4, 'MediaKeys.create()'); |
| |
| // Create 3 sessions. |
| mediaKeySession1 = mediaKeys.createSession(); |
| return mediaKeySession1.generateRequest(initDataType, initData); |
| }).then(function() { |
| assert_true(mediaKeySession1.sessionId && mediaKeySession1.sessionId.length > 0); |
| |
| // Should be 1 MediaKeys + 1 MediaKeySession. |
| // In non-Oilpan, numActiveDOMObjectsCreate() == 2. |
| // In Oilpan, numActiveDOMObjectsCreate() <= 6. |
| // (1 MediaKeys, |
| // 1 MediaKeysInitializer and |
| // 2 MediaKeySystemAccessInitializer, |
| // 1 ContentDecryptionModuleResultPromise and |
| // 1 MediaKeySession). |
| assert_between_inclusive(numActiveDOMObjectsCreated(), 2, 6, 'MediaKeys.createSession(1)'); |
| |
| mediaKeySession2 = mediaKeys.createSession(); |
| return mediaKeySession2.generateRequest(initDataType, initData); |
| }).then(function() { |
| assert_true(mediaKeySession2.sessionId && mediaKeySession2.sessionId.length > 0); |
| |
| // Should be 1 MediaKeys + 2 MediaKeySessions. |
| // In non-Oilpan, numActiveDOMObjectsCreate() == 3. |
| // In Oilpan, numActiveDOMObjectsCreate() <= 8. |
| // (1 MediaKeys, |
| // 1 MediaKeysInitializer and |
| // 2 MediaKeySystemAccessInitializers, |
| // 2 ContentDecryptionModuleResultPromise and |
| // 2 MediaKeySession). |
| assert_between_inclusive(numActiveDOMObjectsCreated(), 3, 8, 'mediaKeys.createSession(2)'); |
| |
| mediaKeySession3 = mediaKeys.createSession(); |
| return mediaKeySession3.generateRequest(initDataType, initData); |
| }).then(function() { |
| assert_true(mediaKeySession3.sessionId && mediaKeySession3.sessionId.length > 0); |
| |
| // Should be 1 MediaKeys + 3 MediaKeySessions. |
| // In non-Oilpan, numActiveDOMObjectsCreate() == 4. |
| // In Oilpan, numActiveDOMObjectsCreate() <= 10. |
| // (1 MediaKeys, |
| // 1 MediaKeysInitializer and |
| // 2 MediaKeySystemAccessInitializers, |
| // 3 ContentDecryptionModuleResultPromise and |
| // 3 MediaKeySession). |
| assert_between_inclusive(numActiveDOMObjectsCreated(), 4, 10, 'mediaKeys.createSession(3)'); |
| |
| // Run gc(). All sessions should remain as we have a |
| // reference to each one. However, running gc() |
| // asynchronously should free up the last PromiseResolver. |
| return createGCPromise(); |
| }).then(function(result) { |
| // Only MediaKeys + 3 MediaKeySessions should remain. |
| // In non-Oilpan, there is also something from createGCPromise(). |
| assert_between_inclusive(numActiveDOMObjectsCreated(), 4, 5, 'After gc()'); |
| |
| // Now drop references to 2 of the sessions. Even though we |
| // don't have a reference, MediaKeys is still around (and |
| // the sessions aren't closed), so the objects won't be |
| // collected. |
| mediaKeySession1 = null; |
| mediaKeySession2 = null; |
| return createGCPromise(); |
| }).then(function(result) { |
| return createGCPromise(); |
| }).then(function(result) { |
| // MediaKeys + 3 MediaKeySessions should remain. |
| // In non-Oilpan, there is also something from createGCPromise(). |
| assert_between_inclusive(numActiveDOMObjectsCreated(), 4, 5, 'After second gc()'); |
| |
| // Now drop the reference to MediaKeys. It and the 2 |
| // unreferenced sessions should be collected. Since |
| // MediaKeySessions remain alive as long as MediaKeys is |
| // around, it is possible that gc() checks one or both |
| // MediaKeySession objects first, and doesn't collect them |
| // since MediaKeys hasn't been collected yet. Thus run gc() |
| // twice, to ensure that the unreferenced MediaKeySession |
| // objects get collected. |
| mediaKeys = null; |
| return createGCPromise(); |
| }).then(function(result) { |
| return createGCPromise(); |
| }).then(function(result) { |
| // Only 1 MediaKeySessions should remain. |
| // In non-Oilpan, there is also something from createGCPromise(). |
| assert_between_inclusive(numActiveDOMObjectsCreated(), 1, 2, 'After mediaKeys = null'); |
| |
| // Drop the reference to the last session. It should get |
| // collected now since MediaKeys is gone. |
| mediaKeySession3 = null; |
| return createGCPromise(); |
| }).then(function(result) { |
| // No MediaKeySessions should remain. |
| // In non-Oilpan, there is also something from createGCPromise(). |
| assert_between_inclusive(numActiveDOMObjectsCreated(), 0, 1, 'After final gc()'); |
| |
| test.done(); |
| }).catch(function(error) { |
| forceTestFailureFromPromise(test, error); |
| }); |
| }, 'MediaKeySession lifetime without release()'); |
| </script> |
| </body> |
| </html> |