One of the most common use cases for a browser add-on is to modify a web page. For example, an add-on might want to change the style applied to a page, hide particular DOM nodes, or inject extra DOM nodes into the page.
There are two ways to do this with WebExtensions:
- declaratively: define a pattern than matches a set of URLs, and ask the browser to load a set of scripts into pages whose URL matches that pattern
- programmatically: using a JavaScript API, load a script into the page hosted by a particular tab.
Either way, these scripts are called content scripts, and are different from the other scripts that make up a WebExtension:
- they only get access to a small subset of the WebExtension APIs
- they get direct access to the web page in which they are loaded
- they communicate with the rest of the WebExtension using a messaging API.
In this article we'll look at both methods of loading a script.
Modifying pages that match a URL pattern
Create a new directory called "modify-page". In that directory, create a file called "manifest.json" which has the following contents:
{ "manifest_version": 2, "name": "modify-page", "version": "1.0", "content_scripts": [ { "matches": ["https://addons.mozilla.org/*"], "js": ["page-eater.js"] } ] }
The content_scripts
key is how you load scripts into pages that match URL patterns. In this case, content_scripts
instructs the browser to load a script called "page-eater.js" into all pages under https://addons.mozilla.org/.
Next, create a file called "page-eater.js" with the following contents:
document.body.textContent = ""; var header = document.createElement('h1'); header.textContent = "This page has been eaten"; document.body.appendChild(header);
Now install the WebExtension, and visit https://addons.mozilla.org/:
{{EmbedYouTube("lxf2Tkg6U1M")}}
Modifying pages programmatically
What if you still want to eat pages, but only when the user asks you to? Let's update this example so we inject the content script when the user clicks a context menu item.
First, update "manifest.json" so it has the following contents:
{ "manifest_version": 2, "name": "modify-page", "version": "1.0", "permissions": [ "activeTab", "contextMenus" ], "background": { "scripts": ["background.js"] } }
Here, we've removed the content_scripts
key, and added two new keys:
permissions
: to inject scripts into pages we need permissions for the page we're modifying. TheactiveTab
permission is a way to get this temporarily for the currently active tab. We also need thecontextMenus
permission to add context menu items.background
: we're using this to load a persistent "background script" called "background.js", in which we'll set up the context menu and inject the content script.
Next, create "background.js", and give it the following contents:
chrome.contextMenus.create({ id: "eat-page", title: "Eat this page" }); chrome.contextMenus.onClicked.addListener(function(info, tab) { if (info.menuItemId == "eat-page") { chrome.tabs.executeScript({ file: "page-eater.js" }); } });
s