tor-browser

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

templates.js (17060B)


      1 /**
      2 * Default list of commands to execute for a PeerConnection test.
      3 */
      4 
      5 const STABLE = "stable";
      6 const HAVE_LOCAL_OFFER = "have-local-offer";
      7 const HAVE_REMOTE_OFFER = "have-remote-offer";
      8 const CLOSED = "closed";
      9 
     10 const ICE_NEW = "new";
     11 const GATH_NEW = "new";
     12 const GATH_GATH = "gathering";
     13 const GATH_COMPLETE = "complete";
     14 
     15 function deltaSeconds(date1, date2) {
     16  return (date2.getTime() - date1.getTime()) / 1000;
     17 }
     18 
     19 function dumpSdp(test) {
     20  if (typeof test._local_offer !== "undefined") {
     21    dump("ERROR: SDP offer: " + test._local_offer.sdp.replace(/[\r]/g, ""));
     22  }
     23  if (typeof test._remote_answer !== "undefined") {
     24    dump("ERROR: SDP answer: " + test._remote_answer.sdp.replace(/[\r]/g, ""));
     25  }
     26 
     27  if (
     28    test.pcLocal &&
     29    typeof test.pcLocal._local_ice_candidates !== "undefined"
     30  ) {
     31    dump(
     32      "pcLocal._local_ice_candidates: " +
     33        JSON.stringify(test.pcLocal._local_ice_candidates) +
     34        "\n"
     35    );
     36    dump(
     37      "pcLocal._remote_ice_candidates: " +
     38        JSON.stringify(test.pcLocal._remote_ice_candidates) +
     39        "\n"
     40    );
     41    dump(
     42      "pcLocal._ice_candidates_to_add: " +
     43        JSON.stringify(test.pcLocal._ice_candidates_to_add) +
     44        "\n"
     45    );
     46  }
     47  if (
     48    test.pcRemote &&
     49    typeof test.pcRemote._local_ice_candidates !== "undefined"
     50  ) {
     51    dump(
     52      "pcRemote._local_ice_candidates: " +
     53        JSON.stringify(test.pcRemote._local_ice_candidates) +
     54        "\n"
     55    );
     56    dump(
     57      "pcRemote._remote_ice_candidates: " +
     58        JSON.stringify(test.pcRemote._remote_ice_candidates) +
     59        "\n"
     60    );
     61    dump(
     62      "pcRemote._ice_candidates_to_add: " +
     63        JSON.stringify(test.pcRemote._ice_candidates_to_add) +
     64        "\n"
     65    );
     66  }
     67 
     68  if (test.pcLocal && typeof test.pcLocal.iceConnectionLog !== "undefined") {
     69    dump(
     70      "pcLocal ICE connection state log: " +
     71        test.pcLocal.iceConnectionLog +
     72        "\n"
     73    );
     74  }
     75  if (test.pcRemote && typeof test.pcRemote.iceConnectionLog !== "undefined") {
     76    dump(
     77      "pcRemote ICE connection state log: " +
     78        test.pcRemote.iceConnectionLog +
     79        "\n"
     80    );
     81  }
     82 
     83  if (
     84    test.pcLocal &&
     85    test.pcRemote &&
     86    typeof test.pcLocal.setRemoteDescDate !== "undefined" &&
     87    typeof test.pcRemote.setLocalDescDate !== "undefined"
     88  ) {
     89    var delta = deltaSeconds(
     90      test.pcLocal.setRemoteDescDate,
     91      test.pcRemote.setLocalDescDate
     92    );
     93    dump(
     94      "Delay between pcLocal.setRemote <-> pcRemote.setLocal: " + delta + "\n"
     95    );
     96  }
     97  if (
     98    test.pcLocal &&
     99    test.pcRemote &&
    100    typeof test.pcLocal.setRemoteDescDate !== "undefined" &&
    101    typeof test.pcLocal.setRemoteDescStableEventDate !== "undefined"
    102  ) {
    103    var delta = deltaSeconds(
    104      test.pcLocal.setRemoteDescDate,
    105      test.pcLocal.setRemoteDescStableEventDate
    106    );
    107    dump(
    108      "Delay between pcLocal.setRemote <-> pcLocal.signalingStateStable: " +
    109        delta +
    110        "\n"
    111    );
    112  }
    113  if (
    114    test.pcLocal &&
    115    test.pcRemote &&
    116    typeof test.pcRemote.setLocalDescDate !== "undefined" &&
    117    typeof test.pcRemote.setLocalDescStableEventDate !== "undefined"
    118  ) {
    119    var delta = deltaSeconds(
    120      test.pcRemote.setLocalDescDate,
    121      test.pcRemote.setLocalDescStableEventDate
    122    );
    123    dump(
    124      "Delay between pcRemote.setLocal <-> pcRemote.signalingStateStable: " +
    125        delta +
    126        "\n"
    127    );
    128  }
    129 }
    130 
    131 // We need to verify that at least one candidate has been (or will be) gathered.
    132 function waitForAnIceCandidate(pc) {
    133  return new Promise(resolve => {
    134    if (!pc.localRequiresTrickleIce || pc._new_local_ice_candidates.length) {
    135      resolve();
    136    } else {
    137      // In some circumstances, especially when both PCs are on the same
    138      // browser, even though we are connected, the connection can be
    139      // established without receiving a single candidate from one or other
    140      // peer.  So we wait for at least one...
    141      pc._pc.addEventListener("icecandidate", resolve);
    142    }
    143  }).then(() => {
    144    ok(
    145      pc._local_ice_candidates.length,
    146      pc + " received local trickle ICE candidates"
    147    );
    148    isnot(
    149      pc._pc.iceGatheringState,
    150      GATH_NEW,
    151      pc + " ICE gathering state is not 'new'"
    152    );
    153  });
    154 }
    155 
    156 async function checkTrackStats(pc, track, outbound) {
    157  const audio = track.kind == "audio";
    158  const msg =
    159    `${pc} stats ${outbound ? "outbound " : "inbound "}` +
    160    `${audio ? "audio" : "video"} rtp track id ${track.id}`;
    161  const stats = await pc.getStats(track);
    162  ok(
    163    pc.hasStat(stats, {
    164      type: outbound ? "outbound-rtp" : "inbound-rtp",
    165      kind: audio ? "audio" : "video",
    166    }),
    167    `${msg} - found expected stats`
    168  );
    169  ok(
    170    !pc.hasStat(stats, {
    171      type: outbound ? "inbound-rtp" : "outbound-rtp",
    172    }),
    173    `${msg} - did not find extra stats with wrong direction`
    174  );
    175  ok(
    176    !pc.hasStat(stats, {
    177      kind: audio ? "video" : "audio",
    178    }),
    179    `${msg} - did not find extra stats with wrong media type`
    180  );
    181 }
    182 
    183 function checkAllTrackStats(pc) {
    184  return Promise.all([
    185    ...pc
    186      .getExpectedActiveReceivers()
    187      .map(({ track }) => checkTrackStats(pc, track, false)),
    188    ...pc
    189      .getExpectedSenders()
    190      .map(({ track }) => checkTrackStats(pc, track, true)),
    191  ]);
    192 }
    193 
    194 // Commands run once at the beginning of each test, even when performing a
    195 // renegotiation test.
    196 var commandsPeerConnectionInitial = [
    197  function PC_LOCAL_SETUP_ICE_LOGGER(test) {
    198    test.pcLocal.logIceConnectionState();
    199  },
    200 
    201  function PC_REMOTE_SETUP_ICE_LOGGER(test) {
    202    test.pcRemote.logIceConnectionState();
    203  },
    204 
    205  function PC_LOCAL_SETUP_SIGNALING_LOGGER(test) {
    206    test.pcLocal.logSignalingState();
    207  },
    208 
    209  function PC_REMOTE_SETUP_SIGNALING_LOGGER(test) {
    210    test.pcRemote.logSignalingState();
    211  },
    212 
    213  function PC_LOCAL_SETUP_TRACK_HANDLER(test) {
    214    test.pcLocal.setupTrackEventHandler();
    215  },
    216 
    217  function PC_REMOTE_SETUP_TRACK_HANDLER(test) {
    218    test.pcRemote.setupTrackEventHandler();
    219  },
    220 
    221  function PC_LOCAL_CHECK_INITIAL_SIGNALINGSTATE(test) {
    222    is(
    223      test.pcLocal.signalingState,
    224      STABLE,
    225      "Initial local signalingState is 'stable'"
    226    );
    227  },
    228 
    229  function PC_REMOTE_CHECK_INITIAL_SIGNALINGSTATE(test) {
    230    is(
    231      test.pcRemote.signalingState,
    232      STABLE,
    233      "Initial remote signalingState is 'stable'"
    234    );
    235  },
    236 
    237  function PC_LOCAL_CHECK_INITIAL_ICE_STATE(test) {
    238    is(
    239      test.pcLocal.iceConnectionState,
    240      ICE_NEW,
    241      "Initial local ICE connection state is 'new'"
    242    );
    243  },
    244 
    245  function PC_REMOTE_CHECK_INITIAL_ICE_STATE(test) {
    246    is(
    247      test.pcRemote.iceConnectionState,
    248      ICE_NEW,
    249      "Initial remote ICE connection state is 'new'"
    250    );
    251  },
    252 
    253  function PC_LOCAL_CHECK_INITIAL_CAN_TRICKLE_SYNC(test) {
    254    is(
    255      test.pcLocal._pc.canTrickleIceCandidates,
    256      null,
    257      "Local trickle status should start out unknown"
    258    );
    259  },
    260 
    261  function PC_REMOTE_CHECK_INITIAL_CAN_TRICKLE_SYNC(test) {
    262    is(
    263      test.pcRemote._pc.canTrickleIceCandidates,
    264      null,
    265      "Remote trickle status should start out unknown"
    266    );
    267  },
    268 ];
    269 
    270 var commandsGetUserMedia = [
    271  function PC_LOCAL_GUM(test) {
    272    return test.pcLocal.getAllUserMediaAndAddStreams(test.pcLocal.constraints);
    273  },
    274 
    275  function PC_REMOTE_GUM(test) {
    276    return test.pcRemote.getAllUserMediaAndAddStreams(
    277      test.pcRemote.constraints
    278    );
    279  },
    280 ];
    281 
    282 var commandsPeerConnectionOfferAnswer = [
    283  function PC_LOCAL_SETUP_ICE_HANDLER(test) {
    284    test.pcLocal.setupIceCandidateHandler(test);
    285  },
    286 
    287  function PC_REMOTE_SETUP_ICE_HANDLER(test) {
    288    test.pcRemote.setupIceCandidateHandler(test);
    289  },
    290 
    291  function PC_LOCAL_CREATE_OFFER(test) {
    292    return test.createOffer(test.pcLocal).then(offer => {
    293      is(
    294        test.pcLocal.signalingState,
    295        STABLE,
    296        "Local create offer does not change signaling state"
    297      );
    298    });
    299  },
    300 
    301  function PC_LOCAL_SET_LOCAL_DESCRIPTION(test) {
    302    return test
    303      .setLocalDescription(test.pcLocal, test.originalOffer, HAVE_LOCAL_OFFER)
    304      .then(() => {
    305        is(
    306          test.pcLocal.signalingState,
    307          HAVE_LOCAL_OFFER,
    308          "signalingState after local setLocalDescription is 'have-local-offer'"
    309        );
    310      });
    311  },
    312 
    313  function PC_REMOTE_GET_OFFER(test) {
    314    test._local_offer = test.originalOffer;
    315    test._offer_constraints = test.pcLocal.constraints;
    316    test._offer_options = test.pcLocal.offerOptions;
    317    return Promise.resolve();
    318  },
    319 
    320  function PC_REMOTE_SET_REMOTE_DESCRIPTION(test) {
    321    return test
    322      .setRemoteDescription(test.pcRemote, test._local_offer, HAVE_REMOTE_OFFER)
    323      .then(() => {
    324        is(
    325          test.pcRemote.signalingState,
    326          HAVE_REMOTE_OFFER,
    327          "signalingState after remote setRemoteDescription is 'have-remote-offer'"
    328        );
    329      });
    330  },
    331 
    332  function PC_REMOTE_CHECK_CAN_TRICKLE_SYNC(test) {
    333    is(
    334      test.pcRemote._pc.canTrickleIceCandidates,
    335      true,
    336      "Remote thinks that local can trickle"
    337    );
    338  },
    339 
    340  function PC_LOCAL_SANE_LOCAL_SDP(test) {
    341    test.pcLocal.localRequiresTrickleIce = sdputils.verifySdp(
    342      test._local_offer,
    343      "offer",
    344      test._offer_constraints,
    345      test._offer_options,
    346      test.testOptions
    347    );
    348  },
    349 
    350  function PC_REMOTE_SANE_REMOTE_SDP(test) {
    351    test.pcRemote.remoteRequiresTrickleIce = sdputils.verifySdp(
    352      test._local_offer,
    353      "offer",
    354      test._offer_constraints,
    355      test._offer_options,
    356      test.testOptions
    357    );
    358  },
    359 
    360  function PC_REMOTE_CREATE_ANSWER(test) {
    361    return test.createAnswer(test.pcRemote).then(answer => {
    362      is(
    363        test.pcRemote.signalingState,
    364        HAVE_REMOTE_OFFER,
    365        "Remote createAnswer does not change signaling state"
    366      );
    367    });
    368  },
    369 
    370  function PC_REMOTE_SET_LOCAL_DESCRIPTION(test) {
    371    return test
    372      .setLocalDescription(test.pcRemote, test.originalAnswer, STABLE)
    373      .then(() => {
    374        is(
    375          test.pcRemote.signalingState,
    376          STABLE,
    377          "signalingState after remote setLocalDescription is 'stable'"
    378        );
    379      });
    380  },
    381 
    382  function PC_LOCAL_GET_ANSWER(test) {
    383    test._remote_answer = test.originalAnswer;
    384    test._answer_constraints = test.pcRemote.constraints;
    385    return Promise.resolve();
    386  },
    387 
    388  function PC_LOCAL_SET_REMOTE_DESCRIPTION(test) {
    389    return test
    390      .setRemoteDescription(test.pcLocal, test._remote_answer, STABLE)
    391      .then(() => {
    392        is(
    393          test.pcLocal.signalingState,
    394          STABLE,
    395          "signalingState after local setRemoteDescription is 'stable'"
    396        );
    397      });
    398  },
    399 
    400  function PC_REMOTE_SANE_LOCAL_SDP(test) {
    401    test.pcRemote.localRequiresTrickleIce = sdputils.verifySdp(
    402      test._remote_answer,
    403      "answer",
    404      test._offer_constraints,
    405      test._offer_options,
    406      test.testOptions
    407    );
    408  },
    409  function PC_LOCAL_SANE_REMOTE_SDP(test) {
    410    test.pcLocal.remoteRequiresTrickleIce = sdputils.verifySdp(
    411      test._remote_answer,
    412      "answer",
    413      test._offer_constraints,
    414      test._offer_options,
    415      test.testOptions
    416    );
    417  },
    418 
    419  function PC_LOCAL_CHECK_CAN_TRICKLE_SYNC(test) {
    420    is(
    421      test.pcLocal._pc.canTrickleIceCandidates,
    422      true,
    423      "Local thinks that remote can trickle"
    424    );
    425  },
    426 
    427  function PC_LOCAL_WAIT_FOR_ICE_CONNECTED(test) {
    428    return test.pcLocal.waitForIceConnected().then(() => {
    429      info(
    430        test.pcLocal +
    431          ": ICE connection state log: " +
    432          test.pcLocal.iceConnectionLog
    433      );
    434    });
    435  },
    436 
    437  function PC_REMOTE_WAIT_FOR_ICE_CONNECTED(test) {
    438    return test.pcRemote.waitForIceConnected().then(() => {
    439      info(
    440        test.pcRemote +
    441          ": ICE connection state log: " +
    442          test.pcRemote.iceConnectionLog
    443      );
    444    });
    445  },
    446 
    447  function PC_LOCAL_VERIFY_ICE_GATHERING(test) {
    448    return waitForAnIceCandidate(test.pcLocal);
    449  },
    450 
    451  function PC_REMOTE_VERIFY_ICE_GATHERING(test) {
    452    return waitForAnIceCandidate(test.pcRemote);
    453  },
    454 
    455  function PC_LOCAL_WAIT_FOR_MEDIA_FLOW(test) {
    456    return test.pcLocal.waitForMediaFlow();
    457  },
    458 
    459  function PC_REMOTE_WAIT_FOR_MEDIA_FLOW(test) {
    460    return test.pcRemote.waitForMediaFlow();
    461  },
    462 
    463  function PC_LOCAL_CHECK_STATS(test) {
    464    return test.pcLocal.getStats().then(stats => {
    465      test.pcLocal.checkStats(stats);
    466    });
    467  },
    468 
    469  function PC_REMOTE_CHECK_STATS(test) {
    470    return test.pcRemote.getStats().then(stats => {
    471      test.pcRemote.checkStats(stats);
    472    });
    473  },
    474 
    475  function PC_LOCAL_CHECK_ICE_CONNECTION_TYPE(test) {
    476    return test.pcLocal.getStats().then(stats => {
    477      test.pcLocal.checkStatsIceConnectionType(
    478        stats,
    479        test.testOptions.expectedLocalCandidateType
    480      );
    481    });
    482  },
    483 
    484  function PC_REMOTE_CHECK_ICE_CONNECTION_TYPE(test) {
    485    return test.pcRemote.getStats().then(stats => {
    486      test.pcRemote.checkStatsIceConnectionType(
    487        stats,
    488        test.testOptions.expectedRemoteCandidateType
    489      );
    490    });
    491  },
    492 
    493  function PC_LOCAL_CHECK_ICE_CONNECTIONS(test) {
    494    return test.pcLocal.getStats().then(stats => {
    495      test.pcLocal.checkStatsIceConnections(stats, test.testOptions);
    496    });
    497  },
    498 
    499  function PC_REMOTE_CHECK_ICE_CONNECTIONS(test) {
    500    return test.pcRemote.getStats().then(stats => {
    501      test.pcRemote.checkStatsIceConnections(stats, test.testOptions);
    502    });
    503  },
    504 
    505  function PC_LOCAL_CHECK_MSID(test) {
    506    return test.pcLocal.checkLocalMsids();
    507  },
    508  function PC_REMOTE_CHECK_MSID(test) {
    509    return test.pcRemote.checkLocalMsids();
    510  },
    511 
    512  function PC_LOCAL_CHECK_TRACK_STATS(test) {
    513    return checkAllTrackStats(test.pcLocal);
    514  },
    515  function PC_REMOTE_CHECK_TRACK_STATS(test) {
    516    return checkAllTrackStats(test.pcRemote);
    517  },
    518  function PC_LOCAL_VERIFY_SDP_AFTER_END_OF_TRICKLE(test) {
    519    if (test.pcLocal.endOfTrickleSdp) {
    520      /* In case the endOfTrickleSdp promise is resolved already it will win the
    521       * race because it gets evaluated first. But if endOfTrickleSdp is still
    522       * pending the rejection will win the race. */
    523      return Promise.race([
    524        test.pcLocal.endOfTrickleSdp,
    525        Promise.reject("No SDP"),
    526      ]).then(
    527        sdp =>
    528          sdputils.checkSdpAfterEndOfTrickle(
    529            sdp,
    530            test.testOptions,
    531            test.pcLocal.label
    532          ),
    533        () =>
    534          info(
    535            "pcLocal: Gathering is not complete yet, skipping post-gathering SDP check"
    536          )
    537      );
    538    }
    539  },
    540  function PC_REMOTE_VERIFY_SDP_AFTER_END_OF_TRICKLE(test) {
    541    if (test.pcRemote.endOfTrickleSdp) {
    542      /* In case the endOfTrickleSdp promise is resolved already it will win the
    543       * race because it gets evaluated first. But if endOfTrickleSdp is still
    544       * pending the rejection will win the race. */
    545      return Promise.race([
    546        test.pcRemote.endOfTrickleSdp,
    547        Promise.reject("No SDP"),
    548      ]).then(
    549        sdp =>
    550          sdputils.checkSdpAfterEndOfTrickle(
    551            sdp,
    552            test.testOptions,
    553            test.pcRemote.label
    554          ),
    555        () =>
    556          info(
    557            "pcRemote: Gathering is not complete yet, skipping post-gathering SDP check"
    558          )
    559      );
    560    }
    561  },
    562 ];
    563 
    564 function PC_LOCAL_REMOVE_ALL_BUT_H264_FROM_OFFER(test) {
    565  isnot(
    566    test.originalOffer.sdp.search("H264/90000"),
    567    -1,
    568    "H.264 should be present in the SDP offer"
    569  );
    570  test.originalOffer.sdp = sdputils.removeAllButCodec(
    571    test.originalOffer.sdp,
    572    "H264"
    573  );
    574  info("Updated H264 only offer: " + JSON.stringify(test.originalOffer));
    575 }
    576 
    577 function PC_LOCAL_REMOVE_ALL_BUT_AV1_FROM_OFFER(test) {
    578  isnot(
    579    test.originalOffer.sdp.search("AV1/90000"),
    580    -1,
    581    "AV1 should be present in the SDP offer"
    582  );
    583  test.originalOffer.sdp = sdputils.removeAllButCodec(
    584    test.originalOffer.sdp,
    585    "AV1"
    586  );
    587  info("Updated AV1 only offer: " + JSON.stringify(test.originalOffer));
    588 }
    589 
    590 function PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER(test) {
    591  test.originalOffer.sdp = sdputils.removeBundle(test.originalOffer.sdp);
    592  info("Updated no bundle offer: " + JSON.stringify(test.originalOffer));
    593 }
    594 
    595 function PC_LOCAL_REMOVE_RTCPMUX_FROM_OFFER(test) {
    596  test.originalOffer.sdp = sdputils.removeRtcpMux(test.originalOffer.sdp);
    597  info("Updated no RTCP-Mux offer: " + JSON.stringify(test.originalOffer));
    598 }
    599 
    600 function PC_LOCAL_REMOVE_SSRC_FROM_OFFER(test) {
    601  test.originalOffer.sdp = sdputils.removeSSRCs(test.originalOffer.sdp);
    602  info("Updated no SSRCs offer: " + JSON.stringify(test.originalOffer));
    603 }
    604 
    605 function PC_REMOTE_REMOVE_SSRC_FROM_ANSWER(test) {
    606  test.originalAnswer.sdp = sdputils.removeSSRCs(test.originalAnswer.sdp);
    607  info("Updated no SSRCs answer: " + JSON.stringify(test.originalAnswer));
    608 }
    609 
    610 var addRenegotiation = (chain, commands, checks) => {
    611  chain.append(commands);
    612  chain.append(commandsPeerConnectionOfferAnswer);
    613  if (checks) {
    614    chain.append(checks);
    615  }
    616 };
    617 
    618 var addRenegotiationAnswerer = (chain, commands, checks) => {
    619  chain.append(function SWAP_PC_LOCAL_PC_REMOTE(test) {
    620    var temp = test.pcLocal;
    621    test.pcLocal = test.pcRemote;
    622    test.pcRemote = temp;
    623  });
    624  addRenegotiation(chain, commands, checks);
    625 };