diff --git a/README.md b/README.md index 08fbcbeec..3f36231d8 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ package in your `package.json`) |`appium:deviceName`|[Required] The name of the connected device, as it shows up in `ares-launch --device-list`| |`appium:deviceHost`|[Required] The IP address of the connected device, as it shows up in `ares-launch --device-list`| |`appium:appId`|[Required] The app package ID, if you want Appium to use an app already on the TV. Exclusive with `appium:app`| -|`appium:app`|[Optional] An absolute path to your `.ipk` app file, if you want Appium to install the app.| +|`appium:app`|[Optional] A path to your `.ipk` app file if you want Appium to install the app. This can either be an absolute path or a https url to where the file is located on the internet.| |`appium:debuggerPort`|[Optional; default `9998`] The port on the device exposed for remote Chromium debugging.| |`appium:chromedriverExecutable`(*)|[Optional] Most LG TVs run a very old version of Chrome. Because this driver uses Chromedriver under the hood, you'll need to have a very old version of Chromedriver handy that works with the version of Chrome backing the apps on your TV. In our testing, we've found Chromedriver 2.36 to work with most TVs. You need to tell the driver where you've installed this version of Chromedriver using the `appium:chromedriverExecutable` capability, passing in an absolute path to the Chromedriver binary.| | `appium:chromedriverExecutableDir`(*) | [Optional] Full path to the folder where chromedriver executables are located. This folder is used then to store the downloaded chromedriver executables if automatic download is enabled with `chromedriver_autodownload` security flag. Please read [Automatic Discovery of Compatible Chromedriver in appium-uiautomator2-driver](https://github.com/appium/appium-uiautomator2-driver?tab=readme-ov-file#automatic-discovery-of-compatible-chromedriver) for more details. If the chrome version on the TV is lower than v63 major version, the using chrome version will be `Chrome/63.0.3239.0` forcefully to use chromedriver 2.36 for the session. Lower chromedriver could raise `cannot find Chrome binary` error, which prevent starting chromedriver session. | diff --git a/lib/cli/ares.js b/lib/cli/ares.js index c3490e769..ac47bad9b 100644 --- a/lib/cli/ares.js +++ b/lib/cli/ares.js @@ -4,6 +4,9 @@ import path from 'path'; import { exec } from 'teen_process'; import { fs, system } from 'appium/support'; import { Env } from '@humanwhocodes/env'; +import {createWriteStream, mkdtempSync, rmSync} from 'fs'; +import https from 'https'; +import {tmpdir} from 'os'; const ARES = 'ares'; const ARES_DEVICE_INFO = 'ares-device-info'; @@ -148,7 +151,15 @@ export async function closeApp(appId, deviceName) { */ export async function installApp(ipkPath, appId, deviceName) { log.info(`Installing app '${appId}' from ${ipkPath}`); + + const isRemoteApp = ipkPath.startsWith('https://'); + if (isRemoteApp) { + ipkPath = await downloadRemoteWebosAppToTempFile(ipkPath); + } await runDeviceCmd(ARES_INSTALL, deviceName, [ipkPath]); + if (isRemoteApp) { + rmSync(ipkPath); + } } /** @@ -160,3 +171,30 @@ export async function uninstallApp(appId, deviceName) { log.info(`Uninstalling app '${appId}'`); await runDeviceCmd(ARES_INSTALL, deviceName, ['-r', appId]); } + +function downloadRemoteWebosAppToTempFile(appUrl) { + const tempDir = mkdtempSync(`${tmpdir()}${path.sep}`); + const filePath = path.join(tempDir, 'app.ipk'); + const file = createWriteStream(filePath); + + return new Promise((resolve, reject) => { + https.get(appUrl, (response) => { + if (response.statusCode !== 200) { + reject(new Error(`Failed to get '${appUrl}' (${response.statusCode})`)); + return; + } + + response.pipe(file); + file.on('finish', () => { + file.close(() => resolve(filePath)); + }); + file.on('error', (err) => { + rmSync(filePath); + reject(err); + }); + }).on('error', (err) => { + rmSync(filePath); + reject(err); + }); + }); +}