├── 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 | ![timetoupgrade](https://user-images.githubusercontent.com/58220766/133908496-316a64a5-f34c-48c0-a48e-eddcb81e172e.png) 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 | }); --------------------------------------------------------------------------------