This code creates a REST API using Express for navigating and interacting with web pages in a Chrome browser instance, utilizing the Chrome Debugging Protocol. It provides functions for waiting for page loads and navigating to specific URLs, as well as API endpoints for retrieving and setting the current URL of the active tab.
var importer = require('../Core');
var express = require('express');
var router = express.Router();
function waitForComplete() {
return promisifyChrome('debugger.sendCommand', {
tabId: getTab()
}, 'Runtime.evaluate', {
expression: `new window.BackupPromise(resolve => {
resolve(document.readyState === "complete" || document.readyState === "interactive");
})`,
awaitPromise: true
})
.then(b => b ? ({value: {}}) : waitForComplete())
}
function go(url) {
return promisifyChrome('windows.getAll', {})
.then(windows => importer.runAllPromises(windows
.map(w => resolve =>
promisifyChrome('tabs.getAllInWindow', w.id)
.then(tabs => resolve(tabs)))))
.then(tabs => {
for (const t of [].concat(...tabs)) {
if (t.url.indexOf(url) > -1 || t.id === getTab()) {
return promisifyChrome(
'tabs.update', t.id, {active: true});
}
}
return promisifyChrome('tabs.create', {
active: true,
url
});
})
.then(t => {
if(t.id !== getTab()) {
setTab(t.id)
return promisifyChrome('debugger.attach', {
tabId: getTab()
}, '1.1')
}
})
.then(() => promisifyChrome('debugger.sendCommand', {
tabId: getTab()
}, 'Page.navigate', {
url: url
}))
.then(() => waitForComplete())
.catch(e => console.log(e))
}
router.get('/session/:sessionId/url', (req, res) => {
response(res, promisifyChrome('tabs.get', {
tabId: getTab()
}).then(r => ({value: r.url})));
})
router.post('/session/:sessionId/url', (req, res) => {
response(res, go(req.body.url))
})
module.exports = {
go,
router
};
const { promisifyChrome } = require('../Core');
const express = require('express');
const router = express.Router();
/**
* Wait for the page to be completely loaded.
* @returns {Promise<{value: {}}> | null}
*/
async function waitForComplete() {
try {
const result = await promisifyChrome('debugger.sendCommand', {
tabId: await getTab()
}, 'Runtime.evaluate', {
expression: `
new window.BackupPromise(resolve => {
resolve(document.readyState === "complete" || document.readyState === "interactive");
})
`,
awaitPromise: true
});
return result? ({ value: {} }) : null;
} catch (error) {
console.error('Error waiting for page to load:', error);
return null;
}
}
/**
* Open or switch to the specified URL.
* @param {string} url - The URL to open or switch to.
* @returns {Promise<{ value: {} }>}
*/
async function go(url) {
// Get all windows and their tabs
const windows = await promisifyChrome('windows.getAll', {});
const tabs = await Promise.all(windows.map(w => resolve =>
promisifyChrome('tabs.getAllInWindow', w.id)
.then(tabs => resolve(tabs))));
// Find the first tab that matches the URL or is the current tab
const tab = tabs.flat().find(t => t.url.includes(url) || t.id === await getTab());
if (tab) {
// Activate the tab
await promisifyChrome('tabs.update', tab.id, { active: true });
} else {
// Create a new tab
const newTab = await promisifyChrome('tabs.create', {
active: true,
url
});
// Set the new tab as the current tab
await setTab(newTab.id);
// Attach the debugger to the new tab
await promisifyChrome('debugger.attach', {
tabId: newTab.id
}, '1.1');
}
// Navigate to the URL
await promisifyChrome('debugger.sendCommand', {
tabId: await getTab()
}, 'Page.navigate', {
url
});
// Wait for the page to load
await waitForComplete();
}
/**
* Get the URL of the current tab.
* @returns {Promise<{value: {url: string}}>}
*/
router.get('/session/:sessionId/url', (req, res) => {
response(res, promisifyChrome('tabs.get', {
tabId: getTab()
}).then(r => ({ value: r.url })));
});
/**
* Open or switch to the specified URL.
* @param {string} url - The URL to open or switch to.
*/
router.post('/session/:sessionId/url', (req, res) => {
response(res, go(req.body.url));
});
module.exports = {
go,
router
};
The provided code defines a set of functions for interacting with a Chrome browser instance using the Chrome Debugging Protocol. It utilizes the express
framework to create a REST API for navigating and interacting with web pages.
waitForComplete()
document.readyState
property to ensure the page is loaded before returning.go(url)
url
.url
or creates a new tab if not found.url
in the new tab.waitForComplete()
.url
./session/:sessionId/url
(GET)url
in JSON format./session/:sessionId/url
(POST)url
using the go(url)
function.url
in JSON format.module.exports = { go, router };
go
function and the router
instance.