Merge remote-tracking branch 'origin/master'

* origin/master: (34 commits)
  add _locales/ja
  Apply minor tweaks and fix typos in inpage-toolbar-ui doc and comments
  Minor tweaks on inpage-toolbar-ui stylesheet
  Add inpage-toolbar-ui add-on example
  Add 48px icon in 'icons' key
  Added README; stop using alarm name for tab ID
  Fix review comments: https://github.com/mdn/webextensions-examples/issues/31#issuecomment-172650159
  Fix review comments: https://github.com/mdn/webextensions-examples/issues/30#issuecomment-172649839
  Fix review comments: https://github.com/mdn/webextensions-examples/issues/29#issuecomment-172646879
  Fix review comments: https://github.com/mdn/webextensions-examples/issues/28#issuecomment-172645256
  add alarms permission, very minor update to a comment
  added comments to one missing file
  added short comments for all JS functions
  ask that examples should contain the  key
  added strict_min_version to manifest.json
  ask that examples include the  key
  use the right size icons
  use the 'icons' key for all examples
  updates and typo fixes for CONTRIBUTING.md
  added draft CONTRIBUTING.md
  ...
This commit is contained in:
Will Bamberg
2016-02-12 11:04:32 -08:00
67 changed files with 577 additions and 124 deletions

