Skip to content

Automation Guide

Let’s see an example of how to use the Automation API to automate the search on Wikipedia. Our extension will consist of a popup with query input where we can type the query we want to search on Wikipedia. When we click the search button, the popup will send a message to the content script with the query.

The simple automation will be: Open a new virtual tab and navigate it to Wikipedia. Then, use of the Automatio API to automate searching for a term.

manifest.json
{
"manifest_version": 3,
"name": "Automated Search on Wikipedia",
"version": "1.0",
"action": {
"default_popup": "popup.html"
},
"content_scripts": [
{
"js": ["content_script.js"]
}
]
}
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Search on Wiki!</title>
<style>
.container{
padding: 30px;
}
.tab-content{
padding: 5px;
}
</style>
</head>
<body>
<div>
<h3>What do you want to search on Wikipedia?</h3>
<input id="wiki-query" type="text" placeholder="Enter your search query">
<button id="search-wiki">Search</button>
</div>
<script>
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
document.getElementById('search-wiki').addEventListener('click', async () => {
console.log('Search button clicked');
// Open a new tab with the Wikipedia URL
browser.tabs.relocate('https://wikipedia.org', newTab = false)
// Wait for the new tab to load
await wait(3000)
// Send a message to the content script to perform the search
const searchQuery = document.getElementById('wiki-query').value;
browser.tabs.sendMessage(null, { type: "search_on_wiki", searchQuery });
// Wait for all the search actions to complete
await wait(10000);
// Scroll down the page
browser.tabs.sendMessage(null, { type: "scroll_down" });
});
</script>
</body>
</html>
content_script.js
console.log('content script loaded');
function buildAutomations(searchQuery) {
const DEFAULT_WAIT_duration = 2000;
const TABBAR_HEIGHT = 40;
const inputBounds = document.querySelector('#searchInput').getBoundingClientRect();
const inputCenterX = inputBounds.left + inputBounds.width / 2;
const inputCenterY = (inputBounds.top + inputBounds.height / 2) + TABBAR_HEIGHT;
const searchButton = document.querySelector('#search-form > fieldset > button').getBoundingClientRect();
const searchButtonX = searchButton.left + 1;
const searchButtonY = searchButton.top + 1 + TABBAR_HEIGHT;
return [
// Focus on the search input
{ "action": "mouse_move", "coordinate": [inputCenterX, inputCenterY] },
{ "action": "wait", "duration": DEFAULT_WAIT_duration },
{ "action": "left_click" },
{ "action": "wait", "duration": DEFAULT_WAIT_duration },
// Type the search query and search
{ "action": "type", "text": searchQuery },
{ "action": "mouse_move", "coordinate": [searchButtonX, searchButtonY] },
{ "action": "wait", "duration": DEFAULT_WAIT_duration },
{ "action": "left_click" },
{ "action": "wait", "duration": DEFAULT_WAIT_duration },
];
}
async function runAutomations(automations) {
// perform the automations
for (const automation of automations) {
const { action } = automation;
delete automation.action;
const args = Object.values(automation);
console.log('running automation', action, ...args);
await browser.webfuseSession.automation[action](...args);
}
}
browser.runtime.onMessage.addListener(async message => {
const { type, searchQuery } = message;
if (type === "search_on_wiki") {
console.log(`searching ${searchQuery} on wiki`);
const automations = buildAutomations(searchQuery);
await runAutomations(automations);
} else if (type === 'scroll_down') {
const scrollAutomations = [
{ "action": "mouse_move", "coordinate": [500, 500] },
{ "action": "scroll", "amount": 300, "direction": "down" },
{ "action": "wait", "duration": 1000 },
{ "action": "scroll", "amount": 800, "direction": "down" },
{ "action": "wait", "duration": 1000 },
{ "action": "scroll", "amount": 400, "direction": "down" },
];
await runAutomations(scrollAutomations);
}
});