0

I am writing an extension that has options which let users decide which sites they want the extension to run on.

Say the user has this site in the options

site                          action
stackoverflow.com/*           change background css to blue
google.com/*                  change background css to green

I store these string in the options. When the content_script runs should I retrieve these strings from options, loop through each one, parse with a urlParser into parts, turn each part into a regex (escaping everything but *), and compare it with document.URL? I recently read that this kind of user options validation for Urls should be done through a background script too so I'm not sure which way to go or if there's a more obvious way to do it.

I think extensions like Adblocker and Vimium seem to have this functionality but for deciding which sites not to run on. I want to figure out how to decide which sites to run on.

Update to the Question: Since my content_script needs to run at document_start (before the page is loaded since it deals with editting the page appearance) as a content_script, will the background page be able to execute the content_script before the webpage is loaded at all?

irregular
  • 1,437
  • 3
  • 20
  • 39

1 Answers1

0

Validated a web page's url should be "validated" via a background page because the user's options will be hosted in local storage in the context of the background page. Here is what I would do... (although it's more of a suggestion that an answer).

I am not sure how the actions on the right column of your list factor into your question, sorry.

(Also note, you would need to incorporate a library (external or self-written) that can parse globs into regex.)

manifest.json

permissions: ["tabs", "storage", "webRequest", "<all_urls>"] 

background.js

//allow the webrequest to run on all urls
var filter = { urls: "<all_urls>" };

//receives url information from webrequest listener
function listen(details) {
    getUserOpts()
        .then(function(arrayOfWhitelistUrls) {
            //you can't use globs here, need to use more powerful filtering mechanisms
            if (arrayOfWhitelistUrls.indexOf(details.url) > -1) {
                message();
            }
        });
}

//returns a promise containing user defined whitelist urls from background local storage
function getUserOpts() {
    return new Promise(function(res, rej) {
        chrome.storage.get("whitelist", function(data) {
            //you are saving all localhost data as a string, so you need to parse it first
            res(JSON.parse(data));
        });
    });
}

//messages content script and allows execution
function message() {
    chrome.tabs.query({active: true}, function(tabs) {
        chrome.tabs.sendMessage(tabs[0].id, {permission: true});
    });
}

chrome.webRequest.onBeforeRequest.addListener(listen, filter)

contentscript.js

function listen(message) {        
    if (message.permission) {
        if (message.permission === true) {
            init();
        }
    }
}

//listen for message
chrome.runtime.onMessage.addEventListener(listen);

So the order in which things run is like:

    1. background page listens to each web request
    1. on each web request, the background page asynchronously fetches user options from local storage
    1. if the url of the current tab passes your filter, message your content script
    1. the content script receives the message and then runs

There might be an easier way to do this; the downside to this method is that you need to include the permission gateway in every content script you have.

Daniel Lizik
  • 3,058
  • 2
  • 20
  • 42
  • You can instead call chrome.tabs.executeScript in the background page to run the content_script. The actions part was just an example, I hope to do more complicated things than change css. My main concern is the User whitelist so for now it seems like a background page is a good idea to not load the entire content_script until it's needed I see – irregular Sep 30 '15 at 03:26
  • @user2807904 that's probably a better solution – Daniel Lizik Sep 30 '15 at 03:33
  • actually I'm not sure if the background page + content_script call will finish running before the page is loaded. Right now my content_script is run at document_start so the javascript finishes running before the page is even loaded. (if you put a breakpoint in the content_script, the browser is completely white with nothing loaded. Would the same for the background script or would the html load while the background.js is running? – irregular Sep 30 '15 at 04:01