rx-player 4.2.0-dev.2024081300 → 4.2.0-dev.2024081301

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.
Files changed (44) hide show
  1. package/VERSION +1 -1
  2. package/dist/commonjs/compat/eme/custom_media_keys/types.d.ts +0 -3
  3. package/dist/commonjs/compat/eme/custom_media_keys/types.d.ts.map +1 -1
  4. package/dist/commonjs/compat/eme/eme-api-implementation.d.ts +2 -2
  5. package/dist/commonjs/compat/eme/eme-api-implementation.d.ts.map +1 -1
  6. package/dist/commonjs/compat/eme/eme-api-implementation.js +2 -17
  7. package/dist/commonjs/compat/eme/get_init_data.d.ts +1 -3
  8. package/dist/commonjs/compat/eme/get_init_data.d.ts.map +1 -1
  9. package/dist/commonjs/compat/eme/get_init_data.js +2 -2
  10. package/dist/commonjs/compat/event_listeners.d.ts +19 -21
  11. package/dist/commonjs/compat/event_listeners.d.ts.map +1 -1
  12. package/dist/commonjs/compat/event_listeners.js +11 -0
  13. package/dist/commonjs/main_thread/api/public_api.js +2 -2
  14. package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts +0 -8
  15. package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  16. package/dist/commonjs/main_thread/decrypt/content_decryptor.js +0 -49
  17. package/dist/commonjs/main_thread/decrypt/types.d.ts +0 -1
  18. package/dist/commonjs/main_thread/decrypt/types.d.ts.map +1 -1
  19. package/dist/es2017/compat/eme/custom_media_keys/types.d.ts +0 -3
  20. package/dist/es2017/compat/eme/custom_media_keys/types.d.ts.map +1 -1
  21. package/dist/es2017/compat/eme/eme-api-implementation.d.ts +2 -2
  22. package/dist/es2017/compat/eme/eme-api-implementation.d.ts.map +1 -1
  23. package/dist/es2017/compat/eme/eme-api-implementation.js +2 -17
  24. package/dist/es2017/compat/eme/get_init_data.d.ts +1 -3
  25. package/dist/es2017/compat/eme/get_init_data.d.ts.map +1 -1
  26. package/dist/es2017/compat/eme/get_init_data.js +2 -2
  27. package/dist/es2017/compat/event_listeners.d.ts +19 -21
  28. package/dist/es2017/compat/event_listeners.d.ts.map +1 -1
  29. package/dist/es2017/compat/event_listeners.js +11 -0
  30. package/dist/es2017/main_thread/api/public_api.js +2 -2
  31. package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts +0 -8
  32. package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  33. package/dist/es2017/main_thread/decrypt/content_decryptor.js +0 -45
  34. package/dist/es2017/main_thread/decrypt/types.d.ts +0 -1
  35. package/dist/es2017/main_thread/decrypt/types.d.ts.map +1 -1
  36. package/dist/rx-player.js +18 -18
  37. package/package.json +1 -1
  38. package/src/compat/eme/custom_media_keys/types.ts +0 -4
  39. package/src/compat/eme/eme-api-implementation.ts +4 -36
  40. package/src/compat/eme/get_init_data.ts +3 -5
  41. package/src/compat/event_listeners.ts +5 -30
  42. package/src/main_thread/api/public_api.ts +2 -2
  43. package/src/main_thread/decrypt/content_decryptor.ts +1 -58
  44. package/src/main_thread/decrypt/types.ts +0 -2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rx-player",
3
3
  "author": "Canal+",
4
- "version": "4.2.0-dev.2024081300",
4
+ "version": "4.2.0-dev.2024081301",
5
5
  "description": "Canal+ HTML5 Video Player",
6
6
  "main": "./dist/commonjs/index.js",
7
7
  "module": "./dist/es2017/index.js",
@@ -60,7 +60,3 @@ export interface IMediaKeySessionEvents {
60
60
  // "keyerror"
61
61
  /* "error" */
62
62
  }
63
-
64
- export interface ICustomMediaEncryptedEvent extends MediaEncryptedEvent {
65
- forceSessionRecreation?: boolean | undefined;
66
- }
@@ -3,7 +3,6 @@ import assert from "../../utils/assert";
3
3
  import globalScope from "../../utils/global_scope";
4
4
  import isNode from "../../utils/is_node";
5
5
  import isNullOrUndefined from "../../utils/is_null_or_undefined";
