how to make chrome.webRequest blocking

3,840 views
Skip to first unread message

Amit Shinde

unread,
Feb 11, 2014, 5:55:22 AM2/11/14
to chromium-...@chromium.org, amitsh...@yahoo.com

Trying POC to intercept the traffic originated from chrome via extension, send it to native host for analysis and convey the verdict back (allow/block the traffic)  based on analysis.

For this reason added listener interceptHeader  to chrome.webRequest.onBeforeSendHeaders with ["blocking", "requestHeaders"] specs. So the interceptHeaders method roughly looks as below.

    interceptHeaders: function(details)
    {
        var verdict = false;
       
        //send request for scanning only if it is a POST request                         
        if (details.method == "POST")
        {
            //create new responseObject
            var responseObject = new ResponseObject();
           
            /use native messaging to send request for scanning
           chrome.runtime.sendNativeMessage('com.my_company.my_application',
                                              requestObject,
                                              responseObject.Callback
                                            );
                                           
            // wait for response - how to efficiently wait unitl responseObject.Callback is processed
            // so that
responseObject.verdict can be used as a return value of interceptHeaders as shown below
            ??????????????           

            //update the verdict (true or false)
            verdict = responseObject.verdict;
           
            console.log ("verdict " + verdict + "for RequestId " + details.requestId);
           
            //delete the responseObject
            delete responseObject;
        }

        return {cancel: verdict};
    }

Now the problem is that chrome.runtime.sendNativeMessage call being asynchronous will return immediately and it will not wait for verdict (which will be received in the responseObject.Callback). What we need is wait till the verdict is received so that the same can be returned as a return value of the
interceptHeaders method.

Any help in this matter would be highly appreciated.


Or Hiltch

unread,
Feb 11, 2014, 6:25:15 AM2/11/14
to chromium-...@chromium.org, amitsh...@yahoo.com
Hi!

I guess that you check for verdict by using some kind of function that looks up the value of the URL in a dictionary or any other kind of data structure. 

Since the blocking of the request has to be synchronous (otherwise your users will get to the site before the content is actually blocked, right?), you need to work out a slightly different architecture. 

What you can do is to have your background page prepare the dictionary where you are looking up the URL's using the async native messaging method, and save that in the localStorage or any other kind of sync storage (you can save the result as an encrypted string if it's sensitive info). You can refresh that store every now and then to get fresh verdicts for URL's. 

Then, on the interceptor code that listens to webRequests, check the existence of the URL in that dictionary synchronously.

Hope this helps,
Or

Amit Shinde

unread,
Feb 11, 2014, 7:04:01 AM2/11/14
to chromium-...@chromium.org, amitsh...@yahoo.com
Or, thank you for the quick reply.

can you please elaborate more on your solution?

 >>Since the blocking of the request has to be synchronous (otherwise your users will get to the site before the content is actually blocked, right?), you need to work out a slightly different architecture.

You are right in that the verdict will either be blocked or allow based on the response received from the native host. So the native application will be invoked by the interceptRequest method and it needs to wait till processing is done. So how this can be achieved with what you proposed?

Or Hiltch

unread,
Feb 11, 2014, 7:45:53 AM2/11/14
to chromium-...@chromium.org, amitsh...@yahoo.com
Sure. 

background.js :

// this bit is pseudo code to update the verdicts db:

var _intervalSet = false;
var _refresh_db_every = 100000;
var db_cache = null;

// get DB Async is the function that constructs the dictionary from native code. it should contain all url/verdict pairs in a format such as this: 
// db_cache['www.dangeroussite.com'] = '1'

if (!intervalSet) {
setInterval(function() {
   getDBAsync('/db/get'/, function(result) { 
db_cache = result;
localStorage.setItem('my_verdicts_db', JSON,stringify(db_cache));
});
}, _refresh_db_every);
}

function getDbSync() {
 return db_cache || JSON.parse(localStorage.getItem('my_verdicts_db'));
}
// this bit is for the interceptor which has to by synchronous
// assuming db_cache is of the form db_cache['www.dangeroussite.com' = '1'
function shouldRequestBeBlocked(inspectUrl) {
 var db = getDbSync();
 return db[inspectUrl] == '1';
}

now, on the function that checks if the request should be blocked, call the shouldRequestBeBlocked, which is synchronous, to be able to tell if you want to block or not. 

Amit Shinde

unread,
Feb 11, 2014, 9:28:03 AM2/11/14
to Or Hiltch, amitsh...@yahoo.com, chromium-...@chromium.org

