From 5643fd8c0f128c97d59e174bf1eae9fc3544cd04 Mon Sep 17 00:00:00 2001 From: reis <29177546+reisxd@users.noreply.github.com> Date: Tue, 9 Jul 2024 20:13:53 +0300 Subject: [PATCH] feat: service mods, launching modules externally This commit includes: - Services for mods - Launching modules externally from an another application - Bug fixes for TizenBrew and Updater --- .github/workflows/build-new-release.yaml | 2 +- docs/MODULES.md | 1 + tizenbrew-app/TizenBrew/config.xml | 2 +- tizenbrew-app/TizenBrew/index.html | 2 +- tizenbrew-app/TizenBrew/js/wsClient.js | 67 +++++++++++++------ tizenbrew-app/TizenBrew/moduleManager.html | 7 +- tizenbrew-app/TizenBrew/service/debugger.js | 3 +- .../TizenBrew/service/moduleLoader.js | 6 ++ tizenbrew-app/TizenBrew/service/service.js | 18 +++++ .../TizenBrew/service/serviceLauncher.js | 10 +-- tizenbrew-updater/TizenBrewUpdater/config.xml | 2 +- .../TizenBrewUpdater/service/service.js | 3 +- 12 files changed, 89 insertions(+), 34 deletions(-) diff --git a/.github/workflows/build-new-release.yaml b/.github/workflows/build-new-release.yaml index a48617e..afba6ca 100644 --- a/.github/workflows/build-new-release.yaml +++ b/.github/workflows/build-new-release.yaml @@ -117,7 +117,7 @@ jobs: - name: Package Updater for Desktop working-directory: tizenbrew-updater/TizenBrewUpdater run: | - pkg -C GZip . + pkg -C GZip . --no-bytecode --public - name: Upload TizenBrew package artifact for Old Tizen uses: actions/upload-artifact@v2 diff --git a/docs/MODULES.md b/docs/MODULES.md index abcbb32..6292668 100644 --- a/docs/MODULES.md +++ b/docs/MODULES.md @@ -18,6 +18,7 @@ Site modification modules are basically the same as application modules, but the - `packageType`: The type of the module. Should be `mods` - `appName`: The name of the module (user friendly, like "TizenTube"). - `websiteURL`: The URL of the website. +- `serviceFile`: The main JavaScript file of the service. Used if exists. - `main`: The JavaScript file to be injected to the website. - `keys`: The keys that should be registered using the [TVInputDevice](https://developer.samsung.com/smarttv/develop/api-references/tizen-web-device-api-references/tvinputdevice-api.html) API. - `tizenAppId`: The Tizen application ID of the application that should be modified. Will be used if it exists. diff --git a/tizenbrew-app/TizenBrew/config.xml b/tizenbrew-app/TizenBrew/config.xml index e6d7ef7..8ea77c4 100644 --- a/tizenbrew-app/TizenBrew/config.xml +++ b/tizenbrew-app/TizenBrew/config.xml @@ -1,5 +1,5 @@ - + diff --git a/tizenbrew-app/TizenBrew/index.html b/tizenbrew-app/TizenBrew/index.html index bc64f1f..a5c374c 100644 --- a/tizenbrew-app/TizenBrew/index.html +++ b/tizenbrew-app/TizenBrew/index.html @@ -121,7 +121,7 @@ break; } - if (packageType === 'service') { + 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() }); diff --git a/tizenbrew-app/TizenBrew/js/wsClient.js b/tizenbrew-app/TizenBrew/js/wsClient.js index 1b27b1f..1539424 100644 --- a/tizenbrew-app/TizenBrew/js/wsClient.js +++ b/tizenbrew-app/TizenBrew/js/wsClient.js @@ -45,16 +45,6 @@ function onMessage(msg) { send({ type: 'getServiceStatuses' }); } else { send({ type: 'canLaunchInDebug' }); - /* - const failedStartupAttempts = parseInt(localStorage.getItem('failedStartupAttempts')); - if (failedStartupAttempts < 2) { - localStorage.setItem('failedStartupAttempts', failedStartupAttempts + 1); - send({ type: 'relaunchInDebug', isTizen3, tvIp: webapis.network.getIp() }); - tizen.application.getCurrentApplication().exit(); - } else { - showError(`Error: Could not connect to the server after 3 attempts. Are you sure you changed the Host PC IP to 127.0.0.1?`); - localStorage.setItem('failedStartupAttempts', '0'); - }*/ } break; } @@ -64,7 +54,7 @@ function onMessage(msg) { document.getElementById('appList').innerHTML = ''; for (const module of message.modules) { document.getElementById('appList').innerHTML += ` -
+

${module.appName}

@@ -95,6 +85,39 @@ function onMessage(msg) { canLaunchModules = true; document.getElementById('wsText').innerText = 'Connected to server.'; + const autoLaunchService = JSON.parse(localStorage.getItem('autoLaunchService')); + + if (autoLaunchService) { + send({ type: 'startService', package: autoLaunchService }); + } + + if (message.appControlData) { + const moduleName = message.appControlData.module.name; + const moduleType = message.appControlData.module.type; + const keys = message.appControlData.module.keys; + const appPath = message.appControlData.module.appPath; + const tizenAppId = message.appControlData.module.tizenAppId; + const args = message.appControlData.args; + + if (keys.length > 0) { + keys.forEach(key => { + tizen.tvinputdevice.registerKey(key); + }); + } + + if (message.appControlData.module.serviceFile) { + send({ type: 'startService', package: { name: moduleName, type: moduleType } }); + } + + setTimeout(() => { + send({ type: 'launch', package: { name: moduleName, type: moduleType } }); + if (!tizenAppId) { + location.href = `${appPath}${args ? `?${args}` : ''}`; + } + }, 250); + return; + } + if (canAutoLaunch && localStorage.getItem('autoLaunch')) { const autoLaunch = JSON.parse(localStorage.getItem('autoLaunch')); const app = document.querySelector(`[data-packagename="${autoLaunch.name}"]`); @@ -110,19 +133,13 @@ function onMessage(msg) { tizen.tvinputdevice.registerKey(keys[i]); } } - var packageType = selectedItem.getAttribute("data-packageType"); - - var moduleType = selectedItem.getAttribute("data-moduleType"); - - if (!canLaunchModules) { - alert("You can't launch modules while the service hasn't connected yet."); - break; - } + var packageType = selectedItem.getAttribute("data-packageType"); - if (packageType === 'service') { + 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') { @@ -163,4 +180,14 @@ function onMessage(msg) { function onOpen() { // We have to get the debug status to know if we need to relaunch in debug mode. send({ type: 'getDebugStatus' }); + const data = tizen.application.getCurrentApplication().getRequestedAppControl().appControl.data; + if (data.length > 0) { + // TizenBrew allows other apps to launch a specific module outside of the TizenBrew app. + const moduleName = data[0].value.moduleName; + const moduleType = data[0].value.moduleType; + const args = data[0].value.args; + + // Send the data to the server and launch it after TizenBrew relaunches. + send({ type: 'launchAppControl', package: { name: moduleName, type: moduleType }, args }); + } } \ No newline at end of file diff --git a/tizenbrew-app/TizenBrew/moduleManager.html b/tizenbrew-app/TizenBrew/moduleManager.html index ffaeb63..32b5281 100644 --- a/tizenbrew-app/TizenBrew/moduleManager.html +++ b/tizenbrew-app/TizenBrew/moduleManager.html @@ -84,7 +84,8 @@ var hasConfirmined = confirm(`Do you want to remove ${packageName}?`); if (hasConfirmined) { var modules = JSON.parse(localStorage.getItem("modules")); - var newModules = modules.filter((module) => module.name != packageName && module.type != packageType); + + var newModules = modules.filter((module) => module.name != packageName); localStorage.setItem("modules", JSON.stringify(newModules)); location.reload(); } @@ -116,7 +117,7 @@ document.getElementById("appList").innerHTML = ""; for (const module of modules) { document.getElementById("appList").innerHTML += ` -
+

${module.name}

`; @@ -156,7 +157,7 @@

This is primarily for development and for developers.

document.getElementById("appList").innerHTML += `

Add Module

- +
`; diff --git a/tizenbrew-app/TizenBrew/service/debugger.js b/tizenbrew-app/TizenBrew/service/debugger.js index f96243e..a556473 100644 --- a/tizenbrew-app/TizenBrew/service/debugger.js +++ b/tizenbrew-app/TizenBrew/service/debugger.js @@ -14,8 +14,9 @@ function startDebugging(port, adb_conn, ip) { ).then( debuggerJson => { global.inDebug.webDebug = true; - global.currentClient.send(JSON.stringify({ type: 'canLaunchModules' })); + global.currentClient.send(JSON.stringify({ type: 'canLaunchModules', appControlData: global.appControlData })); clearInterval(connectionInterval); + global.appControlData = null; return attachDebugger(debuggerJson[0].webSocketDebuggerUrl, adb_conn); }).catch( e => { diff --git a/tizenbrew-app/TizenBrew/service/moduleLoader.js b/tizenbrew-app/TizenBrew/service/moduleLoader.js index 1cf1f41..8df7142 100644 --- a/tizenbrew-app/TizenBrew/service/moduleLoader.js +++ b/tizenbrew-app/TizenBrew/service/moduleLoader.js @@ -35,6 +35,7 @@ function loadModules(moduleList) { appName: moduleJson.appName, description: moduleJson.description, appPath: moduleJson.websiteURL, + serviceFile: moduleJson.serviceFile, packageType: moduleJson.packageType, mainFile: moduleJson.main, keys: moduleJson.keys || [], @@ -47,6 +48,11 @@ function loadModules(moduleList) { .catch(e => { return { appName: module.name, + name: module.name, + appPath: 'file://index.html', + keys: [], + moduleType: module.type, + packageType: 'app', description: `Unknown module ${module.name}. Please check the module name and try again.` } }); diff --git a/tizenbrew-app/TizenBrew/service/service.js b/tizenbrew-app/TizenBrew/service/service.js index 440abe5..d07e579 100644 --- a/tizenbrew-app/TizenBrew/service/service.js +++ b/tizenbrew-app/TizenBrew/service/service.js @@ -49,6 +49,7 @@ module.exports.onStart = function () { }; global.currentClient = null; global.services = new Map(); + global.appControlData = null; function createAdbConnection(isTizen3, ip, appId) { if (adb) { @@ -94,6 +95,20 @@ module.exports.onStart = function () { } switch (message.type) { + case 'launchAppControl': { + loadModules([message.package]).then(modules => { + const module = modules.find(m => m.name === message.package.name); + if (!module) { + ws.send(JSON.stringify({ type: 'error', message: 'Module not found.' })); + return; + } + global.appControlData = { + module, + args: message.args + }; + }); + break; + } case 'getDebugStatus': { ws.send(JSON.stringify({ type: 'debugStatus', inDebug: global.inDebug })); break; @@ -139,6 +154,9 @@ module.exports.onStart = function () { type: 'app', path: `http://127.0.0.1:8081/module/${message.package.type}/${encodeURIComponent(message.package.name)}/${module.appPath}` } + + global.inDebug.tizenDebug = false; + global.inDebug.webDebug = false; } }); break; diff --git a/tizenbrew-app/TizenBrew/service/serviceLauncher.js b/tizenbrew-app/TizenBrew/service/serviceLauncher.js index a458eff..f152cd4 100644 --- a/tizenbrew-app/TizenBrew/service/serviceLauncher.js +++ b/tizenbrew-app/TizenBrew/service/serviceLauncher.js @@ -7,12 +7,14 @@ function startService(module, pkg) { let sandbox = {}; Object.getOwnPropertyNames(global).forEach(prop => { - const disAllowed = ['services', 'module', 'global', 'inDebug', 'currentClient', 'currentModule', 'process']; + const disAllowed = ['services', 'module', 'global', 'inDebug', 'currentClient', 'currentModule']; if (disAllowed.includes(prop)) return; sandbox[prop] = global[prop]; }); - - + + sandbox['require'] = require; + sandbox['module'] = { exports: {} }; + fetch(`https://cdn.jsdelivr.net/${pkg.type}/${pkg.name}/${module.serviceFile}`) .then(res => res.text()) .then(script => { @@ -22,7 +24,7 @@ function startService(module, pkg) { }); try { - vm.runInContext(script, global.services.get(pkg.name).context).catch(e => console.error(e)); + vm.runInContext(script, global.services.get(pkg.name).context); } catch (e) { console.error(e); global.services.get(pkg.name).hasCrashed = true; diff --git a/tizenbrew-updater/TizenBrewUpdater/config.xml b/tizenbrew-updater/TizenBrewUpdater/config.xml index f341734..e80d8fd 100644 --- a/tizenbrew-updater/TizenBrewUpdater/config.xml +++ b/tizenbrew-updater/TizenBrewUpdater/config.xml @@ -1,6 +1,6 @@ + version="1.0.1" viewmodes="maximized"> diff --git a/tizenbrew-updater/TizenBrewUpdater/service/service.js b/tizenbrew-updater/TizenBrewUpdater/service/service.js index be937c0..5dc2278 100644 --- a/tizenbrew-updater/TizenBrewUpdater/service/service.js +++ b/tizenbrew-updater/TizenBrewUpdater/service/service.js @@ -11,8 +11,7 @@ module.exports.onStart = function () { const fetch = require('node-fetch'); const express = require('express'); const app = express(); - app.use(express.static('/snapshot/TizenBrewUpdater')); - const fs = require('fs'); + app.use(express.static(`${process.platform === 'win32' ? 'C:' : '' }/snapshot/TizenBrewUpdater`)); const server = new WebSocket.Server({ server: app.listen(8083) }); global.currentClient = null;