33
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,33 @@
This repository contains example Firefox [WebExtensions](https://developer.mozilla.org/en-US/Add-ons/WebExtensions).
We're really happy to accept contributions, either as new examples or as
improvements to the existing examples. This file lists some general guidelines
to help contributors write useful examples.
The examples are intended to demonstrate how to use the WebExtensions technology,
particularly [APIs](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API),
but also [manifest.json keys](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json)
and more general techniques such as internationalization or message passing.
More specifically, they're intended to be referenced from the MDN documentation
for WebExtensions. So, for example, we'll expect the reference page for
`tabs.executeScript()` to link to some examples that demonstrate how to use this
API.
So examples should:
* have a clear function, that's easy to explain and understand
* focus on demonstrating how to use the WebExtension technology, minimizing any
complex logic that's extraneous to the WebExtension technology itself
* demonstrate good-practice use of the technology, even at the expense of extra
complexity
* include useful optional manifest.json keys:
* [`description`](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/description)
* [`icons`](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/icons)
* `homepage_url`
* [`strict_min_version` in the `applications` key](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/applications)
Finally, note that the examples are all made available under the
[Mozilla Public License 2.0](https://github.com/mdn/webextensions-examples/blob/master/LICENSE),
so any contributions must be
[compatible with that license](https://www.mozilla.org/en-US/MPL/license-policy/).

View File

@@ -1 +1,27 @@
# beastify
## What it does ##
The extension includes:
* a browser action with a popup including HTML, CSS, and JS
* a content script
* three images, each of a different beast, packaged as web accessible resources
When the user clicks the browser action button, the popup is shown, enabling
the user to choose one of three beasts.
When they choose a beast, the extension injects the content script into
the current page, and sends the content script a message containing
the name of the chosen beast.
When the content script receives this message, it replaces the current page
content with an image of the chosen beast.
## What it shows ##
* write a browser action with a popup
* give the popup style and behavior using CSS and JS
* inject a content script programmatically using `tabs.executeScript()`
* send a message from the main extension to a content script
* use web accessible resources to enable web pages to load packaged content

View File

@@ -1 +0,0 @@
The icon "beasts.png" is taken from the IconBeast Lite iconset, and used under the terms of its license (http://www.iconbeast.com/faq/), with a link back to the website: http://www.iconbeast.com/free/.

View File

@@ -1,18 +1,28 @@
// Assign beastify() as a listener for messages from the extension.
chrome.runtime.onMessage.addListener(beastify);
/*
beastify():
* removes every node in the document.body,
* then inserts the chosen beast
* then removes itself as a listener
*/
function beastify(request, sender, sendResponse) {
removeEverything();
insertBeast(beastNameToURL(request.beast));
insertBeast(request.beastURL);
chrome.runtime.onMessage.removeListener(beastify);
}
/*
Remove every node under document.body
*/
function removeEverything() {
while (document.body.firstChild) {
document.body.firstChild.remove();
}
}
/*
Given a URL to a beast image, create and style an IMG node pointing to
that image, then insert the node into the document.
*/
function insertBeast(beastURL) {
var beastImage = document.createElement("img");
beastImage.setAttribute("src", beastURL);
@@ -21,6 +31,15 @@ function insertBeast(beastURL) {
document.body.appendChild(beastImage);
}
/*
Assign beastify() as a listener for messages from the extension.
*/
chrome.runtime.onMessage.addListener(beastify);
/*
Given the name of a beast, get the URL to the corresponding image.
*/
function beastNameToURL(beastName) {
switch (beastName) {
case "Frog":

4
beastify/icons/LICENSE Normal file
View File

@@ -0,0 +1,4 @@
The icon "beasts-32.png" is taken from the IconBeast Lite iconset, and used under the terms of its license (http://www.iconbeast.com/faq/), with a link back to the website: http://www.iconbeast.com/free/.
The icon "beasts-48.png" is taken from Aha-Softs Free Retina iconset, and used under the terms of its license (http://www.aha-soft.com/free-icons/free-retina-icon-set/), with a link back to the website: http://www.aha-soft.com/.

View File

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -4,20 +4,24 @@
"manifest_version": 2,
"name": "Beastify",
"version": "1.0",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify",
"icons": {
"48": "icons/beasts-48.png"
},
"applications": {
"gecko": {
"id": "beastify@mozilla.org"
"id": "beastify@mozilla.org",
"strict_min_version": "45.0.0"
}
},
"permissions": [
"http://*/*",
"https://*/*"
"activeTab"
],
"browser_action": {
"default_icon": "button/beasts.png",
"default_icon": "icons/beasts-32.png",
"default_title": "Beastify",
"default_popup": "popup/choose_beast.html"
},

View File

@@ -1,14 +1,10 @@
html, body {
height: 100px;
width: 100px;
margin: 0;
}
.beast {
height: 30%;
width: 90%;
margin: 3% auto;
padding-top: 6%;
padding: 4px;
text-align: center;
font-size: 1.5em;
background-color: #E5F2F2;

View File

@@ -1,3 +1,18 @@
/*
Given the name of a beast, get the URL to the corresponding image.
*/
function beastNameToURL(beastName) {
switch (beastName) {
case "Frog":
return chrome.extension.getURL("beasts/frog.jpg");
case "Snake":
return chrome.extension.getURL("beasts/snake.jpg");
case "Turtle":
return chrome.extension.getURL("beasts/turtle.jpg");
}
}
/*
Listen for clicks in the popup.
@@ -5,12 +20,10 @@ If the click is not on one of the beasts, return early.
Otherwise, the text content of the node is the name of the beast we want.
Run the "beastify.js" content script in the active tab, calling setBeast()
once the content script has executed.
Inject the "beastify.js" content script in the active tab.
Inside setBeast(), get the active tab, then send it a message containing
the chosen beast's name. This message will be received by the content script
we just executed.
Then get the active tab and send "beastify.js" a message
containing the URL to the chosen beast's image.
*/
document.addEventListener("click", function(e) {
if (!e.target.classList.contains("beast")) {
@@ -18,13 +31,14 @@ document.addEventListener("click", function(e) {
}
var chosenBeast = e.target.textContent;
var chosenBeastURL = beastNameToURL(chosenBeast);
chrome.tabs.executeScript(null, {
file: "content_scripts/beastify.js"
file: "/content_scripts/beastify.js"
});
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {beast: chosenBeast});
chrome.tabs.sendMessage(tabs[0].id, {beastURL: chosenBeastURL});
});
});

14
borderify/README.md Normal file
View File

@@ -0,0 +1,14 @@
# borderify
## What it does
This extension just includes:
* a content script, "borderify.js", that is injected into any pages
under "mozilla.org/" or any of its subdomains
The content script draws a border around the document.body.
## What it shows
* how to inject content scripts declaratively using manifest.json

View File

@@ -1 +1,4 @@
/*
Just draw a border round the document.body.
*/
document.body.style.border = "5px solid red";

1
borderify/icons/LICENSE Normal file
View File

@@ -0,0 +1 @@
The icon “border-48.png” is taken from the Google Material Design iconset, and is used under the terms of the Creative Commons Attribution-ShareAlike license: http://creativecommons.org/licenses/by-sa/3.0/.

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

View File

@@ -4,10 +4,15 @@
"manifest_version": 2,
"name": "Borderify",
"version": "1.0",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/borderify",
"icons": {
"48": "icons/border-48.png"
},
"applications": {
"gecko": {
"id": "borderify@mozilla.org"
"id": "borderify@mozilla.org",
"strict_min_version": "45.0.0"
}
},

View File

@@ -1 +1,24 @@
# chill-out
## What it does
After N seconds of inactivity (defined as, the user not having navigated
or switched the active tab) display show a page action for that tab.
When the user clicks the page action,
navigate to http://chilloutandwatchsomecatgifs.com/.
"N" is set to 6 seconds in this example. Such a short period is chosen to make
the extension's behavior more obvious, but this is not recommended in real life.
Note that in Chrome, alarms cannot be set for less than a minute. In Chrome:
* if you install this extension "unpacked", you'll see a warning
in the console, but the alarm will still go off after 6 seconds
* if you package the extension and install it, then the alarm will go off after
a minute.
## What it shows
* how to use various `tabs` functions
* how to show/hide a page action
* how to set alarms and handle alarms going off

View File

@@ -1,15 +1,25 @@
/*
DELAY is set to 6 seconds in this example. Such a short period is chosen to make
the extension's behavior more obvious, but this is not recommended in real life.
Note that in Chrome, alarms cannot be set for less than a minute. In Chrome:
* if you install this extension "unpacked", you'll see a warning
in the console, but the alarm will still go off after 6 seconds
* if you package the extension and install it, then the alarm will go off after
a minute.
*/
var DELAY = 0.1;
var CATGIFS = "http://chilloutandwatchsomecatgifs.com/";
/*
Start-stop for the currently active tab, whenever this script is run.
Restart alarm for the currently active tab, whenever background.js is run.
*/
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
startStopAlarm(tabs[0].id);
restartAlarm(tabs[0].id);
});
/*
Start-stop for the currently active tab, whenever the user navigates.
Restart alarm for the currently active tab, whenever the user navigates.
*/
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (!changeInfo.url) {
@@ -17,28 +27,28 @@ chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
}
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if (tabId == tabs[0].id) {
startStopAlarm(tabId);
restartAlarm(tabId);
}
});
});
/*
Start-stop for the currently active tab, whenever a new tab becomes active.
Restart alarm for the currently active tab, whenever a new tab becomes active.
*/
chrome.tabs.onActivated.addListener(function (activeInfo) {
startStopAlarm(activeInfo.tabId);
restartAlarm(activeInfo.tabId);
});
/*
Start-stop: clear all alarms,
restartAlarm: clear all alarms,
then set a new alarm for the given tab.
*/
function startStopAlarm(tabId) {
function restartAlarm(tabId) {
chrome.pageAction.hide(tabId);
chrome.alarms.clearAll();
chrome.tabs.get(tabId, function(tab) {
if (tab.url != CATGIFS) {
chrome.alarms.create(tabId, {delayInMinutes: DELAY});
chrome.alarms.create("", {delayInMinutes: DELAY});
}
});
}
@@ -48,7 +58,7 @@ On alarm, show the page action.
*/
chrome.alarms.onAlarm.addListener(function(alarm) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.pageAction.show(alarm.name);
chrome.pageAction.show(tabs[0].id);
});
});

View File

@@ -1 +0,0 @@
The icon "chillout.png" is taken from the IconBeast Lite iconset, and used under the terms of its license (http://www.iconbeast.com/faq/), with a link back to the website: http://www.iconbeast.com/free/.

3
chill-out/icons/LICENSE Normal file
View File

@@ -0,0 +1,3 @@
The icon "chillout-32.png" is taken from the IconBeast Lite iconset, and used under the terms of its license (http://www.iconbeast.com/faq/), with a link back to the website: http://www.iconbeast.com/free/.
The icon "chillout-48.png" is taken from Aha-Softs Free Retina iconset, and used under the terms of its license (http://www.aha-soft.com/free-icons/free-retina-icon-set/), with a link back to the website: http://www.aha-soft.com/.

View File

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,4 +1,12 @@
{
"manifest_version": 2,
"name": "Chill out",
"version": "1.0",
"description": "Show a page action after a period of inactivity. Show cat gifs when the page action is clicked.",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/chill-out",
"icons": {
"48": "icons/chillout-48.png"
},
"manifest_version": 2,
"name": "chillout-page-action",
@@ -11,11 +19,12 @@
},
"permissions": [
"alarms",
"tabs"
],
"page_action": {
"default_icon": "button/chillout.png",
"default_icon": "icons/chillout-32.png",
"default_title": "Chill out"
},

View File

@@ -0,0 +1,27 @@
# inpage-toolbar-ui
## What it does ##
The extension includes:
* a browser action which enables/disables the in-page toolbar
* a content script which creates/removes the in-page toolbar iframe
* the toolbar ui resources, packaged as web accessible resources
When the user clicks the browser action button, a toolbar is shown/hidden
in the current web page.
The toolbar UI is packaged in the add-on resources, exposed to the current
web page as a web accessible resource and injected into the page by the
content script by creating and injecting into the page an iframe which
points to the toolbar UI page.
## What it shows ##
How to expose an in-page toolbar UI by creating an iframe:
* use web accessible resources to enable web pages to load packaged content
* use a content script to create and inject in a web page an iframe which points to the
packaged content
* use the same API enabled in content scripts (but from the add-on iframe)
to exchange messages directly with the add-on background page

View File

@@ -0,0 +1,17 @@
// Send a message to the current tab's content script.
function toggleToolbar() {
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, "toggle-in-page-toolbar");
});
}
// Handle the browser action button.
chrome.browserAction.onClicked.addListener(toggleToolbar);
// Handle connections received from the add-on toolbar ui iframes.
chrome.runtime.onConnect.addListener(function (port) {
if (port.sender.url == chrome.runtime.getURL("toolbar/ui.html")) {
// Handle port messages received from the connected toolbar ui frames.
port.onMessage.addListener(toggleToolbar);
}
});

View File

@@ -0,0 +1,36 @@
var toolbarUI;
// Create the toolbar ui iframe and inject it in the current page
function initToolbar() {
var iframe = document.createElement("iframe");
iframe.setAttribute("src", chrome.runtime.getURL("toolbar/ui.html"));
iframe.setAttribute("style", "position: fixed; top: 0; left: 0; z-index: 10000; width: 100%; height: 36px;");
document.body.appendChild(iframe);
return toolbarUI = {
iframe: iframe, visible: true
};
}
function toggleToolbar(toolbarUI) {
if (toolbarUI.visible) {
toolbarUI.visible = false;
toolbarUI.iframe.style["display"] = "none";
} else {
toolbarUI.visible = true;
toolbarUI.iframe.style["display"] = "block";
}
}
// Handle messages from the add-on background page (only in top level iframes)
if (window.parent == window) {
chrome.runtime.onMessage.addListener(function(msg) {
if (msg == "toggle-in-page-toolbar") {
if (toolbarUI) {
toggleToolbar(toolbarUI);
} else {
toolbarUI = initToolbar();
}
}
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

View File

@@ -0,0 +1,40 @@
{
"description": "Adds a browser action icon to the toolbar. Click the button to inject an in-page toolbar UI into the current webpage. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#inpage-toolbar-ui",
"manifest_version": 2,
"name": "In Page Toolbar UI",
"version": "1.0",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/inpage-toolbar-ui",
"icons": {
"48": "icons/48.png"
},
"permissions": [],
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "icons/32.png",
"default_title": "In Page Toolbar"
},
"content_scripts": [
{
"js": ["contentscript.js"],
"run_at": "document_idle",
"matches": ["<all_urls>"]
}
],
"web_accessible_resources": [
"toolbar/ui.html"
],
"applications": {
"gecko": {
"id": "inpage-toolbar-ui@mozilla.org",
"strict_min_version": "46.0.0"
}
}
}

View File

@@ -0,0 +1,62 @@
body {
overflow: hidden;
color: black;
background: rgba(255,255,255,0.9);
}
#rainbow {
background: linear-gradient(0deg, rgba(217,26,18,0.70) 15%, rgba(225,51,0,0.70) 15%, rgba(255, 127, 20, 0.70) 16%, rgba(242, 171, 3, 0.70) 32%, rgba(235, 192, 0, 0.70) 32%, rgba(250, 222, 0, 0.70) 33%, rgba(239, 255, 3, 0.70) 48%, rgba(86, 252, 2, 0.70) 49%, rgba(82, 255, 1, 0.70) 66%, rgba(74, 222, 126, 0.70) 67%, rgba(59, 170, 242, 0.70) 67%, rgba(59, 170, 242, 0.70) 84%, rgba(115, 55, 247, 0.70) 84%, rgba(107, 64, 242, 0.70) 100%);
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 6px;
}
#title {
font-weight: bold;
font-size: 1em;
}
.whimsy {
width: 36px;
height: 36px;
}
/* Toggle Button. */
#toggle {
top: 8px;
right: 4px;
position: absolute;
margin: 0 1em;
text-decoration: underline;
border-radius: 1em;
background: transparent linear-gradient(0deg, rgb(255, 162, 0), rgba(189, 122, 6, 0.66));
}
/* Annoying animation. */
@keyframes wobbling {
50% {
transform: translateY(-13px);
}
100% {
transform: translateY(0px);
}
}
.wobbling {
display: inline-block;
vertical-align: middle;
transform: translateZ(0);
box-shadow: 0 0 1px rgba(0, 0, 0, 0);
backface-visibility: hidden;
animation-name: wobbling;
animation-duration: 1.25s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-fill-mode: both;
}

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="ui.css">
</head>
<body>
<span>
<div id="rainbow"></div>
<img src="whimsy.png" class="whimsy wobbling">
<span id="title" class="wobbling">In-Page "Amazing and super-useful" Toolbar</span>
</span>
<button id="toggle">toggle</button>
<script src="ui.js">
</script>
</body>
</html>

