Skip to content

Commit 62cee08

Browse files
committed
add copy option to tab context menu, close moritz-h#3
1 parent ffa82be commit 62cee08

File tree

5 files changed

+96
-1
lines changed

5 files changed

+96
-1
lines changed

background.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
browser.contextMenus.create({
2+
id: "url-list-copy-urls",
3+
title: "Copy URLs (all tabs)",
4+
contexts: ["tab"],
5+
});
6+
browser.contextMenus.onClicked.addListener(function (info, tab) {
7+
if (info.menuItemId === "url-list-copy-urls") {
8+
browser.tabs.query({currentWindow: true}).then((tabs) => {
9+
// Use active tab for copy to clipboard, so it is possible to open
10+
// the context menu on inactive tabs. Save clicked tab as fallback.
11+
let activeTabId = tab.id;
12+
let urls = '';
13+
for (let tab of tabs) {
14+
urls += tab.url + "\r\n";
15+
if (tab.active) {
16+
activeTabId = tab.id;
17+
}
18+
}
19+
20+
// example source: https://github.com/mdn/webextensions-examples/tree/master/context-menu-copy-link-with-types
21+
22+
// The example will show how data can be copied, but since background
23+
// pages cannot directly write to the clipboard, we will run a content
24+
// script that copies the actual content.
25+
26+
// clipboard-helper.js defines function copyToClipboard.
27+
const code = "copyToClipboard(" + JSON.stringify(urls) + ");";
28+
29+
browser.tabs.executeScript({
30+
code: "typeof copyToClipboard === 'function';",
31+
}).then(function (results) {
32+
// The content script's last expression will be true if the function
33+
// has been defined. If this is not the case, then we need to run
34+
// clipboard-helper.js to define function copyToClipboard.
35+
if (!results || results[0] !== true) {
36+
return browser.tabs.executeScript(activeTabId, {
37+
file: "clipboard-helper.js",
38+
});
39+
}
40+
}).then(function () {
41+
return browser.tabs.executeScript(activeTabId, {
42+
code,
43+
});
44+
}).catch(function (error) {
45+
// This could happen if the extension is not allowed to run code in
46+
// the page, for example if the tab is a privileged page.
47+
console.error("Failed to copy text: " + error);
48+
notifyError();
49+
});
50+
});
51+
}
52+
});
53+
54+
function notifyError() {
55+
browser.notifications.create({
56+
"type": "basic",
57+
"iconUrl": browser.extension.getURL("icons/error.svg"),
58+
"title": "Error!",
59+
"message": "Cannot write to clipboard on settings tab!"
60+
});
61+
}

clipboard-helper.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// example source: https://github.com/mdn/webextensions-examples/tree/master/context-menu-copy-link-with-types
2+
3+
// This function must be called in a visible page, such as a browserAction popup
4+
// or a content script. Calling it in a background page has no effect!
5+
function copyToClipboard(text) {
6+
function oncopy(event) {
7+
document.removeEventListener("copy", oncopy, true);
8+
// Hide the event from the page to prevent tampering.
9+
event.stopImmediatePropagation();
10+
11+
// Overwrite the clipboard content.
12+
event.preventDefault();
13+
event.clipboardData.setData("text/plain", text);
14+
}
15+
16+
document.addEventListener("copy", oncopy, true);
17+
18+
// Requires the clipboardWrite permission, or a user gesture:
19+
document.execCommand("copy");
20+
}

icons/error.svg

Lines changed: 5 additions & 0 deletions
Loading

icons/icon.svg

Lines changed: 1 addition & 1 deletion
Loading

manifest.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,17 @@
55
"description": "List the URLs of all tabs from the current window as copyable plaintext.",
66
"homepage_url": "https://github.com/moritz-h/urls-list",
77
"permissions": [
8+
"activeTab",
9+
"clipboardWrite",
10+
"contextMenus",
11+
"notifications",
812
"tabs"
913
],
14+
"background": {
15+
"scripts": [
16+
"background.js"
17+
]
18+
},
1019
"browser_action": {
1120
"default_icon": "icons/icon.svg",
1221
"browser_style": true,

0 commit comments

Comments
 (0)