6

I'm coding a chrome extension that interacts with gmail api (chrome 45 is my version) and I am having issues sending a message from the background.js to my content-script. The async aspect is where the issue lies. How can I get the message to be sent after the callback?

//---------in content script---------
chrome.runtime.sendMessage({ messageId: _id }, function (response) {    
    console.log('the respose.messagePayload is: ' + response.messagePayload); 
});

//---------in background script---------
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    getMessage('me', request.messageId, function (payload) {
        //i want to send my response here
        //this executes and grabs the payload of data from the api, but isn't sending back the message to the content-script
        sendResponse({ messagePayload: payload }); 
    });
    //this synchronous call sends a message to the content-script
    //sendResponse({ messagePayload: "payload" });
    return true;
});

function getMessage(userId, messageId,callback) {
    var request = gapi.client.gmail.users.messages.get({
        'userId': userId,
        'id': messageId
    });
    request.execute(callback);
}

Chrome Extension Message passing: response not sent

Community
  • 1
  • 1
pacopicorico
  • 131
  • 1
  • 1
  • 6
  • Are you certain that the callback with `payload` executes? Can you confirm that with logging? – Xan Feb 07 '16 at 12:37
  • @Xan I can confirm that portion works with logging. I have code to add it to localStorage and read from localStorage, but this is a workaround as I want to send the object in sendResponse 'localStorage.setItem(request.messageId, JSON.stringify(payload)); sendResponse({ messagePayload: payload });' – pacopicorico Feb 07 '16 at 14:30
  • @pacopicorico You can use the 'chrome.storage' API to store your response as object rather than using the stringify. Did you try the second approach I posted, I think that will work fine and save you from storing it to the local storage. – Nikhil Sharma Feb 07 '16 at 17:17
  • @NikhilSharma your suggestion did not work. It presents the same issue I am trying to find a solution for. – pacopicorico Feb 08 '16 at 04:29
  • @pacopicorico If you are getting the response from the gmail API and your localstorage workaround is working, then what I suggested should work. Can you post what error you are getting or post the logs from both background script and content script while sending and receiving the messages. – Nikhil Sharma Feb 08 '16 at 04:36

1 Answers1

-1

You should be sending the sendResponse function in your callback.

getMessage('me', request.messageId, sendResponse);

Then execute this when your getMessage call completes.

function getMessage(userId, messageId, sendResponse) {
    var request = gapi.client.gmail.users.messages.get({
        'userId': userId,
        'id': messageId
    });

    request.execute(function(response) {
        sendResponse({messagePayload: response.payload});
    });
}

Another Possible Solution:

  1. Get the tab id from the sender object.
  2. Instead of the callback function just send the tab id to your getMessage function.
  3. Now, your callback function within the getMessage function would send back the payload to your content script.
  4. Add a similar onMessage listener in your content script that will receive your payload and then do what you want to do with the payload.

Your code would be like:

//---------in background script---------
chrome.runtime.onMessage.addListener(function (request, sender,sendResponse) {
    getMessage('me', request.messageId, sender.tab.id);
});

function getMessage(userId, messageId, tabId) {
    var request = gapi.client.gmail.users.messages.get({
        'userId': userId,
        'id': messageId
    });
    request.execute(function(response) {
        // Whatever response you want to sent
        // Below URL explains your response object
        // https://developers.google.com/gmail/api/v1/reference/users/messages#resource
        // Assuming you want to send payload
        chrome.tabs.sendMessage(tab.id, {messagePayload: response.payload});
    });
}

//---------in content script---------
chrome.runtime.sendMessage({ messageId: _id });

chrome.runtime.onMessage.addListener(function (request, sender,sendResponse) {
    // Just to verify that the request is from the getMessage callback
    // Because this will listen to all request from your extension
    if (request.messagePayload) {
        console.log('the respose.messagePayload is: ' + request.messagePayload);
    }
});

I hope this helps.

Nikhil Sharma
  • 891
  • 1
  • 8
  • 11
  • First solution is snake oil - closures will take care of this. Second solution is dodging the problem and won't work well with iframes; also, has errors in it. – Xan Feb 07 '16 at 12:36