Reputation: 23
I know there are a lot of similar questions : Chrome extension messaging: sendResponse returning empty object, etc., but I read and tried all of them before asking my question. My problem is a bit different, so I think that's why their solutions don't work for me.
I want to detect Ctrl+C from the user, so when he clicks on extension icon, the content of the clipboard is displayed inside the popup.
Here's what I've done : a part of manifest.json :
"permissions": [
"activeTab", "tabs", "<all_urls>", "clipboardRead"
],
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["oncopy.js"]
}
],
"background": {
"scripts": ["background.js"],
"persistent": false
}
oncopy.js (content script)
//https://stackoverflow.com/questions/2870369/google-chrome-extensions-how-to-detect-copy-action-ctrl-c-and-edit-copy
function onCopy(e) {
chrome.extension.sendMessage({event: "copy"});
}
document.addEventListener('copy',onCopy,true);
background.js (background script) :
var clipboardContents;
// This part of the script receive the 'copy' event.
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.event == "copy") {
// #### GET CLIPBOARD CONTENT #################################################
bg = chrome.extension.getBackgroundPage(); // get the background page
bg.document.body.innerHTML= ""; // clear the background page
// add a DIV, contentEditable=true, to accept the paste action
var helperdiv = bg.document.createElement("div");
document.body.appendChild(helperdiv);
helperdiv.contentEditable = true;
// focus the helper div's content
helperdiv.innerHTML=""; // clear the buffer
var range = document.createRange();
range.selectNode(helperdiv);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
helperdiv.focus();
// trigger the paste action
bg.document.execCommand("Paste");
clipboardContents = helperdiv.innerText;
// ############################################################################
}
sendResponse({});
});
function send_response(callback){
callback(clipboardContents);
}
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
// When we get a message from the popup
send_response(function(clipboardContents) {
sendResponse(clipboardContents.toString());
});
return true;
// I also tried sendResponse() only, wih and without the return true;
// I also tried sendResponse(clipboardContents) only and sendResponse({data: clipboardContents});
});
popup.js :
chrome.runtime.sendMessage('popup_opened',function(response){
document.getElementById('text').innerHTML = response;
// I tried response.data
});
I always get :
response = an empy object
response.toString() = "[Object : object]"
response.data = undefined
I don't understand what I'm doing wrong. I hope you can help, and that the answer has not be explained elsewhere yet.
Upvotes: 0
Views: 595
Reputation: 73616
The actual cause of the problem is that extension.onMessage is a deprecated alias for runtime.onMessage so you have two listeners for the same event but only the first registered listener's sendResponse is transferred to the caller and that is {}
.
That said, the entire workflow can be extremely simplified: there's no need for the background script or the content script so you can remove "background" and "content_scripts" from manifest.json. No need for messaging either.
You need a browser_action popup and simply read the clipboard in the popup script.
manifest.json:
{
"manifest_version": 2,
"name": "test",
"version": "1.0",
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"clipboardRead"
]
}
popup.html:
<!DOCTYPE html>
<body>
<p id=text contenteditable=true></p>
<script src=popup.js></script>
</body>
popup.js:
document.getElementById('text').focus();
document.execCommand('paste');
This is the entire content of the extension.
Upvotes: 1