4 <title>Test multiple MediaKeys lifetimes</title>
5 <script src="encrypted-media-utils.js"></script>
6 <script src="../../resources/testharness.js"></script>
7 <script src="../../resources/testharnessreport.js"></script>
12 // Since MediaKeys are not ActiveDOMObjects, it is hard to
13 // determine when they are garbage collected. For the test below
14 // a MediaKeySession (which is an ActiveDOMObject) is added to each
15 // MediaKeys object so there is something to count.
17 // MediaKeySessions remain as long as:
18 // JavaScript has a reference to it
19 // OR (MediaKeys is around
20 // AND the session has not received a close() event)
21 // In the tests below, we do not close any session nor keep a
22 // Javascript reference to any session, so MediaKeySessions remain
23 // as long as the associated MediaKeys object is around.
25 // For this test, create several MediaKeys (each with a
26 // MediaKeySession object so they can be counted) and verify
28 async_test(function(test)
31 var initDataType = getInitDataType();
32 var initData = getInitData(initDataType);
34 var startingActiveDOMObjectCount = window.internals.activeDOMObjectCount(document);
36 function numActiveDOMObjectsCreated()
38 return window.internals.activeDOMObjectCount(document) - startingActiveDOMObjectCount;
41 // Create a MediaKeys object and an associated MediaKeySession
42 // object. |mediaKeys| is updated to refer to the new MediaKeys
43 // object. Returns a promise that resolves with the new
44 // MediaKeySession object.
45 function createMediaKeyWithMediaKeySession()
47 return navigator.requestMediaKeySystemAccess('org.w3.clearkey').then(function(access) {
48 return access.createMediaKeys();
49 }).then(function(result) {
51 var mediaKeySession = mediaKeys.createSession();
52 return mediaKeySession.generateRequest(initDataType, initData).then(function() {
53 return mediaKeySession;
58 // Create a few MediaKeys + MediaKeySession objects. Only keep
59 // a reference to the last one created.
60 createMediaKeyWithMediaKeySession().then(function(mediaKeySession) {
61 // Should be 1 MediaKeySession.
62 assert_equals(numActiveDOMObjectsCreated(), 1);
63 return createMediaKeyWithMediaKeySession();
64 }).then(function(mediaKeySession) {
65 // Should be 2 MediaKeySessions.
66 assert_equals(numActiveDOMObjectsCreated(), 2);
67 return createMediaKeyWithMediaKeySession();
68 }).then(function(mediaKeySession) {
69 // Should be 3 MediaKeySessions.
70 assert_equals(numActiveDOMObjectsCreated(), 3);
71 return createMediaKeyWithMediaKeySession();
72 }).then(function(mediaKeySession) {
73 // Should be 4 MediaKeySessions.
74 assert_equals(numActiveDOMObjectsCreated(), 4);
75 return createMediaKeyWithMediaKeySession();
76 }).then(function(mediaKeySession) {
77 // Should be 5 MediaKeySessions.
78 assert_equals(numActiveDOMObjectsCreated(), 5);
80 // |mediaKeys| refers to the most recently created MediaKeys
83 // In order for the MediaKeySession objects to have no
84 // outstanding activity so that they can be garbage
85 // collected, it needs time to process any pending events.
86 // As a "message" event is generated when a new session is
87 // created, we need to allow the event to run (we're not
88 // doing anything with the event in this test).
89 return delayToAllowEventProcessingPromise();
90 }).then(function(result) {
91 // Should be just 5 MediaKeySessions.
92 assert_equals(numActiveDOMObjectsCreated(), 5);
94 // As we only have a reference (|mediaKeys|) to the last
95 // created MediaKeys object, the other 4 MediaKeys objects
96 // are available to be garbage collected.
98 // Since MediaKeySessions remain alive as long as MediaKeys
99 // is around, it is possible that gc() checks the
100 // MediaKeySession object first, and doesn't collect it
101 // since MediaKeys hasn't been collected yet. Thus run gc()
102 // twice, to ensure that the unreferenced MediaKeySession
103 // objects get collected.
104 return createGCPromise();
105 }).then(function(result) {
106 return createGCPromise();
107 }).then(function(result) {
108 // Should be 1 MediaKeySession, the session for |mediaKeys|.
109 assert_equals(numActiveDOMObjectsCreated(), 1);
110 assert_equals(typeof mediaKeys.createSession, 'function');
112 // Release the last MediaKeys object created.
115 // Run gc() again to reclaim the remaining MediaKeys object
116 // and the last MediaKeySession. gc() run twice in case
117 // MediaKeySession checked first and not collected in the
119 return createGCPromise();
120 }).then(function(result) {
121 return createGCPromise();
122 }).then(function(result) {
123 assert_equals(numActiveDOMObjectsCreated(), 0);
125 }).catch(function(error) {
126 forceTestFailureFromPromise(test, error);
128 }, 'Multiple MediaKeys lifetime');