senza-sdk 4.2.64-2642526.0 → 4.2.64

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 (27) hide show
  1. package/dist/bundle.js +1 -1
  2. package/dist/bundle.js.LICENSE.txt +4 -0
  3. package/package.json +10 -16
  4. package/src/{implementation/alarmManager.js → alarmManager.js} +52 -15
  5. package/src/api.js +329 -247
  6. package/src/{interface/devSequence.js → devSequence.js} +35 -0
  7. package/src/{implementation/deviceManager.js → deviceManager.js} +65 -4
  8. package/src/{implementation/lifecycle.js → lifecycle.js} +181 -5
  9. package/src/{implementation/messageManager.js → messageManager.js} +6 -6
  10. package/src/{implementation/platformManager.js → platformManager.js} +4 -5
  11. package/src/{implementation/remotePlayer.js → remotePlayer.js} +16 -7
  12. package/src/{implementation/senzaShakaPlayer.js → senzaShakaPlayer.js} +114 -25
  13. package/src/{implementation/utils.js → utils.js} +6 -15
  14. package/src/implementation/api.js +0 -367
  15. package/src/interface/alarmManager.js +0 -69
  16. package/src/interface/api.js +0 -8
  17. package/src/interface/deviceManager.js +0 -133
  18. package/src/interface/lifecycle.js +0 -278
  19. package/src/interface/messageManager.js +0 -46
  20. package/src/interface/platformManager.js +0 -35
  21. package/src/interface/remotePlayer.js +0 -441
  22. package/src/interface/senzaShakaPlayer.js +0 -171
  23. package/src/interface/utils.js +0 -45
  24. /package/src/{implementation/SessionInfo.js → SessionInfo.js} +0 -0
  25. /package/src/{implementation/devHelper.js → devHelper.js} +0 -0
  26. /package/src/{implementation/eventListenersManager.js → eventListenersManager.js} +0 -0
  27. /package/src/{implementation/subtitlesUtils.js → subtitlesUtils.js} +0 -0
@@ -1,7 +1,8 @@
1
- import { shaka } from "../interface/senzaShakaPlayer";
2
-
1
+ import * as shaka from "shaka-player";
3
2
  import { remotePlayer, lifecycle, getPlatformInfo } from "./api";
4
3
  import { sdkLogger, iso6393to1 } from "./utils";
4
+ import moment from "moment";
5
+
5
6
 
6
7
  // Define custom error category
7
8
  shaka.util.Error.Category.SENZA_PLAYER_ERROR = 50;
@@ -31,6 +32,11 @@ class SenzaError extends shaka.util.Error {
31
32
  }
32
33
 
33
34
 
35
+ // Copy the shaka module and replace the Player class with SenzaShakaPlayer
36
+ // if we don't Copy the shaka module, the Player class will be replaced for all the other modules that import shaka
37
+ const senzaShaka = { ...shaka };
38
+
39
+
34
40
  /**
35
41
  * SenzaShakaPlayer subclass of Shaka that handles both local and remote playback.
36
42
  *
@@ -72,9 +78,9 @@ export class SenzaShakaPlayer extends shaka.Player {
72
78
  * @private
73
79
  * @type {number}
74
80
  * @description Timeout in milliseconds to wait for playing event
75
- * @default 3000
81
+ * @default 4000
76
82
  */
77
- _playingTimeout = 3000;
83
+ _playingTimeout = 4000;
78
84
 
79
85
  /**
80
86
  * @private
@@ -89,7 +95,7 @@ export class SenzaShakaPlayer extends shaka.Player {
89
95
  * @description Whether to stop remote player on error
90
96
  * @default false
91
97
  */
92
- _shouldStopRemotePlayerOnError = false;
98
+ _shouldStopOnRemotePlayerError = false;
93
99
 
