Can a website block a Chrome Extension? [duplicate]

Since the other answer didn’t really answer anything about actually stopping an extension, I thought I would add my own two cents. Using the method in the other answer, you can sometimes detect if a particular extension is installed and react accordingly, but this requires you to test for a particular ID string and file for that particular extension. I am sure that we can all agree that this isn’t a very encompassing solution.

There are many things about extensions that you cannot stop from within your site, such as the chrome.webRequest api that adblock makes use of. There is nothing you can do to interfere directly with that sort of code, but there is plenty you can do on the DOM manipulation side.

Content Scripts operate in an isolated world meaning that they cannot see/interact with the javascript running on the site. They do, however, have complete access to the DOM and can do whatever they want to it. Conversely, your own javascript has the same access to that DOM. Taking advantage of that isolated world we can set up a MutationObserver to watch over the DOM and prevent any unwanted changes. Because of the isolated world, content scripts cannot disable or turn off our observer while our own javascript can do so freely.

Here is an example of a MutationObserver that locks down the DOM with a little jQuery mixed in because I am lazy.

var config= {childList: true,
             attributes: true,
             characterData: true, 
             subtree: true, 
             attributeOldValue: true, 
             characterDataOldValue: true};
var observer = new MutationObserver(function(mutations){
  mutations.forEach(function(mutation){
    switch(mutation.type){
      case "attributes":
        observer.disconnect();
        if(mutation.attributeName == "class")
         mutation.target.className = mutation.oldValue;
        else if(mutation.attributeName=="id"||mutation.attributeName=="title")
         mutation.target[mutation.attributeName] = mutation.oldValue;
        else if(mutation.attributeName == "style")
          mutation.target.style.cssText = mutation.oldValue;
        observer.observe(document,config);
        break;
      case "characterData":
        observer.disconnect();
        mutation.target.data = mutation.oldValue;
        observer.observe(document,config);
        break;
      case "childList":
        observer.disconnect();
        if(mutation.addedNodes.length > 0)
          $(mutation.addedNodes[0]).remove();
        if(mutation.removedNodes.length > 0){
          if(mutation.nextSibling)
            $(mutation.removedNodes[0]).insertBefore(mutation.nextSibling);
          else if(mutation.previousSibling)
            $(mutation.removedNodes[0]).insertAfter(mutation.previousSibling);
          else
            $(mutation.removedNodes[0]).appendTo(mutation.target);
        }
        observer.observe(document,config);
        break;
    }
  });
});

$(function(){
  observer.observe(document,config);
});

Throwing it into a chrome extension with a simple manifest such as:

{
  "name": "DOM Polymerase",
  "version": "1.0",
  "manifest_version": 2,
  "permissions": [
    "tabs","<all_urls>"
  ],
  "content_scripts": [{
    "matches": ["http://example.iana.org/*"],
    "js": ["jquery-1.8.3.min.js","polymerase.js"]
  }]
}

And navigating to http://example.iana.org/ will show that external manipulation of the DOM (except for some attributes, I didn’t code them all in there) is no longer possible. Of course, in this case internal manipulation is also denied, but if the code was in the site instead of an extension, it would be a different story. While this doesn’t disable extensions completely, it should at least preserve your DOM.

Leave a Comment