Every job is the same, after a while we will find ourselves having things that keep repeating daily. Me too, my work is done a lot on Google Chrome and it will be helpful if we have a separate extension to automatically do those repetitive tasks, which is also a way to save time. Save time and more, it looks a lot more professional. You can add other functions to a website that you use it regularly, get data, store … and many other cool things you can do with an extension.
Structure of a Chrome Extension
Basically, a Chrome Extension will mainly be written in Javascript and HTML. You can organize arbitrary folders as appropriate and most convenient in the process of code. For me it will be like this: Below, we will go inside to learn the function of each file
Function of components
1. manifest.json
This is the config file for our extension. It contains basic information about the extension, which files will be run, inject …
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <span class="token punctuation">{</span> <span class="token property">"name"</span> <span class="token operator">:</span> <span class="token string">"Nhaccuatui Extension"</span> <span class="token punctuation">,</span> <span class="token property">"version"</span> <span class="token operator">:</span> <span class="token string">"0.0.1"</span> <span class="token punctuation">,</span> <span class="token property">"manifest_version"</span> <span class="token operator">:</span> <span class="token number">2</span> <span class="token punctuation">,</span> <span class="token property">"description"</span> <span class="token operator">:</span> <span class="token string">"Extension for Nhaccuatui"</span> <span class="token punctuation">,</span> <span class="token property">"icons"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"16"</span> <span class="token operator">:</span> <span class="token string">"images/icon.png"</span> <span class="token punctuation">,</span> <span class="token property">"48"</span> <span class="token operator">:</span> <span class="token string">"images/icon.png"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token property">"browser_action"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"default_icon"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"19"</span> <span class="token operator">:</span> <span class="token string">"images/icon.png"</span> <span class="token punctuation">,</span> <span class="token property">"38"</span> <span class="token operator">:</span> <span class="token string">"images/icon.png"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token property">"default_title"</span> <span class="token operator">:</span> <span class="token string">"Nhaccuatui Extension"</span> <span class="token punctuation">,</span> <span class="token property">"default_popup"</span> <span class="token operator">:</span> <span class="token string">"popup.html"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token property">"background"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"page"</span> <span class="token operator">:</span> <span class="token string">"background.html"</span> <span class="token punctuation">,</span> <span class="token property">"persistent"</span> <span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token property">"content_scripts"</span> <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">"matches"</span> <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token string">"*://nhaccuatui.com/bai-hat/*"</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token property">"js"</span> <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token string">"scripts/content.js"</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token property">"css"</span> <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token string">"styles/font.css"</span> <span class="token punctuation">,</span> <span class="token string">"styles/main.css"</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token property">"run_at"</span> <span class="token operator">:</span> <span class="token string">"document_idle"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token property">"permissions"</span> <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token string">"clipboardWrite"</span> <span class="token punctuation">,</span> <span class="token string">"storage"</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> |
name
: An attribute that identifies your extension nameversion
: The current version, Chrome will use this to determine if your extension has new updatesmanifest_version
: Determines the version of the manifest.json file itselfdescription
: Describe the extension in more detailicons
: The icon of the extension will be displayed on the store. In this case, I put them in the images folderbrowser_action
:default_icon
: The icon will be used to display on the browserdefault_title
: The title will be displayed when hovering on the icon of the extensiondefault_popup
: This is the HTML file that will be displayed when you open the extension. We will talk more about this file later
background
:page
: This will be the page running in the background and usually will only contain a script tag to include the javascript filepersistent
: A flag whose value istrue
orfalse
. Determine how the background page will be run
content_scripts
:matches
: Specify the webpages you want to add your content tojs
: A list of javascript files that will be injected into the above declared websitescss
: Similar to thejs
attribute but a list of css filesrun_at
: Time of injecting the above content files into the site
permissions
: Declare access rights for the extension
2. Content script
These are the components injected into web pages that you declare in the matches
attribute in the manifest.json
file. These components are run in the same environment as the current website, so you can use javascript, css to manipulate DOM components. So you can change the look of the page, add buttons, add other functions you want.
3. Popup page
This is the page that will run and display when you open your extension. Its structure is similar to other HTML pages. In my case, that is the popup.html
page. This page is run in a different environment than the content scripts. It can be roughly understood that they are run in a different browser window than the current browser window.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token doctype"><!doctype html></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> html</span> <span class="token attr-name">lang</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> en <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> head</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> meta</span> <span class="token attr-name">charset</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> utf-8 <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> link</span> <span class="token attr-name">rel</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> stylesheet <span class="token punctuation">"</span></span> <span class="token attr-name">href</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> ./styles/lib/bootstrap.min.css <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> link</span> <span class="token attr-name">rel</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> stylesheet <span class="token punctuation">"</span></span> <span class="token attr-name">href</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> ./styles/page.css <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> title</span> <span class="token punctuation">></span></span> My Extension <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> title</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> head</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> body</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> div</span> <span class="token attr-name">class</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> wrapper <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> h1</span> <span class="token punctuation">></span></span> This is popup page <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> h1</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> div</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> script</span> <span class="token attr-name">src</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> ./scripts/lib/bootstrap.min.js <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> script</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> script</span> <span class="token attr-name">type</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> module <span class="token punctuation">"</span></span> <span class="token attr-name">src</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> ./scripts/popup.js <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> script</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> body</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> html</span> <span class="token punctuation">></span></span> |
You will create the main interface for your extension here. The page will reload every time the extension is opened. You can use localStorage
to store data like a database.
4. Background page
Like the popup.html
page, background.html
will run in the same environment. However, it has no interface, but merely contains a script tag for the purpose of including the background.js
file.
1 2 3 4 5 6 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> html</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> body</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span> script</span> <span class="token attr-name">type</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> module <span class="token punctuation">"</span></span> <span class="token attr-name">src</span> <span class="token attr-value"><span class="token punctuation">=</span> <span class="token punctuation">"</span> ./scripts/background.js <span class="token punctuation">"</span></span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> script</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> body</span> <span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span> html</span> <span class="token punctuation">></span></span> |
By default this page will automatically be generated and automatically inject the background.js
file, but in case you want to customize it this is the place for you to do that.
The background.js
file is used for the same purpose as a server, it listens for events called from the popup or content page. Processing, storing data as well as returning data in response.
Communicate between components
Recently we have somewhat understood the function of the components in an extension. As we all know, the content.js
file is run with the current web page that it was injected into. Meanwhile, popup.js
and background.js
are run in the same environment and they are completely separate from the current window the browser is displaying. Therefore, to have the connection between script files in different environments, Chrome uses messages to express that communication.
Let’s work together as an example to better understand this issue. Our extension will have the function of saving the songs we like on https://www.nhaccuatui.com/ so that we can listen to them everyday without having to search. Of course, practically every music site has a playlist function. Let’s get started.
content.js
In this section, we will handle inserting a button that, when clicked on it, takes the current page’s data and sends it to background.js
for processing:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | window <span class="token punctuation">.</span> <span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> button <span class="token operator">=</span> document <span class="token punctuation">.</span> <span class="token function">createElement</span> <span class="token punctuation">(</span> <span class="token string">'button'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> button <span class="token punctuation">.</span> innerHTML <span class="token operator">=</span> <span class="token string">'Add to Playlist'</span> <span class="token punctuation">;</span> document <span class="token punctuation">.</span> body <span class="token punctuation">.</span> <span class="token function">prepend</span> <span class="token punctuation">(</span> button <span class="token punctuation">)</span> <span class="token punctuation">;</span> button <span class="token punctuation">.</span> <span class="token function">addEventListener</span> <span class="token punctuation">(</span> <span class="token string">'click'</span> <span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> link <span class="token operator">=</span> window <span class="token punctuation">.</span> location <span class="token punctuation">.</span> href <span class="token punctuation">;</span> <span class="token keyword">var</span> name <span class="token operator">=</span> document <span class="token punctuation">.</span> <span class="token function">querySelector</span> <span class="token punctuation">(</span> <span class="token string">'.name_title'</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> innerText <span class="token punctuation">;</span> chrome <span class="token punctuation">.</span> extension <span class="token punctuation">.</span> <span class="token function">sendMessage</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> <span class="token string">'add-song'</span> <span class="token punctuation">,</span> data <span class="token punctuation">:</span> <span class="token punctuation">{</span> link <span class="token punctuation">,</span> name <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
Notice that, in the matches
attribute in manifest.json
, we have a value of "*://nhaccuatui.com/bai-hat/*"
. So the script above will only be run on the page where the song is being played.
background.js
Just now in content.js
we have sent a message. So in order for background.js
receive this message, we must register it to listen for incoming requests
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | chrome <span class="token punctuation">.</span> extension <span class="token punctuation">.</span> onMessage <span class="token punctuation">.</span> <span class="token function">addListener</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> request <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span> request <span class="token punctuation">.</span> type <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token string">'add-song'</span> <span class="token punctuation">:</span> <span class="token function">addSong</span> <span class="token punctuation">(</span> data <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">break</span> <span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token string">'remove-song'</span> <span class="token punctuation">:</span> <span class="token keyword">break</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">addSong</span> <span class="token punctuation">(</span> data <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> songs <span class="token operator">=</span> <span class="token function">getSongs</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> songs <span class="token punctuation">.</span> <span class="token function">push</span> <span class="token punctuation">(</span> data <span class="token punctuation">)</span> <span class="token punctuation">;</span> localStorage <span class="token punctuation">.</span> songs <span class="token operator">=</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> songs <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">getSongs</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> localStorage <span class="token punctuation">.</span> songs <span class="token punctuation">)</span> <span class="token punctuation">{</span> localStorage <span class="token punctuation">.</span> songs <span class="token operator">=</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">stringify</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">parse</span> <span class="token punctuation">(</span> localStorage <span class="token punctuation">.</span> songs <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
When they receive the message, they store the data in the localstorage
.
popup.js
As we saw we use popup.js
in the popup.html
page so here we will handle in popup.js
to show the list of saved songs.
1 2 3 4 5 6 7 8 9 10 | <span class="token function">$</span> <span class="token punctuation">(</span> document <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">ready</span> <span class="token punctuation">(</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> songs <span class="token operator">=</span> <span class="token constant">JSON</span> <span class="token punctuation">.</span> <span class="token function">parse</span> <span class="token punctuation">(</span> localStorage <span class="token punctuation">.</span> songs <span class="token operator">||</span> <span class="token string">'[]'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">var</span> songHTML <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token punctuation">;</span> songs <span class="token punctuation">.</span> <span class="token function">forEach</span> <span class="token punctuation">(</span> song <span class="token operator">=></span> <span class="token punctuation">{</span> songHTML <span class="token operator">=</span> <span class="token function">$</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token string">`<a href="</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> song <span class="token punctuation">.</span> link <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">" target="_blank"></span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> song <span class="token punctuation">.</span> name <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string"></a>`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">$</span> <span class="token punctuation">(</span> <span class="token string">'.wrapper'</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">append</span> <span class="token punctuation">(</span> songHTML <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Thus, each time the extension is opened, we will see the list of songs that we have saved displayed here. You can add other features like automatically play the songs in the list, or download them all to your computer.
Load extension
- You go to google chrome, type in
chrome://extensions/
addresschrome://extensions/
- Click the
Load unpacked
button in the left corner of the screen - Go to the folder containing our extension, that’s it
summary
We have just learned about the components of a chrome extension as well as the functions and communication between them. Hopefully, with those shares, you will somewhat understand the structure of an extension so you can create your own extension, serving your needs.
Here is an extension for your work. Its function is to save the ticket’s data, create a pull request template, create a message to send to the team on chatwork … You can refer here https://github.com/dongoclam/rg-plugin .