shellfox/background.js

155 lines
4.1 KiB
JavaScript
Raw Normal View History

let port = undefined;
// Run the shellfox helper program.
function initShellfoxProgram() {
port = browser.runtime.connectNative("shellfox");
port.onDisconnect.addListener((port) => {
console.log(port.error);
port = undefined;
});
}
// Return the command-string associated with a URL, if any.
function getUrlCommand(url) {
let matchCommand = undefined;
let matchRegex = "";
try {
let savedCommands = JSON.parse(localStorage.getItem("commands"));
let savedRegexRules = JSON.parse(localStorage.getItem("urlRules"));
// Find the most-applicable command…
for (regexCommandIPair of savedRegexRules) {
let regex = regexCommandIPair[0];
let match = url.match(regex);
let compared = compareRegexComplexity(matchRegex, regex);
if (match && (compared == 0 || compared == 1)) {
let command_i = regexCommandIPair[1];
matchCommand = savedCommands[command_i][1];
matchRegex = regex;
}
}
// … and replace the substitution-string with the URL.
matchCommand = matchCommand.replaceAll("$URL", url);
} catch {};
return matchCommand;
}
// Execute the shell command associated with the given URL, if any.
function runUrlCommand(url) {
let command = getUrlCommand(url);
if (!port)
initShellfoxProgram();
if (command && port) {
port.postMessage(command);
}
}
// Compare two regular expressions, returning which one is more specific.
// Returns -1 if a is more specific, 1 if b is, and 0 if they are equal.
// Its a simple (and unreliable) algorithm, for now — purely based on length.
function compareRegexComplexity(a, b) {
if (a && ((a && !b) || (a.length > b.length)))
return -1;
else if (b && ((b && !a) || (a.length < b.length)))
return 1
return 0;
}
// Display the “Run shell command” context-menu item.
function showPageContextMenuItem() {
browser.menus.update("run-page-command", { "visible": true });
}
// Display the “Run command on link” context-menu item.
function showLinkContextMenuItem() {
browser.menus.update("run-page-commands", { "visible": true });
}
// Hide the “Run shell command context-menu item.
function hidePageContextMenuItem() {
browser.menus.update("run-page-command", { "visible": false });
}
// Hide the “Run command on link” context-menu item.
function hideLinkContextMenuItem() {
browser.menus.update("run-page-commands", { "visible": false });
}
// Add a context-menu item for running the current pages associated command.
browser.menus.create(
{
id: "run-page-command",
title: "Run shell command",
contexts: ["page"]
}
);
// Add a context-menu item for running the command associated with a link.
browser.menus.create(
{
id: "run-link-command",
title: "Run command on link",
contexts: ["link"]
}
);
// When the address-bar button is clicked, run the according command (if any).
browser.pageAction.onClicked.addListener((tab) => {
runUrlCommand(tab.url);
});
browser.menus.onShown.addListener(info => {
if (info.contexts.includes("link") && getUrlCommand(info.linkUrl))
showLinkContextMenuItem();
else if (info.contexts.includes("page") && getUrlCommand(info.pageUrl))
showPageContextMenuItem();
else {
hidePageContextMenuItem();
hideLinkContextMenuItem();
}
browser.menus.refresh();
});
// When a tabs URL has been changed, enable/disable the address-bar button
// based on whether or not there is an according command.
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
let command = getUrlCommand(tab.url);
if (command)
browser.pageAction.show(tabId);
else
browser.pageAction.hide(tabId);
});
// When the active tab has changed, enable/disable the address-bar button based
// on whether or not there is an according command for it.
browser.tabs.onActivated.addListener((activeInfo) => {
browser.tabs.get(activeInfo.tabId).then((tab) => {
if (getUrlCommand(tab.url))
browser.pageAction.show(tab.id);
else
browser.pageAction.hide(tab.id);
});
});
// When a context-menu item is selected, lets execute its will!
browser.menus.onClicked.addListener((info, tab) => {
if (info.menuItemId == "run-page-command")
runUrlCommand(tab.url);
else if (info.menuItemId == "run-link-command" && info.linkUrl)
runUrlCommand(info.linkUrl);
});