idle: initial add
This commit is contained in:
parent
007cf2d032
commit
fb99d0e987
@ -10,6 +10,8 @@ import { fileURLToPath } from 'url';
|
||||
import Chromium from './browser/chromium.js';
|
||||
import Firefox from './browser/firefox.js';
|
||||
|
||||
import IdleAPI from './lib/idle.js';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
@ -94,7 +96,7 @@ const startBrowser = async (url, { windowSize, forceBrowser }) => {
|
||||
|
||||
const browserType = browserName.startsWith('firefox') ? 'firefox' : 'chromium';
|
||||
|
||||
return await (browserType === 'firefox' ? Firefox : Chromium)({
|
||||
const Browser = await (browserType === 'firefox' ? Firefox : Chromium)({
|
||||
browserName: browserFriendlyName,
|
||||
dataPath,
|
||||
browserPath
|
||||
@ -102,6 +104,10 @@ const startBrowser = async (url, { windowSize, forceBrowser }) => {
|
||||
url,
|
||||
windowSize
|
||||
});
|
||||
|
||||
Browser.idle = await IdleAPI(Browser.cdp, { browserType, dataPath });
|
||||
|
||||
return Browser;
|
||||
};
|
||||
|
||||
export const open = async (url, { windowSize, onLoad, forceBrowser } = {}) => {
|
||||
|
113
src/lib/idle.js
Normal file
113
src/lib/idle.js
Normal file
@ -0,0 +1,113 @@
|
||||
import { exec } from 'child_process';
|
||||
|
||||
const getProcesses = async containing => process.platform !== 'win32' ? Promise.resolve([]) : new Promise(resolve => exec(`wmic process get Commandline,ProcessID /format:csv`, (e, out) => {
|
||||
resolve(out.toString().split('\r\n').slice(2).map(x => {
|
||||
const parsed = x.trim().split(',').slice(1).reverse();
|
||||
|
||||
return [
|
||||
parseInt(parsed[0]) || parsed[0], // pid to int
|
||||
parsed.slice(1).join(',')
|
||||
];
|
||||
}).filter(x => x[1] && x[1].includes(containing)));
|
||||
}));
|
||||
|
||||
const killProcesses = async pids => process.platform !== 'win32' ? Promise.resolve('') : new Promise(resolve => exec(`taskkill /F ${pids.map(x => `/PID ${x}`).join(' ')}`, (e, out) => resolve(out)));
|
||||
|
||||
export default async (CDP, { browserType, dataPath }) => {
|
||||
if (browserType !== 'chromium') { // current implementation is for chromium-based only
|
||||
const warning = () => log(`Warning: Idle API is currently only for Chromium (running on ${browserType})`);
|
||||
|
||||
return {
|
||||
hibernate: warning,
|
||||
sleep: warning,
|
||||
wake: warning,
|
||||
auto: warning
|
||||
};
|
||||
};
|
||||
|
||||
const killNonCrit = async () => {
|
||||
const procs = await getProcesses(dataPath);
|
||||
const nonCriticalProcs = procs.filter(x => x[1].includes('type='));
|
||||
|
||||
await killProcesses(nonCriticalProcs.map(x => x[0]));
|
||||
log(`killed ${nonCriticalProcs.length} processes`);
|
||||
};
|
||||
|
||||
let hibernating = false;
|
||||
const hibernate = async () => {
|
||||
hibernating = true;
|
||||
|
||||
const startTime = performance.now();
|
||||
|
||||
await killNonCrit();
|
||||
// await killNonCrit();
|
||||
|
||||
log(`hibernated in ${(performance.now() - startTime).toFixed(2)}ms`);
|
||||
};
|
||||
|
||||
const wake = async () => {
|
||||
const startTime = performance.now();
|
||||
|
||||
await CDP.send('Page.reload');
|
||||
|
||||
log(`began wake in ${(performance.now() - startTime).toFixed(2)}ms`);
|
||||
|
||||
hibernating = false;
|
||||
};
|
||||
|
||||
const { windowId } = await CDP.send('Browser.getWindowForTarget');
|
||||
|
||||
let autoEnabled = process.argv.includes('--force-auto-idle'), autoOptions = {
|
||||
timeMinimizedToHibernate: 5
|
||||
};
|
||||
|
||||
let autoInterval;
|
||||
const startAuto = () => {
|
||||
if (autoInterval) return; // already started
|
||||
|
||||
let lastState = '', lastStateWhen = performance.now();
|
||||
autoInterval = setInterval(async () => {
|
||||
const { bounds: { windowState } } = await CDP.send('Browser.getWindowBounds', { windowId });
|
||||
|
||||
if (windowState !== lastState) {
|
||||
lastState = windowState;
|
||||
lastStateWhen = performance.now();
|
||||
}
|
||||
|
||||
if (!hibernating && windowState === 'minimized' && performance.now() - lastStateWhen > autoOptions.timeMinimizedToHibernate * 1000) await hibernate();
|
||||
else if (hibernating && windowState !== 'minimized') await wake();
|
||||
}, 200);
|
||||
|
||||
log('started auto idle');
|
||||
};
|
||||
|
||||
const stopAuto = () => {
|
||||
if (!autoInterval) return; // already stopped
|
||||
|
||||
clearInterval(autoInterval);
|
||||
autoInterval = null;
|
||||
|
||||
log('stopped auto idle');
|
||||
};
|
||||
|
||||
log(`idle API active (window id: ${windowId})`);
|
||||
if (autoEnabled) startAuto();
|
||||
|
||||
return {
|
||||
hibernate,
|
||||
sleep: () => {},
|
||||
wake,
|
||||
|
||||
auto: (enabled, options) => {
|
||||
autoEnabled = enabled;
|
||||
|
||||
autoOptions = {
|
||||
...options,
|
||||
...autoOptions
|
||||
};
|
||||
|
||||
if (enabled) startAuto();
|
||||
else stopAuto();
|
||||
}
|
||||
};
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user