Before I continue, I'd like to point out that you're just dealing with an ordinary content script, not an "injected script" (according to my definition).
Don't send the response at the first request (sendResponse({})
). Instead, call sendResponse
when the response has been finished:
// Content script
chrome.runtime.sendMessage({method: "getResultForRequest"}, function(response) {
});
// Background page
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.method == "getResultForRequest") {
$.ajax({success: sendResponse}); // Example
return true;
}
});
As said at the top of this answer, what you're dealing with is not an injected script, but a content script. The script execution environment of the content script and the page are strictly separated, so the page cannot read the variable. In other words, your premise is flawed; it's fine to pass credentials from the background page to the content script.
I recommend to not use localStorage, but the chrome.storage
API. This asynchronous API allows content scripts to directly read persistent variables stored by the extension. Consequently, you don't need a background or event page any more. For a more detailed comparison and an example, I refer to this answer.
Note: There are two cases when it makes sense to let the background page process the XHR:
- The Content security policy of the page blocks the target URL (this affects Chrome extensions)
- The current page is served over https, whereas the requested resource is served over http. Mixing http and https will change the appearance of the padlock, which should be avoided if possible.
But otherwise, I suggest to use the chrome.storage
API and do the cross-origin http request in your content script.