I want clicking my Chrome extension’s browser action button to copy some text, but the methods used on websites don’t work.
(I realize there are some similar questions, however they answer copying text in injected scripts or browser action popup scripts, not browser action scripts.)
Boilerplate
manifest.json:
{
"name": "Example",
"version": "0.0.0",
"manifest_version": 2,
"permissions": ["clipboardWrite"],
"browser_action": {"default_title": "Copy some text"},
"background": {
"scripts": ["events.js"],
"persistent": false
}
}
events.js:
chrome.browserAction.onClicked.addListener(_ => {
copy(new Date().toISOString().slice(0, 19))
})
// Define copy() here.
Approach 1
Don’t define copy
and hope it’s defined globally as in the console.
It isn’t.
Approach 2
function copy(text) {
navigator.clipboard.writeText(text)
}
This fails with the error message “DOMException: Document is not focused”.
Approach 3
function copy(text) {
focus()
navigator.clipboard.writeText(text)
}
This behaves the same as approach 2.
Approach 4
function copy(text) {
const ta = document.createElement('textarea')
ta.value = text
ta.select()
document.execCommand('copy')
ta.remove()
}
This fails without an error message.
Approach 5
Inject a copying script into the active tab. I didn’t code this one because it would break if there are no accessible active tabs, tabs messed with their globals, JS is paused on the active tab, etc, and would also need excessive permissions.
Approach 6
function copy(text) {
open('copy.html?' + encodeURIComponent(text), '', 'width=1,height=1')
}
(Setting width and height forces opening a window, not a tab, in order to preserve the user’s tab selection and reduce visual impact.)
copy.html:
<!doctype html>
<meta charset="utf-8">
<title>Copying…</title>
<div></div>
<script src="copy.js"></script>
copy.js:
(async _ => {
await navigator.clipboard.writeText(decodeURIComponent(location.search.slice(1)))
close()
})()
This works but isn’t great because it’s visually glitchy, slow, and circuitous.