preface
This article is aimed at getting started with Chrome development. If you need further development, you can go to the Chrome official website to learn. The official website provides a demo to modify the background color of the web page, you can click download, if you have problems with the download, you can go to Github
This article will list some common concepts, including five JS type comparisons, six cores, message communication and some dynamic injection, packaged publishing, etc.
This article concludes with a Chrome demo that turns pages into dark mode
The demo effect is as follows:
The plugin will be highlighted on the JD.com TAB page and the color will be gray on other TAB pages. How to do this is explained in the demo
What is the Chrome plugin?
The real name of chrome plug-in mentioned in this article should be Chrome Extension (Chrome Extension), the real plug-in refers to the lower level of browser function Extension, may need to have a certain understanding of Chrome source code to develop.
The Chrome add-ons in this article refer to some of the Chrome extensions we use everyday.
Extensions are small software programs that customize the browsing experience. They enableusers to tailor Chrome functionality and behavior to individual needs or preferences. They are built on web technologies such as HTML, JavaScript, and CSS.Copy the code
Chrome Extension is a small software program that allows you to customize your browsing experience. They allow users to customize Chrome features and behavior based on their personal needs or preferences. It is built on Web technologies such as HTML, JavaScript, and CSS.
Why learn Chrome Extension development?
With Chrome Extension development, we can easily customize our own browser, enhance some browser functions, strengthen our learning ability, and also have some other aspects of our business thinking.
More skills, more skills, maybe when you go to the next company, you will have more skills.
Six core
The six core concepts include Manifest Format, Manage Events, Design User Interface, Content Scripts, Declare Permissions and Warn Users, and Give Users Options
Manifest Format – The official documentation
Each Chrome Extension comes with a MANIFEST file in JSON format called manifest.json that provides important information. Used to configure all plugin-related configurations, must be placed under the project root directory. The simple configuration is as follows
{
"name": "TimeStone"."manifest_version": 2."version": "1.0"."description": "TimeStone Extension"."page_action": {
"default_icon": "images/icon.png"."default_title": "TimeStone plug-in"."default_popup": "html/home.html"
},
"background": {
"scripts": ["js/background.js"]},"options_page": "html/options.html"."homepage_url": "https://juejin.cn/user/4230576473387773"."permissions": [
"tabs"."storage"."activeTab"]}Copy the code
The configuration is described as follows: [Note] It must be marked in bold and highlighted is recommended
- Manifest_version – You have to have it, and it has to be 2
- Name – Plug-in name
- Version – Indicates the version number
- Description – description
- The ICONS – icon
- Homepage_url – Plugin homepage, ha ha, I usually set to my own gold digging homepage
- background- The background JS or background page that will always be resident, can be specified in two ways
"background"If you specify JS, a background page will be generated automatically"page": "background.html" //"scripts": ["js/background.js"]}Copy the code
- Browser_action, page_Action, app- Displayed in the upper right corner of the browser
"browser_action": { "default_icon": "img/icon.png"// The title of the hovering icon, optional"default_title": "This is a sample Chrome plugin"."default_popup": "popup.html" } "page_action": { "default_icon": "img/icon.png"."default_title": "I am pageAction"."default_popup": "popup.html" } Copy the code
- permissions- Set plug-in permission application
"permissions": [ "contextMenus"// Right-click the menu"tabs", / / label"notifications"/ / notice"webRequest", // Web request"webRequestBlocking"."storage", // Plug-in local storage]Copy the code
- Web_accessible_resources – A list of plug-in resources that can be accessed directly by a normal page
- Chrome_url_overrides – overrides the browser default page
- Options_ui – Plugin configuration page writing
- omnibox- Register a keyword to the address bar to provide search suggestions. Only one keyword can be set
"omnibox": { "keyword" : "rick" } Copy the code
- Default_locale – The default language
- Devtools_page – DevTools page entry. Note that it can only point to an HTML file, not a JS file
Manage Events with Background Scripts -The official documentation
Chrome Ex is an event-based program used to modify or enhance the Chrome browser experience. Events are browser triggers, for example, to navigate to a new page, delete a bookmark or close a TAB. The extender monitors these events in its background scripts and then responds with specified instructions.
Background pages are loaded when needed and unloaded when idle. Some examples of events include:
- The extension is first installed or updated to a new version.
- The background page is listening for an event and has scheduled the event.
- Content scripts or other extensions send messages.
- Another view in the program (for example, the pop-up window) to invoke the runtime. GetBackgroundPage.
Valid background scripts remain dormant until events listen for fire, react to specified instructions, and then unload.
Register Background Scripts
Configure it in manifest.json as follows
{
"name": "Awesome Test Extension"."background": {
"scripts": ["js/background.js"]."persistent": false},... }Copy the code
Initialize the extension
Listen for runtime.onInstalled events, which can be used to set state or perform an initialization. Take the context menu.
chrome.runtime.onInstalled.addListener(function() {
chrome.contextMenus.create({
"id": "sampleContextMenu"."title": "Sample Context Menu"."contexts": ["selection"]}); });Copy the code
Setting up listeners
Build background scripts around extended-dependent events. Defining functionally-relevant events puts background scripts to sleep until they are fired and prevents extensions from missing important triggers.
Listeners must be synchronously registered from the page.
chrome.runtime.onInstalled.addListener(function() {
chrome.contextMenus.create({
"id": "sampleContextMenu"."title": "Sample Context Menu"."contexts": ["selection"]}); }); // This will run when a bookmark is created. chrome.bookmarks.onCreated.addListener(function() {
// do something
});
Copy the code
Do not register listeners asynchronously, because they will not be triggered correctly.
chrome.runtime.onInstalled.addListener(function() {
// ERROR! Events must be registered synchronously from the start of
// the page.
chrome.bookmarks.onCreated.addListener(function() {
// do something
});
});
Copy the code
An extender can remove removeListener listeners from its background scripts with a call. If all listeners for an event are removed, Chrome will no longer load the extension’s background script for the event.
chrome.runtime.onMessage.addListener(function(message, sender, reply) {
chrome.runtime.onMessage.removeListener(event);
});
Copy the code
Screening event
Use an API that supports event filters to limit listeners to cases where the extension is concerned. If the add-in is listening tabs. OnUpdated event, please try to use webNavigation. OnCompleted events with a filter, because tabs API does not support filters.
chrome.webNavigation.onCompleted.addListener(function() {
alert("This is my favorite website!");
}, {url: [{urlMatches : 'https://www.google.com/'}]});
Copy the code
Respond to events
After the event is triggered, there are listeners that can trigger functionality. To react to an event, construct the desired response inside the listener event.
chrome.runtime.onMessage.addListener(function(message, callback) {
if(the message data = ="setAlarm ") {chrome.alarms. Create ({delayInMinutes: 5})}else if(the message data = = "runLogic") {chrome. Tabs. ExecuteScript ({file:'logic.js'});
} else if(the message data = = "changeColor") {chrome. Tabs. ExecuteScript ({code:'document.body.style.backgroundColor="orange"'});
};
});
Copy the code
Uninstalling background Scripts
Data should be saved periodically in case important information is lost and the extension crashes to receive onSuspend. Using the Storage API can help with this task.
chrome.storage.local.set({variable: variableInformation});
Copy the code
If the extension uses messaging, make sure all ports are turned off. Background scripts are not unloaded until all message ports are closed. Listen for the runtime. Port. OnDisconnect events will provide insights about open Port when closed. Turn them off manually using Runtime.port.disconnect.
chrome.runtime.onMessage.addListener(function(message, callback) {
if (message == 'hello') {
sendResponse({greeting: 'welcome! '})}else if (message == 'goodbye') { chrome.runtime.Port.disconnect(); }});Copy the code
You can observe the life of background scripts by monitoring when an extension’s entry appears and disappears from Chrome’s task manager.
After a few seconds of inactivity, the background script unloads itself. If you need a last-minute cleanup, listen to the Runtime.onsuspend event.
chrome.runtime.onSuspend.addListener(function() {
console.log("Unloading.");
chrome.browserAction.setBadgeText({text: ""});
});
Copy the code
In contrast, however, persistent data runtime.onsuspend should be preferred. It doesn’t allow for as much cleanup as possible, and it doesn’t help when it crashes.
Design User Interface – The official documentation
Extending the user interface should be purposeful and minimal. Like the extension itself, the UI should customize or enhance the browsing experience without becoming a distraction.
Enable the extension on all pages
Use browser_action when the extender’s functionality is available in most cases.
-
Register browser_action in manifest.json
{ "name": "My Awesome browser_action Extension"."browser_action": {... }... }Copy the code
Declare “browser_action” and keep the icon in color to indicate that the extension is available to the user.
-
Add a badge
A badge displays some text on an icon and a colored banner containing up to four characters above the browser icon. They can only be used by extensions declared by “browser_action” in its manifest.
Call to set the text of the badge, and call to set the color of the banner. chrome.browserAction.setBadgeText chrome.browserAction.setBadgeBackgroundColor
Activate the extension on the selected page
Use page_action when the extender’s functionality is only available under defined conditions.
- inmanifest.jsonregistered
page_action
{ "name": "My Awesome page_action Extension"."page_action": {... }... }Copy the code
The “page_action” declaration will color the icon only if the extension is available to the user, otherwise it will appear in grayscale.
-
Define the activation extension rule Through the script in the background of chrome. DeclarativeContent runtime. OnInstalled cut with the listener, and define when extended the rules may be used. Example page manipulation through A URL Extension sets a condition that the URL must contain “g”. If the conditions are met, the extension call is made. DeclarativeContent. ShowPageAction () [note] : here is the answer at jd.com TAB page, plug-in highlights show, in other color will be grey TAB page
chrome.runtime.onInstalled.addListener(function() { // Replace all rules ... chrome.declarativeContent.onPageChanged.removeRules(undefined, function() { // With a new rule ... chrome.declarativeContent.onPageChanged.addRules([ { // That fires when a page's URL contains a 'g'... conditions: [ new chrome.declarativeContent.PageStateMatcher({ pageUrl: { urlContains: 'jd.com' }, }) ], // And shows the extension's page action. actions: [ new chrome.declarativeContent.ShowPageAction() ] } ]); }); }); Copy the code
-
Using “page_Action”, an extender can dynamically activate and disable PageAction.hide by calling pageAction.show and.
The MAPPY sample extension scans web pages for addresses and displays pop-up locations on static maps. Because the extension depends on the content of the page, there is no way to declare rules to predict which pages will be relevant. Instead, if the address is found on the page, it calls pageAction.show to color the icon and signal that the extension is available on the TAB.
chrome.runtime.onMessage.addListener(function(req, sender) { chrome.storage.local.set({'address': req.address}) chrome.pageAction.show(sender.tab.id); chrome.pageAction.setTitle({tabId: sender.tab.id, title: req.address}); }); Copy the code
Provide extension ICONS
The extension requires at least one icon to represent it. Although you can accept any WebKit supported format, including BMP, GIF, ICO, and JPEG, ICONS provided in PNG format provide the best visual effects.
-
Specifies the toolbar icon
The toolbar-specific ICONS are registered in fields in the Manifest browser_action or page_action under manifest.json “default_icon”. Encourage inclusion of multiple dimensions to accommodate 16 inclination space. At least 16×16 and 32×32 sizes are recommended.
{ "name": "My Awesome page_action Extension"."page_action": { "default_icon": { "16": "extension_toolbar_icon16.png"."32": "extension_toolbar_icon32.png"}}... }Copy the code
All ICONS should be square, otherwise they may be distorted. If no icon is provided, Chrome adds a generic icon to the toolbar.
-
Create and register additional ICONS – Use additional ICONS of the following sizes outside the toolbar.
Size of the icon The icon to use 16×16 The site icon on the extension page 32×32 Windows computers typically need this size. Providing this option will prevent size distortion from decreasing by 48×48 option. 48×48 Displayed on the extension Management page 128×128 Displayed in the installation and Chrome Webstore { "name": "My Awesome Extension"."icons": { "16": "extension_icon16.png"."32": "extension_icon32.png"."48": "extension_icon48.png"."128": "extension_icon128.png"}... }Copy the code
Other UI functions
-
Popup
A pop-up window is an HTML file that appears in a special window when the user clicks on a toolbar icon. Pop-ups work much like web pages; It can contain links to stylesheet and script tags, but does not allow inline JavaScript.
The Drink Water Event sample pop-up window shows the timer options available. The user sets up the alert by clicking one of the buttons provided.
<html>
<head>
<title>Water Popup</title>
</head>
<body>
<img src='./stay_hydrated.png' id='hydrateImage'>
<button id='sampleSecond' value='0.1'>Sample Second</button>
<button id='15min' value='15'>15 Minutes</button>
<button id='30min' value='30'>30 Minutes</button>
<button id='cancelAlarm'>Cancel Alarm</button>
<script src="popup.js"></script>
</body>
</html>
Copy the code
The Settings above can live in browser_action or page_action
{
"name": "Drink Water Event"."browser_action": {
"default_popup": "popup.html"}... }Copy the code
Pop-ups can also be set dynamically by calling or. BrowserAction. SetPopup, pageAction. SetPopup
chrome.storage.local.get('signed_in'.function(data) {
if (data.signed_in) {
chrome.browserAction.setPopup({popup: 'popup.html'});
} else {
chrome.browserAction.setPopup({popup: 'popup_sign_in.html'}); }});Copy the code
- Tooltip – Use Tooptip to provide short instructions or instructions to the user when hovering over a browser icon.
browser_action
page_action
{
"name": "Tab Flipper"."browser_action": {
"default_title": "Press Ctrl(Win)/Command(Mac)+Shift+Right/Left to flip tabs"}... }Copy the code
The contents of Tooltips can also be updated with methods browserAction.setTitle and PageAction.setTitle.
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.browserAction.setTitle({tabId: tab.id, title: "You are on tab:" + tab.id});
});
Copy the code
- Omnibox users can invoke extension functionality through the Omnibox. Include the “Omnibox” field in the listing and specify the keyword. New TAB in url column search sample extension using “NT” as the keyword.
{
"name": "Omnibox New Tab Search". \..."omnibox": { "keyword" : "nt" },
"default_icon": {
"16": "newtab_search16.png"."32": "newtab_search32.png"}... }Copy the code
When the user enters “nt” in the utility box, it activates the extension. To signal the user, it grays the 16×16 icon provided and includes it in the multifunction box next to the extension.
This extension listens for events. When triggered, the extension opens a new TAB containing a Google search for the user’s entry. omnibox.onInputEntered
chrome.omnibox.onInputEntered.addListener(function(text) {
// Encode user input for special characters , / ? : @ & = + $ #
var newURL = 'https://www.google.com/search?q=' + encodeURIComponent(text);
chrome.tabs.create({ url: newURL });
});
Copy the code
-
Context Menu – Right-click Menu
Apply permission on contextMenus,
{ "name": "Global Google Search"."permissions": ["contextMenus"."storage"]."icons": { "16": "globalGoogle16.png"."48": "globalGoogle48.png"."128": "globalGoogle128.png"}... }Copy the code
The 16×16 icon appears next to the new menu item.
contextMenus.create
background script
runtime.onInstalled
const kLocales = {
'com.au': 'Australia'.'com.br': 'Brazil'.'ca': 'Canada'.'cn': 'China'.'fr': 'France'.'it': 'Italy'.'co.in': 'India'.'co.jp': 'Japan'.'com.ms': 'Mexico'.'ru': 'Russia'.'co.za': 'South Africa'.'co.uk': 'United Kingdom'
};
chrome.runtime.onInstalled.addListener(function() {
for (let key of Object.keys(kLocales)) {
chrome.contextMenus.create({
id: key,
title: kLocales[key],
type: 'normal',
contexts: ['selection']}); }});Copy the code
- Commands extensions can define specific Commands and bind them to composite keys. Register the required commands with the commands
{
"name": "Tab Flipper"."commands": {
"flip-tabs-forward": {
"suggested_key": {
"default": "Ctrl+Shift+Right"."mac": "Command+Shift+Right"
},
"description": "Flip tabs forward"
},
"flip-tabs-backwards": {
"suggested_key": {
"default": "Ctrl+Shift+Left"."mac": "Command+Shift+Left"
},
"description": "Flip tabs backwards"}}... }Copy the code
Commands can be used to provide new or alternative browser shortcuts. The Tab Flipper sample extension listens to Commands. OnCommand event background script for each registered combination and defines functionality.
chrome.commands.onCommand.addListener(function(command) {
chrome.tabs.query({currentWindow: true}, function(tabs) {
// Sort tabs according to their index in the window.
tabs.sort((a, b) => { return a.index < b.index; });
let activeIndex = tabs.findIndex((tab) => { return tab.active; });
let lastTab = tabs.length - 1;
let newIndex = -1;
if (command= = ='flip-tabs-forward')
newIndex = activeIndex === 0 ? lastTab : activeIndex - 1;
else // 'flip-tabs-backwards'
newIndex = activeIndex === lastTab ? 0 : activeIndex + 1;
chrome.tabs.update(tabs[newIndex].id, {active: true, highlighted: true});
});
});
Copy the code
- The Override Pages extension can Override the browser’s HTML with its own
New TAB
或bookmarks
Page. It can contain specialized logic and styles, but does not allow inline JavaScript. A single extension is limited to covering one of three possible pages.
The registration method is as follows
{
"name": "Awesome Override Extension"."chrome_url_overrides" : {
"newtab": "override_page.html"."bookmarks": "book.html"},... }Copy the code
<html>
<head>
<title>New Tab</title>
</head>
<body>
<h1>Hello World</h1>
<script src="logic.js"></script>
</body>
</html>
Copy the code
Content Scripts – The official documentation
Content scripts are files that run in the context of a web page. Using the standard Document Object Model (DOM), they can read the details of a web page visited by the browser, make changes to it and pass the information to its parent extension.
Content scripting capabilities
Content scripts can access the Chrome API used by their parent extension by exchanging messages with the extension. They can also use the URL to access the extension file, Chrome.runtime.geturl () and use the same results as any other URL.
//Code for displaying <extensionDir>/images/myimage.png:
var imgURL = chrome.runtime.getURL("images/myimage.png");
document.getElementById("someImage").src = imgURL;
Copy the code
Content scripts also have access to the following apis
- i18n
- storage
- runtime:
- connect
- getManifest
- getURL
- id
- onConnect
- onMessage
- sendMessage
Way to work
Content scripts run in an isolated world, allowing content scripts to align with JavaScript’s environment for changes without colliding with pages or other content scripts.
The extension can run in a Web page with code similar to the following example.
<html>
<button id="mybutton">click me</button>
<script>
var greeting = "hello, ";
var button = document.getElementById("mybutton");
button.person_name = "Bob";
button.addEventListener("click".function() {
alert(greeting + button.person_name + ".");
}, false);
</script>
</html>
Copy the code
This extension can inject the following content scripts.
var greeting = "hola, ";
var button = document.getElementById("mybutton");
button.person_name = "Roberto";
button.addEventListener("click".function() {
alert(greeting + button.person_name + ".");
}, false);
Copy the code
If this button is pressed, two alarms will appear simultaneously.
The isolated world does not allow content scripts, extensions and web pages to access any variables or functions created by other variables or functions. This also enables content scripts to enable functionality that web pages should not access.
Video learning link
Inject Scripts – Inject Scripts
Content scripts can be injected programmatically or declaratively.
-
Programmatically injected
Use program injection for content scripts that need to be run under specific circumstances. To inject programmatic content scripts, provide activeTab permissions in the manifest. This grants secure access to the active site host and temporary access to TAB permissions, allowing content scripts to run on the current active TAB without specifying cross-domain permissions.
{ "name": "My extension"."permissions": [ "activeTab"],... }Copy the code
Content scripts can be injected as code.
chrome.runtime.onMessage.addListener( function(message, callback) { if"ChangeColor (message = =") {chrome. Tabs. ExecuteScript ({code:'document.body.style.backgroundColor="orange"'}); }});Copy the code
You can also specify files
chrome.runtime.onMessage.addListener(
function(message, callback) {
if(message = = "runContentScript") {chrome. Tabs. ExecuteScript ({file:'contentScript.js'}); }});Copy the code
- Declarative injection is used for content scripts that run automatically on a specified page. The declarative injection script is in the
"content_scripts"
Register in the listing under the field. They can include JavaScript files and/or CSS files. All automatically run content scripts must be specifiedMatch the pattern
{
"name": "My extension"."content_scripts": [{"matches": ["http://*.nytimes.com/*"]."css": ["myStyles.css"]."js": ["contentScript.js"]}],... }Copy the code
The name of the | type | describe |
---|---|---|
matches | array of strings | Needs. Specifies which pages this content script will be injected into. For more details on the syntax of these strings, see”Match the patternFor information on how to exclude urls, seeMatch patterns and globals”. |
css | array of strings | Optional. A list of CSS files to insert that match the page. Before any DOM is constructed or displayed for the page, they are injected in the order in which they appear in this array. |
js | array of strings | Optional. A list of JavaScript files to insert that match the page. These are injected in the order in which they appear in the array. |
match_about_blank | boolean | Optional. Whether the script should inject matches into the About :blank parent frame or open frames that match one of the declared patterns in. The default is false. |
exclude_matches | array of strings | Optional. Exclude pages where this content script will be injected. For more details on the syntax of these strings, seeMatch the pattern. |
include_globs | array of strings | Optional. Then apply matches to include only those urls that also match the glob. Designed to simulate the Greasemonkey keyword.@include |
exclude_globs | array of strings | Optional. Matches is later applied to exclude urls that match the global. Designed to simulate the Greasemonkey keyword.@exclude |
{
"name": "My extension"."content_scripts": [{"matches": ["http://*.nytimes.com/*"]."exclude_matches": ["*://*/*business*"]."js": ["contentScript.js"]}],... }Copy the code
You can also specify the run time, communicate with the embedded page, specify the framework, more configuration please read the official link developer.chrome.com/extensions/…
Declare Permissions and Warn Users
The extension’s ability to access websites and most Chrome apis depends on its declared permissions. Permissions should be limited to those required for its function. Limiting permissions establishes the functionality of an extension and reduces the data intrusion that can result if an attacker breaches the extension. Protect extensions and their users by implementing explicit, minimum, and optional permissions.
Finishing permissions
Permissions are known strings that reference Chrome APIS or match patterns to grant access to one or more hosts. They are listed in the listing and specified as required or optional permissions.
{
"name": "Permissions Extension". // Mandatory permissions"permissions": [
"activeTab"."contextMenus"."storage"], // Optional permission"optional_permissions": [
"topSites"."http://www.developer.chrome.com/*"],..."manifest_version"2} :Copy the code
Determine the required permissions -The official address
A simple extension may require multiple permissions to be requested, and many permissions display warnings at installation time. Users are more likely to trust a limited warning or extension when the limits are explained to them.
Use events to trigger optional permissions
The core function of the optional permission sample extension is to overpower the new TAB page. One is to display the user’s goals for the day. This feature only requires a storage license and contains no warnings.
This extension has additional capabilities. Displays the user’s popular websites. This feature requires topSites permission and comes with a warning.
Give Users Options – The official documentation
There are two entrances, one is the right icon has a “options” menu, and another in the plug-in management page:
Simple configuration
- A full page options
{
"name": "My extension"."options_page": "options.html". }Copy the code
- Embedded options
{
"name": "My extension"."options_ui": {
"page": "options.html"."open_in_tab": false},... }Copy the code
Comparison of 5 JS types -Refer to the link
The JS of Chrome extensions can be classified into five categories: injected Script, Content-Script, Popup JS, Background JS and DevTools JS
Permission to contrast
JS type | Accessible APIS | DOM access | JS access | Direct cross domain |
---|---|---|---|---|
injected script | No different from normal JS, no access to any extension API | You can visit | You can visit | Can not be |
content script | You can only access some apis like Extension and Runtime | You can visit | Can not be | Can not be |
popup js | Access to most apis except the DevTools family | Not directly accessible | Can not be | can |
background js | Access to most apis except the DevTools family | Not directly accessible | Can not be | can |
devtools js | Only some apis such as DevTools, Extension, and Runtime can be accessed | can | can | Can not be |
Message communication -The official documentation
The demo address
Because Content scripts run in the context of a Web page rather than an extender, they often need some way to communicate with the rest of the extender.
Communication between extensions and their content scripts is done using messaging. Either side can listen for messages sent from the other end and respond on the same channel. Messages can contain any valid JSON object (empty, Boolean, number, string, array, or object)
- There is a simple API to handle one-time requests
- A more sophisticated API allows you to have long-term connections to exchange multiple messages with a shared context.
- If you know another extension name, you can also pass messages across extensions. This article will not cover this. If you are interested, go to the official website
Simple one-time pass
If you only need to send a message to another part of the extension (and optionally return a response), use the simplified Runtime. sendMessage or tabs. SendMessage. This allows you to send a JSON-serializable message to the extension once from the content script and vice versa. Optional callback parameters allow you to process the response, if any, from the other side.
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
Copy the code
Sending a request to a content script from an extension looks very similar, except that you need to specify which TAB to send the request to. This example demonstrates a content script that sends a message to a selected TAB.
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
Copy the code
On the receiving side, you need to set up the Runtime. onMessage event listener to process the message. This looks the same from a content script or extension page.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
});
Copy the code
Open the Background default background page to see the message
There will also be responses in content-script.js
A long connection
Sometimes conversations last longer than a single request and response, which is useful. In this case, you can use Runtime.connect or tabs. Connect, respectively, to open long-life channels from content scripts to extended pages, and vice versa. Channels can have a name so that you can distinguish between different types of connections.
When a connection is established, both ends are provided with a Runtime. Port object that is used to send and receive messages over the connection.
The way to send and receive channels from content-script is as follows: Sending a request from an extension to a content script looks very similar, except that you need to specify which TAB to connect to. Simply replace the connect connection in the above example with tabs.connect.
The way to connect a page to content-script is as follows
var port = chrome.runtime.connect({name: "knockknock"});
port.postMessage({joke: "Knock knock"});
port.onMessage.addListener(function(msg) {
if (msg.question == "Who's there?")
port.postMessage({answer: "Madame"});
else if (msg.question == "Madame who?")
port.postMessage({answer: "Madame... Bovary"});
});
Copy the code
To process incoming connections, you need to set up the Runtime. onConnect event listener. This looks the same from a content script or extension page. This event is triggered when another part of the extension calls “connect()”, along with the Runtime.port object that can be used to send and receive messages over the connection. This is what the response incoming connection looks like: Content-script.js
/ / listen long connection chrome. Runtime. OnConnect. AddListener (function(port) {
console.assert(port.name == "knockknock");
port.onMessage.addListener(function(msg) {
if (msg.joke == "Knock knock")
port.postMessage({question: "Who's there?"});
else if (msg.answer == "Madame")
port.postMessage({question: "Madame who?"});
else if (msg.answer == "Madame... Bovary")
port.postMessage({question: "I don't get it."});
});
});
Copy the code
The effect is shown below:
Port life
The port is designed as a method of two-way communication between different parts of the extension, where the (top-level) frame is treated as the smallest part.
A Port is created when tabs. Connect, Runtime. connect, or Runtime. connectNative is called. This port is immediately available to send messages to the other end via postMessage.
If you have more than one frame in the TAB, calling Tabs. Connect results in multiple calls to the Runtime.onConnect event (one for each frame in the TAB). Similarly, if runtime.connect is used, the onConnect event may fire multiple times (once per frame during the extension).
You might want to find out when the connection is closed, for example, if you maintain a separate state for each open port. To do this, you can listen to the runtime. Port. OnDisconnect events. This event is emitted when there is no valid port on the other side of the channel. This happens when:
- There is no listener for Runtime.onConnect on the other end.
- The TAB containing the port is unloaded (for example, if it is navigated).
connect
The framework for the calling location is unloaded.- All frames for the receive port (via Runtime.onConnect) have been unloaded.
- The other end callsruntime.Port.disconnect. Notice if a
connect
The call results in multiple ports at the receiver’s end, anddisconnect()
Is called on any of these ports, then theonDisconnect
Events are emitted only on the sender’s port and not on any other port.
Common method identification
Dynamically inject CSS code
// Execute CSS code dynamically, TODO, chrome.tabs. InsertCSS (tabId, {code:'xxx'}); InsertCSS (tabId, {file:'some-style.css'});
Copy the code
[Note] Because content_scripts has a very high priority for CSS, almost second only to the browser default, it may affect the presentation of some sites if you are not careful, so try not to write styles that affect the whole world. So make sure you test it when you inject it.
Dynamic execution
The official documentation
/ / dynamic execution of JS code chrome. Tabs. ExecuteScript (tabId, {code:'document.body.style.filter = "grayscale(1)"'}); / / dynamic execution of JS file chrome. Tabs. ExecuteScript (tabId, {file:'script.js'});
Copy the code
【 note 】 background and page_action page cannot directly access the dom, but can be by chrome. Tabs. ExecuteScript ({code: script,}) to perform the js
Gets the current window ID -The document
chrome.windows.getCurrent(function(currentWindow)
{
console.log('Window ID:' + currentWindow.id);
});
Copy the code
Debug extensions
For debugging, see the debug extension website for more details, as well as links to videos
Packaging and publishing
We can click on the package extension and generate the.rtx file, which you need to log into your Google account to publish to the Google App Store.
Add dark mode to jingdong page
Directory as follows
Add - dark - to - page ├ ├ ─ README. Md ├ ─ the manifest. Json ├ ─ js | ├ ─ background. Js | └ home. Js ├ ─ images | └ icon. The PNG ├ ─ HTML | | ├ ─ home. HTML └ options. HTML ├ ─ CSS | └ index. The CSSCopy the code
First createmainfest.json
{
"name": "TimeStone1"."manifest_version": 2."version": "1.0"."description": "TimeStone Extension"."page_action": {
"default_icon": "images/icon.png"."default_title": "TimeStone plug-in"."default_popup": "html/home.html"
},
"background": {
"scripts": ["js/background.js"]},"options_page": "html/options.html"."homepage_url": "https://juejin.cn/user/4230576473387773"."permissions": ["tabs"."activeTab"."declarativeContent"]}Copy the code
Dark mode thinking
The dark mode I use here is to control the display of the page through the FILTER property of CSS. You can check it out
Open the chrome: / / extensions /
Then load the decompressed extension program as follows
Create /background.js under home.html and js files
- home.html
<! DOCTYPE HTML > < HTML > <head> <title>TimeStone plugin home page </title> <meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link type="text/css" rel="stylesheet" href=".. /css/index.css" />
</head>
<body>
<div class="time-stone">
<button class="time-stone_btn" id="ChangeBg"<script SRC = "button" style = "max-width: 100%; clear: both; min-height: 1em".. /js/home.js" type="text/javascript"></script>
</div>
</body>
</html>
Copy the code
- home.js
/** * get the URL */function getCurrentTabUrl(callback) {
let queryInfo = {
active: true,
currentWindow: true,
}
chrome.tabs.query(queryInfo, (tabs) => {
let tab = tabs[0]
let url = tab.url
console.assert(typeof url === 'string'.'tab.url should be a string'Callback (url)})} /** * Changes the background color of the current page. * * /function changeBackgroundStyle() {
const script = 'document.body.style.filter = "grayscale(1)"; '
// See https://developer.chrome.com/extensions/tabs#method-executeScript./ / to the page into the JavaScript code. Chrome tabs. ExecuteScript ({code: script,})} / / the plugin will be loaded users choose the color of the last time, if they exist. document.addEventListener('DOMContentLoaded', () = > {getCurrentTabUrl ((url) = > {/ / change the background color ChangeBg. AddEventListener ('click'.function () {
changeBackgroundStyle()
})
})
})
Copy the code
- background.js
chrome.runtime.onInstalled.addListener(function () {
// Replace all rules ...
chrome.declarativeContent.onPageChanged.removeRules(undefined, function () {
// With a new rule ...
chrome.declarativeContent.onPageChanged.addRules([
{
// That fires when a page's URL contains a 'g'... conditions: [ new chrome.declarativeContent.PageStateMatcher({ pageUrl: { urlContains: 'jd.com' }, }), ], // And shows the extension's page action.
actions: [new chrome.declarativeContent.ShowPageAction()],
},
])
})
})
Copy the code
The source address
- Long-link Demo address
- Dark mode source code
- Official program source code
If you have any problem with the above code debugging, please leave a message or issue, thank you!
The following will update some right-click menu, web interception request, right-click menu instances and other demo, thank you for your attention.