0

I am using the following little gem within the background script of a Mozilla webextension:

function makeRequest(url) {
    return new Promise(function(resolve,reject) {
            console.log("begin makeRequest");
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url);
            xhr.onload = function() {
                    if (this.status >= 200 && this.status < 300) {
                            console.log("resolve makeRequest");
                            resolve(xhr.response);
                    } else {
                            console.log("reject makeRequest");
                            reject({
                                    status: this.status,
                                    statusText: xhr.statusText
                            });
                    }
            }
            xhr.onerror = function() {
                    console.log("reject makeRequest by error");
                    reject({
                            status: this.status,
                            statusText: xhr.statusText
                    });
            }
            xhr.send(null);
            console.log("makeRequest sent");
    });
}

I invoke this with a line like makeRequest("http://www.example.com") and I can verify from the Apache access log at www.example.com, that the request succeeds (status code "200"). In particular, this makes me confident that the request does not fail due to some misisng permissions in the manifest or the like. Consequently, I'd expect the xhr.onload to be invoked with this.status == 200. But instead of this, the xhr.onerror is invoked, i.e., the console log reads

begin makeRequest
makeRequest sent
reject makeRequest by error

Why? (As in : How is this even possible?)

Hagen von Eitzen
  • 2,109
  • 21
  • 25
  • Is that the *complete* contents of console.log? What is `this.status`? – Quentin May 11 '17 at 18:52
  • `this` doesn't refer to `xhr` within the onload handler. Use `xhr.status` – James May 11 '17 at 18:55
  • @James OK, thanks for the hint. Though it shouldn't matter as `this.status` is not even evaluated before the system decides to invoke `onerror` instead of `onload`... – Hagen von Eitzen May 11 '17 at 19:03
  • It's worth noting that if the response's content doesn't match the MIME type unusual errors can occur. (A common example is probably a MIME type of `*/json` where the content would cause `JSON.parse(content)` to throw an error) – Patrick Barr May 11 '17 at 19:04
  • @Quentin To be complete, there is a `TypeError: $(...).bootstrapValidator is not a function` with source `main.js` between sent and reject – Hagen von Eitzen May 11 '17 at 19:04
  • What's the URL? Are you performing a cross-server request that's being denied? That would trigger onerror. – James May 11 '17 at 19:13
  • 1
    @PatrickBarr Good hint. The MIME type *is* `Content-type: application/json; charset=utf-8`. However, if I copy/paste the output to an online parser such as http://json.parser.online.fr/ , it seems to be ok. At any rate, if I change the MIME type at the server to `text/plain` there should be no way the MIME type mismatches - but I still end up in `onerror` – Hagen von Eitzen May 11 '17 at 19:13
  • @James Yes, the request is cross-server (as in: ultimately the request to www.example.com is made from the background script as a reaction to a message sent from a content script injected into a tab showing www.something-else.com. So do I have to add www.example.com to the permissions in the manifest somehow? But if the lack of this prevents the http response from going in, why isn't the request blocked from going out in the first place? If it's a security feature, I would have expected the data leak by the request to be blocked as well ...?! – Hagen von Eitzen May 11 '17 at 19:17
  • Not 100% sure but I would check [content_security_policy](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/content_security_policy) – James May 11 '17 at 19:30
  • @James Fair enough. I changed the url to https, added `"content_security_policy": "default-src 'self' https://*.example.com"` to the manifest.json, but nothing changes. Besides, as CSP is a security feature, I would again expect a failure to manifest in the *request* being blocked and not the *response* – Hagen von Eitzen May 11 '17 at 19:57
  • [Check here](http://stackoverflow.com/questions/36629635/firefox-webextensions-and-cross-domain-privileges) – James May 11 '17 at 20:04

0 Answers0