94
100
  /**
95
101
  * @private
@@ -181,7 +187,7 @@ export class SenzaShakaPlayer extends shaka.Player {
181
187
  originatesFromRemotePlayer: true
182
188
  };
183
189
 
184
- const response = await this.getNetworkingEngine().request(shaka.net.NetworkingEngine.RequestType.LICENSE, request).promise;
190
+ const response = await this.getNetworkingEngine().request(senzaShaka.net.NetworkingEngine.RequestType.LICENSE, request).promise;
185
191
 
186
192
  let responseBody = response.data;
187
193
  if (response.status < 200 || response.status >= 300) {
@@ -280,13 +286,15 @@ export class SenzaShakaPlayer extends shaka.Player {
280
286
 
281
287
 
282
288
  /**
283
- * Handles errors for play promises and remote player events.
289
+ * Handles errors received by remote player while waiting for the playing event.
290
+ * The promise returned to the call for video element play will be rejected.
284
291
  * @private
285
292
  * @param {Error} error - The error object.
286
293
  */
287
294
  _handlePlayPromiseError(error) {
288
295
 
289
296
  sdkLogger.error("Error while waiting for playing event:", error);
297
+
290
298
  if (this._playPromiseReject) {
291
299
  this._playPromiseReject(error);
292
300
  this._playPromiseResolve = null;
@@ -296,6 +304,46 @@ export class SenzaShakaPlayer extends shaka.Player {
296
304
  clearTimeout(this._playTimeoutId);
297
305
  this._playTimeoutId = null;
298
306
  }
307
+
308
+ }
309
+
310
+ /**
311
+ * @private
312
+ * @type {number}
313
+ * @description Minimum suggested presentation delay in seconds
314
+ * @default 15
315
+ */
316
+ _minSuggestedPresentationDelay = 15;
317
+
318
+ /**
319
+ * Modifies the suggestedPresentationDelay in the manifest text
320
+ * @private
321
+ * @param {string} manifestText - The MPD manifest text
322
+ * @returns {string} - Modified manifest text , or undefined if no modification was done
323
+ */
324
+ _updateManifestDelayIfBelowMinimum(manifestText) {
325
+ // Look for suggestedPresentationDelay attribute
326
+ const match = manifestText.match(/suggestedPresentationDelay="([^"]+)"/);
327
+ if (match) {
328
+ const durationString = match[1];
329
+ const duration = moment.duration(durationString);
330
+ const currentDelay = duration.asSeconds();
331
+
332
+ sdkLogger.info(`Found suggestedPresentationDelay in manifest: ${currentDelay.toFixed(3)}s`);
333
+
334
+ if (currentDelay < this._minSuggestedPresentationDelay) {
335
+ // Replace the value in the manifest text with 3 decimal places
336
+ manifestText = manifestText.replace(
337
+ /suggestedPresentationDelay="[^"]+"/,
338
+ `suggestedPresentationDelay="PT${this._minSuggestedPresentationDelay.toFixed(3)}S"`
339
+ );
340
+ sdkLogger.info(`Updated manifest suggestedPresentationDelay to ${this._minSuggestedPresentationDelay.toFixed(3)}s`);
341
+ return manifestText;
342
+ }
343
+ } else {
344
+ sdkLogger.info("suggestedPresentationDelay is not defined at the manifest");
345
+ }
346
+ return undefined;
299
347
  }
300
348
 
