Issue with my extension for background activity

237 views
Skip to first unread message

Antoine

unread,
Jan 19, 2023, 7:54:20 AM1/19/23
to Chromium Extensions
Hi,

I have an extension to block websites that are not in the allow list when the extension is enabled. I made a setInterval, but it seems to unload if I close my laptop, the only way to bring it back is to reload the extension. Any thoughts?

var allowonlywebsitesglobal = false;
var websitestoallowglobal = "";

// every time chrome starts
chrome.runtime.onStartup.addListener(function () {

// Interval to run every 5000ms to get data from chrome storage local
setInterval(function () {
// Get the value of allowonlywebsites in chrome storage local
chrome.storage.local.get("allowonlywebsites", function (result) {
// If the result is not undefined
if (result != undefined) {
var allowonlywebsites = result.allowonlywebsites;
saveDataToVar("allowonlywebsites", allowonlywebsites);
}
});

// Get the value of websitestoallow in chrome storage local
chrome.storage.local.get("websitestoallow", function (result) {
// If the result is not undefined
if (result != undefined) {
var websitestoallow = result.websitestoallow;
saveDataToVar("websitestoallow", websitestoallow);
}
});
}, 5000);

function saveDataToVar(dataName, dataValue) {
if (dataName == "allowonlywebsites") {
allowonlywebsitesglobal = dataValue;
} else if (dataName == "websitestoallow") {
websitestoallowglobal = dataValue;
}
}

// Interval to run every 3000ms to check if the user is on a website that is not allowed
setInterval(function () {
// If the user has enabled the option to allow only websites
if (allowonlywebsitesglobal == true) {
// Check if the user is on a website that is not allowed
checkIfWebsiteIsAllowed();
}
}, 3000);

function checkIfWebsiteIsAllowed() {
// Get the value of websitestoallow in chrome storage local
chrome.storage.local.get("websitestoallow", async function (result) {
// If the result is not undefined
if (result != undefined) {
// If the result is not empty
if (result.websitestoallow != "") {
// Split the value of websitestoallow in chrome storage local
var split = result.websitestoallow.split(",");
// Get the current url
let queryOptions = { active: true, currentWindow: true };
let [tab] = await chrome.tabs.query(queryOptions);
if (tab === undefined) {
return;
}

if (tab.url.toString().includes("chrome://")) {
return;
}

if (tab.url.toString().includes("chrome-extension://")) {
return;
}

// Get only host of url without any subdomains
var url = new URL(tab.url);
var host = url.hostname;
host = host.replace("www.", "");
console.log(`Checking if - ${host} - is in the array of websites to allow`)
// Check if the host is in the array of websites to allow
if (split.includes(host)) {
// If the host is in the array of websites to allow, do nothing
console.log("DOMAIN OK")
} else {
// If the host is not in the array of websites to allow, redirect to the options page
chrome.tabs.update({ url: "/pages/blocked.html" });
}
}
}
});
}
});
Message has been deleted

wOxxOm

unread,
Jan 19, 2023, 10:32:12 AM1/19/23
to Chromium Extensions, wOxxOm, Antoine
Oops, my previous message contained a mistake in the code, hopefully fixed here.

The background script is not persistent anymore so it unloads after 30 seconds but anyway this is not how blocking should be implemented in ManifestV3. There's a much more efficient API: declarativeNetRequest which can be configured just once when the extension is installed/updated or when the storage is updated and then the browser will do the blocking without the need for the background script.

// manifest.json
"permissions": ["declarativeNetRequest"]

// background.js
chrome.runtime.onInstalled.addListener(registerRules);
chrome.runtime.onMessage.addListener(msg => msg === 'registerRules' && registerRules());
// alternatively use chrome.storage.onChanged in case you don't write other values to storage

async function registerRules() {
  const {websitestoallow = []} = await chrome.storage.local.get('websitestoallow');
  const domains = websitestoallow.split(',');
  const old = await chrome.declarativeNetRequest.getDynamicRules();
  await chrome.declarativeNetRequest.updateDynamicRules({
    removeRuleIds: old.map(o => o.id),
    addRules: !websitestoallow.length ? undefined : [{
      id: 1,
      condition: {
        excludedRequestDomains: domains,
        resourceTypes: ['main_frame'],
      },
      action: {
        type: 'redirect',
        redirect: {
          extensionPath: '/pages/blocked.html',
        },
      },
    }],
  });
  for (const tab of await chrome.tabs.query({})) {
    if (!domains.includes(new URL(tab.url).hostname.replace(/^www\./, ''))) {
      chrome.tabs.update(tab.id, { url: "/pages/blocked.html" });
    }
  }
}

