tor-browser

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

events_input_source_recreation.https.html (5426B)


      1 <!DOCTYPE html>
      2 <script src="/resources/testharness.js"></script>
      3 <script src="/resources/testharnessreport.js"></script>
      4 <script src="resources/webxr_util.js"></script>
      5 <script src="resources/webxr_test_constants.js"></script>
      6 
      7 <script>
      8 let testName = "Input sources are re-created when handedness or target ray mode changes";
      9 
     10 let watcherDone = new Event("watcherdone");
     11 
     12 let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE;
     13 
     14 let testFunction = function(session, fakeDeviceController, t) {
     15  let eventWatcher = new EventWatcher(t, session, ["watcherdone"]);
     16  let eventPromise = eventWatcher.wait_for(["watcherdone"]);
     17 
     18  let inputChangeEvents = 0;
     19  let cached_input_source = null;
     20  function onInputSourcesChange(event) {
     21    t.step(() => {
     22      inputChangeEvents++;
     23      assert_equals(event.session, session);
     24 
     25      if (inputChangeEvents == 1) {
     26        // The first change event should be adding our controller.
     27        validateAdded(event.added, 1);
     28        validateRemoved(event.removed, 0);
     29        cached_input_source = getInputSources()[0];
     30        assert_not_equals(cached_input_source, null);
     31        assert_equals(cached_input_source.handedness, "none");
     32        assert_equals(cached_input_source.targetRayMode, "gaze");
     33        assertProfilesEqual(cached_input_source.profiles, ["a", "b"]);
     34      } else if (inputChangeEvents == 2) {
     35        // The second event should be replacing the controller with one that has
     36        // the updated target ray mode.
     37        validateInputSourceChange(event, "none", "tracked-pointer", ["a", "b"]);
     38        cached_input_source = getInputSources()[0];
     39      } else if (inputChangeEvents == 3) {
     40        // The third event should be replacing the controller with one that has
     41        // the updated handedness.
     42        validateInputSourceChange(event, "left", "tracked-pointer", ["a", "b"]);
     43        cached_input_source = getInputSources()[0];
     44      } else if (inputChangeEvents == 4) {
     45        // The fourth event should be updating the second value in the profiles
     46        // array.
     47        validateInputSourceChange(event, "left", "tracked-pointer", ["a", "c"]);
     48        cached_input_source = getInputSources()[0];
     49      } else if (inputChangeEvents == 5) {
     50        // The fifth event should be removing the second value from the profiles
     51        // array.
     52        validateInputSourceChange(event, "left", "tracked-pointer", ["a"]);
     53        session.dispatchEvent(watcherDone);
     54      }
     55    });
     56  }
     57 
     58  function assertProfilesEqual(profiles, expected_profiles) {
     59    assert_equals(profiles.length, expected_profiles.length);
     60    for (let i = 0; i < profiles.length; ++i) {
     61      assert_equals(profiles[i], expected_profiles[i]);
     62    }
     63  }
     64 
     65  function validateInputSourceChange(
     66      event, expected_hand, expected_mode, expected_profiles) {
     67    validateAdded(event.added, 1);
     68    validateRemoved(event.removed, 1);
     69    assert_true(event.removed.includes(cached_input_source));
     70    assert_false(event.added.includes(cached_input_source));
     71    let source = event.added[0];
     72    assert_equals(source.handedness, expected_hand);
     73    assert_equals(source.targetRayMode, expected_mode);
     74    assertProfilesEqual(source.profiles, expected_profiles);
     75  }
     76 
     77  function validateAdded(added, length) {
     78    t.step(() => {
     79      assert_not_equals(added, null);
     80      assert_equals(added.length, length,
     81          "Added length matches expectations");
     82 
     83      let currentSources = getInputSources();
     84      added.forEach((source) => {
     85        assert_true(currentSources.includes(source),
     86          "Every element in added should be in the input source list");
     87      });
     88    });
     89  }
     90 
     91  function validateRemoved(removed, length) {
     92    t.step(() => {
     93      assert_not_equals(removed, null);
     94        assert_equals(removed.length, length,
     95            "Removed length matches expectations");
     96 
     97      let currentSources = getInputSources();
     98      removed.forEach((source) => {
     99        assert_false(currentSources.includes(source),
    100          "No element in removed should be in the input source list");
    101      });
    102    });
    103  }
    104 
    105  function getInputSources() {
    106    return Array.from(session.inputSources.values());
    107  }
    108 
    109  session.addEventListener('inputsourceschange', onInputSourcesChange, false);
    110 
    111  // Create a gaze based input source with no handedness that we can change
    112  // to validate SameObject properties.
    113  let input_source = fakeDeviceController.simulateInputSourceConnection({
    114    handedness: "none",
    115    targetRayMode: "gaze",
    116    pointerOrigin: VALID_POINTER_TRANSFORM,
    117    profiles: ["a", "b"]
    118  });
    119 
    120  // Make our first input source change after one frame, and wait an additional
    121  // frame for that change to propogate. Then make additional changes, waiting
    122  // one frame after each one to verify that they fired an inputsourceschanged
    123  // event.
    124  session.requestAnimationFrame((time, xrFrame) => {
    125    input_source.setTargetRayMode("tracked-pointer");
    126    session.requestAnimationFrame((time, xrFrame) => {
    127      input_source.setHandedness("left");
    128      session.requestAnimationFrame((time, xrFrame) => {
    129        input_source.setProfiles(["a", "c"]);
    130        session.requestAnimationFrame((time, xrFrame) => {
    131          input_source.setProfiles(["a"]);
    132          session.requestAnimationFrame((time, xrFrame) => {});
    133        });
    134      });
    135    });
    136  });
    137 
    138  return eventPromise;
    139 };
    140 
    141 xr_session_promise_test(
    142  testName, testFunction, fakeDeviceInitParams, 'immersive-vr');
    143 </script>