@titan-os/sdk 1.7.0 → 1.7.2
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/cjs/sdk.js +1 -1
- package/dist/esm/sdk.js +1033 -818
- package/dist/umd/sdk.js +1 -1
- package/package.json +1 -1
package/dist/esm/sdk.js
CHANGED
|
@@ -112,6 +112,17 @@ class LogSubscriptionManager {
|
|
|
112
112
|
if (this.logBuffer.length > this.maxBufferSize) {
|
|
113
113
|
this.logBuffer.shift();
|
|
114
114
|
}
|
|
115
|
+
const isGatewayEntry = entry.metadata?.source === "Gateway" || entry.metadata?.tunneled === true;
|
|
116
|
+
if (isGatewayEntry && entry.level === "error") {
|
|
117
|
+
const callerInfo = entry.metadata?.caller || "[Gateway]";
|
|
118
|
+
const consoleArgs = formatConsoleOutput(
|
|
119
|
+
entry.module,
|
|
120
|
+
entry.message,
|
|
121
|
+
entry.args || [],
|
|
122
|
+
callerInfo
|
|
123
|
+
);
|
|
124
|
+
outputToConsole("error", consoleArgs);
|
|
125
|
+
}
|
|
115
126
|
this.subscriptions.forEach((subscription) => {
|
|
116
127
|
if (this.shouldNotifySubscription(subscription, entry)) {
|
|
117
128
|
try {
|
|
@@ -183,9 +194,28 @@ class LogSubscriptionManager {
|
|
|
183
194
|
return [...filtered];
|
|
184
195
|
}
|
|
185
196
|
}
|
|
197
|
+
function formatConsoleOutput(module, message, args, callerInfo) {
|
|
198
|
+
const prefix = `[TitanSDK][${module}]`;
|
|
199
|
+
return [`${prefix} ${message}`, ...args, "\n", callerInfo];
|
|
200
|
+
}
|
|
201
|
+
function outputToConsole(level, consoleArgs) {
|
|
202
|
+
switch (level) {
|
|
203
|
+
case "debug":
|
|
204
|
+
console.debug(...consoleArgs);
|
|
205
|
+
break;
|
|
206
|
+
case "info":
|
|
207
|
+
console.info(...consoleArgs);
|
|
208
|
+
break;
|
|
209
|
+
case "warn":
|
|
210
|
+
console.warn(...consoleArgs);
|
|
211
|
+
break;
|
|
212
|
+
case "error":
|
|
213
|
+
console.error(...consoleArgs);
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
186
217
|
const globalLogManager = new LogSubscriptionManager();
|
|
187
218
|
function createEnhancedLogger(module) {
|
|
188
|
-
const prefix = `[TitanSDK] [${module}]`;
|
|
189
219
|
const getStackDetails = (callerInfo) => {
|
|
190
220
|
let fnName = "";
|
|
191
221
|
let fnPath = "";
|
|
@@ -248,28 +278,15 @@ function createEnhancedLogger(module) {
|
|
|
248
278
|
}
|
|
249
279
|
};
|
|
250
280
|
globalLogManager.addLogEntry(entry);
|
|
251
|
-
const shouldLogToConsole = globalLogManager.isDebugMode() || level === "
|
|
281
|
+
const shouldLogToConsole = globalLogManager.isDebugMode() || level === "error";
|
|
252
282
|
if (shouldLogToConsole) {
|
|
253
|
-
const consoleArgs =
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
283
|
+
const consoleArgs = formatConsoleOutput(
|
|
284
|
+
module,
|
|
285
|
+
message,
|
|
286
|
+
args,
|
|
257
287
|
formattedCallerInfo
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
case "debug":
|
|
261
|
-
console.debug(...consoleArgs);
|
|
262
|
-
break;
|
|
263
|
-
case "info":
|
|
264
|
-
console.info(...consoleArgs);
|
|
265
|
-
break;
|
|
266
|
-
case "warn":
|
|
267
|
-
console.warn(...consoleArgs);
|
|
268
|
-
break;
|
|
269
|
-
case "error":
|
|
270
|
-
console.error(...consoleArgs);
|
|
271
|
-
break;
|
|
272
|
-
}
|
|
288
|
+
);
|
|
289
|
+
outputToConsole(level, consoleArgs);
|
|
273
290
|
}
|
|
274
291
|
};
|
|
275
292
|
return {
|
|
@@ -914,14 +931,17 @@ class BaseBridge {
|
|
|
914
931
|
this.initReject = reject;
|
|
915
932
|
log$u.debug("bridge: starting initialization process");
|
|
916
933
|
window.addEventListener("message", this.handleMessage.bind(this));
|
|
934
|
+
let isResolved = false;
|
|
917
935
|
const handleIframeLoad = () => {
|
|
918
|
-
if (this.aborted) return;
|
|
936
|
+
if (this.aborted || isResolved) return;
|
|
937
|
+
isResolved = true;
|
|
919
938
|
this.isInitialized = true;
|
|
920
939
|
log$u.debug("bridge initialized successfully");
|
|
921
940
|
resolve(true);
|
|
922
941
|
};
|
|
923
942
|
const handleIframeError = () => {
|
|
924
|
-
if (this.aborted) return;
|
|
943
|
+
if (this.aborted || isResolved) return;
|
|
944
|
+
isResolved = true;
|
|
925
945
|
log$u.error("Bridge iframe failed to load or initialize.");
|
|
926
946
|
this.isInitialized = false;
|
|
927
947
|
reject(new Error("Bridge iframe failed to load or initialize."));
|
|
@@ -929,7 +949,17 @@ class BaseBridge {
|
|
|
929
949
|
(async () => {
|
|
930
950
|
try {
|
|
931
951
|
await this.setupIframe(handleIframeLoad, handleIframeError);
|
|
952
|
+
if (!isResolved) {
|
|
953
|
+
isResolved = true;
|
|
954
|
+
log$u.warn(
|
|
955
|
+
"Bridge initialization timeout - setupIframe completed but LAUNCHER_READY not received"
|
|
956
|
+
);
|
|
957
|
+
this.isInitialized = false;
|
|
958
|
+
resolve(false);
|
|
959
|
+
}
|
|
932
960
|
} catch (error) {
|
|
961
|
+
if (isResolved) return;
|
|
962
|
+
isResolved = true;
|
|
933
963
|
log$u.error("Failed to setup iframe:", error);
|
|
934
964
|
this.isInitialized = false;
|
|
935
965
|
reject(error);
|
|
@@ -1329,10 +1359,29 @@ __publicField(_CSPDetector, "violations", []);
|
|
|
1329
1359
|
let CSPDetector = _CSPDetector;
|
|
1330
1360
|
const log$s = getLogger("EnhancedBridge");
|
|
1331
1361
|
function isBridgeCspViolation(violation, src) {
|
|
1332
|
-
|
|
1362
|
+
const relevantDirectives = ["frame-src", "child-src", "connect-src"];
|
|
1363
|
+
if (!relevantDirectives.includes(violation.directive) || !violation.blockedURI || !src) {
|
|
1333
1364
|
return false;
|
|
1334
1365
|
}
|
|
1335
|
-
|
|
1366
|
+
const blockedURI = violation.blockedURI;
|
|
1367
|
+
const normalizeUrl = (url) => {
|
|
1368
|
+
return url.replace(/\/+$/, "").toLowerCase();
|
|
1369
|
+
};
|
|
1370
|
+
const normalizedBlocked = normalizeUrl(blockedURI);
|
|
1371
|
+
const normalizedSrc = normalizeUrl(src);
|
|
1372
|
+
const getDomain = (url) => {
|
|
1373
|
+
try {
|
|
1374
|
+
const urlObj = new URL(url);
|
|
1375
|
+
return urlObj.hostname;
|
|
1376
|
+
} catch {
|
|
1377
|
+
const match = url.match(/^(?:https?:\/\/)?([^\/]+)/);
|
|
1378
|
+
return match ? match[1] : "";
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
const blockedDomain = getDomain(blockedURI);
|
|
1382
|
+
const srcDomain = getDomain(src);
|
|
1383
|
+
const isGatewayRelated = normalizedSrc.includes(normalizedBlocked) || normalizedBlocked.includes(normalizedSrc) || blockedDomain && srcDomain && blockedDomain === srcDomain || blockedURI.includes("titanos.tv") && src.includes("titanos.tv") || blockedURI.includes("localhost") && src.includes("localhost");
|
|
1384
|
+
return isGatewayRelated;
|
|
1336
1385
|
}
|
|
1337
1386
|
class EnhancedBaseBridge extends BaseBridge {
|
|
1338
1387
|
constructor(config) {
|
|
@@ -1345,20 +1394,42 @@ class EnhancedBaseBridge extends BaseBridge {
|
|
|
1345
1394
|
cspViolations: []
|
|
1346
1395
|
});
|
|
1347
1396
|
__publicField(this, "cspUnsubscribe");
|
|
1397
|
+
__publicField(this, "cspViolationDetected", false);
|
|
1398
|
+
__publicField(this, "cspViolationPromise");
|
|
1399
|
+
__publicField(this, "cspViolationResolver", null);
|
|
1348
1400
|
this.bridgeHealthStatus.gatewayUrl = this.src;
|
|
1401
|
+
this.cspViolationPromise = new Promise((resolve) => {
|
|
1402
|
+
this.cspViolationResolver = resolve;
|
|
1403
|
+
});
|
|
1349
1404
|
this.setupCspViolationListener();
|
|
1350
1405
|
}
|
|
1351
1406
|
setupCspViolationListener() {
|
|
1352
1407
|
this.cspUnsubscribe = CSPDetector.onViolation(
|
|
1353
1408
|
(violation) => {
|
|
1409
|
+
log$s.debug("CSP violation received in EnhancedBaseBridge:", {
|
|
1410
|
+
directive: violation.directive,
|
|
1411
|
+
blockedURI: violation.blockedURI,
|
|
1412
|
+
gatewayUrl: this.src,
|
|
1413
|
+
isBridgeViolation: isBridgeCspViolation(violation, this.src)
|
|
1414
|
+
});
|
|
1354
1415
|
if (isBridgeCspViolation(violation, this.src)) {
|
|
1416
|
+
const violationString = `${violation.directive}: ${violation.blockedURI || "unknown"}`;
|
|
1417
|
+
if (!this.bridgeHealthStatus.cspViolations.includes(violationString)) {
|
|
1418
|
+
this.bridgeHealthStatus.cspViolations.push(violationString);
|
|
1419
|
+
}
|
|
1355
1420
|
log$s.warn("CSP violation detected for bridge:", {
|
|
1356
1421
|
directive: violation.directive,
|
|
1357
1422
|
blockedURI: violation.blockedURI,
|
|
1358
1423
|
gatewayUrl: this.src
|
|
1359
1424
|
});
|
|
1360
1425
|
this.bridgeHealthStatus.cspBlocked = true;
|
|
1361
|
-
this.bridgeHealthStatus.lastError = `CSP blocked: ${violation.
|
|
1426
|
+
this.bridgeHealthStatus.lastError = `CSP ${violation.directive} blocked: ${violation.blockedURI || "unknown"}`;
|
|
1427
|
+
if (!this.cspViolationDetected && this.cspViolationResolver) {
|
|
1428
|
+
this.cspViolationDetected = true;
|
|
1429
|
+
log$s.debug("Resolving CSP violation Promise");
|
|
1430
|
+
this.cspViolationResolver();
|
|
1431
|
+
this.cspViolationResolver = null;
|
|
1432
|
+
}
|
|
1362
1433
|
}
|
|
1363
1434
|
}
|
|
1364
1435
|
);
|
|
@@ -1392,6 +1463,10 @@ class EnhancedBaseBridge extends BaseBridge {
|
|
|
1392
1463
|
this.cspUnsubscribe();
|
|
1393
1464
|
this.cspUnsubscribe = void 0;
|
|
1394
1465
|
}
|
|
1466
|
+
this.cspViolationDetected = false;
|
|
1467
|
+
this.cspViolationPromise = new Promise((resolve) => {
|
|
1468
|
+
this.cspViolationResolver = resolve;
|
|
1469
|
+
});
|
|
1395
1470
|
this.bridgeHealthStatus = {
|
|
1396
1471
|
connected: false,
|
|
1397
1472
|
cspBlocked: false,
|
|
@@ -1451,6 +1526,50 @@ class EnhancedBaseBridge extends BaseBridge {
|
|
|
1451
1526
|
error: health.lastError
|
|
1452
1527
|
};
|
|
1453
1528
|
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Waits for bridge initialization attempt to complete (success or failure).
|
|
1531
|
+
* This method resolves when the bridge has finished attempting to initialize,
|
|
1532
|
+
* allowing callers to check the initialization status without relying on timeouts.
|
|
1533
|
+
*/
|
|
1534
|
+
async waitForInitializationAttempt() {
|
|
1535
|
+
if (this.isConnected()) {
|
|
1536
|
+
log$s.debug("Bridge already initialized, no need to wait");
|
|
1537
|
+
return;
|
|
1538
|
+
}
|
|
1539
|
+
const bridge = this;
|
|
1540
|
+
if (bridge.initializationPromise) {
|
|
1541
|
+
log$s.debug("Bridge initialization in progress, waiting for completion...");
|
|
1542
|
+
try {
|
|
1543
|
+
await bridge.initializationPromise;
|
|
1544
|
+
log$s.debug("Bridge initialization attempt completed");
|
|
1545
|
+
} catch {
|
|
1546
|
+
log$s.debug("Bridge initialization attempt completed (with error)");
|
|
1547
|
+
}
|
|
1548
|
+
} else {
|
|
1549
|
+
log$s.debug(
|
|
1550
|
+
"No bridge initialization in progress, starting new attempt..."
|
|
1551
|
+
);
|
|
1552
|
+
try {
|
|
1553
|
+
await this.initialize();
|
|
1554
|
+
log$s.debug("Bridge initialization attempt completed");
|
|
1555
|
+
} catch {
|
|
1556
|
+
log$s.debug("Bridge initialization attempt completed (with error)");
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
if (this.bridgeHealthStatus.iframeCreated && !this.isConnected()) {
|
|
1560
|
+
if (this.cspViolationDetected || this.bridgeHealthStatus.cspBlocked) {
|
|
1561
|
+
log$s.debug("CSP violation already detected, no need to wait");
|
|
1562
|
+
} else {
|
|
1563
|
+
log$s.debug(
|
|
1564
|
+
"Iframe created but connection not established, waiting for CSP violation detection..."
|
|
1565
|
+
);
|
|
1566
|
+
await this.cspViolationPromise;
|
|
1567
|
+
log$s.debug(
|
|
1568
|
+
"CSP violation detection completed (or connection established)"
|
|
1569
|
+
);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1454
1573
|
}
|
|
1455
1574
|
class VestelBridge extends EnhancedBaseBridge {
|
|
1456
1575
|
constructor(config) {
|
|
@@ -3884,357 +4003,721 @@ function requireLzString() {
|
|
|
3884
4003
|
return lzString.exports;
|
|
3885
4004
|
}
|
|
3886
4005
|
var lzStringExports = requireLzString();
|
|
3887
|
-
const VERSION = "1.7.
|
|
3888
|
-
const
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
this
|
|
4006
|
+
const VERSION = "1.7.2";
|
|
4007
|
+
const logger$2 = getLogger("RollbarClient");
|
|
4008
|
+
const IGNORED_ERROR_PATTERNS = [
|
|
4009
|
+
"chrome://userjs/",
|
|
4010
|
+
"chrome-extension://",
|
|
4011
|
+
"moz-extension://",
|
|
4012
|
+
"getJWTString",
|
|
4013
|
+
"getjwtstring",
|
|
4014
|
+
"user.js",
|
|
4015
|
+
"userscript",
|
|
4016
|
+
"tampermonkey",
|
|
4017
|
+
"greasemonkey",
|
|
4018
|
+
"can't find variable getjwtstring",
|
|
4019
|
+
"referenceerror: can't find variable: getjwtstring",
|
|
4020
|
+
"unexpected end of json input",
|
|
4021
|
+
"jsonparse"
|
|
4022
|
+
];
|
|
4023
|
+
class RollbarClient {
|
|
4024
|
+
constructor() {
|
|
4025
|
+
__publicField(this, "rollbar", null);
|
|
4026
|
+
__publicField(this, "config", null);
|
|
4027
|
+
__publicField(this, "windowWrapper", new WindowWrapper());
|
|
3907
4028
|
}
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
const success = await this.bridge.initialize();
|
|
3911
|
-
if (success) {
|
|
3912
|
-
this.isInitialized = true;
|
|
3913
|
-
}
|
|
3914
|
-
} catch (error) {
|
|
3915
|
-
log$l.warn("Bridge initialization failed:", error);
|
|
3916
|
-
}
|
|
3917
|
-
this.waitReadyResolver(true);
|
|
4029
|
+
isSDKError(error) {
|
|
4030
|
+
return error instanceof SDKError || error instanceof Error && error.name === "SDKError";
|
|
3918
4031
|
}
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
}
|
|
3924
|
-
if (!localStorage.getItem) {
|
|
3925
|
-
return null;
|
|
3926
|
-
}
|
|
3927
|
-
const cached = localStorage.getItem(this.CACHE_KEY);
|
|
3928
|
-
if (!cached) {
|
|
3929
|
-
return null;
|
|
3930
|
-
}
|
|
3931
|
-
const parsed = JSON.parse(cached);
|
|
3932
|
-
if (Date.now() - parsed.timestamp > this.CACHE_EXPIRY || parsed.lastVersion !== VERSION) {
|
|
3933
|
-
localStorage.removeItem(this.CACHE_KEY);
|
|
3934
|
-
return null;
|
|
3935
|
-
}
|
|
3936
|
-
log$l.debug("Device info loaded from localStorage cache");
|
|
3937
|
-
return parsed;
|
|
3938
|
-
} catch (error) {
|
|
3939
|
-
log$l.warn("Failed to load device info from localStorage:", error);
|
|
3940
|
-
return null;
|
|
4032
|
+
initialize(config) {
|
|
4033
|
+
if (!config.enabled || !config.accessToken) {
|
|
4034
|
+
logger$2.warn("Rollbar not initialized - disabled or missing access token");
|
|
4035
|
+
return;
|
|
3941
4036
|
}
|
|
3942
|
-
}
|
|
3943
|
-
getFromURL() {
|
|
3944
4037
|
try {
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
4038
|
+
this.config = config;
|
|
4039
|
+
this.rollbar = new Rollbar({
|
|
4040
|
+
accessToken: config.accessToken,
|
|
4041
|
+
environment: config.environment || getEnvironment(),
|
|
4042
|
+
captureUncaught: true,
|
|
4043
|
+
captureUnhandledRejections: true,
|
|
4044
|
+
verbose: false,
|
|
4045
|
+
reportLevel: "error",
|
|
4046
|
+
captureIp: false,
|
|
4047
|
+
captureUsername: false,
|
|
4048
|
+
captureEmail: false,
|
|
4049
|
+
maxItems: 100,
|
|
4050
|
+
itemsPerMinute: 60,
|
|
4051
|
+
captureLambdaTimeouts: false,
|
|
4052
|
+
endpoint: `${getLogsDomain()}/logs/`,
|
|
4053
|
+
autoInstrument: {
|
|
4054
|
+
network: false,
|
|
4055
|
+
log: false,
|
|
4056
|
+
dom: false,
|
|
4057
|
+
navigation: false,
|
|
4058
|
+
connectivity: false
|
|
4059
|
+
},
|
|
4060
|
+
payload: {
|
|
4061
|
+
client: {
|
|
4062
|
+
javascript: {
|
|
4063
|
+
code_version: "unknown",
|
|
4064
|
+
source_map_enabled: true
|
|
4065
|
+
}
|
|
3970
4066
|
}
|
|
3971
|
-
}
|
|
3972
|
-
|
|
3973
|
-
|
|
4067
|
+
},
|
|
4068
|
+
transform: (payload) => {
|
|
4069
|
+
if (payload.context) {
|
|
4070
|
+
payload.context = `hephaestus-${payload.context}`;
|
|
4071
|
+
}
|
|
4072
|
+
},
|
|
4073
|
+
checkIgnore: (_isUncaught, args, _payload) => {
|
|
4074
|
+
const error = args[0];
|
|
4075
|
+
const errorMessage = typeof error === "string" ? error : error?.message;
|
|
4076
|
+
const errorStack = typeof error === "object" && error ? error.stack : "";
|
|
4077
|
+
const errorString = String(error).toLowerCase();
|
|
4078
|
+
const ignoredPatterns = IGNORED_ERROR_PATTERNS;
|
|
4079
|
+
return ignoredPatterns.some(
|
|
4080
|
+
(pattern) => errorMessage?.toLowerCase().includes(pattern.toLowerCase()) || errorStack?.toLowerCase().includes(pattern.toLowerCase()) || errorString.includes(pattern.toLowerCase())
|
|
4081
|
+
);
|
|
3974
4082
|
}
|
|
3975
|
-
}
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
}
|
|
3980
|
-
const parsed = JSON.parse(decoded);
|
|
3981
|
-
return parsed;
|
|
4083
|
+
});
|
|
4084
|
+
this.setupGlobalErrorHandlers();
|
|
4085
|
+
logger$2.info("Rollbar initialized successfully", {
|
|
4086
|
+
environment: config.environment
|
|
4087
|
+
});
|
|
3982
4088
|
} catch (error) {
|
|
3983
|
-
|
|
3984
|
-
return null;
|
|
4089
|
+
logger$2.error("Failed to initialize Rollbar", { error, config });
|
|
3985
4090
|
}
|
|
3986
4091
|
}
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
const cacheData = {
|
|
3997
|
-
data,
|
|
3998
|
-
timestamp: Date.now(),
|
|
3999
|
-
lastVersion: VERSION
|
|
4000
|
-
};
|
|
4001
|
-
localStorage.setItem(this.CACHE_KEY, JSON.stringify(cacheData));
|
|
4002
|
-
log$l.debug("Device info saved to localStorage cache");
|
|
4003
|
-
} catch (error) {
|
|
4004
|
-
log$l.warn("Failed to save device info to localStorage:", error);
|
|
4005
|
-
}
|
|
4092
|
+
shouldIgnoreError(error) {
|
|
4093
|
+
if (!error) return true;
|
|
4094
|
+
const errorMessage = typeof error === "string" ? error : error.message || "";
|
|
4095
|
+
const errorStack = typeof error === "object" ? error.stack || "" : "";
|
|
4096
|
+
const errorString = String(error).toLowerCase();
|
|
4097
|
+
const ignoredPatterns = IGNORED_ERROR_PATTERNS;
|
|
4098
|
+
return ignoredPatterns.some(
|
|
4099
|
+
(pattern) => errorMessage?.toLowerCase().includes(pattern.toLowerCase()) || errorStack?.toLowerCase().includes(pattern.toLowerCase()) || errorString.includes(pattern.toLowerCase())
|
|
4100
|
+
);
|
|
4006
4101
|
}
|
|
4007
|
-
async
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
this.saveToLocalStorage(urlData);
|
|
4011
|
-
this.waitReadyResolver(true);
|
|
4012
|
-
return {
|
|
4013
|
-
deviceInfo: urlData,
|
|
4014
|
-
tts: DEFAULT_TTS_SETTINGS,
|
|
4015
|
-
tm: DEFAULT_TM_SETTINGS
|
|
4016
|
-
};
|
|
4102
|
+
async reportError(error, additionalData, severity = "error") {
|
|
4103
|
+
if (!this.rollbar || !this.config?.enabled || !error) {
|
|
4104
|
+
return Promise.resolve(null);
|
|
4017
4105
|
}
|
|
4018
|
-
if (this.
|
|
4019
|
-
|
|
4020
|
-
if (localStorageData) {
|
|
4021
|
-
this.waitReadyResolver(true);
|
|
4022
|
-
return {
|
|
4023
|
-
deviceInfo: localStorageData.data,
|
|
4024
|
-
tts: DEFAULT_TTS_SETTINGS,
|
|
4025
|
-
tm: DEFAULT_TM_SETTINGS
|
|
4026
|
-
};
|
|
4027
|
-
}
|
|
4028
|
-
} else if (this.config.debug) {
|
|
4029
|
-
log$l.debug("Debug mode: skipping cache, fetching fresh data from iframe");
|
|
4106
|
+
if (!this.isSDKError(error)) {
|
|
4107
|
+
return Promise.resolve(null);
|
|
4030
4108
|
}
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4109
|
+
if (this.shouldIgnoreError(error)) {
|
|
4110
|
+
return Promise.resolve(null);
|
|
4111
|
+
}
|
|
4112
|
+
return new Promise((resolve) => {
|
|
4113
|
+
this.getDeviceContext().then((deviceContext) => {
|
|
4114
|
+
try {
|
|
4115
|
+
const allLogs = LogManager.getHistory().filter(
|
|
4116
|
+
(log2) => !log2.module.includes("RollbarClient") && !log2.message.includes("Rollbar") && log2.level !== "debug"
|
|
4117
|
+
).slice(-20);
|
|
4118
|
+
const logsString = allLogs.map(
|
|
4119
|
+
(log2) => `[${log2.timestamp}] ${log2.module}: ${log2.message}${log2.args && log2.args.length > 0 ? "\n Args: " + JSON.stringify(log2.args) : ""}`
|
|
4120
|
+
).join("\n");
|
|
4121
|
+
const context = {
|
|
4122
|
+
logs: logsString,
|
|
4123
|
+
component: additionalData?.component || "SDK",
|
|
4124
|
+
operation: additionalData?.operation,
|
|
4125
|
+
requestId: additionalData?.requestId,
|
|
4126
|
+
timestamp: Date.now(),
|
|
4127
|
+
url: typeof window !== "undefined" ? window.location?.href : void 0,
|
|
4128
|
+
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "unknown",
|
|
4129
|
+
sessionId: this.generateSessionId(),
|
|
4130
|
+
errorStack: typeof error === "object" ? error.stack : void 0,
|
|
4131
|
+
version: typeof window !== "undefined" ? this.windowWrapper.get("TitanSDK")?.VERSION || "unknown" : "unknown",
|
|
4132
|
+
...deviceContext,
|
|
4133
|
+
...additionalData
|
|
4050
4134
|
};
|
|
4051
|
-
|
|
4135
|
+
const rollbarMethod = severity === "critical" ? "critical" : "error";
|
|
4136
|
+
const errorType = severity === "critical" ? "critical_error_with_logs" : "error_with_logs";
|
|
4137
|
+
this.rollbar?.[rollbarMethod](
|
|
4138
|
+
error,
|
|
4139
|
+
{
|
|
4140
|
+
custom: {
|
|
4141
|
+
type: errorType,
|
|
4142
|
+
context,
|
|
4143
|
+
logCount: allLogs.length
|
|
4144
|
+
}
|
|
4145
|
+
},
|
|
4146
|
+
(err, data) => {
|
|
4147
|
+
if (err) {
|
|
4148
|
+
if (!this.shouldIgnoreError(err)) {
|
|
4149
|
+
logger$2.error(
|
|
4150
|
+
`Failed to send ${severity} error to Rollbar`,
|
|
4151
|
+
{
|
|
4152
|
+
error: err,
|
|
4153
|
+
originalError: error
|
|
4154
|
+
}
|
|
4155
|
+
);
|
|
4156
|
+
}
|
|
4157
|
+
resolve(null);
|
|
4158
|
+
} else {
|
|
4159
|
+
const rollbarId = data ? data.uuid || data.result?.uuid || null : null;
|
|
4160
|
+
logger$2.info(
|
|
4161
|
+
`${severity === "critical" ? "Critical error" : "Error"} sent to Rollbar`,
|
|
4162
|
+
{
|
|
4163
|
+
message: typeof error === "string" ? error : error?.message || "Unknown error",
|
|
4164
|
+
component: context.component,
|
|
4165
|
+
rollbarId,
|
|
4166
|
+
logCount: allLogs.length
|
|
4167
|
+
}
|
|
4168
|
+
);
|
|
4169
|
+
resolve(rollbarId);
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
);
|
|
4173
|
+
} catch (rollbarError) {
|
|
4174
|
+
logger$2.error(`Failed to send ${severity} error to Rollbar`, {
|
|
4175
|
+
error: rollbarError,
|
|
4176
|
+
originalError: error
|
|
4177
|
+
});
|
|
4178
|
+
resolve(null);
|
|
4052
4179
|
}
|
|
4053
|
-
)
|
|
4180
|
+
}).catch((deviceError) => {
|
|
4181
|
+
logger$2.error(`Failed to get device context for ${severity} error`, {
|
|
4182
|
+
error: deviceError
|
|
4183
|
+
});
|
|
4184
|
+
resolve(null);
|
|
4185
|
+
});
|
|
4186
|
+
});
|
|
4187
|
+
}
|
|
4188
|
+
collectSDKUsage(functionName, result, success, component) {
|
|
4189
|
+
if (!this.rollbar || !this.config?.enabled) return;
|
|
4190
|
+
try {
|
|
4191
|
+
const logLevel = success ? "info" : "warning";
|
|
4192
|
+
this.rollbar[logLevel](`SDK function execution: ${functionName}`, {
|
|
4193
|
+
custom: {
|
|
4194
|
+
type: "sdk_function_execution",
|
|
4195
|
+
functionName,
|
|
4196
|
+
success,
|
|
4197
|
+
component,
|
|
4198
|
+
result: success ? result : void 0,
|
|
4199
|
+
error: !success ? result : void 0,
|
|
4200
|
+
timestamp: Date.now(),
|
|
4201
|
+
url: typeof window !== "undefined" ? window.location?.href : void 0
|
|
4202
|
+
}
|
|
4203
|
+
});
|
|
4204
|
+
logger$2.info("SDK function execution logged", {
|
|
4205
|
+
functionName,
|
|
4206
|
+
success,
|
|
4207
|
+
component
|
|
4208
|
+
});
|
|
4054
4209
|
} catch (error) {
|
|
4055
|
-
|
|
4210
|
+
logger$2.error("Failed to log SDK function execution", {
|
|
4211
|
+
error,
|
|
4212
|
+
functionName,
|
|
4213
|
+
component
|
|
4214
|
+
});
|
|
4215
|
+
}
|
|
4216
|
+
}
|
|
4217
|
+
generateSessionId() {
|
|
4218
|
+
return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
4219
|
+
}
|
|
4220
|
+
async getDeviceContext() {
|
|
4221
|
+
try {
|
|
4222
|
+
if (window?.TitanSDK) {
|
|
4223
|
+
try {
|
|
4224
|
+
const deviceInfo = await window?.TitanSDK?.deviceInfo?.getDeviceInfo?.();
|
|
4225
|
+
return {
|
|
4226
|
+
deviceInfo: deviceInfo ? JSON.stringify(deviceInfo) : "unavailable"
|
|
4227
|
+
};
|
|
4228
|
+
} catch (sdkError) {
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4056
4231
|
return {
|
|
4057
|
-
deviceInfo:
|
|
4058
|
-
tts: DEFAULT_TTS_SETTINGS,
|
|
4059
|
-
tm: DEFAULT_TM_SETTINGS
|
|
4232
|
+
deviceInfo: `OS: ${navigator?.platform || "unknown"}, Browser: ${this.detectBrowserEngine()}, Storage: ${"localStorage" in (window || {})}`
|
|
4060
4233
|
};
|
|
4234
|
+
} catch (error) {
|
|
4235
|
+
return {};
|
|
4061
4236
|
}
|
|
4062
4237
|
}
|
|
4063
|
-
|
|
4064
|
-
|
|
4238
|
+
detectBrowserEngine() {
|
|
4239
|
+
if (typeof navigator === "undefined") return "unknown";
|
|
4240
|
+
const userAgent = navigator.userAgent;
|
|
4241
|
+
if (userAgent.includes("Chrome")) return "Blink";
|
|
4242
|
+
if (userAgent.includes("Firefox")) return "Gecko";
|
|
4243
|
+
if (userAgent.includes("Safari") && !userAgent.includes("Chrome"))
|
|
4244
|
+
return "WebKit";
|
|
4245
|
+
if (userAgent.includes("Edge")) return "EdgeHTML";
|
|
4246
|
+
return "unknown";
|
|
4065
4247
|
}
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
const
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4248
|
+
setupGlobalErrorHandlers() {
|
|
4249
|
+
if (typeof window === "undefined") return;
|
|
4250
|
+
const originalConsoleError = console.error;
|
|
4251
|
+
console.error = (...args) => {
|
|
4252
|
+
originalConsoleError.apply(console, args);
|
|
4253
|
+
const errorArg = args.find(
|
|
4254
|
+
(arg) => arg instanceof Error || typeof arg === "string" && arg.includes("Error")
|
|
4255
|
+
);
|
|
4256
|
+
if (errorArg && this.isSDKError(errorArg) && !this.shouldIgnoreError(errorArg)) {
|
|
4257
|
+
this.reportError(errorArg, {
|
|
4258
|
+
component: "SDK",
|
|
4259
|
+
operation: "console.error"
|
|
4260
|
+
});
|
|
4261
|
+
}
|
|
4077
4262
|
};
|
|
4263
|
+
if (typeof window !== "undefined") {
|
|
4264
|
+
window.addEventListener("error", (event) => {
|
|
4265
|
+
if (this.isSDKError(event.error) && !this.shouldIgnoreError(event.error)) {
|
|
4266
|
+
this.reportError(event.error || event.message, {
|
|
4267
|
+
component: "SDK",
|
|
4268
|
+
operation: "window.onerror"
|
|
4269
|
+
});
|
|
4270
|
+
}
|
|
4271
|
+
});
|
|
4272
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
4273
|
+
if (this.isSDKError(event.reason) && !this.shouldIgnoreError(event.reason)) {
|
|
4274
|
+
this.reportError(event.reason, {
|
|
4275
|
+
component: "SDK",
|
|
4276
|
+
operation: "unhandledrejection"
|
|
4277
|
+
});
|
|
4278
|
+
}
|
|
4279
|
+
});
|
|
4280
|
+
}
|
|
4078
4281
|
}
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
supportMSSmoothStreaming: false,
|
|
4082
|
-
supportMSSInitiator: false,
|
|
4083
|
-
supportMPEG_DASH: "unknown"
|
|
4084
|
-
};
|
|
4085
|
-
}
|
|
4086
|
-
function detect3DUHDSupport() {
|
|
4087
|
-
try {
|
|
4088
|
-
const sysinfoElement = document.createElement("object");
|
|
4089
|
-
sysinfoElement.setAttribute("id", "sysinfo");
|
|
4090
|
-
sysinfoElement.setAttribute("type", "systeminfoobject");
|
|
4091
|
-
document.body.appendChild(sysinfoElement);
|
|
4092
|
-
const sysinfo = sysinfoElement;
|
|
4093
|
-
const result = {
|
|
4094
|
-
support3d: Boolean(sysinfo.has3D),
|
|
4095
|
-
supportUHD: sysinfo.panelinfo?.toLowerCase() === "3840x2160"
|
|
4096
|
-
};
|
|
4097
|
-
return { ...result, supportFHD: true };
|
|
4098
|
-
} catch (error) {
|
|
4099
|
-
return {
|
|
4100
|
-
support3d: false,
|
|
4101
|
-
supportUHD: false,
|
|
4102
|
-
supportFHD: true
|
|
4103
|
-
};
|
|
4282
|
+
isInitialized() {
|
|
4283
|
+
return this.rollbar !== null && this.config?.enabled === true;
|
|
4104
4284
|
}
|
|
4105
4285
|
}
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4286
|
+
const rollbarClient = new RollbarClient();
|
|
4287
|
+
const lastReportedAtByCode = {};
|
|
4288
|
+
const REPORT_THROTTLE_MS = 5e3;
|
|
4289
|
+
function redactAndTrimContext(context) {
|
|
4290
|
+
const result = {};
|
|
4291
|
+
const SENSITIVE_KEYS = /jwt|token|authorization|cookie|password|secret/i;
|
|
4292
|
+
const trimValue = (value) => {
|
|
4293
|
+
if (typeof value === "string") {
|
|
4294
|
+
return value.length > 500 ? `${value.slice(0, 500)}…` : value;
|
|
4295
|
+
}
|
|
4296
|
+
if (Array.isArray(value)) {
|
|
4297
|
+
const limited = value.slice(-50);
|
|
4298
|
+
return limited.map(
|
|
4299
|
+
(v) => typeof v === "string" && v.length > 500 ? `${v.slice(0, 500)}…` : v
|
|
4300
|
+
);
|
|
4110
4301
|
}
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4302
|
+
return value;
|
|
4303
|
+
};
|
|
4304
|
+
Object.keys(context).forEach((key) => {
|
|
4305
|
+
const raw = context[key];
|
|
4306
|
+
if (SENSITIVE_KEYS.test(key)) {
|
|
4307
|
+
result[key] = "[REDACTED]";
|
|
4308
|
+
} else {
|
|
4309
|
+
result[key] = trimValue(raw);
|
|
4116
4310
|
}
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
return { supportOIPF: false };
|
|
4120
|
-
}
|
|
4311
|
+
});
|
|
4312
|
+
return result;
|
|
4121
4313
|
}
|
|
4122
|
-
function
|
|
4314
|
+
function reportCriticalCode(code, component, operation, context = {}) {
|
|
4123
4315
|
try {
|
|
4124
|
-
const
|
|
4125
|
-
const
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
supportEME: false,
|
|
4137
|
-
hasStorage: false
|
|
4316
|
+
const now = Date.now();
|
|
4317
|
+
const last = lastReportedAtByCode[code] || 0;
|
|
4318
|
+
if (now - last < REPORT_THROTTLE_MS) {
|
|
4319
|
+
return Promise.resolve(null);
|
|
4320
|
+
}
|
|
4321
|
+
lastReportedAtByCode[code] = now;
|
|
4322
|
+
const enriched = {
|
|
4323
|
+
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "unknown",
|
|
4324
|
+
component,
|
|
4325
|
+
operation,
|
|
4326
|
+
context: context ? redactAndTrimContext(context) : void 0,
|
|
4327
|
+
version: VERSION
|
|
4138
4328
|
};
|
|
4329
|
+
logger$2.error("SDK_CRITICAL", {
|
|
4330
|
+
code,
|
|
4331
|
+
component,
|
|
4332
|
+
operation,
|
|
4333
|
+
...enriched.context ? { context: enriched.context } : {}
|
|
4334
|
+
});
|
|
4335
|
+
const err = new SDKError(code, ErrorCode.UNKNOWN, {
|
|
4336
|
+
component,
|
|
4337
|
+
operation,
|
|
4338
|
+
...enriched.context ? { context: enriched.context } : {}
|
|
4339
|
+
});
|
|
4340
|
+
return rollbarClient.reportError(err, enriched, "critical");
|
|
4341
|
+
} catch {
|
|
4342
|
+
return Promise.resolve(null);
|
|
4139
4343
|
}
|
|
4140
4344
|
}
|
|
4141
|
-
const
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
const testObject = document.createElement("object");
|
|
4159
|
-
testObject.type = "application/oipfdrmagent";
|
|
4160
|
-
const agent = testObject;
|
|
4161
|
-
if (typeof agent.sendDRMMessage === "function") {
|
|
4162
|
-
return "OIPF";
|
|
4345
|
+
const rollbarClient$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
4346
|
+
__proto__: null,
|
|
4347
|
+
reportCriticalCode,
|
|
4348
|
+
rollbarClient
|
|
4349
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
4350
|
+
const log$l = getLogger("TVPlatform");
|
|
4351
|
+
class TVPlatform extends BasePlatform {
|
|
4352
|
+
// 7 days
|
|
4353
|
+
constructor(config, bridge) {
|
|
4354
|
+
super(config);
|
|
4355
|
+
__publicField(this, "DEFAULT_DEVICE_INFO", {});
|
|
4356
|
+
__publicField(this, "bridge");
|
|
4357
|
+
__publicField(this, "isInitialized", false);
|
|
4358
|
+
__publicField(this, "CACHE_KEY", "titansdk");
|
|
4359
|
+
__publicField(this, "CACHE_EXPIRY", 7 * 24 * 60 * 60 * 1e3);
|
|
4360
|
+
if (bridge) {
|
|
4361
|
+
this.bridge = bridge;
|
|
4163
4362
|
} else {
|
|
4164
|
-
|
|
4363
|
+
const bridgeConfig = {
|
|
4364
|
+
gatewayUrl: this.config.gatewayUrl
|
|
4365
|
+
};
|
|
4366
|
+
this.bridge = new EnhancedBaseBridge(bridgeConfig);
|
|
4165
4367
|
}
|
|
4166
|
-
|
|
4167
|
-
return "";
|
|
4368
|
+
this.initializeBridgeSafely();
|
|
4168
4369
|
}
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4370
|
+
async initializeBridgeSafely() {
|
|
4371
|
+
try {
|
|
4372
|
+
const success = await this.bridge.initialize();
|
|
4373
|
+
if (success) {
|
|
4374
|
+
this.isInitialized = true;
|
|
4375
|
+
}
|
|
4376
|
+
} catch (error) {
|
|
4377
|
+
log$l.warn("Bridge initialization failed:", error);
|
|
4378
|
+
}
|
|
4379
|
+
this.waitReadyResolver(true);
|
|
4178
4380
|
}
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4381
|
+
getFromLocalStorage() {
|
|
4382
|
+
try {
|
|
4383
|
+
if (typeof localStorage === "undefined") {
|
|
4384
|
+
return null;
|
|
4385
|
+
}
|
|
4386
|
+
if (!localStorage.getItem) {
|
|
4387
|
+
return null;
|
|
4388
|
+
}
|
|
4389
|
+
const cached = localStorage.getItem(this.CACHE_KEY);
|
|
4390
|
+
if (!cached) {
|
|
4391
|
+
return null;
|
|
4392
|
+
}
|
|
4393
|
+
const parsed = JSON.parse(cached);
|
|
4394
|
+
if (Date.now() - parsed.timestamp > this.CACHE_EXPIRY || parsed.lastVersion !== VERSION) {
|
|
4395
|
+
localStorage.removeItem(this.CACHE_KEY);
|
|
4396
|
+
return null;
|
|
4397
|
+
}
|
|
4398
|
+
log$l.debug("Device info loaded from localStorage cache");
|
|
4399
|
+
return parsed;
|
|
4400
|
+
} catch (error) {
|
|
4401
|
+
log$l.warn("Failed to load device info from localStorage:", error);
|
|
4402
|
+
return null;
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
getFromURL() {
|
|
4406
|
+
try {
|
|
4407
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
4408
|
+
const titansdkParam = urlParams.get("titandata");
|
|
4409
|
+
if (!titansdkParam) {
|
|
4410
|
+
return null;
|
|
4411
|
+
}
|
|
4412
|
+
let decoded = null;
|
|
4413
|
+
const windowWrapper2 = new WindowWrapper();
|
|
4414
|
+
try {
|
|
4415
|
+
decoded = lzStringExports.decompressFromEncodedURIComponent(titansdkParam);
|
|
4416
|
+
if (decoded) {
|
|
4417
|
+
log$l.debug("Device info loaded from URL parameter (lz-string)");
|
|
4188
4418
|
}
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4419
|
+
} catch (lzError) {
|
|
4420
|
+
log$l.debug("lz-string decompression failed, trying base64");
|
|
4421
|
+
}
|
|
4422
|
+
if (!decoded) {
|
|
4423
|
+
try {
|
|
4424
|
+
const atobFunc = windowWrapper2.get("atob");
|
|
4425
|
+
if (atobFunc) {
|
|
4426
|
+
const urlDecoded = decodeURIComponent(titansdkParam);
|
|
4427
|
+
decoded = atobFunc(urlDecoded);
|
|
4428
|
+
log$l.debug("Device info loaded from URL parameter (base64)");
|
|
4429
|
+
} else {
|
|
4430
|
+
log$l.warn("atob function not available");
|
|
4431
|
+
return null;
|
|
4432
|
+
}
|
|
4433
|
+
} catch (base64Error) {
|
|
4434
|
+
log$l.warn("Both lz-string and base64 decoding failed");
|
|
4435
|
+
return null;
|
|
4193
4436
|
}
|
|
4194
|
-
|
|
4437
|
+
}
|
|
4438
|
+
if (!decoded) {
|
|
4439
|
+
log$l.warn("Failed to decode URL parameter");
|
|
4440
|
+
return null;
|
|
4441
|
+
}
|
|
4442
|
+
const parsed = JSON.parse(decoded);
|
|
4443
|
+
return parsed;
|
|
4444
|
+
} catch (error) {
|
|
4445
|
+
log$l.warn("Failed to load device info from URL parameter:", error);
|
|
4446
|
+
return null;
|
|
4195
4447
|
}
|
|
4196
|
-
|
|
4197
|
-
|
|
4448
|
+
}
|
|
4449
|
+
saveToLocalStorage(data) {
|
|
4198
4450
|
try {
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
}
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4451
|
+
if (typeof localStorage === "undefined") {
|
|
4452
|
+
return;
|
|
4453
|
+
}
|
|
4454
|
+
if (!data || !data.deviceId || !data.brand || !data.model) {
|
|
4455
|
+
log$l.warn("Skipping cache save - invalid or empty device info");
|
|
4456
|
+
return;
|
|
4457
|
+
}
|
|
4458
|
+
const cacheData = {
|
|
4459
|
+
data,
|
|
4460
|
+
timestamp: Date.now(),
|
|
4461
|
+
lastVersion: VERSION
|
|
4462
|
+
};
|
|
4463
|
+
localStorage.setItem(this.CACHE_KEY, JSON.stringify(cacheData));
|
|
4464
|
+
log$l.debug("Device info saved to localStorage cache");
|
|
4465
|
+
} catch (error) {
|
|
4466
|
+
log$l.warn("Failed to save device info to localStorage:", error);
|
|
4206
4467
|
}
|
|
4207
|
-
}
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4468
|
+
}
|
|
4469
|
+
async getBaseDeviceInfo() {
|
|
4470
|
+
const urlData = this.getFromURL();
|
|
4471
|
+
if (urlData) {
|
|
4472
|
+
this.saveToLocalStorage(urlData);
|
|
4473
|
+
this.waitReadyResolver(true);
|
|
4474
|
+
return {
|
|
4475
|
+
deviceInfo: urlData,
|
|
4476
|
+
tts: DEFAULT_TTS_SETTINGS,
|
|
4477
|
+
tm: DEFAULT_TM_SETTINGS
|
|
4478
|
+
};
|
|
4479
|
+
}
|
|
4480
|
+
if (this.config.useCache !== false) {
|
|
4481
|
+
const localStorageData = this.getFromLocalStorage();
|
|
4482
|
+
if (localStorageData) {
|
|
4483
|
+
this.waitReadyResolver(true);
|
|
4484
|
+
return {
|
|
4485
|
+
deviceInfo: localStorageData.data,
|
|
4486
|
+
tts: DEFAULT_TTS_SETTINGS,
|
|
4487
|
+
tm: DEFAULT_TM_SETTINGS
|
|
4488
|
+
};
|
|
4489
|
+
}
|
|
4490
|
+
} else if (this.config.debug) {
|
|
4491
|
+
log$l.debug("Debug mode: skipping cache, fetching fresh data from iframe");
|
|
4492
|
+
}
|
|
4493
|
+
try {
|
|
4494
|
+
await this.waitReady;
|
|
4495
|
+
return await this.bridge.executeWithFallback(
|
|
4496
|
+
async () => {
|
|
4497
|
+
const deviceInfo = await this.bridge.getDeviceInfo();
|
|
4498
|
+
if (!deviceInfo) {
|
|
4499
|
+
throw new Error("Failed to get device info");
|
|
4500
|
+
}
|
|
4501
|
+
if (deviceInfo.deviceInfo) {
|
|
4502
|
+
this.saveToLocalStorage(deviceInfo.deviceInfo);
|
|
4503
|
+
}
|
|
4504
|
+
return deviceInfo;
|
|
4505
|
+
},
|
|
4506
|
+
async () => {
|
|
4507
|
+
log$l.warn("Bridge unavailable, returning fallback device info");
|
|
4508
|
+
const fallbackData = {
|
|
4509
|
+
deviceInfo: null,
|
|
4510
|
+
tts: DEFAULT_TTS_SETTINGS,
|
|
4511
|
+
tm: DEFAULT_TM_SETTINGS
|
|
4512
|
+
};
|
|
4513
|
+
void reportCriticalCode(
|
|
4514
|
+
"SDK_BRIDGE_FALLBACK",
|
|
4515
|
+
"SDK",
|
|
4516
|
+
"bridge.executeWithFallback",
|
|
4517
|
+
{
|
|
4518
|
+
reason: "bridge unavailable",
|
|
4519
|
+
platformId: this.getId(),
|
|
4520
|
+
isInitialized: this.isInitialized
|
|
4521
|
+
}
|
|
4522
|
+
);
|
|
4523
|
+
return fallbackData;
|
|
4216
4524
|
}
|
|
4217
|
-
|
|
4218
|
-
|
|
4525
|
+
);
|
|
4526
|
+
} catch (error) {
|
|
4527
|
+
log$l.warn("Failed to get device info from bridge:", error);
|
|
4528
|
+
void reportCriticalCode(
|
|
4529
|
+
"SDK_BRIDGE_FALLBACK",
|
|
4530
|
+
"SDK",
|
|
4531
|
+
"bridge.executeWithFallback",
|
|
4219
4532
|
{
|
|
4220
|
-
|
|
4533
|
+
reason: "bridge exception",
|
|
4534
|
+
platformId: this.getId(),
|
|
4535
|
+
isInitialized: this.isInitialized,
|
|
4536
|
+
error: error instanceof Error ? error.message : String(error)
|
|
4221
4537
|
}
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
resolve(true);
|
|
4229
|
-
}).catch(() => {
|
|
4230
|
-
resolve(false);
|
|
4231
|
-
});
|
|
4232
|
-
} catch (e) {
|
|
4233
|
-
resolve(false);
|
|
4538
|
+
);
|
|
4539
|
+
return {
|
|
4540
|
+
deviceInfo: null,
|
|
4541
|
+
tts: DEFAULT_TTS_SETTINGS,
|
|
4542
|
+
tm: DEFAULT_TM_SETTINGS
|
|
4543
|
+
};
|
|
4234
4544
|
}
|
|
4235
|
-
}
|
|
4236
|
-
|
|
4237
|
-
|
|
4545
|
+
}
|
|
4546
|
+
isTV() {
|
|
4547
|
+
return typeof window !== "undefined" && (navigator.userAgent.includes("TV") || navigator.userAgent.includes("SmartTV") || navigator.userAgent.includes("SMART-TV") || window.location.href.includes("file://"));
|
|
4548
|
+
}
|
|
4549
|
+
}
|
|
4550
|
+
const oipfWindow = new WindowWrapper();
|
|
4551
|
+
const windowStorage = new WindowWrapper();
|
|
4552
|
+
function detectStreamingSupport() {
|
|
4553
|
+
const video = document.createElement("video");
|
|
4554
|
+
if (!!video.canPlayType && typeof video.canPlayType === "function") {
|
|
4555
|
+
return {
|
|
4556
|
+
supportAppleHLS: video.canPlayType("application/vnd.apple.mpegURL") !== "" || video.canPlayType("audio/mpegurl") !== "",
|
|
4557
|
+
supportMSSmoothStreaming: video.canPlayType("application/vnd.ms-sstr+xml") !== "",
|
|
4558
|
+
supportMSSInitiator: video.canPlayType("application/vnd.ms-playready.initiator+xml") !== "",
|
|
4559
|
+
supportMPEG_DASH: video.canPlayType("application/dash+xml") !== "" || "unknown"
|
|
4560
|
+
};
|
|
4561
|
+
}
|
|
4562
|
+
return {
|
|
4563
|
+
supportAppleHLS: false,
|
|
4564
|
+
supportMSSmoothStreaming: false,
|
|
4565
|
+
supportMSSInitiator: false,
|
|
4566
|
+
supportMPEG_DASH: "unknown"
|
|
4567
|
+
};
|
|
4568
|
+
}
|
|
4569
|
+
function detect3DUHDSupport() {
|
|
4570
|
+
try {
|
|
4571
|
+
const sysinfoElement = document.createElement("object");
|
|
4572
|
+
sysinfoElement.setAttribute("id", "sysinfo");
|
|
4573
|
+
sysinfoElement.setAttribute("type", "systeminfoobject");
|
|
4574
|
+
document.body.appendChild(sysinfoElement);
|
|
4575
|
+
const sysinfo = sysinfoElement;
|
|
4576
|
+
const result = {
|
|
4577
|
+
support3d: Boolean(sysinfo.has3D),
|
|
4578
|
+
supportUHD: sysinfo.panelinfo?.toLowerCase() === "3840x2160"
|
|
4579
|
+
};
|
|
4580
|
+
return { ...result, supportFHD: true };
|
|
4581
|
+
} catch (error) {
|
|
4582
|
+
return {
|
|
4583
|
+
support3d: false,
|
|
4584
|
+
supportUHD: false,
|
|
4585
|
+
supportFHD: true
|
|
4586
|
+
};
|
|
4587
|
+
}
|
|
4588
|
+
}
|
|
4589
|
+
function detectOIPFSupport() {
|
|
4590
|
+
try {
|
|
4591
|
+
if (oipfWindow.get("oipfObjectFactory") !== void 0) {
|
|
4592
|
+
return { supportOIPF: true };
|
|
4593
|
+
}
|
|
4594
|
+
const testObject = document.createElement("object");
|
|
4595
|
+
testObject.type = "application/oipfdrmagent";
|
|
4596
|
+
const agent = testObject;
|
|
4597
|
+
if (typeof agent.sendDRMMessage === "function") {
|
|
4598
|
+
return { supportOIPF: true };
|
|
4599
|
+
}
|
|
4600
|
+
return { supportOIPF: false };
|
|
4601
|
+
} catch (e) {
|
|
4602
|
+
return { supportOIPF: false };
|
|
4603
|
+
}
|
|
4604
|
+
}
|
|
4605
|
+
function detectBrowserCapabilities() {
|
|
4606
|
+
try {
|
|
4607
|
+
const navigatorWrapper = new WindowWrapper();
|
|
4608
|
+
const navigatorObj = navigatorWrapper.get("navigator");
|
|
4609
|
+
const hasRequestMediaKeySystemAccess = navigatorObj !== void 0 && typeof navigatorObj.requestMediaKeySystemAccess === "function";
|
|
4610
|
+
const hasMSMediaKeys = windowStorage.has("MSMediaKeys");
|
|
4611
|
+
return {
|
|
4612
|
+
supportWebSocket: windowStorage.has("WebSocket"),
|
|
4613
|
+
supportEME: hasRequestMediaKeySystemAccess || hasMSMediaKeys,
|
|
4614
|
+
hasStorage: windowStorage.has("localStorage") && windowStorage.has("sessionStorage")
|
|
4615
|
+
};
|
|
4616
|
+
} catch (e) {
|
|
4617
|
+
return {
|
|
4618
|
+
supportWebSocket: false,
|
|
4619
|
+
supportEME: false,
|
|
4620
|
+
hasStorage: false
|
|
4621
|
+
};
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4624
|
+
const mediaKeyWindow = new WindowWrapper();
|
|
4625
|
+
function detectDRMMethodSupport() {
|
|
4626
|
+
let returnString = "";
|
|
4627
|
+
returnString = checkOIPFDRMAgentObj();
|
|
4628
|
+
try {
|
|
4629
|
+
const hasMediaKeys = mediaKeyWindow.has("MediaKeys");
|
|
4630
|
+
const hasWebKitMediaKeys = mediaKeyWindow.has("WebKitMediaKeys");
|
|
4631
|
+
const hasMSMediaKeys = mediaKeyWindow.has("MSMediaKeys");
|
|
4632
|
+
const eme = hasMediaKeys || hasWebKitMediaKeys || hasMSMediaKeys;
|
|
4633
|
+
returnString = eme ? "EME" : returnString;
|
|
4634
|
+
return { drmMethod: returnString };
|
|
4635
|
+
} catch (e) {
|
|
4636
|
+
return { drmMethod: "" };
|
|
4637
|
+
}
|
|
4638
|
+
}
|
|
4639
|
+
function checkOIPFDRMAgentObj() {
|
|
4640
|
+
try {
|
|
4641
|
+
const testObject = document.createElement("object");
|
|
4642
|
+
testObject.type = "application/oipfdrmagent";
|
|
4643
|
+
const agent = testObject;
|
|
4644
|
+
if (typeof agent.sendDRMMessage === "function") {
|
|
4645
|
+
return "OIPF";
|
|
4646
|
+
} else {
|
|
4647
|
+
return "";
|
|
4648
|
+
}
|
|
4649
|
+
} catch (e) {
|
|
4650
|
+
return "";
|
|
4651
|
+
}
|
|
4652
|
+
}
|
|
4653
|
+
function detectEMESupport() {
|
|
4654
|
+
try {
|
|
4655
|
+
const hasMediaKeys = mediaKeyWindow.has("MediaKeys");
|
|
4656
|
+
const hasWebKitMediaKeys = mediaKeyWindow.has("WebKitMediaKeys");
|
|
4657
|
+
const hasMSMediaKeys = mediaKeyWindow.has("MSMediaKeys");
|
|
4658
|
+
return { supportEME: hasMediaKeys || hasWebKitMediaKeys || hasMSMediaKeys };
|
|
4659
|
+
} catch (e) {
|
|
4660
|
+
return { supportEME: false };
|
|
4661
|
+
}
|
|
4662
|
+
}
|
|
4663
|
+
const log$k = getLogger("PhilipsCapabilities");
|
|
4664
|
+
function checkPlayreadySupport() {
|
|
4665
|
+
const config = [
|
|
4666
|
+
{
|
|
4667
|
+
initDataTypes: ["cenc"],
|
|
4668
|
+
audioCapabilities: [
|
|
4669
|
+
{
|
|
4670
|
+
contentType: 'audio/mp4;codecs="mp4a.40.2"'
|
|
4671
|
+
}
|
|
4672
|
+
],
|
|
4673
|
+
videoCapabilities: [
|
|
4674
|
+
{
|
|
4675
|
+
contentType: 'video/mp4;codecs="avc1.42E01E"'
|
|
4676
|
+
}
|
|
4677
|
+
]
|
|
4678
|
+
}
|
|
4679
|
+
];
|
|
4680
|
+
return new Promise((resolve) => {
|
|
4681
|
+
try {
|
|
4682
|
+
navigator.requestMediaKeySystemAccess("com.microsoft.playready", config).then(() => {
|
|
4683
|
+
resolve(true);
|
|
4684
|
+
}).catch(() => {
|
|
4685
|
+
resolve(false);
|
|
4686
|
+
});
|
|
4687
|
+
} catch (e) {
|
|
4688
|
+
resolve(false);
|
|
4689
|
+
}
|
|
4690
|
+
});
|
|
4691
|
+
}
|
|
4692
|
+
function checkWidevineSupport() {
|
|
4693
|
+
const config = [
|
|
4694
|
+
{
|
|
4695
|
+
initDataTypes: ["cenc"],
|
|
4696
|
+
audioCapabilities: [
|
|
4697
|
+
{
|
|
4698
|
+
contentType: 'audio/mp4;codecs="mp4a.40.2"'
|
|
4699
|
+
}
|
|
4700
|
+
],
|
|
4701
|
+
videoCapabilities: [
|
|
4702
|
+
{
|
|
4703
|
+
contentType: 'video/mp4;codecs="avc1.42E01E"'
|
|
4704
|
+
}
|
|
4705
|
+
]
|
|
4706
|
+
}
|
|
4707
|
+
];
|
|
4708
|
+
return new Promise((resolve) => {
|
|
4709
|
+
try {
|
|
4710
|
+
navigator.requestMediaKeySystemAccess("com.widevine.alpha", config).then(() => {
|
|
4711
|
+
resolve(true);
|
|
4712
|
+
}).catch(() => {
|
|
4713
|
+
resolve(false);
|
|
4714
|
+
});
|
|
4715
|
+
} catch (e) {
|
|
4716
|
+
resolve(false);
|
|
4717
|
+
}
|
|
4718
|
+
});
|
|
4719
|
+
}
|
|
4720
|
+
async function getCapabilities$1(_platform) {
|
|
4238
4721
|
const playreadySupported = await checkPlayreadySupport();
|
|
4239
4722
|
const widevineSupported = await checkWidevineSupport();
|
|
4240
4723
|
const capabilities = {
|
|
@@ -4418,6 +4901,16 @@ class PhilipsCompat extends TVPlatform {
|
|
|
4418
4901
|
legacyInfo.Product.platform = platform;
|
|
4419
4902
|
legacyInfo.Product.language = data.deviceInfo.language;
|
|
4420
4903
|
legacyInfo.Product.mac = data.deviceInfo.mac;
|
|
4904
|
+
if (!legacyInfo.Product.mac) {
|
|
4905
|
+
void reportCriticalCode(
|
|
4906
|
+
"SDK_BRIDGE_NO_MAC",
|
|
4907
|
+
"SDK",
|
|
4908
|
+
"formatBridgeResponse",
|
|
4909
|
+
{
|
|
4910
|
+
deviceInfo: data.deviceInfo
|
|
4911
|
+
}
|
|
4912
|
+
);
|
|
4913
|
+
}
|
|
4421
4914
|
legacyInfo.Product.ifa = data.deviceInfo.ifa || "";
|
|
4422
4915
|
legacyInfo.Product.ifaType = data.deviceInfo.ifaType || "";
|
|
4423
4916
|
legacyInfo.Product.year = data.deviceInfo.year || "";
|
|
@@ -4970,7 +5463,7 @@ function getCapabilities(_platform) {
|
|
|
4970
5463
|
};
|
|
4971
5464
|
if (_platform === "MB191") {
|
|
4972
5465
|
capabilities.supportHDR_DV = false;
|
|
4973
|
-
capabilities.supportHDR_HDR10 =
|
|
5466
|
+
capabilities.supportHDR_HDR10 = true;
|
|
4974
5467
|
capabilities.supportDolbyAtmos = false;
|
|
4975
5468
|
}
|
|
4976
5469
|
return {
|
|
@@ -5037,32 +5530,26 @@ class VestelCompat extends TVPlatform {
|
|
|
5037
5530
|
}
|
|
5038
5531
|
async fetchDeviceInfoInternal() {
|
|
5039
5532
|
try {
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
Capability: capabilities
|
|
5055
|
-
};
|
|
5056
|
-
}
|
|
5533
|
+
const bridgeInfo = await this.getBaseDeviceInfo();
|
|
5534
|
+
const legacyInfo = {
|
|
5535
|
+
Channel: this.DEFAULT_DEVICE_INFO.Channel,
|
|
5536
|
+
Product: this.DEFAULT_DEVICE_INFO.Product
|
|
5537
|
+
};
|
|
5538
|
+
const infoWithProduct = this.formatBridgeResponse(bridgeInfo, legacyInfo);
|
|
5539
|
+
const platform = infoWithProduct.Product.platform;
|
|
5540
|
+
const capabilities = getCapabilities(platform);
|
|
5541
|
+
return {
|
|
5542
|
+
...infoWithProduct,
|
|
5543
|
+
Capability: capabilities
|
|
5544
|
+
};
|
|
5545
|
+
} catch (error) {
|
|
5546
|
+
log$c.error("Error getting device info:", error);
|
|
5057
5547
|
const fallbackCapabilities = getCapabilities();
|
|
5058
5548
|
return {
|
|
5059
5549
|
Channel: this.DEFAULT_DEVICE_INFO.Channel,
|
|
5060
5550
|
Product: this.DEFAULT_DEVICE_INFO.Product,
|
|
5061
5551
|
Capability: fallbackCapabilities
|
|
5062
5552
|
};
|
|
5063
|
-
} catch (error) {
|
|
5064
|
-
log$c.error("Error getting device info:", error);
|
|
5065
|
-
throw error;
|
|
5066
5553
|
}
|
|
5067
5554
|
}
|
|
5068
5555
|
formatBridgeResponse(data, legacyInfo) {
|
|
@@ -5420,7 +5907,7 @@ class BrowserAccessibilityService {
|
|
|
5420
5907
|
log$8.info("TM settings updated:", this.tmSettings);
|
|
5421
5908
|
}
|
|
5422
5909
|
}
|
|
5423
|
-
const logger$
|
|
5910
|
+
const logger$1 = getLogger("BrowserPlatform");
|
|
5424
5911
|
class BrowserCompat extends BasePlatform {
|
|
5425
5912
|
constructor(config) {
|
|
5426
5913
|
super(config);
|
|
@@ -5436,7 +5923,7 @@ class BrowserCompat extends BasePlatform {
|
|
|
5436
5923
|
return true;
|
|
5437
5924
|
}
|
|
5438
5925
|
async getDeviceInfo() {
|
|
5439
|
-
logger$
|
|
5926
|
+
logger$1.debug("Getting default device info for browser");
|
|
5440
5927
|
return this.getDefaultDeviceInfo();
|
|
5441
5928
|
}
|
|
5442
5929
|
getDefaultDeviceInfo() {
|
|
@@ -5740,7 +6227,7 @@ class PhilipsOldAccessibilityService {
|
|
|
5740
6227
|
return false;
|
|
5741
6228
|
}
|
|
5742
6229
|
}
|
|
5743
|
-
const logger
|
|
6230
|
+
const logger = getLogger("PhilipsOldPlatform");
|
|
5744
6231
|
class PhilipsOldCompat extends BasePlatform {
|
|
5745
6232
|
constructor(config) {
|
|
5746
6233
|
super(config);
|
|
@@ -5778,484 +6265,206 @@ class PhilipsOldCompat extends BasePlatform {
|
|
|
5778
6265
|
}
|
|
5779
6266
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
5780
6267
|
const philipsPatterns = ["philips", "saphi", "nettv", "tpvision"];
|
|
5781
|
-
return philipsPatterns.some((pattern) => userAgent.includes(pattern));
|
|
5782
|
-
}
|
|
5783
|
-
async getDeviceInfo() {
|
|
5784
|
-
if (this.deviceInfo) {
|
|
5785
|
-
return this.deviceInfo;
|
|
5786
|
-
}
|
|
5787
|
-
if (this.deviceInfoPromise) {
|
|
5788
|
-
return await this.deviceInfoPromise;
|
|
5789
|
-
}
|
|
5790
|
-
this.deviceInfoPromise = this.fetchDeviceInfoInternal();
|
|
5791
|
-
try {
|
|
5792
|
-
const result = await this.deviceInfoPromise;
|
|
5793
|
-
this.deviceInfo = result;
|
|
5794
|
-
return result;
|
|
5795
|
-
} catch (error) {
|
|
5796
|
-
this.deviceInfoPromise = null;
|
|
5797
|
-
throw error;
|
|
5798
|
-
}
|
|
5799
|
-
}
|
|
5800
|
-
async fetchDeviceInfoInternal() {
|
|
5801
|
-
try {
|
|
5802
|
-
if (await this.waitReady) {
|
|
5803
|
-
const bridgeInfo = await this.fetchDeviceInfo();
|
|
5804
|
-
const legacyInfo = {
|
|
5805
|
-
Channel: this.DEFAULT_DEVICE_INFO.Channel,
|
|
5806
|
-
Product: this.DEFAULT_DEVICE_INFO.Product
|
|
5807
|
-
};
|
|
5808
|
-
if (!bridgeInfo) {
|
|
5809
|
-
const capabilities3 = await getCapabilities$1();
|
|
5810
|
-
return {
|
|
5811
|
-
...legacyInfo,
|
|
5812
|
-
Capability: capabilities3
|
|
5813
|
-
};
|
|
5814
|
-
}
|
|
5815
|
-
const formatted = this.formatBridgeResponse(
|
|
5816
|
-
{
|
|
5817
|
-
deviceInfo: bridgeInfo,
|
|
5818
|
-
tts: DEFAULT_TTS_SETTINGS,
|
|
5819
|
-
tm: DEFAULT_TM_SETTINGS
|
|
5820
|
-
},
|
|
5821
|
-
legacyInfo
|
|
5822
|
-
);
|
|
5823
|
-
const platform = formatted.Product.platform;
|
|
5824
|
-
const capabilities2 = await getCapabilities$1(platform);
|
|
5825
|
-
return {
|
|
5826
|
-
...formatted,
|
|
5827
|
-
Capability: capabilities2
|
|
5828
|
-
};
|
|
5829
|
-
}
|
|
5830
|
-
const capabilities = await getCapabilities$1();
|
|
5831
|
-
return {
|
|
5832
|
-
Channel: this.DEFAULT_DEVICE_INFO.Channel,
|
|
5833
|
-
Product: this.DEFAULT_DEVICE_INFO.Product,
|
|
5834
|
-
Capability: capabilities
|
|
5835
|
-
};
|
|
5836
|
-
} catch (error) {
|
|
5837
|
-
logger$1.warn("Error getting device info:", error);
|
|
5838
|
-
throw error;
|
|
5839
|
-
}
|
|
5840
|
-
}
|
|
5841
|
-
async fetchDeviceInfo() {
|
|
5842
|
-
try {
|
|
5843
|
-
const domain = "app.titanos.tv";
|
|
5844
|
-
const backendInfo = await Promise.race([
|
|
5845
|
-
getDeviceInfoFromBackend(
|
|
5846
|
-
null,
|
|
5847
|
-
domain,
|
|
5848
|
-
"zeasn"
|
|
5849
|
-
),
|
|
5850
|
-
new Promise((resolve) => {
|
|
5851
|
-
setTimeout(() => {
|
|
5852
|
-
logger$1.warn("Zeasn backend device info request timed out");
|
|
5853
|
-
resolve(null);
|
|
5854
|
-
}, this.timeout);
|
|
5855
|
-
})
|
|
5856
|
-
]);
|
|
5857
|
-
if (!backendInfo || !backendInfo.datas?.cookies) {
|
|
5858
|
-
return null;
|
|
5859
|
-
}
|
|
5860
|
-
const profileId = backendInfo.datas.cookies.profileid;
|
|
5861
|
-
const deviceInfo = {
|
|
5862
|
-
profileId,
|
|
5863
|
-
deviceId: decodeURIComponent(backendInfo.datas.cookies.deviceid || ""),
|
|
5864
|
-
model: backendInfo.datas.cookies.deviceYear || "",
|
|
5865
|
-
year: backendInfo.datas.cookies.deviceYear || "",
|
|
5866
|
-
firmwareVersion: backendInfo.datas.cookies.ufversion || "",
|
|
5867
|
-
country: backendInfo.datas.cookies.country || "",
|
|
5868
|
-
language: getBrowserLanguage("en"),
|
|
5869
|
-
brand: PlatformName.PHILIPS,
|
|
5870
|
-
platformName: PlatformName.PHILIPS,
|
|
5871
|
-
mac: decodeURIComponent(backendInfo.datas.cookies.mac || ""),
|
|
5872
|
-
ifa: "",
|
|
5873
|
-
ifaType: ""
|
|
5874
|
-
};
|
|
5875
|
-
return deviceInfo;
|
|
5876
|
-
} catch (error) {
|
|
5877
|
-
logger$1.warn("Error fetching device info from backend", error);
|
|
5878
|
-
return null;
|
|
5879
|
-
}
|
|
5880
|
-
}
|
|
5881
|
-
formatBridgeResponse(data, legacyInfo) {
|
|
5882
|
-
let platform = "TitanOS";
|
|
5883
|
-
let firmwareComponentID = "unknown";
|
|
5884
|
-
if (!data.deviceInfo) {
|
|
5885
|
-
return legacyInfo;
|
|
5886
|
-
}
|
|
5887
|
-
if (data.deviceInfo.profileId) {
|
|
5888
|
-
platform = data.deviceInfo.platformName;
|
|
5889
|
-
if (data.deviceInfo.profileId) {
|
|
5890
|
-
var profileInfo = data.deviceInfo.profileId.split("_");
|
|
5891
|
-
platform = (profileInfo[1] || platform).replace(/\d+$/, "");
|
|
5892
|
-
firmwareComponentID = profileInfo[1] ? decodeURIComponent(profileInfo[1]) : "unknown";
|
|
5893
|
-
}
|
|
5894
|
-
}
|
|
5895
|
-
legacyInfo.Product.firmwareVersion = data.deviceInfo.firmwareVersion;
|
|
5896
|
-
legacyInfo.Product.country = data.deviceInfo.country;
|
|
5897
|
-
legacyInfo.Product.deviceID = data.deviceInfo.deviceId;
|
|
5898
|
-
legacyInfo.Product.platform = platform;
|
|
5899
|
-
legacyInfo.Product.language = data.deviceInfo.language;
|
|
5900
|
-
legacyInfo.Product.mac = data.deviceInfo.mac;
|
|
5901
|
-
legacyInfo.Product.ifa = data.deviceInfo.ifa || "";
|
|
5902
|
-
legacyInfo.Product.ifaType = data.deviceInfo.ifaType || "";
|
|
5903
|
-
legacyInfo.Product.year = data.deviceInfo.year || "";
|
|
5904
|
-
legacyInfo.Product.firmwareComponentID = firmwareComponentID;
|
|
5905
|
-
return legacyInfo;
|
|
5906
|
-
}
|
|
5907
|
-
getPriority() {
|
|
5908
|
-
return 100;
|
|
5909
|
-
}
|
|
5910
|
-
getId() {
|
|
5911
|
-
return "philips";
|
|
5912
|
-
}
|
|
5913
|
-
}
|
|
5914
|
-
class PhilipsOldDeviceInfoService {
|
|
5915
|
-
constructor(config) {
|
|
5916
|
-
__publicField(this, "platform");
|
|
5917
|
-
__publicField(this, "info");
|
|
5918
|
-
this.platform = new PhilipsOldCompat(config);
|
|
5919
|
-
this.info = null;
|
|
5920
|
-
}
|
|
5921
|
-
async getDeviceInfo() {
|
|
5922
|
-
const legacyInfo = await this.platform.getDeviceInfo();
|
|
5923
|
-
this.info = legacyInfo;
|
|
5924
|
-
return this.info;
|
|
5925
|
-
}
|
|
5926
|
-
async getCapabilities() {
|
|
5927
|
-
if (!this.info) {
|
|
5928
|
-
this.info = await this.getDeviceInfo();
|
|
5929
|
-
}
|
|
5930
|
-
return this.info.Capability;
|
|
5931
|
-
}
|
|
5932
|
-
}
|
|
5933
|
-
class PhilipsOldAppControlService {
|
|
5934
|
-
async launch(_appId, _deepLink) {
|
|
5935
|
-
return false;
|
|
5936
|
-
}
|
|
5937
|
-
}
|
|
5938
|
-
class PhilipsOldSDK {
|
|
5939
|
-
constructor(options) {
|
|
5940
|
-
__publicField(this, "accessibilityService");
|
|
5941
|
-
__publicField(this, "deviceInfoService");
|
|
5942
|
-
__publicField(this, "appControlService");
|
|
5943
|
-
__publicField(this, "deviceInfo", {
|
|
5944
|
-
getDeviceInfo: () => this.deviceInfoService.getDeviceInfo(),
|
|
5945
|
-
getCapabilities: () => this.deviceInfoService.getCapabilities()
|
|
5946
|
-
});
|
|
5947
|
-
__publicField(this, "accessibility", {
|
|
5948
|
-
enableReader: (config) => this.accessibilityService.enableReader(config),
|
|
5949
|
-
disableReader: () => this.accessibilityService.disableReader(),
|
|
5950
|
-
isTTSSupported: () => this.accessibilityService.isTTSSupported(),
|
|
5951
|
-
isTTSEnabled: () => this.accessibilityService.isTTSEnabled(),
|
|
5952
|
-
isTMEnabled: () => this.accessibilityService.isTMEnabled(),
|
|
5953
|
-
isTextMagnificationSupported: () => this.accessibilityService.isTextMagnificationSupported(),
|
|
5954
|
-
getTTSSettings: async () => convertToPublicSettings(await this.accessibilityService.getTTSSettings()),
|
|
5955
|
-
getTMSettings: async () => convertToPublicSettings(await this.accessibilityService.getTMSettings()),
|
|
5956
|
-
startSpeaking: (text) => this.accessibilityService.startSpeaking(text),
|
|
5957
|
-
stopSpeaking: () => this.accessibilityService.stopSpeaking(),
|
|
5958
|
-
onTTSSettingsChange: (_callback) => {
|
|
5959
|
-
return () => {
|
|
5960
|
-
};
|
|
5961
|
-
},
|
|
5962
|
-
onTMSettingsChange: (_callback) => {
|
|
5963
|
-
return () => {
|
|
5964
|
-
};
|
|
5965
|
-
}
|
|
5966
|
-
});
|
|
5967
|
-
__publicField(this, "apps", {
|
|
5968
|
-
launch: (appId, deepLink) => this.appControlService.launch(appId, deepLink)
|
|
5969
|
-
});
|
|
5970
|
-
this.accessibilityService = new PhilipsOldAccessibilityService();
|
|
5971
|
-
this.deviceInfoService = new PhilipsOldDeviceInfoService(options);
|
|
5972
|
-
this.appControlService = new PhilipsOldAppControlService();
|
|
5973
|
-
}
|
|
5974
|
-
get logging() {
|
|
5975
|
-
return new LoggingService();
|
|
5976
|
-
}
|
|
5977
|
-
async init() {
|
|
5978
|
-
return true;
|
|
5979
|
-
}
|
|
5980
|
-
}
|
|
5981
|
-
const logger = getLogger("RollbarClient");
|
|
5982
|
-
const IGNORED_ERROR_PATTERNS = [
|
|
5983
|
-
"chrome://userjs/",
|
|
5984
|
-
"chrome-extension://",
|
|
5985
|
-
"moz-extension://",
|
|
5986
|
-
"getJWTString",
|
|
5987
|
-
"getjwtstring",
|
|
5988
|
-
"user.js",
|
|
5989
|
-
"userscript",
|
|
5990
|
-
"tampermonkey",
|
|
5991
|
-
"greasemonkey",
|
|
5992
|
-
"can't find variable getjwtstring",
|
|
5993
|
-
"referenceerror: can't find variable: getjwtstring",
|
|
5994
|
-
"unexpected end of json input",
|
|
5995
|
-
"jsonparse"
|
|
5996
|
-
];
|
|
5997
|
-
class RollbarClient {
|
|
5998
|
-
constructor() {
|
|
5999
|
-
__publicField(this, "rollbar", null);
|
|
6000
|
-
__publicField(this, "config", null);
|
|
6001
|
-
__publicField(this, "windowWrapper", new WindowWrapper());
|
|
6002
|
-
}
|
|
6003
|
-
initialize(config) {
|
|
6004
|
-
if (!config.enabled || !config.accessToken) {
|
|
6005
|
-
logger.warn("Rollbar not initialized - disabled or missing access token");
|
|
6006
|
-
return;
|
|
6007
|
-
}
|
|
6008
|
-
try {
|
|
6009
|
-
this.config = config;
|
|
6010
|
-
this.rollbar = new Rollbar({
|
|
6011
|
-
accessToken: config.accessToken,
|
|
6012
|
-
environment: config.environment || getEnvironment(),
|
|
6013
|
-
captureUncaught: true,
|
|
6014
|
-
captureUnhandledRejections: true,
|
|
6015
|
-
verbose: false,
|
|
6016
|
-
reportLevel: "error",
|
|
6017
|
-
captureIp: false,
|
|
6018
|
-
captureUsername: false,
|
|
6019
|
-
captureEmail: false,
|
|
6020
|
-
maxItems: 100,
|
|
6021
|
-
itemsPerMinute: 60,
|
|
6022
|
-
captureLambdaTimeouts: false,
|
|
6023
|
-
endpoint: `${getLogsDomain()}/logs/`,
|
|
6024
|
-
autoInstrument: {
|
|
6025
|
-
network: false,
|
|
6026
|
-
log: false,
|
|
6027
|
-
dom: false,
|
|
6028
|
-
navigation: false,
|
|
6029
|
-
connectivity: false
|
|
6030
|
-
},
|
|
6031
|
-
payload: {
|
|
6032
|
-
client: {
|
|
6033
|
-
javascript: {
|
|
6034
|
-
code_version: "unknown",
|
|
6035
|
-
source_map_enabled: true
|
|
6036
|
-
}
|
|
6037
|
-
}
|
|
6038
|
-
},
|
|
6039
|
-
transform: (payload) => {
|
|
6040
|
-
if (payload.context) {
|
|
6041
|
-
payload.context = `hephaestus-${payload.context}`;
|
|
6042
|
-
}
|
|
6043
|
-
},
|
|
6044
|
-
checkIgnore: (_isUncaught, args, _payload) => {
|
|
6045
|
-
const error = args[0];
|
|
6046
|
-
const errorMessage = typeof error === "string" ? error : error?.message;
|
|
6047
|
-
const errorStack = typeof error === "object" && error ? error.stack : "";
|
|
6048
|
-
const errorString = String(error).toLowerCase();
|
|
6049
|
-
const ignoredPatterns = IGNORED_ERROR_PATTERNS;
|
|
6050
|
-
return ignoredPatterns.some(
|
|
6051
|
-
(pattern) => errorMessage?.toLowerCase().includes(pattern.toLowerCase()) || errorStack?.toLowerCase().includes(pattern.toLowerCase()) || errorString.includes(pattern.toLowerCase())
|
|
6052
|
-
);
|
|
6053
|
-
}
|
|
6054
|
-
});
|
|
6055
|
-
this.setupGlobalErrorHandlers();
|
|
6056
|
-
logger.info("Rollbar initialized successfully", {
|
|
6057
|
-
environment: config.environment
|
|
6058
|
-
});
|
|
6059
|
-
} catch (error) {
|
|
6060
|
-
logger.error("Failed to initialize Rollbar", { error, config });
|
|
6061
|
-
}
|
|
6062
|
-
}
|
|
6063
|
-
shouldIgnoreError(error) {
|
|
6064
|
-
if (!error) return true;
|
|
6065
|
-
const errorMessage = typeof error === "string" ? error : error.message || "";
|
|
6066
|
-
const errorStack = typeof error === "object" ? error.stack || "" : "";
|
|
6067
|
-
const errorString = String(error).toLowerCase();
|
|
6068
|
-
const ignoredPatterns = IGNORED_ERROR_PATTERNS;
|
|
6069
|
-
return ignoredPatterns.some(
|
|
6070
|
-
(pattern) => errorMessage?.toLowerCase().includes(pattern.toLowerCase()) || errorStack?.toLowerCase().includes(pattern.toLowerCase()) || errorString.includes(pattern.toLowerCase())
|
|
6071
|
-
);
|
|
6072
|
-
}
|
|
6073
|
-
async reportError(error, additionalData, severity = "error") {
|
|
6074
|
-
if (!this.rollbar || !this.config?.enabled || !error) {
|
|
6075
|
-
return Promise.resolve(null);
|
|
6076
|
-
}
|
|
6077
|
-
if (this.shouldIgnoreError(error)) {
|
|
6078
|
-
return Promise.resolve(null);
|
|
6079
|
-
}
|
|
6080
|
-
return new Promise((resolve) => {
|
|
6081
|
-
this.getDeviceContext().then((deviceContext) => {
|
|
6082
|
-
try {
|
|
6083
|
-
const allLogs = LogManager.getHistory().filter(
|
|
6084
|
-
(log2) => !log2.module.includes("RollbarClient") && !log2.message.includes("Rollbar") && log2.level !== "debug"
|
|
6085
|
-
).slice(-20);
|
|
6086
|
-
const logsString = allLogs.map(
|
|
6087
|
-
(log2) => `[${log2.timestamp}] ${log2.module}: ${log2.message}${log2.args && log2.args.length > 0 ? "\n Args: " + JSON.stringify(log2.args) : ""}`
|
|
6088
|
-
).join("\n");
|
|
6089
|
-
const context = {
|
|
6090
|
-
logs: logsString,
|
|
6091
|
-
component: additionalData?.component || "SDK",
|
|
6092
|
-
operation: additionalData?.operation,
|
|
6093
|
-
requestId: additionalData?.requestId,
|
|
6094
|
-
timestamp: Date.now(),
|
|
6095
|
-
url: typeof window !== "undefined" ? window.location?.href : void 0,
|
|
6096
|
-
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "unknown",
|
|
6097
|
-
sessionId: this.generateSessionId(),
|
|
6098
|
-
errorStack: typeof error === "object" ? error.stack : void 0,
|
|
6099
|
-
version: typeof window !== "undefined" ? this.windowWrapper.get("TitanSDK")?.VERSION || "unknown" : "unknown",
|
|
6100
|
-
...deviceContext,
|
|
6101
|
-
...additionalData
|
|
6102
|
-
};
|
|
6103
|
-
const rollbarMethod = severity === "critical" ? "critical" : "error";
|
|
6104
|
-
const errorType = severity === "critical" ? "critical_error_with_logs" : "error_with_logs";
|
|
6105
|
-
this.rollbar?.[rollbarMethod](
|
|
6106
|
-
error,
|
|
6107
|
-
{
|
|
6108
|
-
custom: {
|
|
6109
|
-
type: errorType,
|
|
6110
|
-
context,
|
|
6111
|
-
logCount: allLogs.length
|
|
6112
|
-
}
|
|
6113
|
-
},
|
|
6114
|
-
(err, data) => {
|
|
6115
|
-
if (err) {
|
|
6116
|
-
if (!this.shouldIgnoreError(err)) {
|
|
6117
|
-
logger.error(
|
|
6118
|
-
`Failed to send ${severity} error to Rollbar`,
|
|
6119
|
-
{
|
|
6120
|
-
error: err,
|
|
6121
|
-
originalError: error
|
|
6122
|
-
}
|
|
6123
|
-
);
|
|
6124
|
-
}
|
|
6125
|
-
resolve(null);
|
|
6126
|
-
} else {
|
|
6127
|
-
const rollbarId = data ? data.uuid || data.result?.uuid || null : null;
|
|
6128
|
-
logger.info(
|
|
6129
|
-
`${severity === "critical" ? "Critical error" : "Error"} sent to Rollbar`,
|
|
6130
|
-
{
|
|
6131
|
-
message: typeof error === "string" ? error : error?.message || "Unknown error",
|
|
6132
|
-
component: context.component,
|
|
6133
|
-
rollbarId,
|
|
6134
|
-
logCount: allLogs.length
|
|
6135
|
-
}
|
|
6136
|
-
);
|
|
6137
|
-
resolve(rollbarId);
|
|
6138
|
-
}
|
|
6139
|
-
}
|
|
6140
|
-
);
|
|
6141
|
-
} catch (rollbarError) {
|
|
6142
|
-
logger.error(`Failed to send ${severity} error to Rollbar`, {
|
|
6143
|
-
error: rollbarError,
|
|
6144
|
-
originalError: error
|
|
6145
|
-
});
|
|
6146
|
-
resolve(null);
|
|
6147
|
-
}
|
|
6148
|
-
}).catch((deviceError) => {
|
|
6149
|
-
logger.error(`Failed to get device context for ${severity} error`, {
|
|
6150
|
-
error: deviceError
|
|
6151
|
-
});
|
|
6152
|
-
resolve(null);
|
|
6153
|
-
});
|
|
6154
|
-
});
|
|
6268
|
+
return philipsPatterns.some((pattern) => userAgent.includes(pattern));
|
|
6155
6269
|
}
|
|
6156
|
-
|
|
6157
|
-
if (
|
|
6270
|
+
async getDeviceInfo() {
|
|
6271
|
+
if (this.deviceInfo) {
|
|
6272
|
+
return this.deviceInfo;
|
|
6273
|
+
}
|
|
6274
|
+
if (this.deviceInfoPromise) {
|
|
6275
|
+
return await this.deviceInfoPromise;
|
|
6276
|
+
}
|
|
6277
|
+
this.deviceInfoPromise = this.fetchDeviceInfoInternal();
|
|
6158
6278
|
try {
|
|
6159
|
-
const
|
|
6160
|
-
this.
|
|
6161
|
-
|
|
6162
|
-
type: "sdk_function_execution",
|
|
6163
|
-
functionName,
|
|
6164
|
-
success,
|
|
6165
|
-
component,
|
|
6166
|
-
result: success ? result : void 0,
|
|
6167
|
-
error: !success ? result : void 0,
|
|
6168
|
-
timestamp: Date.now(),
|
|
6169
|
-
url: typeof window !== "undefined" ? window.location?.href : void 0
|
|
6170
|
-
}
|
|
6171
|
-
});
|
|
6172
|
-
logger.info("SDK function execution logged", {
|
|
6173
|
-
functionName,
|
|
6174
|
-
success,
|
|
6175
|
-
component
|
|
6176
|
-
});
|
|
6279
|
+
const result = await this.deviceInfoPromise;
|
|
6280
|
+
this.deviceInfo = result;
|
|
6281
|
+
return result;
|
|
6177
6282
|
} catch (error) {
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
functionName,
|
|
6181
|
-
component
|
|
6182
|
-
});
|
|
6283
|
+
this.deviceInfoPromise = null;
|
|
6284
|
+
throw error;
|
|
6183
6285
|
}
|
|
6184
6286
|
}
|
|
6185
|
-
|
|
6186
|
-
return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
6187
|
-
}
|
|
6188
|
-
async getDeviceContext() {
|
|
6287
|
+
async fetchDeviceInfoInternal() {
|
|
6189
6288
|
try {
|
|
6190
|
-
if (
|
|
6191
|
-
|
|
6192
|
-
|
|
6289
|
+
if (await this.waitReady) {
|
|
6290
|
+
const bridgeInfo = await this.fetchDeviceInfo();
|
|
6291
|
+
const legacyInfo = {
|
|
6292
|
+
Channel: this.DEFAULT_DEVICE_INFO.Channel,
|
|
6293
|
+
Product: this.DEFAULT_DEVICE_INFO.Product
|
|
6294
|
+
};
|
|
6295
|
+
if (!bridgeInfo) {
|
|
6296
|
+
const capabilities3 = await getCapabilities$1();
|
|
6193
6297
|
return {
|
|
6194
|
-
|
|
6298
|
+
...legacyInfo,
|
|
6299
|
+
Capability: capabilities3
|
|
6195
6300
|
};
|
|
6196
|
-
} catch (sdkError) {
|
|
6197
6301
|
}
|
|
6302
|
+
const formatted = this.formatBridgeResponse(
|
|
6303
|
+
{
|
|
6304
|
+
deviceInfo: bridgeInfo,
|
|
6305
|
+
tts: DEFAULT_TTS_SETTINGS,
|
|
6306
|
+
tm: DEFAULT_TM_SETTINGS
|
|
6307
|
+
},
|
|
6308
|
+
legacyInfo
|
|
6309
|
+
);
|
|
6310
|
+
const platform = formatted.Product.platform;
|
|
6311
|
+
const capabilities2 = await getCapabilities$1(platform);
|
|
6312
|
+
return {
|
|
6313
|
+
...formatted,
|
|
6314
|
+
Capability: capabilities2
|
|
6315
|
+
};
|
|
6198
6316
|
}
|
|
6317
|
+
const capabilities = await getCapabilities$1();
|
|
6199
6318
|
return {
|
|
6200
|
-
|
|
6319
|
+
Channel: this.DEFAULT_DEVICE_INFO.Channel,
|
|
6320
|
+
Product: this.DEFAULT_DEVICE_INFO.Product,
|
|
6321
|
+
Capability: capabilities
|
|
6201
6322
|
};
|
|
6202
6323
|
} catch (error) {
|
|
6203
|
-
|
|
6324
|
+
logger.warn("Error getting device info:", error);
|
|
6325
|
+
throw error;
|
|
6204
6326
|
}
|
|
6205
6327
|
}
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6328
|
+
async fetchDeviceInfo() {
|
|
6329
|
+
try {
|
|
6330
|
+
const domain = "app.titanos.tv";
|
|
6331
|
+
const backendInfo = await Promise.race([
|
|
6332
|
+
getDeviceInfoFromBackend(
|
|
6333
|
+
null,
|
|
6334
|
+
domain,
|
|
6335
|
+
"zeasn"
|
|
6336
|
+
),
|
|
6337
|
+
new Promise((resolve) => {
|
|
6338
|
+
setTimeout(() => {
|
|
6339
|
+
logger.warn("Zeasn backend device info request timed out");
|
|
6340
|
+
resolve(null);
|
|
6341
|
+
}, this.timeout);
|
|
6342
|
+
})
|
|
6343
|
+
]);
|
|
6344
|
+
if (!backendInfo || !backendInfo.datas?.cookies) {
|
|
6345
|
+
return null;
|
|
6346
|
+
}
|
|
6347
|
+
const profileId = backendInfo.datas.cookies.profileid;
|
|
6348
|
+
const deviceInfo = {
|
|
6349
|
+
profileId,
|
|
6350
|
+
deviceId: decodeURIComponent(backendInfo.datas.cookies.deviceid || ""),
|
|
6351
|
+
model: backendInfo.datas.cookies.deviceYear || "",
|
|
6352
|
+
year: backendInfo.datas.cookies.deviceYear || "",
|
|
6353
|
+
firmwareVersion: backendInfo.datas.cookies.ufversion || "",
|
|
6354
|
+
country: backendInfo.datas.cookies.country || "",
|
|
6355
|
+
language: getBrowserLanguage("en"),
|
|
6356
|
+
brand: PlatformName.PHILIPS,
|
|
6357
|
+
platformName: PlatformName.PHILIPS,
|
|
6358
|
+
mac: decodeURIComponent(backendInfo.datas.cookies.mac || ""),
|
|
6359
|
+
ifa: "",
|
|
6360
|
+
ifaType: ""
|
|
6361
|
+
};
|
|
6362
|
+
return deviceInfo;
|
|
6363
|
+
} catch (error) {
|
|
6364
|
+
logger.warn("Error fetching device info from backend", error);
|
|
6365
|
+
return null;
|
|
6366
|
+
}
|
|
6215
6367
|
}
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
if (
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
});
|
|
6368
|
+
formatBridgeResponse(data, legacyInfo) {
|
|
6369
|
+
let platform = "TitanOS";
|
|
6370
|
+
let firmwareComponentID = "unknown";
|
|
6371
|
+
if (!data.deviceInfo) {
|
|
6372
|
+
return legacyInfo;
|
|
6373
|
+
}
|
|
6374
|
+
if (data.deviceInfo.profileId) {
|
|
6375
|
+
platform = data.deviceInfo.platformName;
|
|
6376
|
+
if (data.deviceInfo.profileId) {
|
|
6377
|
+
var profileInfo = data.deviceInfo.profileId.split("_");
|
|
6378
|
+
platform = (profileInfo[1] || platform).replace(/\d+$/, "");
|
|
6379
|
+
firmwareComponentID = profileInfo[1] ? decodeURIComponent(profileInfo[1]) : "unknown";
|
|
6229
6380
|
}
|
|
6230
|
-
};
|
|
6231
|
-
if (typeof window !== "undefined") {
|
|
6232
|
-
window.addEventListener("error", (event) => {
|
|
6233
|
-
if (!this.shouldIgnoreError(event.error)) {
|
|
6234
|
-
this.reportError(event.error || event.message, {
|
|
6235
|
-
component: "SDK",
|
|
6236
|
-
operation: "window.onerror"
|
|
6237
|
-
});
|
|
6238
|
-
}
|
|
6239
|
-
});
|
|
6240
|
-
window.addEventListener("unhandledrejection", (event) => {
|
|
6241
|
-
if (!this.shouldIgnoreError(event.reason)) {
|
|
6242
|
-
this.reportError(event.reason, {
|
|
6243
|
-
component: "SDK",
|
|
6244
|
-
operation: "unhandledrejection"
|
|
6245
|
-
});
|
|
6246
|
-
}
|
|
6247
|
-
});
|
|
6248
6381
|
}
|
|
6382
|
+
legacyInfo.Product.firmwareVersion = data.deviceInfo.firmwareVersion;
|
|
6383
|
+
legacyInfo.Product.country = data.deviceInfo.country;
|
|
6384
|
+
legacyInfo.Product.deviceID = data.deviceInfo.deviceId;
|
|
6385
|
+
legacyInfo.Product.platform = platform;
|
|
6386
|
+
legacyInfo.Product.language = data.deviceInfo.language;
|
|
6387
|
+
legacyInfo.Product.mac = data.deviceInfo.mac;
|
|
6388
|
+
legacyInfo.Product.ifa = data.deviceInfo.ifa || "";
|
|
6389
|
+
legacyInfo.Product.ifaType = data.deviceInfo.ifaType || "";
|
|
6390
|
+
legacyInfo.Product.year = data.deviceInfo.year || "";
|
|
6391
|
+
legacyInfo.Product.firmwareComponentID = firmwareComponentID;
|
|
6392
|
+
return legacyInfo;
|
|
6249
6393
|
}
|
|
6250
|
-
|
|
6251
|
-
return
|
|
6394
|
+
getPriority() {
|
|
6395
|
+
return 100;
|
|
6396
|
+
}
|
|
6397
|
+
getId() {
|
|
6398
|
+
return "philips";
|
|
6399
|
+
}
|
|
6400
|
+
}
|
|
6401
|
+
class PhilipsOldDeviceInfoService {
|
|
6402
|
+
constructor(config) {
|
|
6403
|
+
__publicField(this, "platform");
|
|
6404
|
+
__publicField(this, "info");
|
|
6405
|
+
this.platform = new PhilipsOldCompat(config);
|
|
6406
|
+
this.info = null;
|
|
6407
|
+
}
|
|
6408
|
+
async getDeviceInfo() {
|
|
6409
|
+
const legacyInfo = await this.platform.getDeviceInfo();
|
|
6410
|
+
this.info = legacyInfo;
|
|
6411
|
+
return this.info;
|
|
6412
|
+
}
|
|
6413
|
+
async getCapabilities() {
|
|
6414
|
+
if (!this.info) {
|
|
6415
|
+
this.info = await this.getDeviceInfo();
|
|
6416
|
+
}
|
|
6417
|
+
return this.info.Capability;
|
|
6418
|
+
}
|
|
6419
|
+
}
|
|
6420
|
+
class PhilipsOldAppControlService {
|
|
6421
|
+
async launch(_appId, _deepLink) {
|
|
6422
|
+
return false;
|
|
6423
|
+
}
|
|
6424
|
+
}
|
|
6425
|
+
class PhilipsOldSDK {
|
|
6426
|
+
constructor(options) {
|
|
6427
|
+
__publicField(this, "accessibilityService");
|
|
6428
|
+
__publicField(this, "deviceInfoService");
|
|
6429
|
+
__publicField(this, "appControlService");
|
|
6430
|
+
__publicField(this, "deviceInfo", {
|
|
6431
|
+
getDeviceInfo: () => this.deviceInfoService.getDeviceInfo(),
|
|
6432
|
+
getCapabilities: () => this.deviceInfoService.getCapabilities()
|
|
6433
|
+
});
|
|
6434
|
+
__publicField(this, "accessibility", {
|
|
6435
|
+
enableReader: (config) => this.accessibilityService.enableReader(config),
|
|
6436
|
+
disableReader: () => this.accessibilityService.disableReader(),
|
|
6437
|
+
isTTSSupported: () => this.accessibilityService.isTTSSupported(),
|
|
6438
|
+
isTTSEnabled: () => this.accessibilityService.isTTSEnabled(),
|
|
6439
|
+
isTMEnabled: () => this.accessibilityService.isTMEnabled(),
|
|
6440
|
+
isTextMagnificationSupported: () => this.accessibilityService.isTextMagnificationSupported(),
|
|
6441
|
+
getTTSSettings: async () => convertToPublicSettings(await this.accessibilityService.getTTSSettings()),
|
|
6442
|
+
getTMSettings: async () => convertToPublicSettings(await this.accessibilityService.getTMSettings()),
|
|
6443
|
+
startSpeaking: (text) => this.accessibilityService.startSpeaking(text),
|
|
6444
|
+
stopSpeaking: () => this.accessibilityService.stopSpeaking(),
|
|
6445
|
+
onTTSSettingsChange: (_callback) => {
|
|
6446
|
+
return () => {
|
|
6447
|
+
};
|
|
6448
|
+
},
|
|
6449
|
+
onTMSettingsChange: (_callback) => {
|
|
6450
|
+
return () => {
|
|
6451
|
+
};
|
|
6452
|
+
}
|
|
6453
|
+
});
|
|
6454
|
+
__publicField(this, "apps", {
|
|
6455
|
+
launch: (appId, deepLink) => this.appControlService.launch(appId, deepLink)
|
|
6456
|
+
});
|
|
6457
|
+
this.accessibilityService = new PhilipsOldAccessibilityService();
|
|
6458
|
+
this.deviceInfoService = new PhilipsOldDeviceInfoService(options);
|
|
6459
|
+
this.appControlService = new PhilipsOldAppControlService();
|
|
6460
|
+
}
|
|
6461
|
+
get logging() {
|
|
6462
|
+
return new LoggingService();
|
|
6463
|
+
}
|
|
6464
|
+
async init() {
|
|
6465
|
+
return true;
|
|
6252
6466
|
}
|
|
6253
6467
|
}
|
|
6254
|
-
const rollbarClient = new RollbarClient();
|
|
6255
|
-
const rollbarClient$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
6256
|
-
__proto__: null,
|
|
6257
|
-
rollbarClient
|
|
6258
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
6259
6468
|
const log$3 = getLogger("SmartTvA_API");
|
|
6260
6469
|
const initializeSmartTvAPI = async (sdk) => {
|
|
6261
6470
|
log$3.info("Initializing SmartTvA_API with TitanSDK");
|
|
@@ -6639,10 +6848,7 @@ let sdkInstance = null;
|
|
|
6639
6848
|
let sdkResult = null;
|
|
6640
6849
|
let initPromise = null;
|
|
6641
6850
|
let cachedDeviceInfo = null;
|
|
6642
|
-
|
|
6643
|
-
accessToken: "",
|
|
6644
|
-
enabled: false
|
|
6645
|
-
});
|
|
6851
|
+
let rollbarInitialized = false;
|
|
6646
6852
|
const ensureInitialized = async () => {
|
|
6647
6853
|
if (!sdkInstance) {
|
|
6648
6854
|
throw new SDKError(
|
|
@@ -6672,6 +6878,15 @@ const getTitanSDK = (options) => {
|
|
|
6672
6878
|
...options
|
|
6673
6879
|
};
|
|
6674
6880
|
globalLogManager.setDebugMode(finalOptions.debug ?? false);
|
|
6881
|
+
if (!rollbarInitialized) {
|
|
6882
|
+
const rollbarToken = "";
|
|
6883
|
+
const rollbarEnabled = false;
|
|
6884
|
+
rollbarClient.initialize({
|
|
6885
|
+
accessToken: rollbarToken,
|
|
6886
|
+
enabled: rollbarEnabled
|
|
6887
|
+
});
|
|
6888
|
+
rollbarInitialized = true;
|
|
6889
|
+
}
|
|
6675
6890
|
const platformResult = platformDetector.detectPlatform(finalOptions);
|
|
6676
6891
|
const platformType = platformResult.platform;
|
|
6677
6892
|
log.info("Platform detected:", platformType);
|