From 103ae5997a93340b810a60b043aafecf404a06b4 Mon Sep 17 00:00:00 2001 From: reisxd <29177546+reisxd@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:56:20 +0300 Subject: [PATCH] fix: fix invalid json, module not found and more --- tizenbrew-app/TizenBrew/config.xml | 3 +- tizenbrew-app/TizenBrew/index.html | 5 +- tizenbrew-app/TizenBrew/js/wsClient.js | 68 +++++++++--------- .../TizenBrew/service/moduleLoader.js | 35 +++++---- .../TizenBrew/service/package-lock.json | 29 +++++++- tizenbrew-app/TizenBrew/service/package.json | 3 +- tizenbrew-app/TizenBrew/service/service.js | 71 +++++++++++++------ .../TizenBrew/service/serviceLauncher.js | 30 +++++--- tizenbrew-updater/TizenBrewUpdater/config.xml | 2 +- .../TizenBrewUpdater/js/wsClient.js | 5 +- 10 files changed, 163 insertions(+), 88 deletions(-) diff --git a/tizenbrew-app/TizenBrew/config.xml b/tizenbrew-app/TizenBrew/config.xml index 6866448..852cd3a 100644 --- a/tizenbrew-app/TizenBrew/config.xml +++ b/tizenbrew-app/TizenBrew/config.xml @@ -1,5 +1,5 @@ - + @@ -19,7 +19,6 @@ - TizenBrewStandalone diff --git a/tizenbrew-app/TizenBrew/index.html b/tizenbrew-app/TizenBrew/index.html index a5c374c..4560014 100644 --- a/tizenbrew-app/TizenBrew/index.html +++ b/tizenbrew-app/TizenBrew/index.html @@ -121,10 +121,7 @@ break; } - if (packageType === 'service' || packageType === 'service-mods') { - window.send({ type: "startService", package: { name: packageName, type: moduleType } }); - } - window.send({ type: "launch", package: { name: packageName, type: moduleType }, isTizen3, tvIp: webapis.network.getIp() }); + window.send({ type: "launch", package: `${moduleType}/${packageName}`, tvIp: webapis.network.getIp() }); var keys = selectedItem.getAttribute("data-keys"); if (appPath.startsWith("http")) { if (keys.length > 0) { diff --git a/tizenbrew-app/TizenBrew/js/wsClient.js b/tizenbrew-app/TizenBrew/js/wsClient.js index a7b383b..d01a372 100644 --- a/tizenbrew-app/TizenBrew/js/wsClient.js +++ b/tizenbrew-app/TizenBrew/js/wsClient.js @@ -4,6 +4,7 @@ let client; const isTizen3 = navigator.userAgent.includes('Tizen 3.0'); let canLaunchModules = false; let canAutoLaunch = true; +let loadedModules = false; function connect() { const ip = localStorage.getItem('ip'); @@ -49,7 +50,7 @@ function onMessage(msg) { hideError(); localStorage.setItem('failedStartupAttempts', '0'); canLaunchModules = message.inDebug.webDebug; - send({ type: 'loadModules', modules: JSON.parse(localStorage.getItem('modules')) }); + send({ type: 'loadModules', modules: JSON.parse(localStorage.getItem('modules')).map(item => `${item.type}/${item.name}`) }); if (localStorage.getItem('autoLaunchService')) { send({ type: 'startService', package: JSON.parse(localStorage.getItem('autoLaunchService')) }); } @@ -76,6 +77,10 @@ function onMessage(msg) { `; firstOne = false; } + loadedModules = true; + if (canLaunchModules && localStorage.getItem('autoLaunch')) { + autoLaunchModule(); + } window.selectedItem = document.querySelector(".selected"); window.currentRow = selectedItem.parentElement.parentElement; } else { @@ -116,12 +121,8 @@ function onMessage(msg) { }); } - if (message.appControlData.module.serviceFile) { - send({ type: 'startService', package: { name: moduleName, type: moduleType } }); - } - setTimeout(() => { - send({ type: 'launch', package: { name: moduleName, type: moduleType }, isTizen3, tvIp: webapis.network.getIp() }); + send({ type: 'launch', package: `${moduleType}/${moduleName}`, tvIp: webapis.network.getIp() }); if (!tizenAppId) { location.href = `${appPath}${args ? `?${args}` : ''}`; } @@ -130,34 +131,8 @@ function onMessage(msg) { } if (canAutoLaunch && localStorage.getItem('autoLaunch')) { - const autoLaunch = JSON.parse(localStorage.getItem('autoLaunch')); - const app = document.querySelector(`[data-packagename="${autoLaunch.name}"]`); - if (!app) { - showError(`Error: Could not find the module ${autoLaunch.name}.`); - return; - } else { - const appPath = app.getAttribute('data-appPath'); - let keys = app.getAttribute("data-keys"); - if (keys.length > 0) { - keys = selectedItem.getAttribute("data-keys").split(','); - for (var i = 0; i < keys.length; i++) { - tizen.tvinputdevice.registerKey(keys[i]); - } - } - - var packageType = selectedItem.getAttribute("data-packageType"); - - if (packageType === 'service' || packageType === 'service-mods') { - send({ type: "startService", package: autoLaunch }); - } - - setTimeout(() => { - send({ type: 'launch', package: autoLaunch, isTizen3, tvIp: webapis.network.getIp() }); - if (app.getAttribute('data-moddedTizenApp') === 'false') { - location.href = appPath; - } - }, 250); - } + if (!loadedModules) return; + autoLaunchModule(); } break; } @@ -204,4 +179,29 @@ function onOpen() { send({ type: 'getDebugStatus' }); } } else send({ type: 'getDebugStatus' }); +} + +function autoLaunchModule() { + const autoLaunch = JSON.parse(localStorage.getItem('autoLaunch')); + const app = document.querySelector(`[data-packagename="${autoLaunch.name}"]`); + if (!app) { + showError(`Error: Could not find the module ${autoLaunch.name}.`); + return; + } else { + const appPath = app.getAttribute('data-appPath'); + let keys = app.getAttribute("data-keys"); + if (keys.length > 0) { + keys = selectedItem.getAttribute("data-keys").split(','); + for (var i = 0; i < keys.length; i++) { + tizen.tvinputdevice.registerKey(keys[i]); + } + } + + setTimeout(() => { + send({ type: 'launch', package: `${autoLaunch.type}/${autoLaunch.name}`, tvIp: webapis.network.getIp() }); + if (app.getAttribute('data-moddedTizenApp') === 'false') { + location.href = appPath; + } + }, 250); + } } \ No newline at end of file diff --git a/tizenbrew-app/TizenBrew/service/moduleLoader.js b/tizenbrew-app/TizenBrew/service/moduleLoader.js index 3cbbf42..7121b5d 100644 --- a/tizenbrew-app/TizenBrew/service/moduleLoader.js +++ b/tizenbrew-app/TizenBrew/service/moduleLoader.js @@ -4,34 +4,42 @@ const fetch = require('node-fetch'); function loadModules(moduleList) { const modulePromises = moduleList.map(module => { - return fetch(`https://cdn.jsdelivr.net/${module.type}/${module.name}/package.json`) + return fetch(`https://cdn.jsdelivr.net/${module}/package.json`) .then(res => res.json()) .then(moduleJson => { let moduleData; + const splitData = [ + module.substring(0, module.indexOf('/')), + module.substring(module.indexOf('/') + 1) + ]; + const moduleMetadata = { + name: splitData[1], + type: splitData[0] + } if (moduleJson.packageType === 'app') { moduleData = { - name: module.name, + name: moduleMetadata.name, appName: moduleJson.appName, description: moduleJson.description, packageType: moduleJson.packageType, - appPath: `http://127.0.0.1:8081/module/${module.type}/${encodeURIComponent(module.name)}/${moduleJson.appPath}`, + appPath: `http://127.0.0.1:8081/module/${encodeURIComponent(module)}/${moduleJson.appPath}`, keys: moduleJson.keys || [], - moduleType: module.type + moduleType: moduleMetadata.type }; } else if (moduleJson.packageType === 'service') { moduleData = { - name: module.name, + name: moduleMetadata.name, appName: moduleJson.appName, description: moduleJson.description, packageType: moduleJson.packageType, serviceFile: moduleJson.serviceFile, - appPath: `http://127.0.0.1:8081/module/${module.type}/${encodeURIComponent(module.name)}/${moduleJson.appPath}`, + appPath: `http://127.0.0.1:8081/module/${encodeURIComponent(module)}/${moduleJson.appPath}`, keys: moduleJson.keys || [], - moduleType: module.type + moduleType: moduleMetadata.type }; } else { moduleData = { - name: module.name, + name: moduleMetadata.name, appName: moduleJson.appName, description: moduleJson.description, appPath: moduleJson.websiteURL, @@ -40,20 +48,21 @@ function loadModules(moduleList) { mainFile: moduleJson.main, keys: moduleJson.keys || [], tizenAppId: moduleJson.tizenAppId, - moduleType: module.type + moduleType: moduleMetadata.type }; } return moduleData; }) .catch(e => { + console.error(e); return { - appName: module.name, - name: module.name, + appName: 'Unknown Module', + name: module, appPath: '', keys: [], - moduleType: module.type, + moduleType: moduleMetadata.type, packageType: 'app', - description: `Unknown module ${module.name}. Please check the module name and try again.` + description: `Unknown module ${module}. Please check the module name and try again.` } }); }); diff --git a/tizenbrew-app/TizenBrew/service/package-lock.json b/tizenbrew-app/TizenBrew/service/package-lock.json index 295fcef..2b32300 100644 --- a/tizenbrew-app/TizenBrew/service/package-lock.json +++ b/tizenbrew-app/TizenBrew/service/package-lock.json @@ -8,7 +8,8 @@ "adbhost": "^0.0.2", "express": "^4.19.2", "node-fetch": "^2.7.0", - "ws": "^4.1.0" + "ws-new": "npm:ws@^7.5.10", + "ws-old": "npm:ws@^4.1.0" } }, "node_modules/accepts": { @@ -740,7 +741,29 @@ "webidl-conversions": "^3.0.0" } }, - "node_modules/ws": { + "node_modules/ws-new": { + "name": "ws", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/ws-old": { + "name": "ws", "version": "4.1.0", "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", @@ -749,7 +772,7 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/ws/node_modules/safe-buffer": { + "node_modules/ws-old/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" diff --git a/tizenbrew-app/TizenBrew/service/package.json b/tizenbrew-app/TizenBrew/service/package.json index a9c7112..4617c0f 100644 --- a/tizenbrew-app/TizenBrew/service/package.json +++ b/tizenbrew-app/TizenBrew/service/package.json @@ -3,6 +3,7 @@ "adbhost": "^0.0.2", "express": "^4.19.2", "node-fetch": "^2.7.0", - "ws": "^4.1.0" + "ws-new": "npm:ws@^7.5.10", + "ws-old": "npm:ws@^4.1.0" } } diff --git a/tizenbrew-app/TizenBrew/service/service.js b/tizenbrew-app/TizenBrew/service/service.js index cec0607..5d72e95 100644 --- a/tizenbrew-app/TizenBrew/service/service.js +++ b/tizenbrew-app/TizenBrew/service/service.js @@ -6,7 +6,12 @@ module.exports.onStart = function () { console.log('Service started.'); const adbhost = require('adbhost'); const express = require('express'); - const WebSocket = require('ws'); + let WebSocket; + if (process.version === 'v4.4.3') { + WebSocket = require('ws-old'); + } else { + WebSocket = require('ws-new'); + } const startDebugging = require('./debugger.js'); const fetch = require('node-fetch'); const loadModules = require('./moduleLoader.js'); @@ -18,16 +23,15 @@ module.exports.onStart = function () { app.all('*', (req, res) => { if (req.url.startsWith('/module/')) { const splittedUrl = req.url.split('/'); - const moduleType = splittedUrl[2]; - const encodedModuleName = splittedUrl[3]; + const encodedModuleName = splittedUrl[2]; const moduleName = decodeURIComponent(encodedModuleName); - fetch(`https://cdn.jsdelivr.net/${moduleType}/${moduleName}/${req.url.replace(`/module/${moduleType}/${encodedModuleName}/`, '')}`) + fetch(`https://cdn.jsdelivr.net/${moduleName}/${req.url.replace(`/module/${encodedModuleName}/`, '')}`) .then(fetchRes => { return fetchRes.body.pipe(res); }) .then(() => { res.setHeader('Access-Control-Allow-Origin', '*'); - res.type(path.basename(req.url.replace(`/module/${moduleType}/${encodedModuleName}/`, '')).split('.').slice(-1)[0].split('?')[0]); + res.type(path.basename(req.url.replace(`/module/${encodedModuleName}/`, '')).split('.').slice(-1)[0].split('?')[0]); }); } else { res.send('Hello from TizenBrew Standalone Service!'); @@ -65,7 +69,7 @@ module.exports.onStart = function () { adb._stream.on('connect', () => { console.log('ADB connection established'); //Launch app - const tbPackageId = tizen.application.getAppInfo().packageId; + const tbPackageId = tizen.application.getAppInfo().packageId; const shellCmd = adb.createStream(`shell:0 debug ${appId ? appId : `${tbPackageId}.TizenBrewStandalone`}${isTizen3 ? ' 0' : ''}`); shellCmd.on('data', function dataIncoming(data) { const dataString = data.toString(); @@ -98,7 +102,11 @@ module.exports.onStart = function () { switch (message.type) { case 'launchAppControl': { loadModules([message.package]).then(modules => { - const module = modules.find(m => m.name === message.package.name); + const moduleList = [ + message.package.substring(0, message.package.indexOf('/')), + message.package.substring(message.package.indexOf('/') + 1) + ]; + const module = modules.find(m => m.name === moduleList[1]); if (!module) { ws.send(JSON.stringify({ type: 'error', message: 'Module not found.' })); return; @@ -126,7 +134,8 @@ module.exports.onStart = function () { } case 'relaunchInDebug': { setTimeout(() => { - createAdbConnection(message.isTizen3, message.tvIp); + const isTizen3 = tizen.systeminfo.getCapability('http://tizen.org/feature/platform.version').split('.')[0] === '3'; + createAdbConnection(isTizen3, message.tvIp); }, 1000); break; } @@ -138,7 +147,11 @@ module.exports.onStart = function () { } case 'launch': { loadModules([message.package]).then(modules => { - const module = modules.find(m => m.name === message.package.name); + const moduleList = [ + message.package.substring(0, message.package.indexOf('/')), + message.package.substring(message.package.indexOf('/') + 1) + ]; + const module = modules.find(m => m.name === moduleList[1]); if (!module) { ws.send(JSON.stringify({ type: 'error', message: 'Module not found.' })); return; @@ -146,16 +159,27 @@ module.exports.onStart = function () { if (module.packageType === 'mods') { global.currentModule = { type: 'mods', - path: `https://cdn.jsdelivr.net/${message.package.type}/${message.package.name}/${module.mainFile}` + path: `https://cdn.jsdelivr.net/${message.package}/${module.mainFile}` + } + + if (module.serviceFile) { + if (global.services.has(message.package)) { + if (global.services.get(message.package).hasCrashed) { + global.services.delete(message.package); + startService(module, message.package); + } else ws.send(JSON.stringify({ type: 'error', message: 'Service already running.' })); + } else startService(module, message.package); } if (module.tizenAppId) { - createAdbConnection(message.isTizen3, message.tvIp, module.tizenAppId); + const isTizen3 = tizen.systeminfo.getCapability('http://tizen.org/feature/platform.version').split('.')[0] === '3'; + // TODO: Get TV IP from os.networkInterfaces() + createAdbConnection(isTizen3, message.tvIp, module.tizenAppId); } } else { global.currentModule = { type: 'app', - path: `http://127.0.0.1:8081/module/${message.package.type}/${encodeURIComponent(message.package.name)}/${module.appPath}` + path: `http://127.0.0.1:8081/module/${encodeURIComponent(message.package)}/${module.appPath}` } global.inDebug.tizenDebug = false; @@ -166,17 +190,21 @@ module.exports.onStart = function () { } case 'startService': { loadModules([message.package]).then(modules => { - const module = modules.find(m => m.name === message.package.name); + const moduleList = [ + message.package.substring(0, message.package.indexOf('/')), + message.package.substring(message.package.indexOf('/') + 1) + ]; + const module = modules.find(m => m.name === moduleList[1]); if (!module) { ws.send(JSON.stringify({ type: 'error', message: 'Module not found.' })); return; } - if (global.services.has(message.package.name)) { - if (global.services.get(message.package.name).hasCrashed) { - global.services.delete(message.package.name); - startService(module, message.package.type); + if (global.services.has(message.package)) { + if (global.services.get(message.package).hasCrashed) { + global.services.delete(message.package); + startService(module, message.package); } else ws.send(JSON.stringify({ type: 'error', message: 'Service already running.' })); } else startService(module, message.package); }); @@ -184,12 +212,13 @@ module.exports.onStart = function () { } case 'getServiceStatuses': { const serviceList = []; - global.services.forEach((key, value) => { + for (const map of global.services) { serviceList.push({ - name: key, - hasCrashed: value.hasCrashed + name: map[0], + hasCrashed: map[1].hasCrashed, + error: map[1].error }); - }); + } ws.send(JSON.stringify({ type: 'serviceStatuses', services: serviceList })); break; } diff --git a/tizenbrew-app/TizenBrew/service/serviceLauncher.js b/tizenbrew-app/TizenBrew/service/serviceLauncher.js index f152cd4..57f5f8f 100644 --- a/tizenbrew-app/TizenBrew/service/serviceLauncher.js +++ b/tizenbrew-app/TizenBrew/service/serviceLauncher.js @@ -8,26 +8,40 @@ function startService(module, pkg) { Object.getOwnPropertyNames(global).forEach(prop => { const disAllowed = ['services', 'module', 'global', 'inDebug', 'currentClient', 'currentModule']; - if (disAllowed.includes(prop)) return; + // Node.js v4.4.3 does not have Array.prototype.includes... + if (disAllowed.indexOf(prop) >= 0) return; sandbox[prop] = global[prop]; }); sandbox['require'] = require; sandbox['module'] = { exports: {} }; - - fetch(`https://cdn.jsdelivr.net/${pkg.type}/${pkg.name}/${module.serviceFile}`) + fetch(`https://cdn.jsdelivr.net/${pkg}/${module.serviceFile}`) .then(res => res.text()) .then(script => { - global.services.set(pkg.name, { + global.services.set(pkg, { context: vm.createContext(sandbox), - hasCrashed: false + hasCrashed: false, + error: null }); + try { - vm.runInContext(script, global.services.get(pkg.name).context); + vm.runInContext(script, global.services.get(pkg).context); } catch (e) { - console.error(e); - global.services.get(pkg.name).hasCrashed = true; + global.services.get(pkg).hasCrashed = true; + global.services.get(pkg).error = e; + } + }) + .catch(e => { + if (global.services.has(pkg)) { + global.services.get(pkg).hasCrashed = true; + global.services.get(pkg).error = e; + } else { + global.services.set(pkg, { + context: null, + hasCrashed: true, + error: e + }); } }); } diff --git a/tizenbrew-updater/TizenBrewUpdater/config.xml b/tizenbrew-updater/TizenBrewUpdater/config.xml index 09cadc5..a11643c 100644 --- a/tizenbrew-updater/TizenBrewUpdater/config.xml +++ b/tizenbrew-updater/TizenBrewUpdater/config.xml @@ -1,6 +1,6 @@ + version="1.0.2" viewmodes="maximized"> diff --git a/tizenbrew-updater/TizenBrewUpdater/js/wsClient.js b/tizenbrew-updater/TizenBrewUpdater/js/wsClient.js index 4b1c66d..5f680f6 100644 --- a/tizenbrew-updater/TizenBrewUpdater/js/wsClient.js +++ b/tizenbrew-updater/TizenBrewUpdater/js/wsClient.js @@ -73,7 +73,10 @@ function onMessage(msg) { case 'message': { document.getElementById('wsText').innerText = message.msg; if (message.msg === 'App installed') { - alert('TizenBrew has been installed. You can find TizenBrew by going into the app store and clicking the settings icon.'); + const sponsor = confirm('TizenBrew has been installed. You can find TizenBrew by going into the app store and clicking the settings icon..\n\nYou can support the development of TizenBrew by sponsoring reisxd.\nWould you like to do it?'); + if (sponsor) { + window.open('https://github.com/sponsors/reisxd'); + } } break; }