tor-browser

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

test_urgent_start.html (8818B)


      1 <!DOCTYPE HTML>
      2 <!--
      3  https://bugzilla.mozilla.org/show_bug.cgi?id=1348050
      4  Test for fetch and xhr to guarantee we only mark channel as urgent-start when
      5  it is triggered by user input events.
      6 
      7  For { Fetch, SRC-*, XHR }, do the test as following:
      8  Step 1: Verify them not mark the channel when there is no any input event.
      9  Step 2: Verify them mark the channel there is a user input event.
     10  Step 3: Verify them not mark the channel when there is a non input event.
     11 
     12  In each steps, it shows that we only mark channel on direct triggering task.
     13  We won't mark the channel for additional task(setTimeout) or
     14  micro-task(promise).
     15 -->
     16 <html>
     17 <head>
     18  <title>Test for urgent-start on Fetch and XHR</title>
     19  <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
     20  <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
     21  <link rel="stylesheet"
     22        type="text/css"
     23        href="chrome://mochikit/content/tests/SimpleTest/test.css">
     24  <script type="text/javascript" src="manifest.js"></script>
     25 </head>
     26 <body>
     27 <img id="image"></body>
     28 <audio autoplay id="audio"></audio>
     29 <iframe id="iframe"></iframe>
     30 <input type="image" id="input"></input>
     31 <embed id="embed"></embed>
     32 <pre id="test">
     33 <script class="testbody" type="text/javascript">
     34 
     35 SimpleTest.waitForExplicitFinish();
     36 SimpleTest.waitForFocus(runTest);
     37 
     38 const topic_request = "http-on-opening-request";
     39 const topic_response = "http-on-examine-response";
     40 const topic_cachedResponse = "http-on-examine-cached-response";
     41 const scope = "http://mochi.test:8888/chrome/dom/base/test/"
     42 const url = scope + "file_empty.html";
     43 
     44 let expectedResults = [];
     45 let testcases = [
     46  "fetch",
     47  "src-embed",
     48  "src-img",
     49  "src-input",
     50  "src-media",
     51  "xhr",
     52 ];
     53 let testcase;
     54 
     55 function isUrgentStart(aClassFlags) {
     56  if (!aClassFlags) {
     57    return false;
     58  }
     59 
     60  const urgentStartFlag = 1 << 6;
     61  return !!(urgentStartFlag & aClassFlags);
     62 }
     63 
     64 // Test for setTimeout (task)
     65 function testSetTimeout() {
     66  return new Promise(aResolve =>
     67    setTimeout(function() {
     68      testSimple().then(aResolve);
     69    }, 0));
     70 }
     71 
     72 // Test for promise chain (micro-task)
     73 function testPromise() {
     74  return Promise.resolve().then(testSimple);
     75 }
     76 
     77 function testSimple() {
     78  let testUrl = url + "?" + expectedResults.length;
     79 
     80  if (testcase == "fetch") {
     81    return fetch(testUrl);
     82  } else if (testcase == "src-embed") {
     83    document.getElementById('embed').src = testUrl;
     84    return Promise.resolve();
     85  } else if (testcase == "src-img") {
     86    document.getElementById('image').src = testUrl;
     87    return Promise.resolve();
     88  } else if (testcase == "src-input") {
     89    document.getElementById('input').src = testUrl;
     90    return Promise.resolve();
     91  } else if (testcase == "src-media") {
     92    document.getElementById('audio').src = testUrl;
     93    return Promise.resolve();
     94  } else if (testcase == "xhr") {
     95    let xhr = new XMLHttpRequest();
     96    xhr.open("GET", testUrl, true);
     97    xhr.send(null);
     98    return Promise.resolve();
     99  }
    100 
    101  ok(false, "Shouldn't go here.");
    102  return Promise.reject();
    103 }
    104 
    105 function sendRequsetAndCheckUrgentStart(aEventToTest) {
    106  info("SendRequsetAndCheckUrgentStart");
    107 
    108  let promise1, promise2;
    109  let promise1_resolve, promise2_resolve;
    110 
    111  function checkUrgentStart(aSubject) {
    112    var channel = aSubject.QueryInterface(Ci.nsIChannel);
    113    if (!channel.URI.spec.includes(scope) ) {
    114      return;
    115    }
    116 
    117    info("CheckUrgentStart");
    118 
    119    let cos = channel.QueryInterface(Ci.nsIClassOfService);
    120 
    121    let expectedResult = expectedResults.shift();
    122    is(isUrgentStart(cos.classFlags), expectedResult,
    123       "Expect get: " + expectedResult + ", get: " +
    124       isUrgentStart(cos.classFlags) + " in the " +
    125       (9 - expectedResults.length) + " test of " + testcase);
    126 
    127    // Make sure we've run the check.
    128    promise1_resolve();
    129  }
    130 
    131  // Resolve this after we've gotten response to prevent from sending too many
    132  // requests to Necko in a short time.
    133  function getResponse(aSubject) {
    134    var channel = aSubject.QueryInterface(Ci.nsIChannel);
    135    if (!channel.URI.spec.includes(scope) ) {
    136      return;
    137    }
    138    info("GetResponse");
    139 
    140    promise2_resolve();
    141  }
    142 
    143  SpecialPowers.addObserver(checkUrgentStart, topic_request);
    144  SpecialPowers.addObserver(getResponse, topic_response);
    145  SpecialPowers.addObserver(getResponse, topic_cachedResponse);
    146 
    147  return Promise.resolve()
    148    .then(() => {
    149      promise1 = new Promise(aResolve => { promise1_resolve = aResolve; });
    150      promise2 = new Promise(aResolve => { promise2_resolve = aResolve; });
    151      return Promise.all([addListenerAndSendEvent(testSimple, aEventToTest),
    152                          promise1,
    153                          promise2]);
    154    })
    155    .then(() => {
    156      promise1 = new Promise(aResolve => { promise1_resolve = aResolve; });
    157      promise2 = new Promise(aResolve => { promise2_resolve = aResolve; });
    158      return Promise.all([addListenerAndSendEvent(testSetTimeout, aEventToTest),
    159                          promise1,
    160                          promise2]);
    161    })
    162    .then(() => {
    163      promise1 = new Promise(aResolve => { promise1_resolve = aResolve; });
    164      promise2 = new Promise(aResolve => { promise2_resolve = aResolve; });
    165      return Promise.all([addListenerAndSendEvent(testPromise, aEventToTest),
    166                          promise1,
    167                          promise2]);
    168    })
    169    .then(() => {
    170      // remove obs if we've tested each three conditions
    171      // (simple, promise, setTimeout).
    172      SpecialPowers.removeObserver(checkUrgentStart, topic_request);
    173      SpecialPowers.removeObserver(getResponse,topic_response);
    174      SpecialPowers.removeObserver(getResponse, topic_cachedResponse);
    175      return Promise.resolve();
    176    });
    177 }
    178 
    179 function addListenerAndSendEvent(aFunction, aEventToTest) {
    180  info("AddListenerAndSendEvent:" + aEventToTest);
    181 
    182  let eventHandle = function () {
    183    return aFunction();
    184  };
    185 
    186  if (aEventToTest === TestEvent.USER_INPUT_EVENT) {
    187    // User Input Event
    188    window.addEventListener("mousedown", eventHandle, {once: true});
    189  } else if (aEventToTest === TestEvent.NONUSER_INPUT_EVENT) {
    190    window.addEventListener("message", eventHandle, {once: true});
    191  }
    192 
    193  if (aEventToTest === TestEvent.USER_INPUT_EVENT) {
    194    // User Input Event
    195    synthesizeMouseAtPoint(1, 1, { type: "mousedown" });
    196  } else if (aEventToTest === TestEvent.NONUSER_INPUT_EVENT) {
    197    window.postMessage("hello", "*");
    198  } else if (aEventToTest === TestEvent.NOEVENT) {
    199    eventHandle();
    200  }
    201 }
    202 
    203 const TestEvent = {
    204  NOEVENT: 0,
    205  USER_INPUT_EVENT: 1,
    206  NONUSER_INPUT_EVENT: 2,
    207 };
    208 
    209 function executeTest() {
    210  is(expectedResults.length, 0, "expectedResults should be 0 be executeTest.");
    211 
    212  // We will test fetch first and then xhr.
    213  testcase = testcases.shift();
    214  info("Verify " + testcase);
    215 
    216  expectedResults = [
    217    /* SimpleTest without any events */ false,
    218    /* PromiseTest without any events */ false,
    219    /* SetTimeoutTest without any events */ false,
    220    /* SimpleTest with a user input event */ true,
    221    /* PromiseTest with a user input event */ false,
    222    /* SetTimeoutTest with user input event */ false,
    223    /* SimpleTest with a non user input event */ false,
    224    /* PromiseTest with a non user input event */ false,
    225    /* SetTimeoutTest with a non user input event */ false,
    226  ];
    227 
    228  return Promise.resolve()
    229  // Verify urgent-start is not set when the request is not triggered by any
    230  // events.
    231    .then(() => sendRequsetAndCheckUrgentStart(TestEvent.NOEVENT))
    232 
    233  // Verify urgent-start is set only when the request is triggered by a user
    234  // input event. (not for another microtask (e.g. promise-chain) and
    235  // task (e.g. setTimeout)).
    236    .then(() => sendRequsetAndCheckUrgentStart(TestEvent.USER_INPUT_EVENT))
    237 
    238  // Verify urgent-start is not set when the request is triggered by a non user
    239  // input event.
    240    .then(() => sendRequsetAndCheckUrgentStart(TestEvent.NONUSER_INPUT_EVENT))
    241    .then(_ => {
    242      if (testcases.length !== 0) {
    243        // Run the other test if we still have tests needed to be run.
    244        return executeTest();
    245      }
    246 
    247      return Promise.resolve();
    248    });
    249 }
    250 
    251 function endCheck() {
    252  info("End Check: make sure that we've done all the tests.");
    253 
    254  is(testcases.length, 0, "All the tests should be executed.");
    255  is(expectedResults.length, 0, "All the tests should be executed.");
    256 
    257  return Promise.resolve();
    258 }
    259 
    260 function runTest() {// Disable mixed-content upgrading as this test is expecting an HTTP load
    261  return SpecialPowers.pushPrefEnv(
    262    {"set": [
    263      ["security.mixed_content.upgrade_display_content", false],
    264      ["network.http.rcwn.enabled", false],
    265    ]}
    266    )
    267    .then(executeTest)
    268    .then(endCheck)
    269    .catch(aError => ok(false, "Some test failed with error " + aError))
    270    .then(SimpleTest.finish);
    271 }
    272 </script>
    273 </pre>
    274 </body>
    275 </html>