The goal is to send a message to a content script from a background script after a URL is changed.
Here is my function:
chrome.tabs.onUpdated.addListener(
function (tabId, changeInfo, tab){
if(changeInfo.url && changeInfo.url.includes('https://example')){
chrome.runtime.sendMessage(tabId, {warn: 'message'}, function(resp){})
}
});
But I get an error: Error, in event handler: TypeError: Error in invocation of runtime.sendMessage(optional string extensionId, any message, optional object options, optional function callback): Error at parameter 'options': Unexpected property: 'warn'.
I tried to code according to documentation, but can't find the error
I was getting a similar error until I did something like
chrome.tabs.sendMessage(tabId, {warn: 'message'});
Note: tabs, not runtime method.
I had to leave out the message parameter. Not sure about callback.
You are using the API wrong. sendMessage should receive two parameters. The first one can be an object and the second one would be a callback with the response. This way:
chrome.runtime.sendMessage(
{
message: "this is a message",
},
(response) => {
// ... do something with the response
}
);
Related
I'm writing a chrome extension and I'm getting this error
Error in event handler for webRequest.onBeforeSendHeaders/2: Error: Invalid value for argument 4. Property '$$state': Unexpected property
I'm not even sure where it's coming from so not sure what code snippet to provide to get started.
Any idea how I should even read this error message? What does the "/2" in "onBeforeSendHeaders/2" mean?
Perhaps there's a clue in my listener (simplified for our sake. I'm really doing an ajax fetch to get data before returning a promise of the headers)
chrome.webRequest.onBeforeSendHeaders.addListener(function(details) {
return new Promise((resolve,reject) => {
resolve({requestHeaders: [name:'authorization',value:'...']}
});
},
{urls: [ "<all_urls>" ]},
['requestHeaders','blocking']);
Bonus question. The listener doesn't seem to be adding the header I injected when resolved in a Promise. It works if I just return {requestHeaders: ...} directly.
Thoughts?
getUser: function(req, res){
Model.getUser({}, function(error, models){
if(error){
let response = {
code: 'ERR0001',
msg: 'Facing issues while ....',
err: error
}
res.json(response);
} else {
res.json(models)
}
}
};
Above code is working fine for all positive scenarios. But for error scenario I am not getting complete error message instead it shows 'err: {}'.
I have already registered JSON parser with Express app object.
Response I am getting in POSTMAN console in case error is
{
code: 'ERR0001',
msg: 'Facing issues while ....',
err: {}
}
As per my requirement it should display something like:
{
code: 'ERR0001',
msg: 'Facing issues while ....',
err: 'ERROR: whatever exception occurred on database operation...'
}
Please help me to understand cause of this issue.
Express is stringifying your JSON response when you use res.json().
However, because the Error object doesn't get handled by JSON.stringify() as you would expect, you're not seeing the content of it; like the stack trace property for example.
For details on what's happening with JSON.stringify() and the Error object, check out this other stack overflow answer (I won't duplicate that here):
https://stackoverflow.com/a/18391400/2387067
So, using a variation of that answer, I will do this when I want to send back a Javascript Error object to the client from Express:
function replaceErrors(key, value) {
if (value instanceof Error) {
var error = {};
Object.getOwnPropertyNames(value).forEach(function (key) {
error[key] = value[key];
});
return error;
}
return value;
}
function getPureError(error) {
return JSON.parse(JSON.stringify(error, replaceErrors));
}
and then make a call to it in my response like this:
res.status(500).json(getPureError(error));
The call to getPureError() stringifys the Error object and gets all of the properties because of the call to replaceErrors(). It then parses it back to a pure object. That pure object plays nicely with Express when the .json() call is made so you get all of your properties that you were expecting. It is a bit wasteful but you get the result you're looking for.
This results in my seeing the full, Error object; stack trace and all.
When I first encountered this problem, I was doing this:
res.status(500).json(error);
and I was getting back {} in my response on the server. It took me a bit of time to sort out what was happening there. I originally thought that I wasn't chaining that json() command incorrectly but I was. The actual problem was that the Error object doesn't behave like other objects with JSON.stringify() as described above.
I hope that helps you or at least someone else after all this time!
I am working on a Chrome extension. I have a content script and an event page. From the content script, I send a message using chrome.runtime.sendMessage() to the event page. On the event page, I use onMessage event listener to send back a reponse -- however, I would like to send this reponse AFTER chrome has detected that a file has started downloading.
contentScript.js
window.location.href = download_link; //redirecting to download a file
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
eventPage.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
chrome.downloads.onCreated.addListener(function(DownloadItem downloadItem) {
sendResponse({farewell: "goodbye"});
return true;
});
});
Now, I haven't tried chrome.downloads.onCreated listener before, but I'm assuming this is the correct syntax. However, the code is not working, and the console is returning this error:
Error in event handler for (unknown): Cannot read property 'farewell' of undefined
Stack trace: TypeError: Cannot read property 'farewell' of undefined
at chrome-extension://dlkbhmbjncfpnmfgmpbmdfjocjbflmbj/ytmp3.js:59:31
at disconnectListener (extensions::messaging:335:9)
at Function.target.(anonymous function) (extensions::SafeBuiltins:19:14)
at EventImpl.dispatchToListener (extensions::event_bindings:395:22)
at Function.target.(anonymous function) (extensions::SafeBuiltins:19:14)
at Event.publicClass.(anonymous function) [as dispatchToListener] (extensions::utils:65:26)
at EventImpl.dispatch_ (extensions::event_bindings:378:35)
at EventImpl.dispatch (extensions::event_bindings:401:17)
at Function.target.(anonymous function) (extensions::SafeBuiltins:19:14)
at Event.publicClass.(anonymous function) [as dispatch] (extensions::utils:65:26)
I have tried this without the chrome.downloads.onCreated listener and it works, the response is fetched by the content script. I read online that you need to add return true; in order to make it work, but it's not working for me. I suspect it's because of the second event listener, which enters a new scope meaning that sendResponse cannot be called from there -- if that's the case, how do I call the sendResponse function?
You return true; from the wrong place.
The purpose of that return is to say "I have not called sendResponse yet, but I'm going to".
However, you are returning it from inside the onCreated callback - it is too late by then, as right after the listener is added your original onMessage handler terminates. You just have to move the line:
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) {
chrome.downloads.onCreated.addListener( function(DownloadItem downloadItem) {
sendResponse({farewell: "goodbye"});
});
return true;
});
I'm using the sendgrid library for node.js. Currently there is a callback that it's getting fired twice.
#invite = (email, agencyId, callback) ->
(app.get 'agencies').findOne {_id: agencyId}, {name:1}, (error, agency) ->
sendgrid.send {
to: email,
from: 'yamil.asusta#upr.edu',
subject: "You have been invited to #{agency.name}",
html: "<html><body>Have fun</a></body></html>"
}, (success, message) ->
console.log arguments
if success
console.log callback
callback()
else
console.log message
This is what I get from the console
{ '0': true, '1': undefined }
[Function]
{ '0': false, '1': 'Invalid JSON response from server' }
Invalid JSON response from server
The thing is, I invoke the function from 1 route and it works perfectly fine. If I invoke it from another separate route, it fires the callback but, it says the callback variable (function) is undefined.
Any clues?
I suggest you log the arguments to the #invite function. I suspect that is getting called twice, once with correct arguments and once with incorrect arguments due to a bug elsewhere in your program.
background.js :
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse)
{
console.log(request.filter)
chrome.webRequest.onBeforeRequest.addListener(request.func, request.filter, ["blocking"]);
}
);
content script:
chrome.extension.sendRequest(
{
func: requestInterceptor,
filter: requestFilter
}
);
The line chrome.webRequest.onBeforeRequest.addListener(request.func, request.filter, ["blocking"]); is triggering the following error:
Error in event handler for 'undefined': Error: Parameter 1 is required.
How can I fix it?
On message passing, requests are JSON-serialized.
Functions are not serializable, so they're not sent.
chrome.extension.sendRequest( {
func: requestInterceptor, // Function
filter: requestFilter // Array of strings
});
is received as
{
filter: requestFilter
}
Move the function logic to the background page.
If you want to add a webRequest event listener from the content script, pass all necessary (JSON-serializable) data to the background page using chrome.extension.sendRequest. The receiver (background), also gets a MessageSender type, which can be used to read the tab of the origin (which supplies all necessary information, including the tabId).