@krx3d/tizentube2 1.30.490 → 1.30.500

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@krx3d/tizentube2",
3
3
  "appName": "TizenTube",
4
- "version": "1.30.490",
4
+ "version": "1.30.500",
5
5
  "description": "TizenTube is an ad-free and sponsor-free solution for your favourite streaming website on your Tizen (Samsung) TVs.",
6
6
  "packageType": "mods",
7
7
  "websiteURL": "https://youtube.com/tv?additionalDataUrl=http%3A%2F%2Flocalhost%3A8085%2Fdial%2Fapps%2FYouTube",
@@ -59,6 +59,83 @@
59
59
  var MAX_BUFFERED_LOGS = 100;
60
60
  var bufferedLogs = [];
61
61
 
62
+ // Every line above goes to the service, which means a service that never
63
+ // answers takes the account of its own failure with it — the reason the
64
+ // 6.5 failure has no capture. These breadcrumbs go to this page's own
65
+ // localStorage instead, which needs nothing and no one, and are handed
66
+ // over the next time the service does answer. So a start that dies
67
+ // silently is read back on the next start that works.
68
+ //
69
+ // This page's origin is the widget's own, so this storage is private to
70
+ // it and survives the TV being switched off. Reinstalling clears it,
71
+ // which is worth knowing: reinstall after a failure and the breadcrumbs
72
+ // go with it.
73
+ var BREADCRUMB_KEY = 'ttStartupBreadcrumbs';
74
+ var MAX_BREADCRUMBS = 40;
75
+ var startedAt = Date.now();
76
+
77
+ function breadcrumb(stage, detail) {
78
+ try {
79
+ var all = [];
80
+ try { all = JSON.parse(window.localStorage.getItem(BREADCRUMB_KEY) || '[]'); } catch (e) { all = []; }
81
+ if (!(all instanceof Array)) all = [];
82
+ all.push({ ts: new Date().toISOString(), at: Date.now() - startedAt, stage: String(stage), detail: detail === undefined ? null : detail });
83
+ while (all.length > MAX_BREADCRUMBS) all.shift();
84
+ window.localStorage.setItem(BREADCRUMB_KEY, JSON.stringify(all));
85
+ } catch (e) { }
86
+ }
87
+
88
+ // Stages a start is meant to end at. Anything else as the last entry
89
+ // means that start never got anywhere.
90
+ var TERMINAL_STAGES = ['cdp-handoff', 'proxy-nav'];
91
+
92
+ function reportPreviousStart() {
93
+ try {
94
+ var all = [];
95
+ try { all = JSON.parse(window.localStorage.getItem(BREADCRUMB_KEY) || '[]'); } catch (e) { return; }
96
+ if (!(all instanceof Array) || !all.length) return;
97
+ window.localStorage.removeItem(BREADCRUMB_KEY);
98
+ var last = all[all.length - 1];
99
+ var ended = TERMINAL_STAGES.indexOf(last.stage) !== -1;
100
+ sendLog(ended ? 'INFO' : 'ERROR',
101
+ 'previous start ' + (ended ? 'reached' : 'DIED AT') + ' "' + last.stage + '"'
102
+ + ' after ' + last.at + 'ms (' + last.ts + '), ' + all.length + ' stages: '
103
+ + JSON.stringify(all));
104
+ } catch (e) { }
105
+ }
106
+
107
+ // The service's own account of itself: uptime above all, which says
108
+ // whether this start is talking to a fresh process or to one that has
109
+ // been up for days. A request that never comes back is the finding.
110
+ function reportServiceHealth() {
111
+ var asked = Date.now();
112
+ var settled = false;
113
+ try {
114
+ var timer = setTimeout(function () {
115
+ if (settled) return;
116
+ settled = true;
117
+ breadcrumb('health-timeout');
118
+ sendLog('ERROR', 'health did not answer within 3000ms - the service holds the port but is not serving');
119
+ }, 3000);
120
+ fetch('http://localhost:8099/tizentube/health')
121
+ .then(function (r) { return r.json(); })
122
+ .then(function (h) {
123
+ if (settled) return;
124
+ settled = true;
125
+ clearTimeout(timer);
126
+ breadcrumb('health-ok', h.uptimeSec);
127
+ sendLog('INFO', 'service health after ' + (Date.now() - asked) + 'ms: ' + JSON.stringify(h));
128
+ })
129
+ .catch(function (e) {
130
+ if (settled) return;
131
+ settled = true;
132
+ clearTimeout(timer);
133
+ breadcrumb('health-unreachable');
134
+ sendLog('INFO', 'health unreachable (normal before the service is up): ' + (e && e.message || e));
135
+ });
136
+ } catch (e) { }
137
+ }
138
+
62
139
  function postLog(entry) {
63
140
  return fetch('http://localhost:8099/tizentube/log', {
64
141
  method: 'POST',
@@ -101,6 +178,8 @@
101
178
  }
102
179
 
103
180
  sendLog('INFO', 'index.html script started');
181
+ reportPreviousStart();
182
+ breadcrumb('script-started');
104
183
 
105
184
  tizen.tvinputdevice.registerKey("ColorF0Red");
106
185
  tizen.tvinputdevice.registerKey("ColorF1Green");
@@ -157,10 +236,12 @@
157
236
  sendLog('INFO', 'getState resolved: ' + JSON.stringify(res));
158
237
  if (res.canConnectToDaemon && !res.isConnecting) {
159
238
  sendLog('INFO', 'Taking CDP-injection path, launching debugger and exiting');
239
+ breadcrumb('cdp-handoff');
160
240
  fetch(`http://localhost:8099/tizentube/debugger${args ? `?${args}` : ''}`);
161
241
  tizen.application.getCurrentApplication().exit();
162
242
  } else if (!res.canConnectToDaemon) {
163
243
  sendLog('INFO', 'Taking proxy path, navigating to localhost:8099/tv');
244
+ breadcrumb('proxy-nav');
164
245
  location.href = `http://localhost:8099/tv?additionalDataUrl=http%3A%2F%2Flocalhost%3A8095%2Fdial%2Fapps%2FYouTube${args ? `&${args}` : ''}`
165
246
  } else if (connectingPolls < MAX_CONNECTING_POLLS) {
166
247
  // canConnectToDaemon && isConnecting: a connection attempt is
@@ -179,6 +260,7 @@
179
260
  // fall back to the proxy instead of sitting on the splash
180
261
  // screen indefinitely, which is what this state used to do.
181
262
  sendLog('ERROR', 'isConnecting still true after ' + MAX_CONNECTING_POLLS + ' polls, falling back to proxy path');
263
+ breadcrumb('proxy-nav', 'after isConnecting gave up');
182
264
  location.href = `http://localhost:8099/tv?additionalDataUrl=http%3A%2F%2Flocalhost%3A8095%2Fdial%2Fapps%2FYouTube${args ? `&${args}` : ''}`
183
265
  }
184
266
  }).catch((err) => {
@@ -196,6 +278,7 @@
196
278
  return;
197
279
  }
198
280
  sendLog('ERROR', 'getState still failing after ' + MAX_STARTUP_RETRIES + ' retries, reloading: ' + (err && err.message || err));
281
+ breadcrumb('getState-gave-up', String(err && err.message || err));
199
282
  window.location.reload();
200
283
  });
201
284
  }
@@ -322,11 +405,14 @@
322
405
 
323
406
  function launchService() {
324
407
  sendLog('INFO', 'Launching StandaloneService via launchAppControl');
408
+ breadcrumb('launch-service');
325
409
  tizen.application.launchAppControl(
326
410
  new tizen.ApplicationControl("http://tizen.org/appcontrol/operation/service"),
327
411
  serviceId,
328
412
  function () {
329
413
  sendLog('INFO', 'launchAppControl success callback fired');
414
+ breadcrumb('service-launched');
415
+ reportServiceHealth();
330
416
  waitForNetworkThen(useInjectorOrProxy);
331
417
  },
332
418
  function (e) {
@@ -337,6 +423,7 @@
337
423
  // below which already retries automatically. User had
338
424
  // to manually close/reopen the app to get past it.
339
425
  // Retry the same way instead.
426
+ breadcrumb('launch-failed', String(e && e.message || e));
340
427
  sendLog('ERROR', 'launchAppControl failed, retrying in 1s: ' + e.message);
341
428
  setTimeout(launchService, 1000);
342
429
  }