301
349
  /**
@@ -325,14 +373,38 @@ export class SenzaShakaPlayer extends shaka.Player {
325
373
  const playTimeout = getPlatformInfo()?.sessionInfo?.settings?.["ui-streamer"]?.playingEventTimeout;
326
374
  this._playingTimeout = (playTimeout >= 0) ? playTimeout*1000 : this._playingTimeout;
327
375
 
376
+ // Initialize minSuggestedPresentationDelay from UI settings or use default
377
+ const uiSettings = getPlatformInfo()?.sessionInfo?.settings?.["ui-streamer"];
378
+ if (uiSettings?.minSuggestedPresentationDelay !== undefined) {
379
+ this._minSuggestedPresentationDelay = uiSettings.minSuggestedPresentationDelay;
380
+ sdkLogger.info(`Using configured minSuggestedPresentationDelay: ${this._minSuggestedPresentationDelay}s`);
381
+ }
382
+
328
383
  // if video element is provided, add the listeres here. In this case ,there is no need to call attach.
329
384
  if (videoElement) {
330
385
  this._attach(videoElement);
331
386
  sdkLogger.warn("SenzaShakaPlayer constructor Adding videoElement in the constructor is going to be deprecated in the future. Please use attach method instead.");
332
387
  }
333
388
 
389
+ this.configure({
390
+ manifest: {
391
+ defaultPresentationDelay: this._minSuggestedPresentationDelay // in seconds
392
+ }
393
+ });
394
+
395
+ remotePlayer.configure({
396
+ minSuggestedPresentationDelay: this._minSuggestedPresentationDelay
397
+ });
398
+
399
+ this.addEventListener("buffering", () => {
400
+ if (this.videoElement) {
401
+ sdkLogger.info("Buffering at time:", this.videoElement.currentTime);
402
+ }
403
+ });
404
+
334
405
  }
335
406
 
407
+
336
408
  _attach(videoElement) {
337
409
  this.videoElement = videoElement;
338
410
 
@@ -556,11 +628,12 @@ export class SenzaShakaPlayer extends shaka.Player {
556
628
  const isCritical = this._isErrorCritical(remotePlayerErrorCode);
557
629
  const error = this._createSenzaError(remotePlayerErrorCode, message, isCritical);
558
630
  const errorMap = new Map();
631
+ const shouldStopPlayback = this._shouldStopOnRemotePlayerError && this.videoElement && isCritical;
559
632
  errorMap.set("detail", error);
560
633
 
561
634
  // Check if we should stop playback - only for critical errors when configured
562
- if (this._shouldStopRemotePlayerOnError &&
563
- this.videoElement && isCritical) {
635
+
636
+ if (shouldStopPlayback) {
564
637
  try {
565
638
  sdkLogger.warn("Stopping local player playback due to critical error");
566
639
  // Stop only local playback
@@ -568,9 +641,11 @@ export class SenzaShakaPlayer extends shaka.Player {
568
641
  } catch (stopError) {
569
642
  sdkLogger.error("Error while trying to stop video element playback:", stopError);
570
643
  }
644
+ // Handle error while waiting for play event. If the error is not critical or the system is configured not to stop remote player on error,
645
+ // the playback timeout will start the local playback
646
+ this._handlePlayPromiseError(error);
571
647
  }
572
- // Handle error while waiting for play event
573
- this._handlePlayPromiseError(error);
648
+
574
649
  this.dispatchEvent(new shaka.util.FakeEvent("error", errorMap));
575
650
  }
576
651
 
@@ -608,16 +683,30 @@ export class SenzaShakaPlayer extends shaka.Player {
608
683
 
609
684
  // This callbakc will be activated when the manifest is loaded. It will trigger load of the remote player.
610
685
  // This will ensure that the remote player is loaded only after the manifest is loaded by local player.
611
- const responseFilterCallback = async (type) => {
612
- if (type === shaka.net.NetworkingEngine.RequestType.MANIFEST && !manifestLoadHandled) {
613
- manifestLoadHandled = true;
686
+ const responseFilterCallback = async (type, response) => {
687
+ if (type === shaka.net.NetworkingEngine.RequestType.MANIFEST) {
614
688
  try {
615
- await this._remotePlayerLoad(url, startTime);
616
- remoteLoadResolver();
689
+ if (response.data && this._minSuggestedPresentationDelay > 0) {
690
+ const manifestText = new TextDecoder().decode(response.data);
691
+ const modifiedText = this._updateManifestDelayIfBelowMinimum(manifestText);
692
+ if (modifiedText) {
693
+ const responseData = new TextEncoder().encode(modifiedText).buffer;
694
+ response.data = responseData;
695
+ }
696
+ }
617
697
  } catch (error) {
618
- remoteLoadRejecter(error);
698
+ sdkLogger.error("Error processing manifest:", error);
619
699
  }
620
700
 
701
+ if (!manifestLoadHandled) {
702
+ manifestLoadHandled = true;
703
+ try {
704
+ await this._remotePlayerLoad(url, startTime);
705
+ remoteLoadResolver();
706
+ } catch (error) {
707
+ remoteLoadRejecter(error);
708
+ }
709
+ }
621
710
  }
622
711
  };
623
712
 
@@ -680,14 +769,14 @@ export class SenzaShakaPlayer extends shaka.Player {
680
769
  /**
681
770
  * Override the configure method to add custom configuration handling
682
771
  * Supports the following additional configuration options:
683
- * - shouldStopRemotePlayerOnError: boolean - If true, remote player will be stopped on error
772
+ * - shouldStopOnRemotePlayerError: boolean - If true, local player will be stopped on remote player error
684
773
  *
685
774
  * @override
686
775
  * @param {Object} config - Configuration object to be merged with existing config
687
- * @param {boolean} [config.shouldStopRemotePlayerOnError=true] - Whether to stop remote player on error
776
+ * @param {boolean} [config.shouldStopOnRemotePlayerError=true] - Whether to stop local player on remote player error
688
777
  * @example
689
778
  * player.configure({
690
- * shouldStopRemotePlayerOnError: false, // Don't stop remote player on error
779
+ * shouldStopOnRemotePlayerError: false, // Don't stop local playback on remote player error
691
780
  * // ... other shaka configurations
692
781
  * });
693
782
  */