// popup.js
(async () => {
  await chrome.storage.local.set({websitestoallow: 'example.com'});
  chrome.runtime.sendMessage('registerRules');
})();

On Thursday, January 19, 2023 at 6:26:27 PM UTC+3 wOxxOm wrote:
The background script is not persistent anymore so it unloads after 30 seconds but anyway this is not how blocking should be implemented in ManifestV3. There's a much more efficient API: declarativeNetRequest which can be configured just once when the extension is installed/updated or when the storage is updated and then the browser will do the blocking without the need for the background script.

// manifest.json
"permissions": ["declarativeNetRequest"]

// background.js
chrome.runtime.onInstalled.addListener(registerRules);
chrome.runtime.onMessage.addListener(msg => msg === 'registerRules' && registerRules());
// alternatively use chrome.storage.onChanged in case you don't write other values to storage

async function registerRules() {
  const {websitestoallow = ''} = await chrome.storage.local.get('websitestoallow');
  const domains = websitestoallow.split(',');
  const old = await chrome.declarativeNetRequest.getDynamicRules();
  await chrome.declarativeNetRequest.updateDynamicRules({
    removeRuleIds: old.map(o => o.id),
    addRules: !websitestoallow.length ? undefined : [{
      id: 1,
      condition: {
        requestDomains: domains,
        resourceTypes: ['main_frame'],
      },
      action: {
        redirect: {
          extensionPath: '/pages/blocked.html',
        },
      },
    }],
  });
  for (const tab of await chrome.tabs.query({ url: domains.map(d => `*://*.${d}/*`) })) {
    chrome.tabs.update(tab.id, { url: "/pages/blocked.html" });
  }
}

// popup.js
(async () => {
  await chrome.storage.local.set({websitestoallow: 'example.com'});
  chrome.runtime.sendMessage('registerRules');
})();

Antoine

unread,
Jan 19, 2023, 11:53:07 AM1/19/23
to Chromium Extensions, wOxxOm, Antoine
Thanks so much!! Amazing I'l try it out.

But how can I unregister it from the popup. Like have a button for enabling and for disabling. I see you added chrome.runtime.sendMessage('registerRules') would there be a way to disable it?

Thanks in advance

Antoine

Antoine

unread,
Jan 19, 2023, 11:54:51 AM1/19/23
to Chromium Extensions, Antoine, wOxxOm
I would also want it to run constatly to always block every site that is not allowed until it is disabled

Antoine

unread,
Jan 19, 2023, 12:09:12 PM1/19/23
to Chromium Extensions, Antoine, wOxxOm
How can I also not block stuff that starts with like chrome://

wOxxOm

unread,
Jan 19, 2023, 1:52:39 PM1/19/23
to Chromium Extensions, Antoine, wOxxOm
There's no need for special handling of chrome:// URLs because extensions shouldn't be able to block those.
There's no need to "block constantly" because the browser does it automatically whenever the user tries to open a matching site.

Antoine

unread,
Jan 20, 2023, 9:13:23 AM1/20/23
to Chromium Extensions, wOxxOm, Antoine
Hi, It does not seem to work, when i press enable it immediately kicks every page that isn't allowed but I can open a site that is not authorized after that..

And the extension seems to be able to block those it kicks the chrome://  urls

Antoine

Antoine

unread,
Jan 20, 2023, 9:16:27 AM1/20/23
to Chromium Extensions, Antoine, wOxxOm
Would I need to add an event listener like on tab update.. but how would I disable the net 

wOxxOm

unread,
Jan 20, 2023, 9:45:10 AM1/20/23
to Chromium Extensions, Antoine, wOxxOm
There's no need for a tab update listener. The code I've shown wasn't tested, sorry. It's supposed to be a starting point. I've just tried it myself and indeed there were some things I should have probably mentioned explicitly as well as a mistake that I found now by debugging in devtools.
  • manifest.json "host_permissions": ["<all_urls>"]
  • manifest.json "permissions": ["tabs",  "storage", "declarativeNetRequestWithHostAccess"]
  • chrome.tabs.query({url: ['*://*/*', 'file://*/*']}) instead of just {} which is what caused chrome:// pages to be blocked.
  • it doesn't block anything when websitestoallow is empty but you may want to change that by removing websitestoallow.length condition.
Reply all
Reply to author
Forward
0 new messages