tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_XHR.js (13462B)


      1 "use strict";
      2 
      3 /* eslint-disable mozilla/no-comparison-or-assignment-inside-ok */
      4 
      5 SimpleTest.waitForExplicitFinish();
      6 
      7 var gen = runTests();
      8 function continueTest() {
      9  gen.next();
     10 }
     11 
     12 function* runTests() {
     13  var expectHttp2Results = location.href.includes("http2");
     14 
     15  var path = "/tests/dom/xhr/tests/";
     16 
     17  var passFiles = [
     18    ["file_XHR_pass1.xml", "GET", 200, "OK", "text/xml"],
     19    ["file_XHR_pass2.txt", "GET", 200, "OK", "text/plain"],
     20    ["file_XHR_pass3.txt", "GET", 200, "OK", "text/plain"],
     21    ["data:text/xml,%3Cres%3Ehello%3C/res%3E%0A", "GET", 200, "OK", "text/xml"],
     22    ["data:text/plain,hello%20pass%0A", "GET", 200, "OK", "text/plain"],
     23    ["data:,foo", "GET", 200, "OK", "text/plain;charset=US-ASCII", "foo"],
     24    ["data:text/plain;base64,Zm9v", "GET", 200, "OK", "text/plain", "foo"],
     25    ["data:text/plain,foo#bar", "GET", 200, "OK", "text/plain", "foo"],
     26    ["data:text/plain,foo%23bar", "GET", 200, "OK", "text/plain", "foo#bar"],
     27  ];
     28 
     29  var blob = new Blob(["foo"], { type: "text/plain" });
     30  var blobURL = URL.createObjectURL(blob);
     31 
     32  passFiles.push([blobURL, "GET", 200, "OK", "text/plain", "foo"]);
     33 
     34  var failFiles = [
     35    ["//example.com" + path + "file_XHR_pass1.xml", "GET"],
     36    ["ftp://localhost" + path + "file_XHR_pass1.xml", "GET"],
     37    ["file_XHR_fail1.txt", "GET"],
     38  ];
     39 
     40  for (i = 0; i < passFiles.length; ++i) {
     41    // Function to give our hacked is() a scope
     42    (function (oldIs) {
     43      function is(actual, expected, message) {
     44        oldIs(actual, expected, message + " for " + passFiles[i][0]);
     45      }
     46      xhr = new XMLHttpRequest();
     47      is(xhr.getResponseHeader("Content-Type"), null, "should be null");
     48      is(xhr.getAllResponseHeaders(), "", "should be empty string");
     49      is(xhr.responseType, "", "wrong initial responseType");
     50      xhr.open(passFiles[i][1], passFiles[i][0], false);
     51      xhr.send(null);
     52      is(xhr.status, passFiles[i][2], "wrong status");
     53 
     54      // over HTTP2, no status text is received for network requests (but
     55      // data/blob URLs default to "200 OK" responses)
     56      let expectedStatusText = passFiles[i][3];
     57      if (
     58        expectHttp2Results &&
     59        !passFiles[i][0].startsWith("data:") &&
     60        !passFiles[i][0].startsWith("blob:")
     61      ) {
     62        expectedStatusText = "";
     63      }
     64      is(xhr.statusText, expectedStatusText, "wrong statusText");
     65 
     66      is(
     67        xhr.getResponseHeader("Content-Type"),
     68        passFiles[i][4],
     69        "wrong content type"
     70      );
     71      var headers = xhr.getAllResponseHeaders();
     72      ok(
     73        /(?:^|\n)Content-Type:\s*([^\r\n]*)\r\n/i.test(headers) &&
     74          RegExp.$1 === passFiles[i][4],
     75        "wrong response headers"
     76      );
     77      if (xhr.responseXML) {
     78        is(
     79          new XMLSerializer().serializeToString(
     80            xhr.responseXML.documentElement
     81          ),
     82          passFiles[i][5] || "<res>hello</res>",
     83          "wrong responseXML"
     84        );
     85        is(
     86          xhr.response,
     87          passFiles[i][5] || "<res>hello</res>\n",
     88          "wrong response"
     89        );
     90      } else {
     91        is(
     92          xhr.responseText,
     93          passFiles[i][5] || "hello pass\n",
     94          "wrong responseText"
     95        );
     96        is(xhr.response, passFiles[i][5] || "hello pass\n", "wrong response");
     97      }
     98    })(is);
     99  }
    100 
    101  URL.revokeObjectURL(blobURL);
    102 
    103  for (i = 0; i < failFiles.length; ++i) {
    104    xhr = new XMLHttpRequest();
    105    let didthrow = false;
    106    try {
    107      xhr.open(failFiles[i][1], failFiles[i][0], false);
    108      xhr.send(null);
    109    } catch (e) {
    110      didthrow = true;
    111    }
    112    if (!didthrow) {
    113      is(xhr.status, 301, "wrong status");
    114      is(xhr.responseText, "redirect file\n", "wrong response");
    115    } else {
    116      ok(1, "should have thrown or given incorrect result");
    117    }
    118  }
    119 
    120  function checkResponseTextAccessThrows(xhr) {
    121    let didthrow = false;
    122    try {
    123      xhr.responseText;
    124    } catch (e) {
    125      didthrow = true;
    126    }
    127    ok(didthrow, "should have thrown when accessing responseText");
    128  }
    129  function checkResponseXMLAccessThrows(xhr) {
    130    let didthrow = false;
    131    try {
    132      xhr.responseXML;
    133    } catch (e) {
    134      didthrow = true;
    135    }
    136    ok(didthrow, "should have thrown when accessing responseXML");
    137  }
    138  function checkSetResponseType(xhr, type) {
    139    let didthrow = false;
    140    try {
    141      xhr.responseType = type;
    142    } catch (e) {
    143      didthrow = true;
    144    }
    145    is(xhr.responseType, type, "responseType should be " + type);
    146    ok(!didthrow, "should not have thrown when setting responseType");
    147  }
    148  function checkSetResponseTypeThrows(xhr, type) {
    149    let didthrow = false;
    150    try {
    151      xhr.responseType = type;
    152    } catch (e) {
    153      didthrow = true;
    154    }
    155    ok(didthrow, "should have thrown when setting responseType");
    156  }
    157  function checkOpenThrows(xhr, method, url, async) {
    158    let didthrow = false;
    159    try {
    160      xhr.open(method, url, async);
    161    } catch (e) {
    162      didthrow = true;
    163    }
    164    ok(didthrow, "should have thrown when open is called");
    165  }
    166 
    167  // test if setting responseType before calling open() works
    168  xhr = new XMLHttpRequest();
    169  checkSetResponseType(xhr, "");
    170  checkSetResponseType(xhr, "text");
    171  checkSetResponseType(xhr, "document");
    172  checkSetResponseType(xhr, "arraybuffer");
    173  checkSetResponseType(xhr, "blob");
    174  checkSetResponseType(xhr, "json");
    175  checkOpenThrows(xhr, "GET", "file_XHR_pass2.txt", false);
    176 
    177  // test response (sync, responseType is not changeable)
    178  xhr = new XMLHttpRequest();
    179  xhr.open("GET", "file_XHR_pass2.txt", false);
    180  checkSetResponseTypeThrows(xhr, "");
    181  checkSetResponseTypeThrows(xhr, "text");
    182  checkSetResponseTypeThrows(xhr, "document");
    183  checkSetResponseTypeThrows(xhr, "arraybuffer");
    184  checkSetResponseTypeThrows(xhr, "blob");
    185  checkSetResponseTypeThrows(xhr, "json");
    186  xhr.send(null);
    187  checkSetResponseTypeThrows(xhr, "document");
    188  is(xhr.status, 200, "wrong status");
    189  is(xhr.response, "hello pass\n", "wrong response");
    190 
    191  // test response (responseType='document')
    192  xhr = new XMLHttpRequest();
    193  xhr.open("GET", "file_XHR_pass1.xml");
    194  xhr.responseType = "document";
    195  xhr.onloadend = continueTest;
    196  xhr.send(null);
    197  yield undefined;
    198  checkSetResponseTypeThrows(xhr, "document");
    199  is(xhr.status, 200, "wrong status");
    200  checkResponseTextAccessThrows(xhr);
    201  is(
    202    new XMLSerializer().serializeToString(xhr.response.documentElement),
    203    "<res>hello</res>",
    204    "wrong response"
    205  );
    206 
    207  // test response (responseType='text')
    208  xhr = new XMLHttpRequest();
    209  xhr.open("GET", "file_XHR_pass2.txt");
    210  xhr.responseType = "text";
    211  xhr.onloadend = continueTest;
    212  xhr.send(null);
    213  yield undefined;
    214  is(xhr.status, 200, "wrong status");
    215  checkResponseXMLAccessThrows(xhr);
    216  is(xhr.response, "hello pass\n", "wrong response");
    217 
    218  // test response (responseType='arraybuffer')
    219  function arraybuffer_equals_to(ab, s) {
    220    is(ab.byteLength, s.length, "wrong arraybuffer byteLength");
    221 
    222    var u8v = new Uint8Array(ab);
    223    is(String.fromCharCode.apply(String, u8v), s, "wrong values");
    224  }
    225 
    226  // with a simple text file
    227  xhr = new XMLHttpRequest();
    228  xhr.open("GET", "file_XHR_pass2.txt");
    229  xhr.responseType = "arraybuffer";
    230  xhr.onloadend = continueTest;
    231  xhr.send(null);
    232  yield undefined;
    233  is(xhr.status, 200, "wrong status");
    234  checkResponseTextAccessThrows(xhr);
    235  checkResponseXMLAccessThrows(xhr);
    236  var ab = xhr.response;
    237  ok(ab != null, "should have a non-null arraybuffer");
    238  arraybuffer_equals_to(ab, "hello pass\n");
    239 
    240  // test reusing the same XHR (Bug 680816)
    241  xhr.open("GET", "file_XHR_binary1.bin");
    242  xhr.responseType = "arraybuffer";
    243  xhr.onloadend = continueTest;
    244  xhr.send(null);
    245  yield undefined;
    246  is(xhr.status, 200, "wrong status");
    247  var ab2 = xhr.response;
    248  ok(ab2 != null, "should have a non-null arraybuffer");
    249  ok(ab2 != ab, "arraybuffer on XHR reuse should be distinct");
    250  arraybuffer_equals_to(ab, "hello pass\n");
    251  arraybuffer_equals_to(ab2, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
    252 
    253  // with a binary file
    254  xhr = new XMLHttpRequest();
    255  xhr.open("GET", "file_XHR_binary1.bin");
    256  xhr.responseType = "arraybuffer";
    257  xhr.onloadend = continueTest;
    258  xhr.send(null);
    259  yield undefined;
    260  is(xhr.status, 200, "wrong status");
    261  checkResponseTextAccessThrows(xhr);
    262  checkResponseXMLAccessThrows(xhr);
    263  ab = xhr.response;
    264  ok(ab != null, "should have a non-null arraybuffer");
    265  arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb");
    266  is(xhr.response, xhr.response, "returns the same ArrayBuffer");
    267 
    268  // test response (responseType='json')
    269  var xhr = new XMLHttpRequest();
    270  xhr.open("POST", "responseIdentical.sjs");
    271  xhr.responseType = "json";
    272  var jsonObjStr = JSON.stringify({ title: "aBook", author: "john" });
    273  xhr.onloadend = continueTest;
    274  xhr.send(jsonObjStr);
    275  yield undefined;
    276  is(xhr.status, 200, "wrong status");
    277  checkResponseTextAccessThrows(xhr);
    278  checkResponseXMLAccessThrows(xhr);
    279  is(JSON.stringify(xhr.response), jsonObjStr, "correct result");
    280  is(xhr.response, xhr.response, "returning the same object on each access");
    281 
    282  // with invalid json
    283  xhr = new XMLHttpRequest();
    284  xhr.open("POST", "responseIdentical.sjs");
    285  xhr.responseType = "json";
    286  xhr.onloadend = continueTest;
    287  xhr.send("{");
    288  yield undefined;
    289  is(xhr.status, 200, "wrong status");
    290  checkResponseTextAccessThrows(xhr);
    291  checkResponseXMLAccessThrows(xhr);
    292  is(xhr.response, null, "Bad JSON should result in null response.");
    293  is(
    294    xhr.response,
    295    null,
    296    "Bad JSON should result in null response even 2nd time."
    297  );
    298 
    299  // Test status/statusText in all readyStates
    300  xhr = new XMLHttpRequest();
    301  function checkXHRStatus() {
    302    if (xhr.readyState == xhr.UNSENT || xhr.readyState == xhr.OPENED) {
    303      is(xhr.status, 0, "should be 0 before getting data");
    304      is(xhr.statusText, "", "should be empty before getting data");
    305    } else {
    306      is(xhr.status, 200, "should be 200 when we have data");
    307      if (expectHttp2Results) {
    308        is(xhr.statusText, "", "should be '' when over HTTP2");
    309      } else {
    310        is(xhr.statusText, "OK", "should be OK when we have data");
    311      }
    312    }
    313  }
    314  checkXHRStatus();
    315  xhr.open("GET", "file_XHR_binary1.bin");
    316  checkXHRStatus();
    317  xhr.responseType = "arraybuffer";
    318  xhr.send(null);
    319  xhr.onreadystatechange = continueTest;
    320  while (xhr.readyState != 4) {
    321    checkXHRStatus();
    322    yield undefined;
    323  }
    324  checkXHRStatus();
    325 
    326  // test response (responseType='blob')
    327  // with a simple text file
    328  xhr = new XMLHttpRequest();
    329  xhr.open("GET", "file_XHR_pass2.txt");
    330  xhr.responseType = "blob";
    331  xhr.onloadend = continueTest;
    332  xhr.send(null);
    333  yield undefined;
    334  is(xhr.status, 200, "wrong status");
    335  checkResponseTextAccessThrows(xhr);
    336  checkResponseXMLAccessThrows(xhr);
    337  var b = xhr.response;
    338  ok(b, "should have a non-null blob");
    339  ok(b instanceof Blob, "should be a Blob");
    340  ok(!(b instanceof File), "should not be a File");
    341  is(b.size, "hello pass\n".length, "wrong blob size");
    342 
    343  var fr = new FileReader();
    344  fr.onload = continueTest;
    345  fr.readAsBinaryString(b);
    346  yield undefined;
    347  is(fr.result, "hello pass\n", "wrong values");
    348 
    349  // with a binary file
    350  xhr = new XMLHttpRequest();
    351  xhr.open("GET", "file_XHR_binary1.bin", true);
    352  xhr.send(null);
    353  xhr.onreadystatechange = continueTest;
    354  while (xhr.readyState != 2) {
    355    yield undefined;
    356  }
    357 
    358  is(xhr.status, 200, "wrong status");
    359  xhr.responseType = "blob";
    360 
    361  while (xhr.readyState != 4) {
    362    yield undefined;
    363  }
    364 
    365  xhr.onreadystatechange = null;
    366 
    367  b = xhr.response;
    368  ok(b != null, "should have a non-null blob");
    369  is(b.size, 12, "wrong blob size");
    370 
    371  fr = new FileReader();
    372  fr.readAsBinaryString(b);
    373  xhr = null; // kill the XHR object
    374  b = null;
    375  SpecialPowers.gc();
    376  fr.onload = continueTest;
    377  yield undefined;
    378  is(
    379    fr.result,
    380    "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb",
    381    "wrong values"
    382  );
    383 
    384  // with a larger binary file
    385  xhr = new XMLHttpRequest();
    386  xhr.open("GET", "file_XHR_binary2.bin", true);
    387  xhr.responseType = "blob";
    388  xhr.send(null);
    389  xhr.onreadystatechange = continueTest;
    390 
    391  while (xhr.readyState != 4) {
    392    yield undefined;
    393  }
    394 
    395  xhr.onreadystatechange = null;
    396 
    397  b = xhr.response;
    398  ok(b != null, "should have a non-null blob");
    399  is(b.size, 65536, "wrong blob size");
    400 
    401  fr = new FileReader();
    402  fr.readAsArrayBuffer(b);
    403  fr.onload = continueTest;
    404  xhr = null; // kill the XHR object
    405  b = null;
    406  SpecialPowers.gc();
    407  yield undefined;
    408 
    409  var u8 = new Uint8Array(fr.result);
    410  for (var i = 0; i < 65536; i++) {
    411    if (u8[i] !== (i & 255)) {
    412      break;
    413    }
    414  }
    415  is(i, 65536, "wrong value at offset " + i);
    416 
    417  var client = new XMLHttpRequest();
    418  client.open("GET", "file_XHR_pass1.xml", true);
    419  client.send();
    420  client.onreadystatechange = function () {
    421    if (client.readyState == 4) {
    422      try {
    423        is(client.responseXML, null, "responseXML should be null.");
    424        is(client.responseText, "", "responseText should be empty string.");
    425        is(client.response, "", "response should be empty string.");
    426        is(client.status, 0, "status should be 0.");
    427        is(client.statusText, "", "statusText should be empty string.");
    428        is(
    429          client.getAllResponseHeaders(),
    430          "",
    431          "getAllResponseHeaders() should return empty string."
    432        );
    433      } catch (ex) {
    434        ok(false, "Shouldn't throw! [" + ex + "]");
    435      }
    436    }
    437  };
    438  client.abort();
    439 
    440  SimpleTest.finish();
    441 } /* runTests */