senza-sdk 4.2.64-70c0747.0 → 4.2.65-90c49ac.0
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/dist/bundle.js +1 -1
- package/package.json +7 -15
- package/src/{implementation/alarmManager.js → alarmManager.js} +52 -15
- package/src/api.js +350 -183
- package/src/{implementation/deviceManager.js → deviceManager.js} +65 -4
- package/src/{implementation/lifecycle.js → lifecycle.js} +215 -28
- package/src/{implementation/messageManager.js → messageManager.js} +6 -6
- package/src/{implementation/platformManager.js → platformManager.js} +4 -5
- package/src/{implementation/remotePlayer.js → remotePlayer.js} +22 -18
- package/src/{implementation/senzaShakaPlayer.js → senzaShakaPlayer.js} +28 -18
- package/src/{implementation/utils.js → utils.js} +6 -15
- package/src/implementation/api.js +0 -367
- package/src/interface/alarmManager.js +0 -69
- package/src/interface/api.js +0 -8
- package/src/interface/deviceManager.js +0 -133
- package/src/interface/lifecycle.js +0 -278
- package/src/interface/messageManager.js +0 -46
- package/src/interface/platformManager.js +0 -35
- package/src/interface/remotePlayer.js +0 -441
- package/src/interface/senzaShakaPlayer.js +0 -171
- package/src/interface/utils.js +0 -45
- /package/src/{implementation/SessionInfo.js → SessionInfo.js} +0 -0
- /package/src/{implementation/devHelper.js → devHelper.js} +0 -0
- /package/src/{interface/devSequence.js → devSequence.js} +0 -0
- /package/src/{implementation/eventListenersManager.js → eventListenersManager.js} +0 -0
- /package/src/{implementation/subtitlesUtils.js → subtitlesUtils.js} +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { RemotePlayer as RemotePlayerInterface } from "../interface/remotePlayer";
|
|
2
1
|
import {
|
|
3
2
|
getFCID,
|
|
4
3
|
isAudioSyncConfigured,
|
|
@@ -83,7 +82,7 @@ function setPlaybackInfo(playbackInfo) {
|
|
|
83
82
|
* @fires seeked (Not implemented yet)
|
|
84
83
|
* @fires loadedmetadata (Not implemented yet)
|
|
85
84
|
*/
|
|
86
|
-
class RemotePlayer extends
|
|
85
|
+
class RemotePlayer extends EventTarget {
|
|
87
86
|
constructor() {
|
|
88
87
|
super();
|
|
89
88
|
/**
|
|
@@ -1134,8 +1133,13 @@ class RemotePlayer extends RemotePlayerInterface {
|
|
|
1134
1133
|
|
|
1135
1134
|
// If seeking in progress, wait for seek to complete before playing
|
|
1136
1135
|
if (this._isSeekingByApplication) {
|
|
1137
|
-
|
|
1138
|
-
|
|
1136
|
+
if (lifecycle.state === lifecycle.UiState.FOREGROUND) {
|
|
1137
|
+
sdkLogger.info("application requesting play during seek. setting targetSeekPlayingState to PLAYING_UI");
|
|
1138
|
+
this._targetSeekPlayingState = TargetPlayingState.PLAYING_UI;
|
|
1139
|
+
} else {
|
|
1140
|
+
sdkLogger.info("application requesting play during seek. setting targetSeekPlayingState to PLAYING_ABR");
|
|
1141
|
+
this._targetSeekPlayingState = TargetPlayingState.PLAYING_ABR;
|
|
1142
|
+
}
|
|
1139
1143
|
return Promise.resolve(true);
|
|
1140
1144
|
}
|
|
1141
1145
|
/*
|
|
@@ -1657,9 +1661,7 @@ class RemotePlayer extends RemotePlayerInterface {
|
|
|
1657
1661
|
}
|
|
1658
1662
|
}
|
|
1659
1663
|
|
|
1660
|
-
|
|
1661
|
-
if (this._remotePlayerApiVersion >= 2 && !this._isSeekingByPlatform && !this._isSeekingByApplication &&
|
|
1662
|
-
(lifecycle.state === lifecycle.UiState.FOREGROUND || lifecycle.state === lifecycle.UiState.IN_TRANSITION_TO_FOREGROUND)) {
|
|
1664
|
+
if (this._remotePlayerApiVersion >= 2 && !this._isSeekingByPlatform && !this._isSeekingByApplication) {
|
|
1663
1665
|
this._atomicSeek();
|
|
1664
1666
|
} else {
|
|
1665
1667
|
sdkLogger.info(`Seeking: skipping seeking event to currentTime: ${playbackPosition}, internalSeek: ${this._isSeekingByPlatform}, localPlayerSeek: ${this._isSeekingByApplication}, state: ${lifecycle.state}`);
|
|
@@ -1678,16 +1680,16 @@ class RemotePlayer extends RemotePlayerInterface {
|
|
|
1678
1680
|
* */
|
|
1679
1681
|
async _atomicSeek() {
|
|
1680
1682
|
sdkLogger.info("Seeking: local video element seeking start while isPlaying: ", this._isPlaying);
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1683
|
+
if (this._isPlaying) {
|
|
1684
|
+
if (!lifecycle._inTransitionToForeground && (lifecycle._inTransitionToBackground || lifecycle.state === lifecycle.UiState.BACKGROUND || lifecycle.state === lifecycle.UiState.IN_TRANSITION_TO_BACKGROUND)) {
|
|
1685
|
+
sdkLogger.info("seek in background", this._isPlaying);
|
|
1686
|
+
this._targetSeekPlayingState = TargetPlayingState.PLAYING_ABR;
|
|
1687
|
+
} else {
|
|
1688
|
+
this._targetSeekPlayingState = TargetPlayingState.PLAYING_UI;
|
|
1689
|
+
}
|
|
1690
|
+
} else {
|
|
1691
|
+
this._targetSeekPlayingState = TargetPlayingState.PAUSED;
|
|
1692
|
+
}
|
|
1691
1693
|
|
|
1692
1694
|
// The platform could be currently syncing audio/video using playback rate. Reset when performing seek.
|
|
1693
1695
|
if (this._videoElement) {
|
|
@@ -1754,7 +1756,7 @@ class RemotePlayer extends RemotePlayerInterface {
|
|
|
1754
1756
|
|
|
1755
1757
|
// If in TargetPlayingState.PAUSE, no need to resume.
|
|
1756
1758
|
// Resume without awaiting to avoid blocking the seek process anymore
|
|
1757
|
-
// In case where we aborted, we don't want to resume playback.
|
|
1759
|
+
// In case where we aborted (new load or unload called), we don't want to resume playback.
|
|
1758
1760
|
if (!this._abortSeeking) {
|
|
1759
1761
|
if (this._targetSeekPlayingState === TargetPlayingState.PLAYING_UI) {
|
|
1760
1762
|
if (!this._isAudioSyncEnabled()) {
|
|
@@ -1763,6 +1765,8 @@ class RemotePlayer extends RemotePlayerInterface {
|
|
|
1763
1765
|
// resume audio play only if _isAudioSyncEnabled
|
|
1764
1766
|
this._play(StreamType.AUDIO);
|
|
1765
1767
|
} else if (this._targetSeekPlayingState === TargetPlayingState.PLAYING_ABR) {
|
|
1768
|
+
// When moving back to background, we need to put the remote player back into play mode
|
|
1769
|
+
this._changePlayMode(true);
|
|
1766
1770
|
lifecycle._moveToBackground();
|
|
1767
1771
|
}
|
|
1768
1772
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import * as shaka from "shaka-player";
|
|
3
2
|
import { remotePlayer, lifecycle, getPlatformInfo } from "./api";
|
|
4
3
|
import { sdkLogger, iso6393to1 } from "./utils";
|
|
5
4
|
|
|
@@ -31,6 +30,11 @@ class SenzaError extends shaka.util.Error {
|
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
|
|
33
|
+
// Copy the shaka module and replace the Player class with SenzaShakaPlayer
|
|
34
|
+
// if we don't Copy the shaka module, the Player class will be replaced for all the other modules that import shaka
|
|
35
|
+
const senzaShaka = { ...shaka };
|
|
36
|
+
|
|
37
|
+
|
|
34
38
|
/**
|
|
35
39
|
* SenzaShakaPlayer subclass of Shaka that handles both local and remote playback.
|
|
36
40
|
*
|
|
@@ -74,7 +78,7 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
74
78
|
* @description Timeout in milliseconds to wait for playing event
|
|
75
79
|
* @default 3000
|
|
76
80
|
*/
|
|
77
|
-
_playingTimeout =
|
|
81
|
+
_playingTimeout = 4000;
|
|
78
82
|
|
|
79
83
|
/**
|
|
80
84
|
* @private
|
|
@@ -89,7 +93,7 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
89
93
|
* @description Whether to stop remote player on error
|
|
90
94
|
* @default false
|
|
91
95
|
*/
|
|
92
|
-
|
|
96
|
+
_shouldStopOnRemotePlayerError = false;
|
|
93
97
|
|
|
94
98
|
/**
|
|
95
99
|
* @private
|
|
@@ -181,7 +185,7 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
181
185
|
originatesFromRemotePlayer: true
|
|
182
186
|
};
|
|
183
187
|
|
|
184
|
-
const response = await this.getNetworkingEngine().request(
|
|
188
|
+
const response = await this.getNetworkingEngine().request(senzaShaka.net.NetworkingEngine.RequestType.LICENSE, request).promise;
|
|
185
189
|
|
|
186
190
|
let responseBody = response.data;
|
|
187
191
|
if (response.status < 200 || response.status >= 300) {
|
|
@@ -280,13 +284,15 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
280
284
|
|
|
281
285
|
|
|
282
286
|
/**
|
|
283
|
-
* Handles errors
|
|
287
|
+
* Handles errors received by remote player while waiting for the playing event.
|
|
288
|
+
* The promise returned to the call for video element play will be rejected.
|
|
284
289
|
* @private
|
|
285
290
|
* @param {Error} error - The error object.
|
|
286
291
|
*/
|
|
287
292
|
_handlePlayPromiseError(error) {
|
|
288
293
|
|
|
289
294
|
sdkLogger.error("Error while waiting for playing event:", error);
|
|
295
|
+
|
|
290
296
|
if (this._playPromiseReject) {
|
|
291
297
|
this._playPromiseReject(error);
|
|
292
298
|
this._playPromiseResolve = null;
|
|
@@ -296,6 +302,7 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
296
302
|
clearTimeout(this._playTimeoutId);
|
|
297
303
|
this._playTimeoutId = null;
|
|
298
304
|
}
|
|
305
|
+
|
|
299
306
|
}
|
|
300
307
|
|
|
301
308
|
/**
|
|
@@ -556,11 +563,12 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
556
563
|
const isCritical = this._isErrorCritical(remotePlayerErrorCode);
|
|
557
564
|
const error = this._createSenzaError(remotePlayerErrorCode, message, isCritical);
|
|
558
565
|
const errorMap = new Map();
|
|
566
|
+
const shouldStopPlayback = this._shouldStopOnRemotePlayerError && this.videoElement && isCritical;
|
|
559
567
|
errorMap.set("detail", error);
|
|
560
568
|
|
|
561
569
|
// Check if we should stop playback - only for critical errors when configured
|
|
562
|
-
|
|
563
|
-
|
|
570
|
+
|
|
571
|
+
if (shouldStopPlayback) {
|
|
564
572
|
try {
|
|
565
573
|
sdkLogger.warn("Stopping local player playback due to critical error");
|
|
566
574
|
// Stop only local playback
|
|
@@ -568,9 +576,11 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
568
576
|
} catch (stopError) {
|
|
569
577
|
sdkLogger.error("Error while trying to stop video element playback:", stopError);
|
|
570
578
|
}
|
|
579
|
+
// 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,
|
|
580
|
+
// the playback timeout will start the local playback
|
|
581
|
+
this._handlePlayPromiseError(error);
|
|
571
582
|
}
|
|
572
|
-
|
|
573
|
-
this._handlePlayPromiseError(error);
|
|
583
|
+
|
|
574
584
|
this.dispatchEvent(new shaka.util.FakeEvent("error", errorMap));
|
|
575
585
|
}
|
|
576
586
|
|
|
@@ -680,14 +690,14 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
680
690
|
/**
|
|
681
691
|
* Override the configure method to add custom configuration handling
|
|
682
692
|
* Supports the following additional configuration options:
|
|
683
|
-
* -
|
|
693
|
+
* - shouldStopOnRemotePlayerError: boolean - If true, local player will be stopped on remote player error
|
|
684
694
|
*
|
|
685
695
|
* @override
|
|
686
696
|
* @param {Object} config - Configuration object to be merged with existing config
|
|
687
|
-
* @param {boolean} [config.
|
|
697
|
+
* @param {boolean} [config.shouldStopOnRemotePlayerError=true] - Whether to stop local player on remote player error
|
|
688
698
|
* @example
|
|
689
699
|
* player.configure({
|
|
690
|
-
*
|
|
700
|
+
* shouldStopOnRemotePlayerError: false, // Don't stop local playback on remote player error
|
|
691
701
|
* // ... other shaka configurations
|
|
692
702
|
* });
|
|
693
703
|
*/
|
|
@@ -695,12 +705,12 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
695
705
|
sdkLogger.log("configure player with: ", JSON.stringify(config));
|
|
696
706
|
|
|
697
707
|
// Handle custom configuration
|
|
698
|
-
if (config.
|
|
699
|
-
this.
|
|
708
|
+
if (config.shouldStopOnRemotePlayerError !== undefined) {
|
|
709
|
+
this._shouldStopOnRemotePlayerError = !!config.shouldStopOnRemotePlayerError;
|
|
700
710
|
// Remove our custom config so it doesn't get passed to parent
|
|
701
711
|
// Use rest operator without creating a named variable for the removed property
|
|
702
712
|
// eslint-disable-next-line no-unused-vars
|
|
703
|
-
const {
|
|
713
|
+
const { shouldStopOnRemotePlayerError, ...shakaConfig } = config;
|
|
704
714
|
config = shakaConfig;
|
|
705
715
|
}
|
|
706
716
|
|
|
@@ -800,5 +810,5 @@ export class SenzaShakaPlayer extends shaka.Player {
|
|
|
800
810
|
|
|
801
811
|
}
|
|
802
812
|
|
|
803
|
-
|
|
804
|
-
export { shaka };
|
|
813
|
+
senzaShaka.Player = SenzaShakaPlayer;
|
|
814
|
+
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({
|
|
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({
|
|
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({
|
|
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 = {
|
|
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
|
-
}
|