Skip to content

Commit 4446839

Browse files
authored
Switch to modern Clipboard API (#649)
> Context: #440 (comment) This commit removes the need for content script in Firefox by switching to modern Clipboard API that landed in Firefox 63. As a result, we were able to switch copying in Chrome back to the background page, which fixed copying URLs for SVG and PDF in both browsers.
2 parents d59416d + f707f44 commit 4446839

File tree

1 file changed

+26
-31
lines changed

1 file changed

+26
-31
lines changed

add-on/src/lib/copier.js

+26-31
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,34 @@
11
'use strict'
22

3-
const browser = require('webextension-polyfill')
43
const { safeIpfsPath, trimHashAndSearch } = require('./ipfs-path')
54
const { findValueForContext } = require('./context-menus')
65

7-
async function copyTextToClipboard (copyText) {
8-
const currentTab = await browser.tabs.query({ active: true, currentWindow: true }).then(tabs => tabs[0])
9-
const tabId = currentTab.id
10-
// Lets take a moment and ponder on the state of copying a string in 2017:
11-
const copyToClipboardIn2017 = `function copyToClipboardIn2017(text) {
12-
function oncopy(event) {
13-
document.removeEventListener('copy', oncopy, true);
14-
event.stopImmediatePropagation();
15-
event.preventDefault();
16-
event.clipboardData.setData('text/plain', text);
17-
}
18-
document.addEventListener('copy', oncopy, true);
19-
document.execCommand('copy');
20-
}`
21-
22-
// In Firefox you can't select text or focus an input field in background pages,
23-
// so you can't write to the clipboard from a background page.
24-
// We work around this limitation by injecting content script into a tab and copying there.
25-
// Yes, this is 2017.
6+
async function copyTextToClipboard (text, notify) {
267
try {
27-
const copyHelperPresent = (await browser.tabs.executeScript(tabId, { runAt: 'document_start', code: "typeof copyToClipboardIn2017 === 'function';" }))[0]
28-
if (!copyHelperPresent) {
29-
await browser.tabs.executeScript(tabId, { runAt: 'document_start', code: copyToClipboardIn2017 })
8+
try {
9+
// Modern API (spotty support, but works in Firefox)
10+
await navigator.clipboard.writeText(text)
11+
// FUN FACT:
12+
// Before this API existed we had no access to cliboard from
13+
// the background page in Firefox and had to inject content script
14+
// into current page to copy there:
15+
// https://github.com/ipfs-shipyard/ipfs-companion/blob/b4a168880df95718e15e57dace6d5006d58e7f30/add-on/src/lib/copier.js#L10-L35
16+
// :-))
17+
} catch (e) {
18+
// Fallback to old API (works only in Chromium)
19+
function oncopy (event) { // eslint-disable-line no-inner-declarations
20+
document.removeEventListener('copy', oncopy, true)
21+
event.stopImmediatePropagation()
22+
event.preventDefault()
23+
event.clipboardData.setData('text/plain', text)
24+
}
25+
document.addEventListener('copy', oncopy, true)
26+
document.execCommand('copy')
3027
}
31-
await browser.tabs.executeScript(tabId, { runAt: 'document_start', code: 'copyToClipboardIn2017(' + JSON.stringify(copyText) + ');' })
28+
notify('notify_copiedTitle', text)
3229
} catch (error) {
33-
console.error('Failed to copy text: ' + error)
30+
console.error('[ipfs-companion] Failed to copy text', error)
31+
notify('notify_addonIssueTitle', 'Unable to copy')
3432
}
3533
}
3634

@@ -39,8 +37,7 @@ function createCopier (getState, getIpfs, notify) {
3937
async copyCanonicalAddress (context, contextType) {
4038
const url = await findValueForContext(context, contextType)
4139
const rawIpfsAddress = safeIpfsPath(url)
42-
copyTextToClipboard(rawIpfsAddress)
43-
notify('notify_copiedTitle', rawIpfsAddress)
40+
await copyTextToClipboard(rawIpfsAddress, notify)
4441
},
4542

4643
async copyRawCid (context, contextType) {
@@ -49,8 +46,7 @@ function createCopier (getState, getIpfs, notify) {
4946
const url = await findValueForContext(context, contextType)
5047
const rawIpfsAddress = trimHashAndSearch(safeIpfsPath(url))
5148
const directCid = (await ipfs.resolve(rawIpfsAddress, { recursive: true, dhtt: '5s', dhtrc: 1 })).split('/')[2]
52-
copyTextToClipboard(directCid)
53-
notify('notify_copiedTitle', directCid)
49+
await copyTextToClipboard(directCid, notify)
5450
} catch (error) {
5551
console.error('Unable to resolve/copy direct CID:', error.message)
5652
if (notify) {
@@ -71,8 +67,7 @@ function createCopier (getState, getIpfs, notify) {
7167
const url = await findValueForContext(context, contextType)
7268
const state = getState()
7369
const urlAtPubGw = url.replace(state.gwURLString, state.pubGwURLString)
74-
copyTextToClipboard(urlAtPubGw)
75-
notify('notify_copiedTitle', urlAtPubGw)
70+
await copyTextToClipboard(urlAtPubGw, notify)
7671
}
7772
}
7873
}

0 commit comments

Comments
 (0)