rx-player 4.3.0-dev.2024112900 → 4.3.0-dev.2025012900
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -8
- package/VERSION +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_worker.js +1 -1
- package/dist/commonjs/compat/browser_compatibility_types.d.ts +7 -2
- package/dist/commonjs/compat/browser_compatibility_types.d.ts.map +1 -1
- package/dist/commonjs/compat/browser_compatibility_types.js +0 -1
- package/dist/commonjs/compat/browser_detection.js +1 -1
- package/dist/commonjs/compat/event_listeners.d.ts.map +1 -1
- package/dist/commonjs/compat/event_listeners.js +2 -4
- package/dist/commonjs/compat/has_mse_in_worker.d.ts.map +1 -1
- package/dist/commonjs/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
- package/dist/commonjs/core/cmcd/cmcd_data_builder.js +1 -2
- package/dist/commonjs/core/main/worker/send_message.d.ts.map +1 -1
- package/dist/commonjs/core/main/worker/send_message.js +0 -1
- package/dist/commonjs/core/main/worker/worker_main.js +1 -1
- package/dist/commonjs/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
- package/dist/commonjs/core/stream/adaptation/adaptation_stream.js +4 -8
- package/dist/commonjs/core/stream/period/period_stream.js +1 -3
- package/dist/commonjs/core/stream/period/utils/get_adaptation_switch_strategy.js +1 -2
- package/dist/commonjs/experimental/tools/mediaCapabilitiesProber/api/index.d.ts.map +1 -1
- package/dist/commonjs/main_thread/api/public_api.js +4 -4
- package/dist/commonjs/main_thread/decrypt/clear_on_stop.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/clear_on_stop.js +60 -14
- package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/content_decryptor.js +21 -9
- package/dist/commonjs/main_thread/decrypt/dispose_decryption_resources.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/dispose_decryption_resources.js +2 -18
- package/dist/commonjs/main_thread/decrypt/find_key_system.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/find_key_system.js +134 -68
- package/dist/commonjs/main_thread/decrypt/get_key_system_configuration.js +2 -2
- package/dist/commonjs/main_thread/decrypt/get_media_keys.js +5 -3
- package/dist/commonjs/main_thread/decrypt/init_media_keys.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/init_media_keys.js +2 -2
- package/dist/{es2017/main_thread/decrypt/utils/media_keys_infos_store.d.ts → commonjs/main_thread/decrypt/utils/media_keys_attacher.d.ts} +31 -9
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -0
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.js +282 -0
- package/dist/commonjs/main_thread/init/utils/rebuffering_controller.d.ts.map +1 -1
- package/dist/commonjs/main_thread/init/utils/rebuffering_controller.js +20 -9
- package/dist/commonjs/main_thread/text_displayer/html/text_track_cues_store.js +1 -1
- package/dist/commonjs/main_thread/tracks_store/track_dispatcher.d.ts.map +1 -1
- package/dist/commonjs/main_thread/tracks_store/track_dispatcher.js +3 -4
- package/dist/commonjs/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
- package/dist/commonjs/main_thread/tracks_store/tracks_store.js +1 -1
- package/dist/commonjs/manifest/classes/representation.d.ts +15 -1
- package/dist/commonjs/manifest/classes/representation.d.ts.map +1 -1
- package/dist/commonjs/manifest/classes/representation.js +17 -0
- package/dist/commonjs/manifest/utils.d.ts +15 -0
- package/dist/commonjs/manifest/utils.d.ts.map +1 -1
- package/dist/commonjs/manifest/utils.js +28 -5
- package/dist/commonjs/parsers/manifest/dash/common/parse_representations.js +2 -2
- package/dist/commonjs/playback_observer/media_element_playback_observer.js +1 -1
- package/dist/commonjs/public_types.d.ts +44 -0
- package/dist/commonjs/public_types.d.ts.map +1 -1
- package/dist/commonjs/utils/flat_map.d.ts +2 -2
- package/dist/commonjs/utils/flat_map.js +2 -2
- package/dist/commonjs/utils/url-utils.d.ts.map +1 -1
- package/dist/commonjs/utils/url-utils.js +11 -10
- package/dist/commonjs/utils/xml-parser.d.ts.map +1 -1
- package/dist/commonjs/utils/xml-parser.js +10 -8
- package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_worker.js +1 -1
- package/dist/es2017/compat/browser_compatibility_types.d.ts +7 -2
- package/dist/es2017/compat/browser_compatibility_types.d.ts.map +1 -1
- package/dist/es2017/compat/browser_compatibility_types.js +0 -1
- package/dist/es2017/compat/browser_detection.js +1 -1
- package/dist/es2017/compat/event_listeners.d.ts.map +1 -1
- package/dist/es2017/compat/event_listeners.js +2 -4
- package/dist/es2017/compat/has_mse_in_worker.d.ts.map +1 -1
- package/dist/es2017/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
- package/dist/es2017/core/cmcd/cmcd_data_builder.js +1 -2
- package/dist/es2017/core/main/worker/send_message.d.ts.map +1 -1
- package/dist/es2017/core/main/worker/send_message.js +0 -1
- package/dist/es2017/core/main/worker/worker_main.js +1 -1
- package/dist/es2017/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
- package/dist/es2017/core/stream/adaptation/adaptation_stream.js +4 -6
- package/dist/es2017/core/stream/period/period_stream.js +1 -3
- package/dist/es2017/core/stream/period/utils/get_adaptation_switch_strategy.js +1 -2
- package/dist/es2017/experimental/tools/mediaCapabilitiesProber/api/index.d.ts.map +1 -1
- package/dist/es2017/main_thread/api/public_api.js +4 -4
- package/dist/es2017/main_thread/decrypt/clear_on_stop.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/clear_on_stop.js +3 -3
- package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/content_decryptor.js +21 -9
- package/dist/es2017/main_thread/decrypt/dispose_decryption_resources.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/dispose_decryption_resources.js +2 -12
- package/dist/es2017/main_thread/decrypt/find_key_system.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/find_key_system.js +102 -56
- package/dist/es2017/main_thread/decrypt/get_key_system_configuration.js +2 -2
- package/dist/es2017/main_thread/decrypt/get_media_keys.js +2 -2
- package/dist/es2017/main_thread/decrypt/init_media_keys.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/init_media_keys.js +2 -2
- package/dist/{commonjs/main_thread/decrypt/utils/media_keys_infos_store.d.ts → es2017/main_thread/decrypt/utils/media_keys_attacher.d.ts} +31 -9
- package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -0
- package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.js +180 -0
- package/dist/es2017/main_thread/init/utils/rebuffering_controller.d.ts.map +1 -1
- package/dist/es2017/main_thread/init/utils/rebuffering_controller.js +20 -9
- package/dist/es2017/main_thread/text_displayer/html/text_track_cues_store.js +1 -1
- package/dist/es2017/main_thread/tracks_store/track_dispatcher.d.ts.map +1 -1
- package/dist/es2017/main_thread/tracks_store/track_dispatcher.js +3 -4
- package/dist/es2017/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
- package/dist/es2017/main_thread/tracks_store/tracks_store.js +2 -2
- package/dist/es2017/manifest/classes/representation.d.ts +15 -1
- package/dist/es2017/manifest/classes/representation.d.ts.map +1 -1
- package/dist/es2017/manifest/classes/representation.js +17 -0
- package/dist/es2017/manifest/utils.d.ts +15 -0
- package/dist/es2017/manifest/utils.d.ts.map +1 -1
- package/dist/es2017/manifest/utils.js +27 -5
- package/dist/es2017/parsers/manifest/dash/common/parse_representations.js +2 -2
- package/dist/es2017/playback_observer/media_element_playback_observer.js +1 -1
- package/dist/es2017/public_types.d.ts +44 -0
- package/dist/es2017/public_types.d.ts.map +1 -1
- package/dist/es2017/utils/flat_map.d.ts +2 -2
- package/dist/es2017/utils/flat_map.js +2 -2
- package/dist/es2017/utils/url-utils.d.ts.map +1 -1
- package/dist/es2017/utils/url-utils.js +11 -10
- package/dist/es2017/utils/xml-parser.d.ts.map +1 -1
- package/dist/es2017/utils/xml-parser.js +10 -8
- package/dist/rx-player.js +505 -372
- package/dist/rx-player.min.js +18 -18
- package/dist/worker.js +6 -6
- package/package.json +21 -19
- package/src/__GENERATED_CODE/embedded_worker.ts +1 -1
- package/src/compat/browser_compatibility_types.ts +22 -4
- package/src/compat/browser_detection.ts +1 -1
- package/src/compat/event_listeners.ts +2 -4
- package/src/compat/has_mse_in_worker.ts +1 -1
- package/src/core/cmcd/cmcd_data_builder.ts +1 -4
- package/src/core/main/worker/send_message.ts +4 -2
- package/src/core/main/worker/worker_main.ts +1 -1
- package/src/core/stream/adaptation/adaptation_stream.ts +4 -7
- package/src/core/stream/period/period_stream.ts +3 -3
- package/src/core/stream/period/utils/get_adaptation_switch_strategy.ts +1 -2
- package/src/main_thread/api/public_api.ts +4 -4
- package/src/main_thread/decrypt/__tests__/__global__/media_key_system_access.test.ts +239 -6
- package/src/main_thread/decrypt/__tests__/find_key_system.test.ts +325 -0
- package/src/main_thread/decrypt/clear_on_stop.ts +3 -3
- package/src/main_thread/decrypt/content_decryptor.ts +26 -8
- package/src/main_thread/decrypt/dispose_decryption_resources.ts +2 -13
- package/src/main_thread/decrypt/find_key_system.ts +120 -81
- package/src/main_thread/decrypt/get_key_system_configuration.ts +2 -2
- package/src/main_thread/decrypt/get_media_keys.ts +2 -2
- package/src/main_thread/decrypt/init_media_keys.ts +2 -2
- package/src/main_thread/decrypt/utils/media_keys_attacher.ts +284 -0
- package/src/main_thread/init/utils/rebuffering_controller.ts +20 -10
- package/src/main_thread/text_displayer/html/text_track_cues_store.ts +1 -1
- package/src/main_thread/tracks_store/track_dispatcher.ts +3 -6
- package/src/main_thread/tracks_store/tracks_store.ts +2 -1
- package/src/manifest/classes/representation.ts +18 -1
- package/src/manifest/utils.ts +30 -9
- package/src/parsers/manifest/dash/common/parse_representations.ts +2 -2
- package/src/playback_observer/media_element_playback_observer.ts +1 -1
- package/src/public_types.ts +45 -0
- package/src/utils/__tests__/flat_map.test.ts +7 -20
- package/src/utils/flat_map.ts +2 -2
- package/src/utils/url-utils.ts +11 -10
- package/src/utils/xml-parser.ts +13 -8
- package/vitest.config.mjs +9 -23
- package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts +0 -60
- package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts.map +0 -1
- package/dist/commonjs/main_thread/decrypt/attach_media_keys.js +0 -124
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +0 -1
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.js +0 -45
- package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts +0 -60
- package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts.map +0 -1
- package/dist/es2017/main_thread/decrypt/attach_media_keys.js +0 -73
- package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +0 -1
- package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.js +0 -43
- package/src/main_thread/decrypt/attach_media_keys.ts +0 -125
- package/src/main_thread/decrypt/utils/media_keys_infos_store.ts +0 -88
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import type { MockInstance } from "vitest";
|
|
2
|
+
import { describe, beforeEach, it, expect, vi } from "vitest";
|
|
3
|
+
import eme from "../../../compat/eme";
|
|
4
|
+
import type { IKeySystemOption } from "../../../public_types";
|
|
5
|
+
import TaskCanceller from "../../../utils/task_canceller";
|
|
6
|
+
import getMediaKeySystemAccess from "../find_key_system";
|
|
7
|
+
import LoadedSessionsStore from "../utils/loaded_sessions_store";
|
|
8
|
+
import mediaKeysAttacher from "../utils/media_keys_attacher";
|
|
9
|
+
|
|
10
|
+
describe("find_key_systems - ", () => {
|
|
11
|
+
let requestMediaKeySystemAccessMock: MockInstance;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
vi.resetModules();
|
|
15
|
+
vi.restoreAllMocks();
|
|
16
|
+
requestMediaKeySystemAccessMock = vi.spyOn(eme, "requestMediaKeySystemAccess");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const baseEmeConfiguration: MediaKeySystemConfiguration = {
|
|
20
|
+
initDataTypes: ["cenc"],
|
|
21
|
+
videoCapabilities: [
|
|
22
|
+
{
|
|
23
|
+
contentType: 'video/mp4;codecs="avc1.4d401e"',
|
|
24
|
+
robustness: "HW_SECURE_ALL",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
contentType: 'video/mp4;codecs="avc1.42e01e"',
|
|
28
|
+
robustness: "HW_SECURE_ALL",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
contentType: 'video/mp4;codecs="hvc1.1.6.L93.B0"',
|
|
32
|
+
robustness: "HW_SECURE_ALL",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
contentType: 'video/webm;codecs="vp8"',
|
|
36
|
+
robustness: "HW_SECURE_ALL",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
contentType: 'video/mp4;codecs="avc1.4d401e"',
|
|
40
|
+
robustness: "HW_SECURE_DECODE",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
contentType: 'video/mp4;codecs="avc1.42e01e"',
|
|
44
|
+
robustness: "HW_SECURE_DECODE",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
contentType: 'video/mp4;codecs="hvc1.1.6.L93.B0"',
|
|
48
|
+
robustness: "HW_SECURE_DECODE",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
contentType: 'video/webm;codecs="vp8"',
|
|
52
|
+
robustness: "HW_SECURE_DECODE",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
contentType: 'video/mp4;codecs="avc1.4d401e"',
|
|
56
|
+
robustness: "HW_SECURE_CRYPTO",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
contentType: 'video/mp4;codecs="avc1.42e01e"',
|
|
60
|
+
robustness: "HW_SECURE_CRYPTO",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
contentType: 'video/mp4;codecs="hvc1.1.6.L93.B0"',
|
|
64
|
+
robustness: "HW_SECURE_CRYPTO",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
contentType: 'video/webm;codecs="vp8"',
|
|
68
|
+
robustness: "HW_SECURE_CRYPTO",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
contentType: 'video/mp4;codecs="avc1.4d401e"',
|
|
72
|
+
robustness: "SW_SECURE_DECODE",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
contentType: 'video/mp4;codecs="avc1.42e01e"',
|
|
76
|
+
robustness: "SW_SECURE_DECODE",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
contentType: 'video/mp4;codecs="hvc1.1.6.L93.B0"',
|
|
80
|
+
robustness: "SW_SECURE_DECODE",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
contentType: 'video/webm;codecs="vp8"',
|
|
84
|
+
robustness: "SW_SECURE_DECODE",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
contentType: 'video/mp4;codecs="avc1.4d401e"',
|
|
88
|
+
robustness: "SW_SECURE_CRYPTO",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
contentType: 'video/mp4;codecs="avc1.42e01e"',
|
|
92
|
+
robustness: "SW_SECURE_CRYPTO",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
contentType: 'video/mp4;codecs="hvc1.1.6.L93.B0"',
|
|
96
|
+
robustness: "SW_SECURE_CRYPTO",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
contentType: 'video/webm;codecs="vp8"',
|
|
100
|
+
robustness: "SW_SECURE_CRYPTO",
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
audioCapabilities: [
|
|
104
|
+
{
|
|
105
|
+
contentType: 'audio/mp4;codecs="mp4a.40.2"',
|
|
106
|
+
robustness: "HW_SECURE_ALL",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
contentType: "audio/webm;codecs=opus",
|
|
110
|
+
robustness: "HW_SECURE_ALL",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
contentType: 'audio/mp4;codecs="mp4a.40.2"',
|
|
114
|
+
robustness: "HW_SECURE_DECODE",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
contentType: "audio/webm;codecs=opus",
|
|
118
|
+
robustness: "HW_SECURE_DECODE",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
contentType: 'audio/mp4;codecs="mp4a.40.2"',
|
|
122
|
+
robustness: "HW_SECURE_CRYPTO",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
contentType: "audio/webm;codecs=opus",
|
|
126
|
+
robustness: "HW_SECURE_CRYPTO",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
contentType: 'audio/mp4;codecs="mp4a.40.2"',
|
|
130
|
+
robustness: "SW_SECURE_DECODE",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
contentType: "audio/webm;codecs=opus",
|
|
134
|
+
robustness: "SW_SECURE_DECODE",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
contentType: 'audio/mp4;codecs="mp4a.40.2"',
|
|
138
|
+
robustness: "SW_SECURE_CRYPTO",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
contentType: "audio/webm;codecs=opus",
|
|
142
|
+
robustness: "SW_SECURE_CRYPTO",
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
distinctiveIdentifier: "optional",
|
|
146
|
+
persistentState: "optional",
|
|
147
|
+
sessionTypes: ["temporary"],
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
it("should create a media key the first time and then reuse the previous one if it's the same configuration", async () => {
|
|
151
|
+
requestMediaKeySystemAccessMock.mockImplementation(() => {
|
|
152
|
+
return {
|
|
153
|
+
keySystem: "com.widevine.alpha",
|
|
154
|
+
createMediaKeys: () => ({
|
|
155
|
+
createSession: () => ({
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
157
|
+
generateRequest: () => {},
|
|
158
|
+
}),
|
|
159
|
+
}),
|
|
160
|
+
getConfiguration: () => {
|
|
161
|
+
return baseEmeConfiguration;
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
const mediaElement = document.createElement("video");
|
|
166
|
+
const keySystemOptionsA: IKeySystemOption[] = [
|
|
167
|
+
{
|
|
168
|
+
type: "com.widevine.alpha",
|
|
169
|
+
getLicense: () => null,
|
|
170
|
+
persistentState: "optional",
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
const taskCanceller = new TaskCanceller();
|
|
175
|
+
const event1 = await getMediaKeySystemAccess(
|
|
176
|
+
mediaElement,
|
|
177
|
+
keySystemOptionsA,
|
|
178
|
+
taskCanceller.signal,
|
|
179
|
+
);
|
|
180
|
+
expect(event1.type).toBe("create-media-key-system-access");
|
|
181
|
+
|
|
182
|
+
// create the mediaKeys and add it to the cache
|
|
183
|
+
const mediaKeys = await event1.value.mediaKeySystemAccess.createMediaKeys();
|
|
184
|
+
await mediaKeysAttacher.attach(mediaElement, {
|
|
185
|
+
keySystemOptions: keySystemOptionsA[0],
|
|
186
|
+
emeImplementation: eme,
|
|
187
|
+
askedConfiguration: baseEmeConfiguration,
|
|
188
|
+
mediaKeys,
|
|
189
|
+
mediaKeySystemAccess: event1.value.mediaKeySystemAccess,
|
|
190
|
+
loadedSessionsStore: new LoadedSessionsStore(mediaKeys),
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const event2 = await getMediaKeySystemAccess(
|
|
194
|
+
mediaElement,
|
|
195
|
+
keySystemOptionsA,
|
|
196
|
+
taskCanceller.signal,
|
|
197
|
+
);
|
|
198
|
+
expect(event2.type).toBe("reuse-media-key-system-access");
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("should create a media key the first time and then create another one if the previous is not compatible.", async () => {
|
|
202
|
+
requestMediaKeySystemAccessMock.mockImplementation(() => {
|
|
203
|
+
return {
|
|
204
|
+
keySystem: "com.widevine.alpha",
|
|
205
|
+
createMediaKeys: () => ({
|
|
206
|
+
createSession: () => ({
|
|
207
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
208
|
+
generateRequest: () => {},
|
|
209
|
+
}),
|
|
210
|
+
}),
|
|
211
|
+
getConfiguration: () => {
|
|
212
|
+
return baseEmeConfiguration;
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
const mediaElement = document.createElement("video");
|
|
217
|
+
const keySystemOptionsA: IKeySystemOption[] = [
|
|
218
|
+
{
|
|
219
|
+
type: "com.widevine.alpha",
|
|
220
|
+
getLicense: () => null,
|
|
221
|
+
persistentState: "optional",
|
|
222
|
+
},
|
|
223
|
+
];
|
|
224
|
+
|
|
225
|
+
const taskCanceller = new TaskCanceller();
|
|
226
|
+
const event1 = await getMediaKeySystemAccess(
|
|
227
|
+
mediaElement,
|
|
228
|
+
keySystemOptionsA,
|
|
229
|
+
taskCanceller.signal,
|
|
230
|
+
);
|
|
231
|
+
expect(event1.type).toBe("create-media-key-system-access");
|
|
232
|
+
|
|
233
|
+
// create the mediaKeys and add it to the cache
|
|
234
|
+
const mediaKeys = await event1.value.mediaKeySystemAccess.createMediaKeys();
|
|
235
|
+
await mediaKeysAttacher.attach(mediaElement, {
|
|
236
|
+
keySystemOptions: keySystemOptionsA[0],
|
|
237
|
+
emeImplementation: eme,
|
|
238
|
+
askedConfiguration: baseEmeConfiguration,
|
|
239
|
+
mediaKeys,
|
|
240
|
+
mediaKeySystemAccess: event1.value.mediaKeySystemAccess,
|
|
241
|
+
loadedSessionsStore: new LoadedSessionsStore(mediaKeys),
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const keySystemOptionsB: IKeySystemOption[] = [
|
|
245
|
+
{
|
|
246
|
+
type: "com.widevine.alpha",
|
|
247
|
+
getLicense: () => null,
|
|
248
|
+
persistentState: "required", // persistentState differs from configuration A.
|
|
249
|
+
},
|
|
250
|
+
];
|
|
251
|
+
|
|
252
|
+
const event2 = await getMediaKeySystemAccess(
|
|
253
|
+
mediaElement,
|
|
254
|
+
keySystemOptionsB,
|
|
255
|
+
taskCanceller.signal,
|
|
256
|
+
);
|
|
257
|
+
expect(event2.type).toBe("create-media-key-system-access");
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it("should create a media key the first time and then reuse the previous one if it's a different configuration but it's a compatible configuration.", async () => {
|
|
261
|
+
requestMediaKeySystemAccessMock.mockImplementation(() => {
|
|
262
|
+
return {
|
|
263
|
+
keySystem: "com.widevine.alpha",
|
|
264
|
+
createMediaKeys: () => ({
|
|
265
|
+
createSession: () => ({
|
|
266
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
267
|
+
generateRequest: () => {},
|
|
268
|
+
}),
|
|
269
|
+
}),
|
|
270
|
+
getConfiguration: () => {
|
|
271
|
+
return baseEmeConfiguration;
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
});
|
|
275
|
+
const mediaElement = document.createElement("video");
|
|
276
|
+
const keySystemOptionsA: IKeySystemOption[] = [
|
|
277
|
+
{
|
|
278
|
+
type: "com.widevine.alpha",
|
|
279
|
+
getLicense: () => null,
|
|
280
|
+
videoCapabilitiesConfig: {
|
|
281
|
+
type: "contentType",
|
|
282
|
+
value: ['video/mp4;codecs="avc1.4d401e', 'video/mp4;codecs="hvc1.1.6.L93.B0"'],
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
];
|
|
286
|
+
|
|
287
|
+
const taskCanceller = new TaskCanceller();
|
|
288
|
+
const event1 = await getMediaKeySystemAccess(
|
|
289
|
+
mediaElement,
|
|
290
|
+
keySystemOptionsA,
|
|
291
|
+
taskCanceller.signal,
|
|
292
|
+
);
|
|
293
|
+
expect(event1.type).toBe("create-media-key-system-access");
|
|
294
|
+
|
|
295
|
+
// create the mediaKeys and add it to the cache
|
|
296
|
+
const mediaKeys = await event1.value.mediaKeySystemAccess.createMediaKeys();
|
|
297
|
+
await mediaKeysAttacher.attach(mediaElement, {
|
|
298
|
+
keySystemOptions: keySystemOptionsA[0],
|
|
299
|
+
emeImplementation: eme,
|
|
300
|
+
askedConfiguration: baseEmeConfiguration,
|
|
301
|
+
mediaKeys,
|
|
302
|
+
mediaKeySystemAccess: event1.value.mediaKeySystemAccess,
|
|
303
|
+
loadedSessionsStore: new LoadedSessionsStore(mediaKeys),
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
const keySystemOptionsB: IKeySystemOption[] = [
|
|
307
|
+
{
|
|
308
|
+
type: "com.widevine.alpha",
|
|
309
|
+
getLicense: () => null,
|
|
310
|
+
videoCapabilitiesConfig: {
|
|
311
|
+
type: "contentType",
|
|
312
|
+
// configB contains only codec "avc1", it's a subset of configA, it should be compatible.
|
|
313
|
+
value: ['video/mp4;codecs="avc1.4d401e'],
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
];
|
|
317
|
+
|
|
318
|
+
const event2 = await getMediaKeySystemAccess(
|
|
319
|
+
mediaElement,
|
|
320
|
+
keySystemOptionsB,
|
|
321
|
+
taskCanceller.signal,
|
|
322
|
+
);
|
|
323
|
+
expect(event2.type).toBe("reuse-media-key-system-access");
|
|
324
|
+
});
|
|
325
|
+
});
|
|
@@ -18,7 +18,7 @@ import type { IMediaElement } from "../../compat/browser_compatibility_types";
|
|
|
18
18
|
import shouldUnsetMediaKeys from "../../compat/should_unset_media_keys";
|
|
19
19
|
import log from "../../log";
|
|
20
20
|
import disposeDecryptionResources from "./dispose_decryption_resources";
|
|
21
|
-
import
|
|
21
|
+
import MediaKeysAttacher from "./utils/media_keys_attacher";
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Clear DRM-related resources that should be cleared when the current content
|
|
@@ -26,14 +26,14 @@ import MediaKeysInfosStore from "./utils/media_keys_infos_store";
|
|
|
26
26
|
* @param {HTMLMediaElement} mediaElement
|
|
27
27
|
* @returns {Promise}
|
|
28
28
|
*/
|
|
29
|
-
export default function clearOnStop(mediaElement: IMediaElement): Promise<unknown> {
|
|
29
|
+
export default async function clearOnStop(mediaElement: IMediaElement): Promise<unknown> {
|
|
30
30
|
log.info("DRM: Clearing-up DRM session.");
|
|
31
31
|
if (shouldUnsetMediaKeys()) {
|
|
32
32
|
log.info("DRM: disposing current MediaKeys.");
|
|
33
33
|
return disposeDecryptionResources(mediaElement);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const currentState =
|
|
36
|
+
const currentState = await MediaKeysAttacher.getAttachedMediaKeysState(mediaElement);
|
|
37
37
|
if (
|
|
38
38
|
currentState !== null &&
|
|
39
39
|
currentState.keySystemOptions.closeSessionsOnStop === true
|
|
@@ -30,7 +30,6 @@ import isNullOrUndefined from "../../utils/is_null_or_undefined";
|
|
|
30
30
|
import { objectValues } from "../../utils/object_values";
|
|
31
31
|
import { bytesToHex } from "../../utils/string_parsing";
|
|
32
32
|
import TaskCanceller from "../../utils/task_canceller";
|
|
33
|
-
import attachMediaKeys from "./attach_media_keys";
|
|
34
33
|
import createOrLoadSession from "./create_or_load_session";
|
|
35
34
|
import type { ICodecSupportList } from "./find_key_system";
|
|
36
35
|
import type { IMediaKeysInfos } from "./get_media_keys";
|
|
@@ -57,6 +56,7 @@ import {
|
|
|
57
56
|
areSomeKeyIdsContainedIn,
|
|
58
57
|
} from "./utils/key_id_comparison";
|
|
59
58
|
import type KeySessionRecord from "./utils/key_session_record";
|
|
59
|
+
import MediaKeysAttacher from "./utils/media_keys_attacher";
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
62
|
* Module communicating with the Content Decryption Module (or CDM) to be able
|
|
@@ -287,8 +287,12 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
|
|
|
287
287
|
};
|
|
288
288
|
|
|
289
289
|
log.debug("DRM: Attaching current MediaKeys");
|
|
290
|
-
|
|
290
|
+
MediaKeysAttacher.attach(mediaElement, stateToAttach)
|
|
291
291
|
.then(async () => {
|
|
292
|
+
if (this._isStopped()) {
|
|
293
|
+
// We might be stopped since then
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
292
296
|
this._stateData.isMediaKeysAttached = MediaKeyAttachmentStatus.Attached;
|
|
293
297
|
|
|
294
298
|
const { serverCertificate } = options;
|
|
@@ -526,13 +530,14 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
|
|
|
526
530
|
this._lockInitDataQueue();
|
|
527
531
|
|
|
528
532
|
let wantedSessionType: MediaKeySessionType;
|
|
529
|
-
if (
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
} else {
|
|
533
|
+
if (
|
|
534
|
+
canCreatePersistentSession(mediaKeySystemAccess) &&
|
|
535
|
+
(!isNullOrUndefined(options.persistentLicenseConfig) ||
|
|
536
|
+
!canCreateTemporarySession(mediaKeySystemAccess))
|
|
537
|
+
) {
|
|
535
538
|
wantedSessionType = "persistent-license";
|
|
539
|
+
} else {
|
|
540
|
+
wantedSessionType = "temporary";
|
|
536
541
|
}
|
|
537
542
|
|
|
538
543
|
const {
|
|
@@ -993,6 +998,19 @@ function canCreatePersistentSession(
|
|
|
993
998
|
return sessionTypes !== undefined && arrayIncludes(sessionTypes, "persistent-license");
|
|
994
999
|
}
|
|
995
1000
|
|
|
1001
|
+
/**
|
|
1002
|
+
* Returns `true` if the given MediaKeySystemAccess can create
|
|
1003
|
+
* "temporary" MediaKeySessions.
|
|
1004
|
+
* @param {MediaKeySystemAccess} mediaKeySystemAccess
|
|
1005
|
+
* @returns {Boolean}
|
|
1006
|
+
*/
|
|
1007
|
+
function canCreateTemporarySession(
|
|
1008
|
+
mediaKeySystemAccess: MediaKeySystemAccess | ICustomMediaKeySystemAccess,
|
|
1009
|
+
): boolean {
|
|
1010
|
+
const { sessionTypes } = mediaKeySystemAccess.getConfiguration();
|
|
1011
|
+
return sessionTypes !== undefined && arrayIncludes(sessionTypes, "temporary");
|
|
1012
|
+
}
|
|
1013
|
+
|
|
996
1014
|
/**
|
|
997
1015
|
* Return the list of key IDs present in the `expectedKeyIds` array
|
|
998
1016
|
* but that are not present in `actualKeyIds`.
|
|
@@ -15,9 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import type { IMediaElement } from "../../compat/browser_compatibility_types";
|
|
18
|
-
import
|
|
19
|
-
import log from "../../log";
|
|
20
|
-
import MediaKeysInfosStore from "./utils/media_keys_infos_store";
|
|
18
|
+
import MediaKeysAttacher from "./utils/media_keys_attacher";
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
21
|
* Free up all ressources taken by the content decryption logic.
|
|
@@ -27,14 +25,5 @@ import MediaKeysInfosStore from "./utils/media_keys_infos_store";
|
|
|
27
25
|
export default async function disposeDecryptionResources(
|
|
28
26
|
mediaElement: IMediaElement,
|
|
29
27
|
): Promise<unknown> {
|
|
30
|
-
|
|
31
|
-
if (currentState === null) {
|
|
32
|
-
return undefined;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
log.info("DRM: Disposing of the current MediaKeys");
|
|
36
|
-
const { loadedSessionsStore } = currentState;
|
|
37
|
-
MediaKeysInfosStore.clearState(mediaElement);
|
|
38
|
-
await loadedSessionsStore.closeAllSessions();
|
|
39
|
-
return setMediaKeys(currentState.emeImplementation, mediaElement, null);
|
|
28
|
+
return MediaKeysAttacher.clearMediaKeys(mediaElement);
|
|
40
29
|
}
|