Skip to content

Commit e1253d9

Browse files
rebloordotprotoRob--W
authored
MDN get started tutorial examples to manifest V3 (#608)
* MDN get started tutorial examples to manifest V3 * Migrate to Scripting API * Updated to readmes and code comments * Apply suggestions to readmes from review Co-authored-by: Simeon Vincent <svincent@gmail.com> * Convert choose_beast.js to async * Apply suggestions from review Co-authored-by: Simeon Vincent <svincent@gmail.com> * Updated illustrated API list for beastify * Apply suggestions from review Co-authored-by: Rob Wu <rob@robwu.nl> --------- Co-authored-by: Simeon Vincent <svincent@gmail.com> Co-authored-by: Rob Wu <rob@robwu.nl>
1 parent 04e5fa5 commit e1253d9

8 files changed

Lines changed: 118 additions & 78 deletions

File tree

beastify/README.md

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,41 @@
11
# beastify
22

3+
This extension used a tootlbar button to enable the section of beast that replaces the content of the active web page.
4+
35
## What it does ##
46

57
The extension includes:
68

7-
* a browser action with a popup including HTML, CSS, and JS
8-
* a content script
9-
* three images, each of a different beast, packaged as web accessible resources
9+
* An action with a popup that includes HTML, CSS, and JavaScript.
10+
* A content script.
11+
* Three images, each of a beast, packaged as web accessible resources.
1012

11-
When the user clicks the browser action button, the popup is shown, enabling
12-
the user to choose one of three beasts.
13+
When the user clicks the action (toolbar button), the extension's popup opens, enabling the user to choose one of three beasts.
1314

14-
When it is shown, the popup injects a content script into the current page.
15+
When opened, the popup injects a content script into the active page.
1516

16-
When the user chooses a beast, the extension sends the content script a message containing
17-
the name of the chosen beast.
17+
When the user chooses a beast, the extension sends the content script a message containing the name of the chosen beast.
1818

19-
When the content script receives this message, it replaces the current page
20-
content with an image of the chosen beast.
19+
When the content script receives this message, it replaces the active page content with an image of the chosen beast.
2120

22-
When the user clicks the reset button, the page reloads, and reverts to its original form.
21+
When the user clicks the reset button, the page reloads and reverts to its original form.
2322

2423
Note that:
2524

26-
* if the user reloads the tab, or switches tabs, while the popup is open, then the popup won't be able to beastify the page any more (because the content script was injected into the original tab).
25+
* If the user reloads the tab, or switches tabs, while the popup is open, then the popup can't beastify the page (because the content script was injected into the original tab).
2726

28-
* by default [`tabs.executeScript()`](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/executeScript) injects the script only when the web page and its resources have finished loading. This means that clicks in the popup will have no effect until the page has finished loading.
27+
* By default, [`scripting.executeScript()`](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/scripting/executeScript) injects the script only when the web page and its resources have finished loading. This means that clicks in the popup have no effect until the page has finished loading.
2928

30-
* it's not possible to inject content scripts into certain pages, including privileged browser pages like "about:debugging" and the [addons.mozilla.org](https://addons.mozilla.org/) website. If the user clicks the beastify icon when such a page is loaded into the active tab, the popup displays an error message.
29+
* Browsers don't allow extensions to inject content scripts into specific pages. In Firefox, this includes privileged browser pages, such as "about:debugging", and the [addons.mozilla.org](https://addons.mozilla.org/) website. In Chrome, this includes internal pages, such as `chrome://extensions`, and the [chromewebstore.google.com](https://chromewebstore.google.com/) website. If the user clicks the beastify icon on one of these pages, the popup displays an error message.
3130

3231
## What it shows ##
3332

34-
* write a browser action with a popup
35-
* how to have different browser_action images based upon the theme
36-
* give the popup style and behavior using CSS and JS
37-
* inject a content script programmatically using `tabs.executeScript()`
38-
* send a message from the main extension to a content script
39-
* use web accessible resources to enable web pages to load packaged content
40-
* reload web pages
33+
In this example, you see how to:
34+
35+
* Write an action (toolbar button) with a popup.
36+
* Display action (toolbar button) icons based on the browser theme.
37+
* Give a popup style and behavior using CSS and JavaScript.
38+
* Inject a content script programmatically using `scripting.executeScript()`.
39+
* Send a message from the main extension to a content script.
40+
* Use `web_accessible_resources` to enable web pages to load packaged content.
41+
* Reload web pages.

beastify/content_scripts/beastify.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
11
(function() {
22
/**
3-
* Check and set a global guard variable.
4-
* If this content script is injected into the same page again,
5-
* it will do nothing next time.
3+
* Check and set a global guard variable to
4+
* ensure that if this content script is injected into a page again,
5+
* it returns (and does nothing).
66
*/
77
if (window.hasRun) {
88
return;
99
}
1010
window.hasRun = true;
1111

1212
/**
13-
* Given a URL to a beast image, remove all existing beasts, then
14-
* create and style an IMG node pointing to
15-
* that image, then insert the node into the document.
13+
* Given a URL for a beast image, remove all beasts,
14+
* then create and style an IMG node pointing to the image and
15+
* insert the node into the document.
1616
*/
1717
function insertBeast(beastURL) {
1818
removeExistingBeasts();
1919
let beastImage = document.createElement("img");
2020
beastImage.setAttribute("src", beastURL);
21-
beastImage.style.height = "100vh";
21+
beastImage.style.objectFit = "contain";
22+
beastImage.style.position = "fixed";
23+
beastImage.style.height = "100%";
24+
beastImage.style.width = "100%";
2225
beastImage.className = "beastify-image";
2326
document.body.appendChild(beastImage);
2427
}
2528

2629
/**
27-
* Remove every beast from the page.
30+
* Remove all beasts from the page.
2831
*/
2932
function removeExistingBeasts() {
3033
let existingBeasts = document.querySelectorAll(".beastify-image");
@@ -35,7 +38,7 @@
3538

3639
/**
3740
* Listen for messages from the background script.
38-
* Call "beastify()" or "reset()".
41+
* Depending on the message, call "beastify()" or "reset()".
3942
*/
4043
browser.runtime.onMessage.addListener((message) => {
4144
if (message.command === "beastify") {

beastify/manifest.json

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22

33
"description": "Adds a browser action icon to the toolbar. Click the button to choose a beast. The active tab's body content is then replaced with a picture of the chosen beast. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#beastify",
4-
"manifest_version": 2,
4+
"manifest_version": 3,
55
"name": "Beastify",
66
"version": "1.0",
77
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify",
@@ -10,10 +10,20 @@
1010
},
1111

1212
"permissions": [
13-
"activeTab"
13+
"activeTab",
14+
"scripting"
1415
],
1516

16-
"browser_action": {
17+
"browser_specific_settings": {
18+
"gecko": {
19+
"id": "beastify@mozilla.org",
20+
"data_collection_permissions": {
21+
"required": ["none"]
22+
}
23+
}
24+
},
25+
26+
"action": {
1727
"default_icon": "icons/beasts-32.png",
1828
"theme_icons": [{
1929
"light": "icons/beasts-32-light.png",
@@ -25,7 +35,10 @@
2535
},
2636

2737
"web_accessible_resources": [
28-
"beasts/*.jpg"
38+
{
39+
"resources": [ "beasts/*.jpg" ],
40+
"matches": [ "*://*/*" ]
41+
}
2942
]
3043

3144
}

beastify/popup/choose_beast.js

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
/**
22
* CSS to hide everything on the page,
3-
* except for elements that have the "beastify-image" class.
3+
* except for elements that have the ".beastify-image" class.
44
*/
55
const hidePage = `body > :not(.beastify-image) {
6-
display: none;
6+
display: none !important;
77
}`;
88

99
/**
1010
* Listen for clicks on the buttons, and send the appropriate message to
1111
* the content script in the page.
1212
*/
1313
function listenForClicks() {
14-
document.addEventListener("click", (e) => {
15-
14+
document.addEventListener("click", async (e) => {
1615
/**
17-
* Given the name of a beast, get the URL to the corresponding image.
16+
* Given the name of a beast, get the URL for the corresponding image.
1817
*/
1918
function beastNameToURL(beastName) {
2019
switch (beastName) {
@@ -29,33 +28,35 @@ function listenForClicks() {
2928

3029
/**
3130
* Insert the page-hiding CSS into the active tab,
32-
* then get the beast URL and
31+
* get the beast URL, and
3332
* send a "beastify" message to the content script in the active tab.
3433
*/
35-
function beastify(tabs) {
36-
browser.tabs.insertCSS({code: hidePage}).then(() => {
37-
const url = beastNameToURL(e.target.textContent);
38-
browser.tabs.sendMessage(tabs[0].id, {
39-
command: "beastify",
40-
beastURL: url
41-
});
34+
async function beastify(tab) {
35+
await browser.scripting.insertCSS({
36+
target: { tabId: tab.id },
37+
css: hidePage,
38+
});
39+
const url = beastNameToURL(e.target.textContent);
40+
await browser.tabs.sendMessage(tab.id, {
41+
command: "beastify",
42+
beastURL: url,
4243
});
4344
}
4445

4546
/**
46-
* Remove the page-hiding CSS from the active tab,
47+
* Remove the page-hiding CSS from the active tab and
4748
* send a "reset" message to the content script in the active tab.
4849
*/
49-
function reset(tabs) {
50-
browser.tabs.removeCSS({code: hidePage}).then(() => {
51-
browser.tabs.sendMessage(tabs[0].id, {
52-
command: "reset",
53-
});
50+
async function reset(tab) {
51+
await browser.scripting.removeCSS({
52+
target: { tabId: tab.id },
53+
css: hidePage,
5454
});
55+
await browser.tabs.sendMessage(tab.id, { command: "reset" });
5556
}
5657

5758
/**
58-
* Just log the error to the console.
59+
* Log the error to the console.
5960
*/
6061
function reportError(error) {
6162
console.error(`Could not beastify: ${error}`);
@@ -68,15 +69,18 @@ function listenForClicks() {
6869
if (e.target.tagName !== "BUTTON" || !e.target.closest("#popup-content")) {
6970
// Ignore when click is not on a button within <div id="popup-content">.
7071
return;
71-
}
72-
if (e.target.type === "reset") {
73-
browser.tabs.query({active: true, currentWindow: true})
74-
.then(reset)
75-
.catch(reportError);
76-
} else {
77-
browser.tabs.query({active: true, currentWindow: true})
78-
.then(beastify)
79-
.catch(reportError);
72+
}
73+
74+
try {
75+
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
76+
77+
if (e.target.type === "reset") {
78+
await reset(tab);
79+
} else {
80+
await beastify(tab);
81+
}
82+
} catch (error) {
83+
reportError(error);
8084
}
8185
});
8286
}
@@ -92,10 +96,20 @@ function reportExecuteScriptError(error) {
9296
}
9397

9498
/**
95-
* When the popup loads, inject a content script into the active tab,
99+
* When the popup loads, inject a content script into the active tab
96100
* and add a click handler.
97-
* If we couldn't inject the script, handle the error.
101+
* If the extension couldn't inject the script, handle the error.
98102
*/
99-
browser.tabs.executeScript({file: "/content_scripts/beastify.js"})
100-
.then(listenForClicks)
101-
.catch(reportExecuteScriptError);
103+
(async function runOnPopupOpened() {
104+
try {
105+
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
106+
107+
await browser.scripting.executeScript({
108+
target: { tabId: tab.id },
109+
files: ["/content_scripts/beastify.js"],
110+
});
111+
listenForClicks();
112+
} catch (e) {
113+
reportExecuteScriptError(e);
114+
}
115+
})();

borderify/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
# borderify
22

3-
**This add-on injects JavaScript into web pages. The `addons.mozilla.org` domain disallows this operation, so this add-on will not work properly when it's run on pages in the `addons.mozilla.org` domain.**
3+
This add-on injects JavaScript into mozilla.org web pages.
44

55
## What it does
66

7-
This extension just includes:
7+
This extension includes a content script, "borderify.js", that is injected into any pages
8+
under "mozilla.org/" or any of its subdomains.
89

9-
* a content script, "borderify.js", that is injected into any pages
10-
under "mozilla.org/" or any of its subdomains
10+
**The `addons.mozilla.org` domain doesn't allow scripts to be injected into its pages. Therefore, this extension doesn't work on pages in the `addons.mozilla.org` domain.**
1111

1212
The content script draws a border around the document.body.
1313

1414
## What it shows
1515

16-
* how to inject content scripts declaratively using manifest.json
16+
From this example, you see how to inject content scripts declaratively using manifest.json.

borderify/borderify.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
/*
2-
Just draw a border round the document.body.
2+
Draw a border round the document.body.
33
*/
44
document.body.style.border = "5px solid red";

borderify/manifest.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
{
22

33
"description": "Adds a solid red border to all webpages matching mozilla.org. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#borderify",
4-
"manifest_version": 2,
4+
"manifest_version": 3,
55
"name": "Borderify",
66
"version": "1.0",
77
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/borderify",
88
"icons": {
99
"48": "icons/border-48.png"
1010
},
1111

12+
"browser_specific_settings": {
13+
"gecko": {
14+
"id": "borderify@mozilla.org",
15+
"data_collection_permissions": {
16+
"required": ["none"]
17+
}
18+
}
19+
},
20+
1221
"content_scripts": [
1322
{
1423
"matches": ["*://*.mozilla.org/*"],

examples.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@
3131
{
3232
"description": "Adds a browser action icon to the toolbar. Click the button to choose a beast. The active tab's body content is then replaced with a picture of the chosen beast.",
3333
"javascript_apis": [
34-
"extension.getURL",
34+
"runtime.getURL",
3535
"runtime.onMessage",
36+
"scripting.insertCSS",
37+
"scripting.removeCSS",
3638
"tabs.executeScript",
37-
"tabs.insertCSS",
3839
"tabs.query",
39-
"tabs.removeCSS",
4040
"tabs.sendMessage",
4141
"tabs.Tab"
4242
],

0 commit comments

Comments
 (0)