In a Chrome App, I have a webview
that uses an onHeadersReceived
handler to redirect certain requests to a data URI constructed on the fly. The data URI depends on data from a remote script that manipulates contents from the original URL.
function getDataUri(myurl, callback) {
var url = "http://some.where/myscript?url=" + myurl;
$.getJSON(url, function(data){
var dataUri = "data:application/json;charset=utf-8;base64,"
+ btoa(JSON.stringify(data));
callback(dataUri);
})
}
webview.request.onHeadersReceived.addListener(
function(info) {
var myDataUri;
getDataUri(info.url, function(dataUri) {
myDataUri = dataUri;
console.log("Here is my data uri:", dataUri);
})
return {redirectUrl: myDataUri}; // This won't work!
},
{urls: ["*://example.com/*"]}, ["blocking"]
);
//Calling it directly works fine:
var url = "http://example.com/some/path";
getDataUri(url, function(dataUri){
console.log("Here is my data uri:", dataUri);
})
A synchronous AJAX request would be an easy workaround, but this is not allowed in Chrome apps.
The example uses jQuery $.getJSON
, but that is not important. It could be a plain XHR request instead.
I am fully aware of the asynchronous nature of JavaScript and use it extensively throughout the 2800 lines of code. But, in this case, I need to chain the getDataUri()
function from a webrequest
event handler and I can't figure out how this is done. And, if it is possible at all.
To expand a bit more on the problem:
The real problem is that the event listener can't return until the data URI is ready. Since we can't pass on a promise or a callback, we will somehow have to wait for dataUri
to be populated. This implies some form of synchronous mode which is why it is perhaps not possible at all.
If this wasn't going on in an event handler, I could simply pass the callback on all the way from the first level.