Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Service Workers in Google Chrome extensions to modify an HTTP response body?

Now that Google Chrome extensions can register Service Workers, how can I use them in order to modify HTTP responses from all hosts, e.g. by replacing all occurrences of cat with dog?

Below is a sample code from Craig Russell, but how to use it inside Chrome extensions and bind it to all hosts?

self.addEventListener('fetch', function(event) {
    event.respondWith(
        fetch(event.request).then(function(response) {
            var init = {
                status:     response.status,
                statusText: response.statusText,
                headers:    {'X-Foo': 'My Custom Header'}
            };
            response.headers.forEach(function(v,k) {
                init.headers[k] = v;
            });
            return response.text().then(function(body) {
                return new Response(body.replace(/cat/g, 'dog'), init);
            });
        })
    );
});
like image 437
niutech Avatar asked Dec 27 '16 18:12

niutech


People also ask

What is a service worker Chrome extension?

A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don't need a web page or user interaction.

How does a service worker work?

Service workers are specialized JavaScript assets that act as proxies between web browsers and web servers. They aim to improve reliability by providing offline access, as well as boost page performance.


1 Answers

Solution

≪manifest.json≫:

{"manifest_version":2,"name":"","version":"0","background":{"scripts":["asd"]}}

≪asd≫:

navigator.serviceWorker.register('sdf.js').then(x=>console.log('done', x))

≪sdf.js≫:

addEventListener('fetch', e=> e.respondWith(fetch/*btw xhr is undefined*/(e.request).then(r=>{
  if(r.headers === undefined /*request not end with <.htm>, <.html>*/){}else{
    console.assert(r.headers.get('content-type')===null)/*for some odd reason this is empty*///[
      let h = new Headers()
      r.headers.forEach((v,k)=>h.append(k,v))
      Object.defineProperty(r,'headers',{'writable':true})
      r.headers = h
      r.headers.append('content-type','text/html'/*btw <htm> doesnt work*/)
    //]
  }
  return r.text().then(_=>new Response(_.replace(/cat/g,'dog'),r))
})))

Go to &Lt;page url&Gt; (&Lt;chrome-extension://&Lt;ext id&Gt;/&Lt;page path&Gt;&Gt;) and see the replacements.


Standalone response

&Lt;manifest.json&Gt; and &Lt;asd&Gt; same as above.

&Lt;sdf.js&Gt;:

addEventListener('fetch', e=> e.respondWith(new Response('url: '+e.request.url,{headers:{'content-type':'text/html'/*, etc*/}})))


Btw

Serviceworker has other events that can be delved into eg:

addEventListener('message', e=>{
  console.log('onmessage', e)
})
addEventListener('activate', e=>{
  console.log('onactivate', e)
})
addEventListener('install', e=>{
  console.log('oninstall', e)
})


Alternatives

Note that currently serviceworker [–cf webNavigation, webRequest] is the only way to do this because some lamer in Google development team has decided that its "insecure" for response-modifying webNavigation and webRequest.


Note

Chrome bugs:

  • Extension &Lt;Reload&Gt; will not reload serviceworkers. You need to remove the extension and load it back in.
  • Page refresh does not refresh, even with chrome devtools disable cache hard reload. Use normal page visit.
like image 158
Pacerier Avatar answered Sep 28 '22 06:09

Pacerier