6
- import objectAssign from "../../utils/object_assign";
7
6
  import type { CancellationSignal } from "../../utils/task_canceller";
8
7
  import type { IMediaElement } from "../browser_compatibility_types";
9
8
  import { isIE11 } from "../browser_detection";
@@ -20,10 +19,7 @@ import getMozMediaKeysCallbacks, {
20
19
  import getOldKitWebKitMediaKeyCallbacks, {
21
20
  isOldWebkitMediaElement,
22
21
  } from "./custom_media_keys/old_webkit_media_keys";
23
- import type {
24
- ICustomMediaEncryptedEvent,
25
- ICustomMediaKeys,
26
- } from "./custom_media_keys/types";
22
+ import type { ICustomMediaKeys } from "./custom_media_keys/types";
27
23
  import getWebKitMediaKeysCallbacks from "./custom_media_keys/webkit_media_keys";
28
24
  import { WebKitMediaKeysConstructor } from "./custom_media_keys/webkit_media_keys_constructor";
29
25
 
@@ -67,7 +63,7 @@ export interface IEmeApiImplementation {
67
63
  */
68
64
  onEncrypted: (
69
65
  target: IEventTargetLike,
70
- listener: (evt: ICustomMediaEncryptedEvent) => void,
66
+ listener: (evt: unknown) => void,
71
67
  cancelSignal: CancellationSignal,
72
68
  ) => void;
73
69
 
@@ -147,8 +143,8 @@ function getEmeApiImplementation(
147
143
  let createCustomMediaKeys: (keyType: string) => ICustomMediaKeys;
148
144
 
149
145
  if (preferredApiType === "webkit" && WebKitMediaKeysConstructor !== undefined) {
146
+ onEncrypted = createCompatibleEventListener(["needkey"]);
150
147
  const callbacks = getWebKitMediaKeysCallbacks();
151
- onEncrypted = createOnEncryptedForWebkit();
152
148
  isTypeSupported = callbacks.isTypeSupported;
153
149
  createCustomMediaKeys = callbacks.createCustomMediaKeys;
154
150
  setMediaKeys = callbacks.setMediaKeys;
@@ -164,7 +160,7 @@ function getEmeApiImplementation(
164
160
  implementation = "older-webkit";
165
161
  // This is for WebKit with prefixed EME api
166
162
  } else if (WebKitMediaKeysConstructor !== undefined) {
167
- onEncrypted = createOnEncryptedForWebkit();
163
+ onEncrypted = createCompatibleEventListener(["needkey"]);
168
164
  const callbacks = getWebKitMediaKeysCallbacks();
169
165
  isTypeSupported = callbacks.isTypeSupported;
170
166
  createCustomMediaKeys = callbacks.createCustomMediaKeys;
@@ -278,34 +274,6 @@ function getEmeApiImplementation(
278
274
  implementation,
279
275
  };
280
276
  }
281
- /**
282
- * Create an event listener for the "webkitneedkey" event
283
- * @returns
284
- */
285
- function createOnEncryptedForWebkit(): IEmeApiImplementation["onEncrypted"] {
286
- const compatibleEventListener = createCompatibleEventListener(
287
- ["needkey"],
288
- undefined /* prefixes */,
289
- );
290
- const onEncrypted = (
291
- target: IEventTargetLike,
292
- listener: (event: ICustomMediaEncryptedEvent) => void,
293
- cancelSignal: CancellationSignal,
294
- ) => {
295
- compatibleEventListener(
296
- target,
297
- (event?: Event) => {
298
- const patchedEvent = objectAssign(
299
- { forceSessionRecreation: true },
300
- event as MediaEncryptedEvent,
301
- );
302
- listener(patchedEvent);
303
- },
304
- cancelSignal,
305
- );
306
- };
307
- return onEncrypted;
308
- }
309
277
 
310
278
  /**
311
279
  * Set the given MediaKeys on the given HTMLMediaElement.
@@ -20,7 +20,6 @@ import areArraysOfNumbersEqual from "../../utils/are_arrays_of_numbers_equal";
20
20
  import { be4toi } from "../../utils/byte_parsing";
21
21
  import isNullOrUndefined from "../../utils/is_null_or_undefined";
22
22
  import { PSSH_TO_INTEGER } from "./constants";
23
- import type { ICustomMediaEncryptedEvent } from "./custom_media_keys/types";
24
23
 
25
24
  /** Data recuperated from parsing the payload of an `encrypted` event. */
26
25
  export interface IEncryptedEventData {
@@ -51,7 +50,6 @@ export interface IEncryptedEventData {
51
50
  */
52
51
  data: Uint8Array;
53
52
  }>;
54
- forceSessionRecreation?: boolean | undefined;
55
53
  }
56
54
 
57
55
  /**
@@ -147,9 +145,9 @@ function isPSSHAlreadyEncountered(
147
145
  * encountered in the given event.
148
146
  */
149
147
  export default function getInitData(
150
- encryptedEvent: ICustomMediaEncryptedEvent,
148
+ encryptedEvent: MediaEncryptedEvent,
151
149
  ): IEncryptedEventData | null {
152
- const { initData, initDataType, forceSessionRecreation } = encryptedEvent;
150
+ const { initData, initDataType } = encryptedEvent;
153
151
  if (isNullOrUndefined(initData)) {
154
152
  log.warn("Compat: No init data found on media encrypted event.");
155
153
  return null;
@@ -157,5 +155,5 @@ export default function getInitData(
157
155
 
158
156
  const initDataBytes = new Uint8Array(initData);
159
157
  const values = getInitializationDataValues(initDataBytes);
160
- return { type: initDataType, values, forceSessionRecreation };
158
+ return { type: initDataType, values };
161
159
  }
@@ -30,7 +30,6 @@ import type {
30
30
  IEventTarget,
31
31
  IMediaElement,
32
32
  } from "./browser_compatibility_types";
33
- import type { ICustomMediaEncryptedEvent } from "./eme/custom_media_keys/types";
34
33
 
35
34
  const BROWSER_PREFIXES = ["", "webkit", "moz", "ms"];
36
35
 
@@ -83,14 +82,8 @@ function eventPrefixed(eventNames: string[], prefixes?: string[]): string[] {
83
82
  }
84
83
 
85
84
  export interface IEventEmitterLike {
86
- addEventListener: (
87
- eventName: string,
88
- handler: EventListenerOrEventListenerObject,
89
- ) => void;
90
- removeEventListener: (
91
- eventName: string,
92
- handler: EventListenerOrEventListenerObject,
93
- ) => void;
85
+ addEventListener: (eventName: string, handler: () => void) => void;
86
+ removeEventListener: (eventName: string, handler: () => void) => void;
94
87
  }
95
88
 
96
89
  export type IEventTargetLike = HTMLElement | IEventEmitterLike | IEventEmitter<unknown>;
@@ -106,31 +99,12 @@ export type IEventTargetLike = HTMLElement | IEventEmitterLike | IEventEmitter<u
106
99
  * @returns {Function} - Returns function allowing to easily add a callback to
107
100
  * be triggered when that event is emitted on a given event target.
108
101
  */
109
-
110
- function createCompatibleEventListener(
111
- eventNames: Array<"needkey" | "encrypted">,
112
- prefixes?: string[],
113
- ): (
114
- element: IEventTargetLike,
115
- listener: (event: ICustomMediaEncryptedEvent) => void,
116
- cancelSignal: CancellationSignal,
117
- ) => void;
118
-
119
102
  function createCompatibleEventListener(
120
103
  eventNames: string[],
121
104
  prefixes?: string[],
122
105
  ): (
123
106
  element: IEventTargetLike,
124
- listener: (event?: Event) => void,
125
- cancelSignal: CancellationSignal,
126
- ) => void;
127
-
128
- function createCompatibleEventListener(
129
- eventNames: string[] | Array<"needkey" | "encrypted">,
130
- prefixes?: string[],
131
- ): (
132
- element: IEventTargetLike,
133
- listener: (event?: Event | MediaEncryptedEvent) => void,
107
+ listener: (event?: unknown) => void,
134
108
  cancelSignal: CancellationSignal,
135
109
  ) => void {
136
110
  let mem: string | undefined;
@@ -138,12 +112,13 @@ function createCompatibleEventListener(
138
112
 
139
113
  return (
140
114
  element: IEventTargetLike,
141
- listener: (event?: Event) => void,
115
+ listener: (event?: unknown) => void,
142
116
  cancelSignal: CancellationSignal,
143
117
  ) => {
144
118
  if (cancelSignal.isCancelled()) {
145
119
  return;
146
120
  }
121
+
147
122
  // if the element is a HTMLElement we can detect
148
123
  // the supported event, and memoize it in `mem`
149
124
  if (typeof HTMLElement !== "undefined" && element instanceof HTMLElement) {
@@ -409,7 +409,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
409
409
  // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
410
410
  videoElement.preload = "auto";
411
411
 
412
- this.version = /* PLAYER_VERSION */ "4.2.0-dev.2024081300";
412
+ this.version = /* PLAYER_VERSION */ "4.2.0-dev.2024081301";
413
413
  this.log = log;
414
414
  this.state = "STOPPED";
415
415
  this.videoElement = videoElement;
@@ -3235,7 +3235,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
3235
3235
  }
3236
3236
  }
3237
3237
  }
3238
- Player.version = /* PLAYER_VERSION */ "4.2.0-dev.2024081300";
3238
+ Player.version = /* PLAYER_VERSION */ "4.2.0-dev.2024081301";
3239
3239
 
3240
3240
  /** Every events sent by the RxPlayer's public API. */
3241
3241
  interface IPublicAPIEvent {
@@ -177,7 +177,7 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
177
177
  mediaElement,
178
178
  (evt) => {
179
179
  log.debug("DRM: Encrypted event received from media element.");
180
- const initData = getInitData(evt);
180
+ const initData = getInitData(evt as MediaEncryptedEvent);
181
181
  if (initData !== null) {
182
182
  this.onInitializationData(initData);
183
183
  }
@@ -730,21 +730,6 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
730
730
  return false;
731
731
  }
732
732
 
733
- /**
734
- * On Safari using Directfile, the old EME implementation triggers
735
- * the "webkitneedkey" event instead of "encrypted". There's an issue in Safari
736
- * where "webkitneedkey" fires too early before all tracks are added from an HLS playlist.
737
- * Safari incorrectly assumes some keys are missing for these tracks,
738
- * leading to repeated "webkitneedkey" events. Because RxPlayer recognizes
739
- * it already has a session for these keys and ignores the events,
740
- * the content remains frozen. To resolve this, the session is re-created.
741
- */
742
- const forceSessionRecreation = initializationData.forceSessionRecreation;
743
- if (forceSessionRecreation === true) {
744
- this.removeSessionForInitData(initializationData, mediaKeysData);
745
- return false;
746
- }
747
-
748
733
  // Check if the compatible session is blacklisted
749
734
  const blacklistedSessionError = compatibleSessionInfo.blacklistedSessionError;
750
735
  if (!isNullOrUndefined(blacklistedSessionError)) {
@@ -849,48 +834,6 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
849
834
  return false;
850
835
  }
851
836
 
852
- /**
853
- * Remove the session corresponding to the initData provided, and close it.
854
- * It does nothing if no session was found for this initData.
855
- * @param {Object} initData : The initialization data corresponding to the session
856
- * that need to be removed
857
- * @param {Object} mediaKeysData : The media keys data
858
- */
859
- private removeSessionForInitData(
860
- initData: IProcessedProtectionData,
861
- mediaKeysData: IAttachedMediaKeysData,
862
- ) {
863
- const { stores } = mediaKeysData;
864
- /** Remove the session and close it from the loadedSessionStore */
865
- const entry = stores.loadedSessionsStore.reuse(initData);
866
- if (entry !== null) {
867
- stores.loadedSessionsStore
868
- .closeSession(entry.mediaKeySession)
869
- .catch(() =>
870
- log.error("DRM: Cannot close the session from the loaded session store"),
871
- );
872
- }
873
-
874
- /**
875
- * If set, a currently-used key session is already compatible to this
876
- * initialization data.
877
- */
878
- const compatibleSessionInfo = arrayFind(this._currentSessions, (x) =>
879
- x.record.isCompatibleWith(initData),
880
- );
881
- if (compatibleSessionInfo === undefined) {
882
- return;
883
- }
884
- /** Remove the session from the currentSessions */
885
- const indexOf = this._currentSessions.indexOf(compatibleSessionInfo);
886
- if (indexOf !== -1) {
887
- log.debug(
888
- "DRM: A session from a processed init is removed due to forceSessionRecreation policy.",
889
- );
890
- this._currentSessions.splice(indexOf, 1);
891
- }
892
- }
893
-
894
837
  /**
895
838
  * Callback that should be called if an error that made the current
896
839
  * `ContentDecryptor` instance unusable arised.
@@ -122,8 +122,6 @@ export interface IProtectionData {
122
122
  content?: IContent;
123
123
  /** Every initialization data for that type. */
124
124
  values: IInitDataValue[];
125
-
126
- forceSessionRecreation?: boolean | undefined;
127
125
  }
128
126
 
129
127
  /** Protection initialization data actually processed by the `ContentDecryptor`. */