Messaging APIs allow you to communicate between different scripts running in contexts associated with your extension. This includes communication between your service worker, chrome-extension://pages and content scripts. For example, an RSS reader extension might use content scripts to detect the presence of an RSS feed on a page, then notify the service worker to update the action icon for that page.
There are two message passing APIs: one for one-time requests, and a more complex one for long-lived connections that allow multiple messages to be sent.
For information about sending messages between extensions, see the cross-extension messages section.
One-time requests
To send a single message to another part of your extension, and optionally get a
response, call runtime.sendMessage() or tabs.sendMessage().
These methods let you send a one-time JSON-serializable message from a content script to the
extension, or from the extension to a content script. Both APIs return a Promise
which resolves to the response provided by a recipient.
Sending a request from a content script looks like this:
content-script.js:
(async () => {
const response = await chrome.runtime.sendMessage({greeting: "hello"});
// do something with response here, not outside the function
console.log(response);
})();
Responses
To listen for a message, use the chrome.runtime.onMessage event:
// Event listener
function handleMessages(message, sender, sendResponse) {
if (message !== 'get-status') return;
fetch('https://example.com')
.then((response) => sendResponse({statusCode: response.status}))
// Since `fetch` is asynchronous, must return an explicit `true`
return true;
}
chrome.runtime.onMessage.addListener(handleMessages);
// From the sender's context...
const {statusCode} = await chrome.runtime.sendMessage('get-status');
When the event listener is called, a sendResponse function is passed as the
third parameter. This is a function that can be called to provide a response. By
default, the sendResponse callback must be called synchronously.
If you call sendResponse without any parameters, null is sent as a response.
To send a response asynchronously, you have two options: returning true or
returning a promise.
Return true
To respond asynchronously using sendResponse(), return a literal true
(not just a truthy value) from the event listener. Doing so will keep the
message channel open to the other end until sendResponse is called, allowing
you to call it later.
Return a promise
From Chrome 148, you can return a promise from a message listener to
respond asynchronously. This update is rolling out gradually, so you may find
that it's not yet available in all users' browsers. You should make sure your
extension can handle whether this capability is enabled or not. Using
return true; will continue to work for asynchronous responses whether this
capability is enabled or not.
If the promise resolves, its resolved value is sent as the response.
If the promise is rejected, the sender's sendMessage() call
will be rejected with the error's message. See the
error handling section for more details and examples.
An example that shows returning a promise that could resolve or reject:
// Event listener
function handleMessages(message, sender, sendResponse) {
// Return a promise that wraps fetch
// If the response is OK, resolve with the status. If it's not OK then reject
// with the network error that prevents the fetch from completing.
return new Promise((resolve, reject) => {
fetch('https://example.com')
.then(response => {
if (!response.ok) {
reject(response);
} else {
resolve(response.status);
}
})
.catch(error => {
reject(error);
});
});
}
chrome.runtime.onMessage.addListener(handleMessages);
You can also declare a listener as async to return a promise:
chrome.runtime.onMessage.addListener(async function(message, sender) {
const response = await fetch('https://example.com');
if (!response.ok) {
// rejects the promise returned by `async function`.
throw new Error(`Fetch failed: ${response.status}`);
}
// resolves the promise returned by `async function`.
return