@@ -695,12 +784,12 @@ export class SenzaShakaPlayer extends shaka.Player {
695
784
  sdkLogger.log("configure player with: ", JSON.stringify(config));
696
785
 
697
786
  // Handle custom configuration
698
- if (config.shouldStopRemotePlayerOnError !== undefined) {
699
- this._shouldStopRemotePlayerOnError = !!config.shouldStopRemotePlayerOnError;
787
+ if (config.shouldStopOnRemotePlayerError !== undefined) {
788
+ this._shouldStopOnRemotePlayerError = !!config.shouldStopOnRemotePlayerError;
700
789
  // Remove our custom config so it doesn't get passed to parent
701
790
  // Use rest operator without creating a named variable for the removed property
702
791
  // eslint-disable-next-line no-unused-vars
703
- const { shouldStopRemotePlayerOnError, ...shakaConfig } = config;
792
+ const { shouldStopOnRemotePlayerError, ...shakaConfig } = config;
704
793
  config = shakaConfig;
705
794
  }
706
795
 
@@ -800,5 +889,5 @@ export class SenzaShakaPlayer extends shaka.Player {
800
889
 
801
890
  }
802
891
 
803
- shaka.Player = SenzaShakaPlayer;
804
- export { shaka };
892
+ senzaShaka.Player = SenzaShakaPlayer;
893
+ export { senzaShaka as shaka };
@@ -1,15 +1,10 @@
1
1
  import { getPlatformInfo } from "./api";
2
+ import pack from "../package.json";
2
3
  import { sessionInfo } from "./SessionInfo";
4
+ const { version } = pack;
3
5
 
4
6
  const REST_RESPONSE_TIMEOUT_SECONDS = 5;
5
7
 
6
- export function getVersion() {
7
- return typeof IMPLEMENTATION_VERSION !== "undefined"
8
- // eslint-disable-next-line no-undef
9
- ? IMPLEMENTATION_VERSION
10
- : "unknown";
11
- };
12
-
13
8
  export function getFCID() {
14
9
  return Math.round(Math.random() * 100000) + "-" + getPlatformInfo().sessionInfo?.connectionId;
15
10
  }
@@ -47,7 +42,7 @@ class SdkLogger {
47
42
  console.info(`[hs-sdk] [metrics] ${JSON.stringify(metricObj)}`);
48
43
  }
49
44
  withFields(logFields) {
50
- return new SdkLogger({ ...this.logFields, ...logFields });
45
+ return new SdkLogger({...this.logFields, ...logFields});
51
46
  }
52
47
  formatLogString(data) {
53
48
  let logString = "[hs-sdk] " + data.join(" ");
@@ -56,13 +51,9 @@ class SdkLogger {
56
51
  }
57
52
  return logString;
58
53
  }
59
- addfields(fields) {
60
- this.logFields = { ...this.logFields, ...fields };
61
- return this;
62
- }
63
54
  }
64
55
 
65
- export const sdkLogger = new SdkLogger({ sdkVersion: getVersion(), url: window?.location?.href ?? "" });
56
+ export const sdkLogger = new SdkLogger({sdkVersion: version, url: window?.location?.href ?? ""});
66
57
 
67
58
  export async function getRestResponse(messageName) {
68
59
 
@@ -73,14 +64,14 @@ export async function getRestResponse(messageName) {
73
64
 
74
65
  return new Promise((resolve, reject) => {
75
66
  const FCID = getFCID();
76
- const logger = sdkLogger.withFields({ FCID });
67
+ const logger = sdkLogger.withFields({FCID});
77
68
  const message = {
78
69
  type: "restRequest",
79
70
  name: messageName,
80
71
  method: "GET",
81
72
  fcid: FCID
82
73
  };
83
- const request = { target: "TC", waitForResponse: true, message: JSON.stringify(message) };
74
+ const request = {target: "TC", waitForResponse: true, message: JSON.stringify(message)};
84
75
  let timeoutHandler = 0;
85
76
  const queryId = window.cefQuery({
86
77
  request: JSON.stringify(request),
@@ -1,367 +0,0 @@
1
- import { getFCID, sdkLogger, getVersion } from "./utils.js";
2
- import { sessionInfo } from "./SessionInfo.js";
3
- import { lifecycle } from "./lifecycle.js";
4
- import { alarmManager } from "./alarmManager.js";
5
-
6
- let authToken;
7
-
8
- const API_VERSION = "1.0";
9
- let interfaceVersion;
10
-
11
- typeof document !== "undefined" && document.addEventListener("keydown", (event) => {
12
- sdkLogger.log(`Got ${event.key} key`);
13
- });
14
-
15
- /** @namespace auth
16
- *@example
17
- * import { auth } from "senza-sdk";
18
- **/
19
- export const auth = {
20
-
21
- /** Should be called upon startup and be embedded in future requests */
22
- getToken,
23
-
24
- /** Should be called upon '401' event (unauthorized) */
25
- forceTokenUpdate,
26
-
27
- getClientAssertion
28
-
29
- };
30
-
31
- import { remotePlayer } from "./remotePlayer.js";
32
- export { remotePlayer };
33
-
34
- /** Should be called once to init the library
35
- *@example
36
- * import { init } from "senza-sdk";
37
- * await init();
38
- **/
39
- export async function init(interfaceApiVersion, showSequenceFunc, initSequenceFunc) {
40
- interfaceVersion = interfaceApiVersion;
41
- sdkLogger.addfields({ interfaceVersion });
42
- sdkLogger.log(`init. Interface version: ${interfaceVersion}. Implementation version: ${getVersion()}`);
43
-
44
- if (!window.diagnostics) {
45
- // ------------------------------------------------------------------------------------------------
46
- // -- Do NOT change this log, as ui-streamer is checking this string to detect abnormal behavior --
47
- // ------------------------------------------------------------------------------------------------
48
- sdkLogger.error("[ init ] window.diagnostics is undefined");
49
- }
50
-
51
- if (window.cefQuery) {
52
-
53
- // First, check compatability with ui-streamer api version
54
- await new Promise((resolve, reject) => {
55
- window.cefQuery({
56
- request: "apiVersion " + API_VERSION,
57
- persistent: false,
58
- onSuccess: () => {
59
- sdkLogger.log("api version compatability check succeeded");
60
- resolve();
61
- },
62
- onFailure: (code, msg) => {
63
- sdkLogger.error("api version compatability check failed: " + msg);
64
- reject(msg);
65
- }
66
- });
67
- });
68
-
69
- const sessionInfoStr = await new Promise((resolve) => {
70
- window.cefQuery({
71
- request: "sessionInfo",
72
- persistent: false,
73
- onSuccess: (response) => {
74
- sdkLogger.log("sessionInfo request successfully returned " + response);
75
- resolve(response);
76
- },
77
- onFailure: (code, msg) => {
78
- sdkLogger.error(`sessionInfo request failed: ${code} ${msg}`);
79
- }
80
- });
81
- });
82
-
83
- sessionInfo.setSessionInfoStr(sessionInfoStr);
84
- const sessionInfoObj = JSON.parse(sessionInfoStr);
85
- authToken = sessionInfoObj?.settings?.webUI?.backendHeaders?.Authorization;
86
- sdkLogger.log(`authToken: token = ${authToken}`);
87
- // Listen to updateSession event to set the new token
88
- document.addEventListener("updateSession", (e) => {
89
- authToken = e.detail?.updateObj;
90
- sdkLogger.log(`onUpdateSessionEvent: token = ${authToken}`);
91
- });
92
-
93
- // Set default alarm timeout using UI-Streamer settings
94
- const alarmTimeout = sessionInfoObj?.settings?.["ui-streamer"]?.alarmTimeout;
95
- if (alarmTimeout) {
96
- alarmManager._setDefaultTimeout(alarmTimeout);
97
- }
98
-
99
- // Get trigger event
100
- const triggerEventStr = await new Promise((resolve) => {
101
- const FCID = getFCID();
102
- const logger = sdkLogger.withFields({ FCID });
103
- const message = { type: "triggerEvent", fcid: FCID };
104
- const request = { target: "UI-Streamer", waitForResponse: false, message: JSON.stringify(message) };
105
- window.cefQuery({
106
- request: JSON.stringify(request),
107
- persistent: false,
108
- onSuccess: (response) => {
109
- logger.log(`triggerEvent request successfully returned '${response}'`);
110
- resolve(response);
111
- },
112
- onFailure: (code, msg) => {
113
- logger.error(`triggerEvent request failed: ${code} ${msg}`);
114
- resolve("");
115
- }
116
- });
117
- });
118
- let triggerEvent = {};
119
- if (triggerEventStr) {
120
- try {
121
- triggerEvent = JSON.parse(triggerEventStr);
122
- } catch (e) {
123
- sdkLogger.error(`failed to parse trigger event string ${triggerEventStr}: ${e.message}`);
124
- }
125
- }
126
-
127
- // Initialize lifecycle first to make sure the state is updated.
128
- await lifecycle._init(sessionInfoObj?.settings?.["ui-streamer"], triggerEvent);
129
- await remotePlayer._init(sessionInfoObj?.settings?.["ui-streamer"], triggerEvent);
130
-
131
- const devSequence = sessionInfoObj?.settings?.["ui-streamer"]?.devSequence;
132
- if (devSequence) {
133
- initSequenceFunc({ lifecycle, remotePlayer });
134
- showSequenceFunc(true);
135
- }
136
-
137
- } else {
138
- authToken = getPlatformInfo().sessionInfo?.settings?.webUI?.backendHeaders?.Authorization;
139
- sdkLogger.log(`authToken dummy: token = ${authToken}`);
140
- }
141
-
142
- // override window.close() since it's not allowed to close the application this way
143
- window.close = () => {
144
- sdkLogger.warn("window.close is disabled on Senza platform. Use lifecycle.exitApplication() instead.");
145
- };
146
-
147
-
148
- }
149
-
150
- // Returns the platform information, including version, pod, pod ip and session info.
151
- export function getPlatformInfo() {
152
- if (typeof window !== "undefined" && window.diagnostics) {
153
- try {
154
- const platformInfo = window.diagnostics() || {};
155
- platformInfo.sessionInfo = sessionInfo.sessionInfoObj;
156
- return platformInfo;
157
- } catch (e) {
158
- sdkLogger.error("Could not get platform info", e.stack);
159
- }
160
-
161
- } else {
162
- if (typeof window !== "undefined" && !window.diagnostics) {
163
- sdkLogger.error("[ getPlatformInfo ] window.diagnostics is undefined");
164
- }
165
- return {
166
- version: "X.X.XX-X",
167
- pod: "ui-streamer-X.X.XX-X-QWERT-ASDFG-XXX-XXXXXX-XXXXX",
168
- podIP: "0.0.0.0",
169
- sessionInfo: {
170
- userAgent: "SynamediaSenza/XX.YY.ZZ",
171
- connectionId: "dummy",
172
- deviceId: "123456789",
173
- community: "LocalDev",
174
- tenant: "XXXXXX",
175
- tenantId: "XXXXXX",
176
- manifest: {
177
- transcontainer: "X.X.XX-X"
178
- },
179
- settings: {
180
- webUI: {
181
- backendHeaders: {
182
- Authorization: "Bearer dummytoken"
183
- }
184
- }
185
- },
186
- homeSessionInfo: {
187
- tenantId: "XXXXXX",
188
- community: "LocalDev"
189
- }
190
- }
191
- };
192
- }
193
- }
194
-
195
- async function getToken() {
196
- if (!authToken) {
197
- sdkLogger.log("getToken wait for promise updateSession event");
198
- return new Promise((resolve) => {
199
- // Listen to updateSession event to set the new token
200
- document.addEventListener("updateSession", (e) => {
201
- authToken = e.detail?.updateObj;
202
- sdkLogger.log(`onUpdateSessionEvent: token= ${authToken}`);
203
- resolve(authToken);
204
- }, { once: true });
205
- });
206
- }
207
- return Promise.resolve(authToken);
208
- }
209
-
210
- function forceTokenUpdate() {
211
- authToken = null;
212
-
213
- if (window.cefQuery) {
214
- const FCID = getFCID();
215
- const logger = sdkLogger.withFields({ FCID });
216
- logger.log("forceTokenUpdate: sending updateSessionRequest");
217
- const message = {
218
- type: "updateSessionRequest",
219
- updateKey: "authorization",
220
- parentPath: "settings.webUI.backendHeaders.Authorization",
221
- fcid: FCID
222
- };
223
- const request = { target: "TC", waitForResponse: false, message: JSON.stringify(message) };
224
- window.cefQuery({
225
- request: JSON.stringify(request),
226
- persistent: false,
227
- onSuccess: () => {
228
- logger.log("updateSessionRequest successfully sent");
229
- },
230
- onFailure: (code, msg) => {
231
- logger.error(`updateSessionRequest failed: ${code} ${msg}`);
232
- }
233
- });
234
- } else {
235
- sdkLogger.error("forceTokenUpdate: window.cefQuery is undefined");
236
- }
237
- }
238
-
239
- /** Returns a boolean that indicates whether we are running in an e2e environment, or on local browser */
240
- export function isRunningE2E() {
241
- return !!(typeof window !== "undefined" && window.cefQuery);
242
- }
243
-
244
- /** Call this API once after application startup, when the ui is ready to accept keys/events */
245
- export function uiReady() {
246
- if (window.cefQuery) {
247
- window.cefQuery({
248
- request: "uiReady",
249
- persistent: false,
250
- onSuccess: () => {
251
- sdkLogger.log("uiReady request successfully sent");
252
- },
253
- onFailure: (code, msg) => {
254
- sdkLogger.error(`uiReady request failed: ${code} ${msg}`);
255
- }
256
- });
257
- } else {
258
- sdkLogger.error("uiReady: window.cefQuery is undefined");
259
- }
260
- }
261
-
262
- export { lifecycle } from "./lifecycle.js";
263
- export { deviceManager } from "./deviceManager.js";
264
- export { platformManager } from "./platformManager.js";
265
- export { alarmManager };
266
- export { messageManager } from "./messageManager.js";
267
- export { SenzaShakaPlayer as ShakaPlayer, shaka } from "./senzaShakaPlayer.js";
268
-
269
- import "./devHelper.js";
270
-
271
- /**
272
- * The function receives a license response and passes it to platform.
273
- * @param {number} statusCode status code that was received from the license server
274
- * @param {ArrayBuffer|string} licenseResponse a license response that was received from the license server to be passed to platform.
275
- * @param {string} fcid a fcid received with the license request
276
- * @param {string} sessionId a sessionId received with the license request
277
- * In case of success licenceResponse is of type @type {ArrayBuffer}
278
- * In case of error licenseResponse is of type @type {string}
279
- */
280
- export function writeLicenseResponse(statusCode, licenseResponse, fcid, sessionId) {
281
-
282
- if (statusCode >= 200 && statusCode < 300) {
283
- licenseResponse = window.btoa(String.fromCharCode.apply(null, new Uint8Array(licenseResponse))); // to base64
284
- }
285
-
286
- if (window.cefQuery) {
287
- const message = {
288
- type: "updateLicense",
289
- sessionId,
290
- fcid
291
- };
292
- message[statusCode >= 200 && statusCode < 300 ? "response" : "error"] = licenseResponse;
293
- const request = { target: "TC", waitForResponse: false, message: JSON.stringify(message) };
294
- window.cefQuery({
295
- request: JSON.stringify(request),
296
- persistent: false,
297
- onSuccess: () => {
298
- sdkLogger.log("updateLicense request successfully sent");
299
- },
300
- onFailure: (code, msg) => {
301
- sdkLogger.error(`updateLicense request failed: ${code} ${msg}`);
302
- }
303
- });
304
- }
305
-
306
- }
307
-
308
- export class ClientAssertionError extends Error {
309
- constructor(code, message) {
310
- super(message);
311
- this.code = code;
312
- }
313
- }
314
-
315
- /**
316
- * @typedef Token
317
- * @property {string} hostplatform_assertion The client assertion token.
318
- */
319
-
320
- /**
321
- * Async function that returns the client assertion
322
- * @return {Promise<Token>} Promise which is resolved to a client assertion object when getClientAssertion has been successfully performed. * client assertion object contains hostplatform_assertion property which holds the client assertion token.
323
- * Failure to getClientAssertion for any reason, result in the promise being rejected.
324
- * Error status codes:
325
- * Status code 400 - Tenant configuration is missing
326
- * Status code 0 - General error
327
- * @example
328
- * try {
329
- * const client_assertion = await auth.getClientAssertion();
330
- * console.log("Client assertion token is", client_assertion.hostplatform_assertion);
331
- * } catch (e) {
332
- * console.error("getClientAssertion failed", e);
333
- * }
334
- */
335
- export function getClientAssertion() {
336
- if (window.cefQuery) {
337
- sdkLogger.log("getClientAssertion is called");
338
-
339
- return new Promise((resolve, reject) => {
340
- window.cefQuery({
341
- request: "client_assertion",
342
- persistent: false,
343
- onSuccess: (response) => {
344
- try {
345
- const json_response = JSON.parse(response);
346
- sdkLogger.log(`client_assertion request successfully returned ${response}`);
347
- resolve(json_response);
348
- } catch (e) {
349
- sdkLogger.error(`Failed to parse client assertion ${response}: ${e.message}`);
350
- reject(new ClientAssertionError(0, "Failed to parse client assertion"));
351
- }
352
-
353
- },
354
- onFailure: (code, msg) => {
355
- sdkLogger.log(`client_assertion request failed: ${code} ${msg}`);
356
- reject(new ClientAssertionError(code, msg));
357
- }
358
- });
359
- });
360
- }
361
- sdkLogger.warn("getClientAssertion is not supported if NOT running e2e");
362
- }
363
-
364
- import * as senzaSDK from "./api.js";
365
- if (typeof window !== "undefined") {
366
- window.senzaSDKImplementation = window.senzaSDKImplementation || senzaSDK; // this is only for testing purposes which allows us to use and test senza APIs in pipeline tests
367
- }