Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

Modify a web page

One of the most common use cases for an extension is to modify a web page. For example, an extension 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 APIs:

  • Declaratively: Define a pattern that matches a set of URLs, and 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 calledcontent scripts, and are different from the other scripts that make up an extension:

  • 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 extension using a messaging API.

In this article we'll look at both methods of loading a script.

Modifying pages that match a URL pattern

First of all, create a new directory called "modify-page". In that directory, create a file called "manifest.json", with the following contents:

json
{  "manifest_version": 2,  "name": "modify-page",  "version": "1.0",  "content_scripts": [    {      "matches": ["https://developer.mozilla.org/*"],      "js": ["page-eater.js"]    }  ]}

Thecontent_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 underhttps://developer.mozilla.org/.

Note:Since the"js" property ofcontent_scripts is an array, you can use it to inject more than one script into matching pages. If you do this the pages share the same scope, just like multiple scripts loaded by a page, and they are loaded in the order that they are listed in the array.

Note:Thecontent_scripts key also has a"css" property that you can use to inject CSS stylesheets.

Next, create a file called "page-eater.js" inside the "modify-page" directory, and give it the following contents:

js
document.body.textContent = "";let header = document.createElement("h1");header.textContent = "This page has been eaten";document.body.appendChild(header);

Nowinstall the extension, and visithttps://developer.mozilla.org/. The page should look like this:

developer.mozilla.org page "eaten" by the script

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:

json
{  "manifest_version": 2,  "name": "modify-page",  "version": "1.0",  "permissions": ["activeTab", "contextMenus"],  "background": {    "scripts": ["background.js"]  }}

Here, we've removed thecontent_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 be able to add context menu items.
  • background: We're using this to load a persistent"background script" calledbackground.js, in which we'll set up the context menu and inject the content script.

Let's create this file. Create a new file calledbackground.js in themodify-page directory, and give it the following contents:

js
browser.contextMenus.create({  id: "eat-page",  title: "Eat this page",});browser.contextMenus.onClicked.addListener((info, tab) => {  if (info.menuItemId === "eat-page") {    browser.tabs.executeScript({      file: "page-eater.js",    });  }});

In this script we're creating acontext menu item, giving it a specific id and title (the text to be displayed in the context menu). Then we set up an event listener so that when the user clicks a context menu item, we check to see if it is oureat-page item. If it is, we inject "page-eater.js" into the current tab using thetabs.executeScript() API. This API optionally takes a tab ID as an argument: we've omitted the tab ID, which means that the script is injected into the currently active tab.

At this point the extension should look like this:

modify-page/    background.js    manifest.json    page-eater.js

Nowreload the extension, open a page (any page, this time) activate the context menu, and select "Eat this page":

Option to eat a page on the context menu

Messaging

Content scripts and background scripts can't directly access each other's state. However, they can communicate by sending messages. One end sets up a message listener, and the other end can then send it a message. The following table summarizes the APIs involved on each side:

In content scriptIn background script
Send a messagebrowser.runtime.sendMessage()browser.tabs.sendMessage()
Receive a messagebrowser.runtime.onMessagebrowser.runtime.onMessage

Note:In addition to this method of communication, which sends one-off messages, you can also use aconnection-based approach to exchange messages. For advice on choosing between the options, seeChoosing between one-off messages and connection-based messaging.

Let's update our example to show how to send a message from the background script.

First, editbackground.js so that it has these contents:

js
browser.contextMenus.create({  id: "eat-page",  title: "Eat this page",});function messageTab(tabs) {  browser.tabs.sendMessage(tabs[0].id, {    replacement: "Message from the extension!",  });}function onExecuted(result) {  let querying = browser.tabs.query({    active: true,    currentWindow: true,  });  querying.then(messageTab);}browser.contextMenus.onClicked.addListener((info, tab) => {  if (info.menuItemId === "eat-page") {    let executing = browser.tabs.executeScript({      file: "page-eater.js",    });    executing.then(onExecuted);  }});

Now, after injectingpage-eater.js, we usetabs.query() to get the currently active tab, and then usetabs.sendMessage() to send a message to the content scripts loaded into that tab. The message has the payload{replacement: "Message from the extension!"}.

Next, updatepage-eater.js like this:

js
function eatPageReceiver(request, sender, sendResponse) {  document.body.textContent = "";  let header = document.createElement("h1");  header.textContent = request.replacement;  document.body.appendChild(header);}browser.runtime.onMessage.addListener(eatPageReceiver);

Now, instead of just eating the page right away, the content script listens for a message usingruntime.onMessage. When a message arrives, the content script runs essentially the same code as before, except that the replacement text is taken fromrequest.replacement.

Sincetabs.executeScript() is an asynchronous function, and to ensure we send message only after listener has been added inpage-eater.js, we useonExecuted() which will be called afterpage-eater.js executed.

Note:PressCtrl+Shift+J (orCmd+Shift+J on macOS) ORweb-ext run --bc to openBrowser Console to viewconsole.log in background script.

Alternatively, useAdd-on Debugger which allows you set breakpoint. There is currently no way tostart Add-on Debugger directly from web-ext.

If we want send messages back from the content script to the background page, we would useruntime.sendMessage() instead oftabs.sendMessage(), e.g.:

js
browser.runtime.sendMessage({  title: "from page-eater.js",});

Note:These examples all inject JavaScript; you can also inject CSS programmatically using thetabs.insertCSS() function.

Learn more

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp