Placing a variable’s content into the clipboard on chrome or opera is described here
In these browser, it can be done from a background script, and for a user, the textarea is not visible.
To my understanding, this must be done in a content script in Firefox.
I tried the following code in a content script //request.data is the value I want to place in the clipboard
var ta = document.getElementById(‘filteredClipboard_data’);
if( ta == null){
ta = document.createElement(‘textarea’);
ta.contentEditable = “true”; //ta.hidden = “true”; ta.id = ‘filteredClipboard_data’;
document.body.appendChild(ta);
} else {
console.log(“found ta”);
The copy command works, but my problem is that with ff53 the browser scroll down at the bottom of the page where the textarea is plain visible. This is not the case with nigthly. The code works.
Adding ta.hidden = true fails in both version: it's the selected text that is copied and not the the string received from the background script.
Please note: starting the add-on with web-ext run --firefox=“C:\Program Files\Nightly\firefox.exe”
does not work: it seems that the content script is not reached. I received the error “Error: Could not establish connection. Receiving end does not exist”. I have to pack the add-on and drag it on the extension page to get it work correctly.
Using a testarea to put data in the clipboard seems unnecessarily complicated, and the current webside will be able to read the data from the textarea, which can be a privacy issue.
I have written this function to copy to the clipboard:
/**
* Attempts to write data to the users clipboard.
* @param {string|object} data Ether a plain string or an object of multiple pairs { [mimeType]: data, } to write.
* @param {natural} time Maximum runtime of this asynchronous operation after which it will be canceled and rejected.
* @return {Promise} Promise that rejects if the timeout or an error occurred. If it resolves the operation should have succeeded.
*/
function writeToClipboard(data, time) { return new Promise(function(resolve, reject) {
let done = false;
function onCopy(event) { try {
if (done) { return; } done = true;
document.removeEventListener('copy', onCopy);
const transfer = event.clipboardData;
transfer.clearData();
if (typeof data === 'string') {
transfer.setData('text/plain', data);
} else {
Object.keys(data).forEach(mimeType => transfer.setData(mimeType, data[mimeType]));
}
event.preventDefault();
resolve();
} catch (error) { reject(error); } }
setTimeout(() => {
if (done) { return; } done = true;
document.removeEventListener('copy', onCopy);
reject(new Error('Timeout after '+ (time || 1000) +'ms'));
}, time || 1000);
document.addEventListener('copy', onCopy);
document.execCommand('copy', false, null);
}); }
It doesn’t need to add any DOM-Elements and won’t tell the page what was copied.
web-ext run does pretty much the same thing as firefox -no-remote -Profile "path/to/some/temp/folder" and then loading the unpacked extension via about:debugging.
There shouldn’t be any difference (at runtime) between packed and unpacked extensions(*). If there are differences, those are bugs. And if you are reasonably sure that you found a bug, you should report it.
*) One difference I know of are stacktraces. For unpacked extensions they sometimes contain the absolute file system path of the unpacked file, for packed extensions the path to the .xpi file plus ! and the relative path to the file within the .xpi. In both cases, it should be moz-extension://<uuid>/relative/path. But I very much doubt that affects you.