├── images
├── icon-128x128.png
├── icon-16x16.png
├── icon-32x32.png
└── icon-48x48.png
├── options_script.js
├── popup_script.js
├── README.md
├── foreground_styles.css
├── popup.html
├── options.html
├── manifest.json
├── foreground.js
└── background.js
/images/icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/an-object-is-a/chrome-ext-mv3-how-to/HEAD/images/icon-128x128.png
--------------------------------------------------------------------------------
/images/icon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/an-object-is-a/chrome-ext-mv3-how-to/HEAD/images/icon-16x16.png
--------------------------------------------------------------------------------
/images/icon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/an-object-is-a/chrome-ext-mv3-how-to/HEAD/images/icon-32x32.png
--------------------------------------------------------------------------------
/images/icon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/an-object-is-a/chrome-ext-mv3-how-to/HEAD/images/icon-48x48.png
--------------------------------------------------------------------------------
/options_script.js:
--------------------------------------------------------------------------------
1 | chrome.runtime.sendMessage({
2 | message: "get_name"
3 | }, response => {
4 | if (response.message === 'success') {
5 | document.querySelector('div').innerHTML = `Hello ${response.payload}`;
6 | }
7 | });
--------------------------------------------------------------------------------
/popup_script.js:
--------------------------------------------------------------------------------
1 | chrome.runtime.sendMessage({
2 | message: "get_name"
3 | }, response => {
4 | if (response.message === 'success') {
5 | document.querySelector('div').innerHTML = `Hello ${response.payload}`;
6 | }
7 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # If you want the video tutorial, head over to our [courses page!](https://anobjectisa.wixsite.com/website "courses page!")
2 |
3 | 
4 |
--------------------------------------------------------------------------------
/foreground_styles.css:
--------------------------------------------------------------------------------
1 | .ce_main {
2 | width: 400px;
3 | height: 600px;
4 | display: flex;
5 | flex-direction: column;
6 | justify-content: space-evenly;
7 | align-items: center;
8 | position: absolute;
9 | z-index: 999999;
10 | top: 50%;
11 | left: 50%;
12 | transform: translate(-50%, -50%);
13 |
14 | color: white;
15 | background-color: red;
16 | }
17 |
18 | #ce_name {
19 | font-size: 70px;
20 | }
21 |
22 | #ce_button {
23 | padding: 60px 30px;
24 | border-radius: 5px;
25 |
26 | font-size: 30px;
27 |
28 | background-color: black;
29 |
30 | cursor: pointer;
31 | }
--------------------------------------------------------------------------------
/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Document
9 |
23 |
24 |
25 |
26 |
27 | Hello NAME
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/options.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Document
9 |
25 |
26 |
27 |
28 |
29 | Hello NAME
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Chrome Extension MV3",
3 | "description": "Building a Chrome Extension MV3",
4 | "version": "0.1.0",
5 | "manifest_version": 3,
6 | "icons": {
7 | "16": "./images/icon-16x16.png",
8 | "32": "./images/icon-32x32.png",
9 | "48": "./images/icon-48x48.png",
10 | "128": "./images/icon-128x128.png"
11 | },
12 | "background": {
13 | "service_worker": "./background.js"
14 | },
15 | "action": {
16 | "default_popup": "./popup.html",
17 | "default_icons": {
18 | "16": "./images/icon-16x16.png",
19 | "32": "./images/icon-32x32.png",
20 | "48": "./images/icon-48x48.png",
21 | "128": "./images/icon-128x128.png"
22 | }
23 | },
24 | "options_page": "./options.html",
25 | "permissions": [
26 | "activeTab",
27 | "tabs",
28 | "storage",
29 | "scripting"
30 | ],
31 | "host_permissions": [
32 | "https://www.google.com/*"
33 | ]
34 | }
--------------------------------------------------------------------------------
/foreground.js:
--------------------------------------------------------------------------------
1 | const ce_main_container = document.createElement('DIV');
2 | const ce_name = document.createElement('DIV');
3 | const ce_input = document.createElement('INPUT');
4 | const ce_button = document.createElement('DIV');
5 |
6 | ce_main_container.classList.add('ce_main');
7 | ce_name.id = 'ce_name';
8 | ce_input.id = 'ce_input';
9 | ce_button.id = 'ce_button';
10 |
11 | ce_name.innerHTML = `Hello NAME`;
12 | ce_button.innerHTML = `Change name.`;
13 |
14 | ce_main_container.appendChild(ce_name);
15 | ce_main_container.appendChild(ce_input);
16 | ce_main_container.appendChild(ce_button);
17 |
18 |
19 | document.querySelector('body').appendChild(ce_main_container);
20 |
21 | chrome.runtime.sendMessage({
22 | message: "get_name"
23 | }, response => {
24 | if (response.message === 'success') {
25 | ce_name.innerHTML = `Hello ${response.payload}`;
26 | }
27 | });
28 |
29 | ce_button.addEventListener('click', () => {
30 | chrome.runtime.sendMessage({
31 | message: "change_name",
32 | payload: ce_input.value
33 | }, response => {
34 | if (response.message === 'success') {
35 | ce_name.innerHTML = `Hello ${ce_input.value}`;
36 | }
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/background.js:
--------------------------------------------------------------------------------
1 | chrome.runtime.onInstalled.addListener(() => {
2 | chrome.storage.local.set({
3 | name: "Jack"
4 | });
5 | });
6 |
7 | chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
8 | if (changeInfo.status === 'complete' && /^http/.test(tab.url)) {
9 | chrome.scripting.insertCSS({
10 | target: { tabId: tabId },
11 | files: ["./foreground_styles.css"]
12 | })
13 | .then(() => {
14 | console.log("INJECTED THE FOREGROUND STYLES.");
15 |
16 | chrome.scripting.executeScript({
17 | target: { tabId: tabId },
18 | files: ["./foreground.js"]
19 | })
20 | .then(() => {
21 | console.log("INJECTED THE FOREGROUND SCRIPT.");
22 | });
23 | })
24 | .catch(err => console.log(err));
25 | }
26 | });
27 |
28 | chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
29 | if (request.message === 'get_name') {
30 | chrome.storage.local.get('name', data => {
31 | if (chrome.runtime.lastError) {
32 | sendResponse({
33 | message: 'fail'
34 | });
35 |
36 | return;
37 | }
38 |
39 | sendResponse({
40 | message: 'success',
41 | payload: data.name
42 | });
43 | });
44 |
45 | return true;
46 | } else if (request.message === 'change_name') {
47 | chrome.storage.local.set({
48 | name: request.payload
49 | }, () => {
50 | if (chrome.runtime.lastError) {
51 | sendResponse({ message: 'fail' });
52 | return;
53 | }
54 |
55 | sendResponse({ message: 'success' });
56 | })
57 |
58 | return true;
59 | }
60 | });
--------------------------------------------------------------------------------