View File

@@ -0,0 +1,8 @@
// Connect to the background page.
var port = chrome.runtime.connect();
// Handle click events on the toolbar button.
document.querySelector("#toggle").addEventListener("click", function() {
// Ask the background page to toggle the toolbar on the current tab
port.postMessage("toggle-in-page-toolbar");
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1 +0,0 @@
The "link.png" icon is taken from the Geomicons iconset, and is used here under the MIT license: http://opensource.org/licenses/MIT.

View File

@@ -0,0 +1,25 @@
# notify-link-clicks-i18n
## What it does
This extension includes:
* a content script, "content-script.js", that is injected into all pages
* a background script, "background-script.js"
The content script listens for clicks in the page it's attached to.
If a click is on a link, the content script sends the link's href
to the background script.
The background script listens for this message. When the background script
receives the message, it displays a notification containing the href.
The notification's content, as well as the extension's name and description, are
localized into German and Dutch, as well as en-US.
# What it shows
* how to inject content scripts declaratively using manifest.json
* how to send messages from a content script to a background script
* how to display system notifications using the notifications API
* how to use the internationalization (i18n) system

View File

@@ -1,6 +1,6 @@
{
"extensionName": {
"message": "Notify link clicks",
"message": "Notify link clicks i18n",
"description": "Name of the extension."
},

View File

@@ -0,0 +1,21 @@
{
"extensionName": {
"message": "リンクを通知する",
"description": "拡張機能の名前です。"
},
"extensionDescription": {
"message": "ユーザーがリンクをクリックした時通知を表示します。",
"description": "拡張機能の説明です。"
},
"notificationTitle": {
"message": "クリック通知",
"description": "pushのタイトルです。"
},
"notificationContent": {
"message": "$1がクリックされました。",
"description": "リンクをクリックした時通知を表示します。:変数$1にはurlが代入されます。"
}
}

View File

@@ -1,13 +1,21 @@
chrome.runtime.onMessage.addListener(notify);
/*
Log that we received the message.
Then display a notification. The notification contains the URL,
which we read from the message.
*/
function notify(message) {
console.log("background script received message");
var title = chrome.i18n.getMessage("notificationTitle");
var content = chrome.i18n.getMessage("notificationContent", message.url);
chrome.notifications.create({
"type": "basic",
"iconUrl": chrome.extension.getURL("link.png"),
"iconUrl": chrome.extension.getURL("icons/link-48.png"),
"title": title,
"message": content
});
}
/*
Assign `notify()` as a listener to messages from the content script.
*/
chrome.runtime.onMessage.addListener(notify);

View File

@@ -1,9 +1,20 @@
window.addEventListener("click", notifyExtension);
/*
If the click was on a link, send a message to the background page.
The message contains the link's URL.
*/
function notifyExtension(e) {
console.log("content script sending message");
if (e.target.tagName != "A") {
return;
var target = e.target;
while ((target.tagName != "A" || !target.href) && target.parentNode) {
target = target.parentNode;
}
chrome.runtime.sendMessage({"url": e.target.href});
if (target.tagName != "A")
return;
console.log("content script sending message");
chrome.runtime.sendMessage({"url": target.href});
}
/*
Add notifyExtension() as a listener to click events.
*/
window.addEventListener("click", notifyExtension);

View File

@@ -0,0 +1 @@
The "link-48.png" icon is taken from the Geomicons iconset, and is used here under the MIT license: http://opensource.org/licenses/MIT.

View File

Before

Width:  |  Height:  |  Size: 596 B

After

Width:  |  Height:  |  Size: 596 B

View File

@@ -4,9 +4,15 @@
"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"version": "1.0",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n",
"icons": {
"48": "icons/link-48.png"
},
"applications": {
"gecko": {
"id": "notify-link-clicks@mozilla.org"
"id": "notify-link-clicks-i18n@mozilla.org",
"strict_min_version": "45.0.0"
}
},

View File

@@ -1 +0,0 @@
The "link.png" icon is taken from the Geomicons iconset, and is used here under the MIT license: http://opensource.org/licenses/MIT.

View File

@@ -1,11 +0,0 @@
chrome.runtime.onMessage.addListener(notify);
function notify(message) {
console.log("background script received message");
chrome.notifications.create({
"type": "basic",
"iconUrl": chrome.extension.getURL("link.png"),
"title": "You clicked a link!",
"message": message.url
});
}

View File

@@ -1,9 +0,0 @@
window.addEventListener("click", notifyExtension);
function notifyExtension(e) {
console.log("content script sending message");
if (e.target.tagName != "A") {
return;
}
chrome.runtime.sendMessage({"url": e.target.href});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

View File

@@ -1,25 +0,0 @@
{
"description": "Displays notifications when the user clicks links. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#notify-link-clicks",
"manifest_version": 2,
"name": "Notify link clicks",
"version": "1.0",
"applications": {
"gecko": {
"id": "notify-link-clicks@mozilla.org"
}
},
"permissions": ["notifications"],
"background": {
"scripts": ["background-script.js"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content-script.js"]
}
]
}

View File

@@ -1,5 +1,11 @@
/*
Add openMyPage() as a listener to clicks on the browser action.
*/
chrome.browserAction.onClicked.addListener(openMyPage);
/*
Open a new tab, and load "my-page.html" into it.
*/
function openMyPage() {
console.log("injecting");
chrome.tabs.create({

View File

@@ -1 +0,0 @@
The icon "beasts.png" is taken from the IconBeast Lite iconset, and used under the terms of its license (http://www.iconbeast.com/faq/), with a link back to the website: http://www.iconbeast.com/free/.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 B

View File

@@ -0,0 +1,2 @@
The "page-32.png" and "page-48.png" icons are taken from the miu iconset created by Linh Pham Thi Dieu, and are used under the terms of its license: http://linhpham.me/miu/.

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

View File

@@ -4,23 +4,24 @@
"manifest_version": 2,
"name": "open-my-page",
"version": "1.0",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/open-my-page-button",
"icons": {
"48": "icons/page-48.png"
},
"applications": {
"gecko": {
"id": "open-my-page-button@mozilla.org"
"id": "open-my-page-button@mozilla.org",
"strict_min_version": "45.0.0"
}
},
"permissions": [
"tabs"
],
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "button/beasts.png"
"default_icon": "icons/page-32.png"
}
}

View File

@@ -1,3 +1,7 @@
/*
Listen for messages from the page.
If the message was from the page script, show an alert.
*/
window.addEventListener("message", function(event) {
if (event.source == window &&
event.data.direction &&
@@ -6,13 +10,19 @@ window.addEventListener("message", function(event) {
}
});
/*
Add messagePageScript() as a listener to click events on
the "from-content-script" element.
*/
var fromContentScript = document.getElementById("from-content-script");
fromContentScript.addEventListener("click", messagePageScript);
/*
Send a message to the page script.
*/
function messagePageScript() {
window.postMessage({
direction: "from-content-script",
message: "Message from the content script"
}, "*");
}, "https://mdn.github.io");
}

View File

@@ -0,0 +1,2 @@
The "message-48.png" icon is taken from the miu iconset created by Linh Pham Thi Dieu, and is used under the terms of its license: http://linhpham.me/miu/.

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

View File

@@ -4,10 +4,15 @@
"name": "Page to extension messaging",
"description": "Visit https://mdn.github.io/webextensions-examples/content-script-page-script-messaging.html for the demo. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#page-to-extension-messaging",
"version": "1.0",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/page-to-extension-messaging",
"icons": {
"48": "icons/message-48.png"
},
"applications": {
"gecko": {
"id": "page-to-extension-messaging@mozilla.org"
"id": "page-to-extension-messaging@mozilla.org",
"strict_min_version": "45.0.0"
}
},

View File

@@ -1,19 +1,37 @@
"use strict";
/*
This is the page for which we want to rewrite the User-Agent header.
*/
var targetPage = "http://useragentstring.com/*";
/*
Map browser names to UA strings.
*/
var uaStrings = {
"Firefox 41": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:41.0) Gecko/20100101 Firefox/41.0",
"Chrome 41": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"IE 11": "Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"
}
/*
Initialize the UA to Firefox 41.
*/
var ua = uaStrings["Firefox 41"];
/*
Add rewriteUserAgentHeader as a listener to onBeforeSendHeaders,
only for the target page.
Make it "blocking" so we can modify the headers.
*/
chrome.webRequest.onBeforeSendHeaders.addListener(rewriteUserAgentHeader,
{urls: [targetPage]},
["blocking", "requestHeaders"]);
/*
Rewrite the User-Agent header to "ua".
*/
function rewriteUserAgentHeader(e) {
for (var header of e.requestHeaders) {
if (header.name == "User-Agent") {
@@ -23,8 +41,9 @@ function rewriteUserAgentHeader(e) {
return {requestHeaders: e.requestHeaders};
}
chrome.runtime.onMessage.addListener(setUaString);
function setUaString(message) {
ua = uaStrings[message.uaString];
/*
Update ua to a new value, mapped from the uaString parameter.
*/
function setUaString(uaString) {
ua = uaStrings[uaString];
}

View File

@@ -1 +0,0 @@
The icon “choose_ua.png” is taken from Yummygums Iconsweets iconset, and is used under the terms of its license (http://yummygum.com/work/iconsweets).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 471 B

View File

@@ -0,0 +1 @@
The "person-32.png" "person-48.png" icons are taken from the Ionicons iconset (http://ionicons.com/), and are used here under the MIT license: http://opensource.org/licenses/MIT.

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 573 B

View File

@@ -4,10 +4,15 @@
"manifest_version": 2,
"name": "user-agent-rewriter",
"version": "1.0",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/user-agent-rewriter",
"icons": {
"48": "icons/person-48.png"
},
"applications": {
"gecko": {
"id": "user-agent-rewriter@mozilla.org"
"id": "user-agent-rewriter@mozilla.org",
"strict_min_version": "45.0.0"
}
},
@@ -18,9 +23,9 @@
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": "button/choose_ua.png",
"default_icon": "icons/person-32.png",
"default_title": "Choose a user agent",
"default_popup": "popup/choose_ua.html"
}

View File

@@ -1,14 +1,19 @@
html, body {
html, body, .ua-choices {
height: 100px;
width: 100px;
width: 120px;
margin: 0;
}
.ua-choices {
display: flex;
flex-direction: column;
justify-content: space-around;
}
.ua-choice {
height: 20%;
width: 90%;
margin: 3% auto;
padding: 8% 6% 0 6%;
margin: 0.2em;
padding: 0.2em;
background-color: #E5F2F2;
cursor: pointer;
}

View File

@@ -8,9 +8,11 @@
<body>
<div class="ua-choice">Firefox 41</div>
<div class="ua-choice">Chrome 41</div>
<div class="ua-choice">IE 11</div>
<div class="ua-choices">
<div class="ua-choice">Firefox 41</div>
<div class="ua-choice">Chrome 41</div>
<div class="ua-choice">IE 11</div>
</div>
<script src="choose_ua.js"></script>
</body>

View File

@@ -1,12 +1,15 @@
/*
If the user clicks on an element which has the class "ua-choice":
* fetch the element's textContent: for example, "IE 11"
* pass it into the background page's setUaString() function
*/
document.addEventListener("click", function(e) {
if (!e.target.classList.contains("ua-choice")) {
return;
}
var chosenUa = e.target.textContent;
chrome.runtime.sendMessage({
"command": "set-user-agent",
"uaString": chosenUa
});
var backgroundPage = chrome.extension.getBackgroundPage();
backgroundPage.setUaString(chosenUa);
});