This is a detailed customized chrome extension configuration cheatsheet.
Manifest
1 | { |
BrowerAction Methods
1 | chrome.browserAction.method(params) |
- setTitle({ title: string, tabId?: number }, callback)
- getTitle({ tabId?: number },
callback) - setIcon({ imageData?: ImageDataType | object, path?: string | object, tabId?: number }, callback)
- setPopup({ tabId?: number, popup: string }, callback)
- getPopup({ tabId?: number },
callback) - setBadgeText({ text: string, tabId?: number }, callback)
- getBadgeText({ tabId?: number },
callback) - setBadgeBackgroundColor({ color: string or ColorArray, tabId?: number }, callback)
- getBadgeBackgroundColor({ tabId?: number }, callback)
- enable({ tabId?: number }, callback)
- disable({ tabId?: number }, callback)
BrowserAction Events
1 | chrome.browserAction.onClicked.addEventListener((tab: tabs.Tab) => {}) |
PageAction Methods
1 | chrome.pageAction.method(params) |
- show({ tabId: number }, callback), the page action is shown whenever the tab is selected
- hide({ tabId: number }, callback), hide the page action, means set the page action gray
- setTitle({ tabId: number, title: string }, callback)
- getTitle({ tabId: number },
callback) - setIcon({ imageData: object | ImageDataType, path?: string | object, }), the path to the icons could be a dictionary {size => relative image path}, the actual image to be used is chosen depending on screen’s pixel density. Note that path = ‘foo’ equals to path = { ‘16’: foo }, implicitly converted into a dictionary.
- setPopup({ tabId: number, popup: string }, callback)
- getPopup({ tabId },
callback)
PageAction Events
1 | chrome.pageAction.onClicked.addEventListener((tab: tabs.Tab) => {}) |
Background
Extensions are event-driven programs used to modify or enhance the chrome browsing experience. Events are browser triggers and extensions monitor them in background scripts, then react to specified instructions.
A background page is loaded when it is needed, and unloaded when it goes idle.
- The extension is first installed or updated to a new version.
- The background page was listening for an event, and the event is dispatched.
- A content script or other extension sends a message.
- Another view in the extension, such as a popup, calls `runtime.getBackgroundPage`.
Register background scripts
Background scripts are registered in the manifest under the “background” field. They are listed in an array of “background.scripts”.
Remember to set “persistent” to false unless the extension uses chrome.webRequest
API to block or modify network requests.
Initialize the extension
Listen to runtime.onInstalled
event to initialize an extension on installation. Use this event to set a state or for one-time initialization, such as a context menu.
1 | chrome.runtime.onInstalled.addListener(() => { |
Set up listeners
Structure background scripts around events the extension depends on. Defining functionally relevant events allows background scripts to lie dormant until those events are fired and prevents the extension from missing important triggers.
Listeners must be registered synchronously from the start of the page.
1 | // This will run when a bookmark is created |
Do not register listeners asynchronously, as they will not be properly triggered.
1 | // DO NOT DO THIS |
Filter events
Use APIs that supports event filters
to restrict listeners to the cases the extension cares about. If an extension is listening for the tabs.onUpdated
event, try using the webNavigation.onCompleted
event with filters instead, as the tabs API does not support filters.
1 | chrome.webNavigation.onCompleted.addListener( |
React to listeners
1 | chrome.runtime.onMessage.addListener((message, callback) => { |
Unload background scripts
Data should be persisted periodically so that important information is not lost if an extension crashes without receiving onSuspend
. Use the storage
API to assist with this.
1 | chrome.storage.local.set({ variable: 'info' }) |
If an extension uses message passing
, ensure all ports are closed. The background script will not unload until all message ports have shut.
Listen to runtime.Port.onDisconnect
event will give insight to when open ports are closing. Manually close them with runtime.Port.disconnect
.
Background scripts unload themself after a few seconds of inactivity. If any last minute cleanup is required, listen to runtime.onSuspend
event.
1 | chrome.runtime.onSuspend.addListener(() => { |
Content scripts
Content scripts are files that run in the context of web pages. By using the standard DOM, they are able to read details of the web pages the browser visits, make changes to them and pass information to their parent extension.
Content scripts can access chrome APIs used by their parent extension by exchanging messages with the extension. They can also access the URL of an extension’s file with chrome.runtime.getURL()
and use the result the same as other URLs.
Content scripts can access the following chrome APIs directly:
- i18n
- storage
- runtime
- connect
- getManifest
- getURL
- id
- onConnect
- onMessage
- sendMessage
Content scripts are unable to access other APIs directly.
Work in isolated worlds
Content scripts live in an isolated world, allowing a content script to makes chagnes to its JavaScript environment without conflicting with the page or additional content scripts.
Inject scripts
Content scripts can be programmatically or declaratively injected.
Inject Programmatically
Use programmatic injection for content scripts that need to run on specific occasions.
To inject a programmatic content script, provide the activeTab
permission in the manifest. This grants secure access to the active site’s host and temporary access to the tabs
permission, enabling the content script to run on the current active tab without specifying cross-origin premissions
.
1 | { |
Then content scripts can be injected as code
1 | chrome.runtime.onMessage.addListener((message, callback) => { |
Inject declaratively
Use declarative injection for content scripts that should be automatically run on specified pages.
Declaratively injected scripts are registered in the manifest.content_scripts field.
1 | { |
Chrome Permissions
Use the chrome.permission
API to request declared optional permissions at run time rather than install time, so users understand why the permissions are needed and grant only those that are necessary.
Decide which permissions are required and which are optional
An extension can declare both required and optional permissions. In general, you should:
- Use required permissions when they are needed for your extension’s basic functionality.
- Use optional permissions when they are needed for optional features in your extension.
Advantages of required permissions:
- Fewer prompts: An extension can prompt the user once to accept all permissions.
- Simpler development: Required permissions are guaranteed to be present.
Advantages of optional permissions:
- Better security
- Better information for users: An extension can explain why it needs a particular permission when the user enables the relevant feature.
- Easier upgrades: When you upgrades your extension, chrome will not disable it for your users if the upgrade adds optional rather than required permissions.
Declare optional permissions in your extension manifest with the optional_permissions
key, using the same format as the permission
field.
Request optional permissions
Request the permission from within a user gesture using permissions.request()
.
1 | document.querySelector('#my-button').addEventListener('click', (e) => { |
Check the extension’s current permissions
1 | chrome.permissions.contains( |
Remove the permissions
1 | chrome.permissions.remove( |
Requirements
Technologies required by the app or extension. Hosting sites such as chrome web store may use this list to dissuade users from installing apps or extensions that will not work on their computer.
Supported requirements currently include “3D” and “plugins”.
Messages
Since content scripts run in the context of a web page and not the extension, they often need some way of communicating with the rest of the extension. For example, an RSS reader extension might use content script to detect the presence of an RSS feed on a page, then notify the background page in order to display a page action icon for that page.
Communication between extensions and their content script scripts works by using message passing. Either side can listen for message sent from the other end, and respond on the same channel. A message can contain any valid JSON object.
Simple one-time requests
If you only need to send a single message to another part of your extension, you should use the simplified runtime.sendMessage
and tabs.sendMessage
. This lets you send a one-time JSON-serializable message from a content script to extension, or vice versa, respectively.
1 | // send a request from content script |
1 | // send a request from the extension to a content script works similar, except that you need to specify which tab to send it to. |
On the receiving end, you need to set up an runtime.onMessage
event listener to handle the message.
1 | chrome.runtime.onMessage.addListener((req, sender, sendRespond) => { |
In the above example, the sendResponse
is called synchronously. If you want to call the sendResponse
asynchronously, simple return true
at the end.
Note: If multiple pages are listening on the onMessage events, only the first to call
sendResponse
for a particular event will succeed in sending response. Other response will be ignored.
Note: call sendResponse synchronously or return true. Without return true, sendResponse(undefined) will be called automatically and implicitly.
Long-lived connections
Sometimes it’s useful to have a conversation lasting longer than one-time request.
You can open a long-lived channel from content script to an extension page, or vice versa, by using runtime.connect
or tab.connect
.
When establishing a connection, each end is given a runtime.Port
object which is used for sending and receiving messages through that connection.
1 | const port = chrome.runtime.connect({ name: 'knockknock' }) |