Or, apologies for not making the requirements clear in first place.

Native host needs http headers and payload of the post request for scanning (both available in the interceptHeaders method) in order to determine the verdict. So interceptHeaders method needs to wait until callback (supplied to the chrome.sendNativeMessage) gets called for each post request in real time (and not asynchronously). So this is not just url based verdict.

Ameet

--
You received this message because you are subscribed to the Google Groups "Chromium-extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To post to this group, send email to chromium-...@chromium.org.
Visit this group at http://groups.google.com/a/chromium.org/group/chromium-extensions/.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/d55b7f4f-363d-4190-837b-92b16ce21d92%40chromium.org.
For more options, visit https://groups.google.com/a/chromium.org/groups/opt_out.

Or Hiltch

unread,
Feb 11, 2014, 9:42:13 AM2/11/14
to chromium-...@chromium.org, Or Hiltch, amitsh...@yahoo.com
I am pretty sure that the BlockingResponse callback has to be synchronous. You can easily test that -

From Google API Docs:
chrome.webRequest.onBeforeRequest.addListener(
  function(details) {
    return {cancel: details.url.indexOf("://www.evil.com/") != -1};
  },
  {urls: ["<all_urls>"]},
  ["blocking"]);

The callback (which gets "details" as input) implementation has to return the value that tells chrome to block the request or not. This has to be synchronous as far as I can gather (it would also make sense in terms of the design because if evil.com has some malicious content, it a part of it has been loaded, blocking it later might not be very helpful). If someone can correct or confirm it would be nice.

Since you have to use native calls, you are out of luck for doing it real time (both Native Client [NaCl] and nativeMessaging API's are async). I would imagine that in a production application you would not want to slow down browsing by actually scanning real time if there exists another option (like working with a pre-made DB of URL's that you are going to block). 

If could do something crazy like using your scanning native code inside a web service and then calling that web service with a sync ajax request, but that would be very not efficient...
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extensions+unsub...@chromium.org.

Amit Shinde

unread,
Feb 12, 2014, 1:12:50 AM2/12/14
to chromium-...@chromium.org, Or Hiltch, amitsh...@yahoo.com
Or, We need to check contents for sensitive data (and not just do blanket URL blocking) i.e. we need to inspect file to be uploaded when user is trying to send file as an email attachment.

Having said that, is there option of using PPAPI for this purpose? Does it use synchronous APIs? As per the following page, synchronous communication using PPAPI has been discouraged.
http://code.google.com/p/ppapi/wiki/InterfacingWithJavaScript

After investigating PPAPI, it seems that (Can someone please validate the following?)
  1. PPAPI plugin needs to be compiled with Nacl compiler which puts API restrictions on it.
  2. Additionally loading of PPAPI plugin seems to be only possible if they are published via Chrome Webstore
  3. PPAPI will support asynchronous communication henceforth like native messaging as per https://developers.google.com/native-client/devguide/coding/message-system

Is there any way to simulate wait in JavaScript?


Or Hiltch

unread,
Feb 12, 2014, 5:43:34 AM2/12/14
to chromium-...@chromium.org, Or Hiltch, amitsh...@yahoo.com
Hi,

Regarding NaCl - it's async (no sync interface for JS).

About simulating a wait - since JS is single threaded, blocking the only thread by waiting on something is kind of something the languages does not support. You could try something like a while (true) {} loop that breaks when you set a variable to quit the loop once the native code posted the response, but my guess is that this will just make your extension crash or get stuck (worth the experiment though). 

Another wacky solution would be like I suggested, using sync XML Http to call a web service that will process the request data using your native code. 

But I would say that both of these solutions are against the basic design of chrome extensions and javascript in general. 

Cheers,
Or

Amit Shinde

unread,
Feb 12, 2014, 7:54:32 AM2/12/14
to chromium-...@chromium.org, Or Hiltch, amitsh...@yahoo.com
Or, thank you again for the details.

Also it seems that due to single threaded nature of JavaScript, not sure whether it will invoke another event/message even after simulating wait (as JavaScript handles only one event/message at a time). Is this something possible using webworker thread?

Michael Vidrevich

unread,
Nov 14, 2017, 8:50:08 AM11/14/17
to Chromium-Extensions-Announce, amitsh...@yahoo.com
Hi Amit,

I have the same problem. In Mozilla Firefox we can resolve the problem by using Promise technology. But in Chrome there is no appropriate solution yet (or, at least, i not found it)
Please update the topic when you will find something

Regards,
Michael
Reply all
Reply to author
Forward
0 new messages