I'm trying to get some user configs from the background page of my chrome extension to the content script (or popup) but I'm having some problems, I think the problem is that chrome.storage.sync.get is async, I tried using callbacks but I also read that callbacks can't return the value so I have no idea how to solve this.
Here's kinda how the code looks:
popup.js:
(function() {
chrome.runtime.sendMessage({
message: "loadconfig"
}, function(response) {
console.log(response);
if (response.status === 'success') {
console.log(response);
} else {
console.log(response.except);
}
});
})();
background.js
(function() {
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
switch (request.message) {
case "loadconfig":
sendResponse(loadStuff());
break;
default:
sendResponse({
reply: null
});
break;
}
});
function loadStuff() {
var to_return_configs = {
blocked_characters: '',
good_post: ''
};
var function_status = 'failed';
var exception = '';
var blocked_characters_parsed, good_post_parsed;
try {
var to_get = ["blocked_characters_saved", "good_post_saved"];
chrome.storage.sync.get(to_get, function(result) {
to_get.forEach(function(got) {
if (got === "good_post_saved") {
to_return_configs.good_post = result[got];
}
if (got === "blocked_characters_saved") {
to_return_configs.blocked_characters = result[got];
}
});
});
exception = '';
function_status = 'success';
} catch (err) {
exception = String(err);
function_status = 'failed';
}
var to_return = {
status: function_status,
configs: to_return_configs,
except: (exception)
};
return to_return;
}
})();
The problem here is that when I'm looking at the popup.js console, "blocked_characters" and "good_post" are both empty.
How can I solve this?
You do not need Message API for communication between Popup and Background. Popup in chrome extension can directly call methods of Background .
You can do something like this
BG = chrome.extension.getBackgroundPage();
And then you can call BG.loadStuff() in your popup js.
From within loadStuff, you can pass a callback which can return data to you. So it should look like
BG.loadStuff(function(items) {
console.log(items);
});
background.js
function loadStuff(cb) {
chrome.storage.sync.get(null, function(superObj) {
cb.call(null, superObj);
});
}
For more understanding, read these
http://blog.papersapp.com/chrome-development-parent-and-child-windows/
https://stackoverflow.com/a/17276475/816213
https://stackoverflow.com/a/17378016/816213
sendResponse(function) becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called). See the reference: onMessage.
Because sendResponse is called asynchronously in chrome.storage.sync.get's callback, you need to return true from the onMessage listener to prevent the function from being invalidated. Code similar is Like:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.message === 'loadconfig') {
sendResponse(loadStuff());
return true;
}
return false;
});
Related
I am trying to build a chrome extension.
chrome.runtime.onMessage.addListener(gotMessage);
const htmlTag = document.getElementsByTagName("html")[0];
function gotMessage(message, sender, sendResponse) {
let events = ["click"];
if(message.txt == 'start') {
// Attach all events to the window
events.forEach((eventName) => {
htmlTag.addEventListener(eventName, consoles);
});
}
else {
events.forEach((eventName) => {
htmlTag.removeEventListener(eventName, consoles);
});
}
function consoles() {
console.log('test');
}
};
This function attach the events I mentioned in events[] but I cann't detech it in else function. When I pass stop txt, it still displays console log. Consider for if condition, message.txt = 'start' and for else, message.txt = 'stop'. Please suggest me what I am missing here?
I am trying to communicate with a google chrome extension using JavaScript. I have succeeded in calling the extension from my code. But can't read the response back to my application.
I have written the calling function like this.
function extensionCall(){
var event = document.createEvent('Event');
event.initEvent('EXTENSION_READ_EVENT');
document.dispatchEvent(event);
}
And the code inside the extension is
document.addEventListener("EXTENSION_READ_EVENT", function (data) {
chrome.runtime.sendMessage("test", function (response) {
});
});
chrome.extension.onMessage.addListener(function (msg, sender, sendResponse) {
if (msg.action == 'EXTENSION_DATA') {
try {
readExtension($.parseJSON(msg.response));
}
catch (e) {
var error = "error" + e;
}
}
});
And I am expecting the response here..
function readExtension(val){
console.log(val);
}
But unfortunately, I am not getting any response from the extension.
How can I access the data to my application?
I am getting a trouble about passing message inside background page of chrome extension.
In content page
I send a message and wait for a response from background page:
chrome.runtime.sendMessage({"name": "Calling"}, function (response) {
console.log(response);
});
In background page
I have an event listener to listen message from content page:
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.name == "Calling") {
doTask().then(function (message) {
sendResponse(message);
});
return true; // Make respond asynchronously
}
}
);
Inside "Calling" event Listener, i call the function doTask() which return a promise:
var doTask = function(){
return new Promise(function (resolve) {
chrome.runtime.sendMessage({"name": "DoTask"}, function (response) {
resolve(response);
});
});
};
Inside doTask() i send another message "DoTask", and wait for response.
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.name == "DoTask") {
var message = "Task has done!";
sendResponse(message);
return true; // Make respond asynchronously
}
}
);
I expect "Task has done!" will be printed in content page, but nothing appears! When debugging i realize "DoTask" event listener cannot receive any message.
What wrong here? Thank you.
P/S: I make sure that all scripts are injected in manifest.json
This question already has an answer here:
Clipboard Copy / Paste on Content script (Chrome Extension)
(1 answer)
Closed 6 years ago.
Quick summary
The code below is a file called popup.js. It listens for a click, and sends a message to background.js. Background.js executes another script, and a variable is created.
I somehow need to pass this variable back to popup.js, and continue within the userHasClicked function. The way it is now the response I get is "undefined", and there's nowhere to go from there.
var theParent = document.querySelector("#MENY");
theParent.addEventListener("click", userHasClicked, false);
function userHasClicked(e) {
if (e.target !== e.currentTarget) {
var clickedItem = e.target.id;
chrome.runtime.sendMessage({type: "ResponseType", directive: clickedItem}, function(response) {
console.log(response);
this.close();
});
};
e.stopPropagation();
}
Routine:
User clicks on an option in popup.html
Event("click") -> sendmessage("type of click")
background.js listens for the message, and executes content.js
content.js creates the variable and can send it back to anyone who listens.
The problem:
The variable must come as a response argument to step 2 (within eventloop)
Save the response as variable.
document.execCommand("copy").
Done
This code below is the relevant part of background.js.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.type) {
case "ResponseType":
var LoggType = request.directive;
console.log(LoggType)
chrome.tabs.executeScript(null, {
code: 'var LoggType = "'+LoggType+'";'
}, function() {
chrome.tabs.executeScript(null, {file:"content.js"});
});
chrome.runtime.onMessage.addListener(function(req, snd, sndRes) {
if (req.type = "LogIsGenerated") {
var Logg = req.directive;
console.log(Logg);
} sndRes({});
});
if (typeof Logg !== "undefined") {
alert("Feedback from content.js received");
sendResponse({type: "FinalVar", directive: Logg});
}
else {
alert("No feedback received");
sendResponse({});
};
break};
return true;
}
);
content.js ends with this line.
chrome.extension.sendMessage({type: "LogIsGenerated", directive: Logg});
Logg is the variable containing the text string I want to add to the clipboard.
At the moment this the code below alerts for No feedback received.
chrome.runtime.onMessage.addListener(function(req, snd, sndRes) {
if (req.type = "LogIsGenerated") {
var Logg = req.directive;
console.log(Logg);
} sndRes({});
});
if (typeof Logg !== "undefined") {
alert("Feedback from content.js received");
sendResponse({type: "FinalVar", directive: Logg});
}
else {
alert("No feedback received");
sendResponse({});
};
Rob W presented a solution here: Background script can write to clipboard in a very simple manner
Worked excellently.
I send a message from a ContextMenu within content.js to background.js. When I send a message, I expect to see an alert of just two variables which are sent with the request. When I send multiple request(few times in a row) I receive alerts including previously sent messages. It seems that all messages are stored somewhere. How do you disable this? I would like to see alerts of only the most recent message.
contents.js:
$(document).mousedown(function(event) {
var url = window.location.href;
var contents = window.getSelection().toString();
switch (event.which) {
case 3:
chrome.runtime.sendMessage({contents: contents, url: url}, function(response) {
//console.log(response.farewell);
});
break;
}
});
background.js
chrome.extension.onMessage.addListener(function (message, sender, sendResponse) {
if (message.url) {
chrome.contextMenus.onClicked.addListener(function testFunc2(info, tab){
alert(message.url);
alert(typeof message.contents);
}
)
}
});
manifest.json
"background": {
"scripts": ["jquery-1.11.1.min.js", "background.js"],
//"page": "background.html",
"persistent": true
},
It's because of this code
chrome.extension.onMessage.addListener(function (message, sender, sendResponse) {
if (message.url) {
chrome.contextMenus.onClicked.addListener(function testFunc2(info, tab){
alert(message.url);
alert(typeof message.contents);
}
)
}
});
What you are saying is that every onMessage event add a listener for onClicked events. So if you send three messages you end up with three testFunc2 methods acting on onClicked events.
Since you are trying to use information from two different asynchronous events. You will have to store one of them temporarily. Something like this would probably work.
var lastMessage;
chrome.extension.onMessage.addListener(function(message, sender, sendResponse) {
if (message.url) {
lastMessage = message;
} else {
lastMessage = undefined;
}
});
chrome.contextMenus.onClicked.addListener(function(info, tab) {
if(lastMessage !== undefined) {
testFunc2(message, info, tab);
}
});
function testFunc2(info, tab){
alert(message.url);
alert(typeof message.contents);
// cleanup
lastMessage = undefined;
});