@webex/internal-plugin-device 3.6.0-next.1 → 3.6.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/device.js CHANGED
@@ -765,7 +765,7 @@ var Device = _webexCore.WebexPlugin.extend((_dec = (0, _webexCore.waitForValue)(
765
765
  _this9.resetLogoutTimer();
766
766
  });
767
767
  } /* eslint-enable require-jsdoc */,
768
- version: "3.6.0-next.1"
768
+ version: "3.6.0-next.3"
769
769
  }, ((0, _applyDecoratedDescriptor2.default)(_obj, "refresh", [_common.oneFlight, _dec], (0, _getOwnPropertyDescriptor.default)(_obj, "refresh"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "register", [_common.oneFlight, _dec2], (0, _getOwnPropertyDescriptor.default)(_obj, "register"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "unregister", [_common.oneFlight, _dec3], (0, _getOwnPropertyDescriptor.default)(_obj, "unregister"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "markUrlFailedAndGetNew", [_dec4], (0, _getOwnPropertyDescriptor.default)(_obj, "markUrlFailedAndGetNew"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "initialize", [_dec5], (0, _getOwnPropertyDescriptor.default)(_obj, "initialize"), _obj)), _obj)));
770
770
  var _default = exports.default = Device;
771
771
  //# sourceMappingURL=device.js.map
@@ -14,6 +14,12 @@ var _webexCore = require("@webex/webex-core");
14
14
  * Copyright (c) 2015-2023 Cisco Systems, Inc. See LICENSE file.
15
15
  */
16
16
 
17
+ var STATE = {
18
+ INITIAL: 'initial',
19
+ IN_PROGRESS: 'in-progress',
20
+ IDLE: 'idle'
21
+ };
22
+
17
23
  /**
18
24
  * @class
19
25
  */
@@ -27,9 +33,11 @@ var IpNetworkDetector = _webexCore.WebexPlugin.extend({
27
33
  // time [ms] it took to receive first IPv6 candidate
28
34
  firstMdns: ['number', true, -1],
29
35
  // time [ms] it took to receive first mDNS candidate
30
- totalTime: ['number', true, -1] // total time [ms] it took to do the last IP network detection
36
+ totalTime: ['number', true, -1],
37
+ // total time [ms] it took to do the last IP network detection
38
+ state: ['string', true, STATE.INITIAL],
39
+ pendingDetection: ['object', false, undefined]
31
40
  },
32
-
33
41
  derived: {
34
42
  /**
35
43
  * True if we know we're on an IPv4 network,
@@ -165,35 +173,59 @@ var IpNetworkDetector = _webexCore.WebexPlugin.extend({
165
173
  * Detects if we are on IPv4 and/or IPv6 network. Once it resolves, read the
166
174
  * supportsIpV4 and supportsIpV6 props to find out the result.
167
175
  *
168
- * @returns {Promise<Object>}
176
+ * @param {boolean} force - if false, the detection will only be done if we haven't managed to get any meaningful results yet
177
+ * @returns {Promise<void>}
169
178
  */
170
179
  detect: function detect() {
171
- var _this2 = this;
180
+ var _arguments = arguments,
181
+ _this2 = this;
172
182
  return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
173
- var results, pc;
183
+ var force, results, pc, forceParam;
174
184
  return _regenerator.default.wrap(function _callee2$(_context2) {
175
185
  while (1) switch (_context2.prev = _context2.next) {
176
186
  case 0:
177
- _context2.prev = 0;
187
+ force = _arguments.length > 0 && _arguments[0] !== undefined ? _arguments[0] : false;
188
+ if (!(_this2.state === STATE.IN_PROGRESS)) {
189
+ _context2.next = 4;
190
+ break;
191
+ }
192
+ _this2.pendingDetection = {
193
+ force: force
194
+ };
195
+ return _context2.abrupt("return");
196
+ case 4:
197
+ if (!(!force && _this2.state !== STATE.INITIAL && !_this2.receivedOnlyMDnsCandidates())) {
198
+ _context2.next = 6;
199
+ break;
200
+ }
201
+ return _context2.abrupt("return");
202
+ case 6:
203
+ _context2.prev = 6;
204
+ _this2.state = STATE.IN_PROGRESS;
178
205
  pc = new RTCPeerConnection();
179
- _context2.next = 4;
206
+ _context2.next = 11;
180
207
  return _this2.gatherLocalCandidates(pc);
181
- case 4:
208
+ case 11:
182
209
  results = _context2.sent;
183
- case 5:
184
- _context2.prev = 5;
210
+ case 12:
211
+ _context2.prev = 12;
185
212
  pc.close();
186
- return _context2.finish(5);
187
- case 8:
188
- return _context2.abrupt("return", results);
189
- case 9:
213
+ _this2.state = STATE.IDLE;
214
+ return _context2.finish(12);
215
+ case 16:
216
+ if (_this2.pendingDetection) {
217
+ forceParam = _this2.pendingDetection.force;
218
+ _this2.pendingDetection = undefined;
219
+ _this2.detect(forceParam);
220
+ }
221
+ case 17:
190
222
  case "end":
191
223
  return _context2.stop();
192
224
  }
193
- }, _callee2, null, [[0,, 5, 8]]);
225
+ }, _callee2, null, [[6,, 12, 16]]);
194
226
  }))();
195
227
  },
196
- version: "3.6.0-next.1"
228
+ version: "3.6.0-next.3"
197
229
  });
198
230
  var _default = exports.default = IpNetworkDetector;
199
231
  //# sourceMappingURL=ipNetworkDetector.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_webexCore","require","IpNetworkDetector","WebexPlugin","extend","idAttribute","namespace","props","firstIpV4","firstIpV6","firstMdns","totalTime","derived","supportsIpV4","deps","fn","undefined","receivedOnlyMDnsCandidates","supportsIpV6","gatherLocalCandidates","pc","_this","_asyncToGenerator2","default","_regenerator","mark","_callee","wrap","_callee$","_context","prev","next","abrupt","_promise","resolve","reject","done","startTime","performance","now","doneGatheringIceCandidates","onicecandidate","event","_event$candidate","candidate","address","endsWith","includes","onicegatheringstatechange","iceGatheringState","createDataChannel","createOffer","then","offer","setLocalDescription","catch","e","webex","logger","error","stop","detect","_this2","_callee2","results","_callee2$","_context2","RTCPeerConnection","sent","close","finish","version","_default","exports"],"sources":["ipNetworkDetector.ts"],"sourcesContent":["/*!\n * Copyright (c) 2015-2023 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {WebexPlugin} from '@webex/webex-core';\n\n/**\n * @class\n */\nconst IpNetworkDetector = WebexPlugin.extend({\n idAttribute: 'IpNetworkDetectorId',\n\n namespace: 'Device',\n\n props: {\n firstIpV4: ['number', true, -1], // time [ms] it took to receive first IPv4 candidate\n firstIpV6: ['number', true, -1], // time [ms] it took to receive first IPv6 candidate\n firstMdns: ['number', true, -1], // time [ms] it took to receive first mDNS candidate\n totalTime: ['number', true, -1], // total time [ms] it took to do the last IP network detection\n },\n\n derived: {\n /**\n * True if we know we're on an IPv4 network,\n * False if we know that we are not on an IPv4 network,\n * undefined if we are not sure\n */\n supportsIpV4: {\n deps: ['firstIpV4', 'firstIpV6', 'firstMdns', 'totalTime'],\n /**\n * Function for calculating the value of supportsIpV4 prop\n * @returns {boolean | undefined}\n */\n fn() {\n if (this.firstIpV4 >= 0) {\n return true;\n }\n if (this.totalTime < 0) {\n // we haven't completed the detection, yet\n return undefined;\n }\n if (this.receivedOnlyMDnsCandidates()) {\n return undefined;\n }\n\n return false;\n },\n },\n /**\n * True if we know we're on an IPv6 network,\n * False if we know that we are not on an IPv6 network,\n * undefined if we are not sure\n */\n supportsIpV6: {\n deps: ['firstIpV4', 'firstIpV6', 'firstMdns', 'totalTime'],\n /**\n * Function for calculating the value of supportsIpV6 prop\n * @returns {boolean | undefined}\n */ fn() {\n if (this.firstIpV6 >= 0) {\n return true;\n }\n if (this.totalTime < 0) {\n // we haven't completed the detection, yet\n return undefined;\n }\n if (this.receivedOnlyMDnsCandidates()) {\n return undefined;\n }\n\n return false;\n },\n },\n },\n\n /**\n * Returns true if we have received only mDNS candidates - browsers usually do that if we don't have any user media permissions\n *\n * @private\n * @returns {boolean}\n */\n receivedOnlyMDnsCandidates() {\n return this.totalTime >= 0 && this.firstMdns >= 0 && this.firstIpV4 < 0 && this.firstIpV6 < 0;\n },\n\n /**\n *\n * @param {RTCPeerConnection} pc Peer connection to use\n * @private\n * @returns {Promise<void>}\n */\n async gatherLocalCandidates(pc: RTCPeerConnection): Promise<void> {\n return new Promise((resolve, reject) => {\n let done = false;\n\n this.firstIpV4 = -1;\n this.firstIpV6 = -1;\n this.firstMdns = -1;\n this.totalTime = -1;\n const startTime = performance.now();\n\n const doneGatheringIceCandidates = () => {\n if (done) {\n return;\n }\n done = true;\n\n this.totalTime = performance.now() - startTime;\n\n resolve();\n };\n\n pc.onicecandidate = (event) => {\n if (event.candidate?.address) {\n if (event.candidate.address.endsWith('.local')) {\n // if we don't have camera/mic permissions, browser just gives us mDNS candidates\n if (this.firstMdns === -1) {\n this.firstMdns = performance.now() - startTime;\n }\n } else if (event.candidate.address.includes(':')) {\n if (this.firstIpV6 === -1) {\n this.firstIpV6 = performance.now() - startTime;\n }\n } else if (this.firstIpV4 === -1) {\n this.firstIpV4 = performance.now() - startTime;\n }\n\n if (this.firstIpV4 >= 0 && this.firstIpV6 >= 0) {\n // if we've got both ipv4 and ipv6 candidates, there is no need to wait for any more candidates, we can resolve now\n resolve();\n }\n } else if (event.candidate === null) {\n doneGatheringIceCandidates();\n }\n };\n\n pc.onicegatheringstatechange = () => {\n if (pc.iceGatheringState === 'complete') {\n doneGatheringIceCandidates();\n }\n };\n\n pc.createDataChannel('data');\n\n pc.createOffer()\n .then((offer) => pc.setLocalDescription(offer))\n .catch((e) => {\n this.webex.logger.error('Failed to detect ip network version:', e);\n reject(e);\n });\n });\n },\n\n /**\n * Detects if we are on IPv4 and/or IPv6 network. Once it resolves, read the\n * supportsIpV4 and supportsIpV6 props to find out the result.\n *\n * @returns {Promise<Object>}\n */\n async detect() {\n let results;\n let pc;\n\n try {\n pc = new RTCPeerConnection();\n\n results = await this.gatherLocalCandidates(pc);\n } finally {\n pc.close();\n }\n\n return results;\n },\n});\n\nexport default IpNetworkDetector;\n"],"mappings":";;;;;;;;;;;AAIA,IAAAA,UAAA,GAAAC,OAAA;AAJA;AACA;AACA;;AAIA;AACA;AACA;AACA,IAAMC,iBAAiB,GAAGC,sBAAW,CAACC,MAAM,CAAC;EAC3CC,WAAW,EAAE,qBAAqB;EAElCC,SAAS,EAAE,QAAQ;EAEnBC,KAAK,EAAE;IACLC,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAAE;IACjCC,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAAE;IACjCC,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAAE;IACjCC,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE;EACnC,CAAC;;EAEDC,OAAO,EAAE;IACP;AACJ;AACA;AACA;AACA;IACIC,YAAY,EAAE;MACZC,IAAI,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC;MAC1D;AACN;AACA;AACA;MACMC,EAAE,WAAAA,GAAA,EAAG;QACH,IAAI,IAAI,CAACP,SAAS,IAAI,CAAC,EAAE;UACvB,OAAO,IAAI;QACb;QACA,IAAI,IAAI,CAACG,SAAS,GAAG,CAAC,EAAE;UACtB;UACA,OAAOK,SAAS;QAClB;QACA,IAAI,IAAI,CAACC,0BAA0B,CAAC,CAAC,EAAE;UACrC,OAAOD,SAAS;QAClB;QAEA,OAAO,KAAK;MACd;IACF,CAAC;IACD;AACJ;AACA;AACA;AACA;IACIE,YAAY,EAAE;MACZJ,IAAI,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC;MAC1D;AACN;AACA;AACA;MAAUC,EAAE,WAAAA,GAAA,EAAG;QACP,IAAI,IAAI,CAACN,SAAS,IAAI,CAAC,EAAE;UACvB,OAAO,IAAI;QACb;QACA,IAAI,IAAI,CAACE,SAAS,GAAG,CAAC,EAAE;UACtB;UACA,OAAOK,SAAS;QAClB;QACA,IAAI,IAAI,CAACC,0BAA0B,CAAC,CAAC,EAAE;UACrC,OAAOD,SAAS;QAClB;QAEA,OAAO,KAAK;MACd;IACF;EACF,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACEC,0BAA0B,WAAAA,2BAAA,EAAG;IAC3B,OAAO,IAAI,CAACN,SAAS,IAAI,CAAC,IAAI,IAAI,CAACD,SAAS,IAAI,CAAC,IAAI,IAAI,CAACF,SAAS,GAAG,CAAC,IAAI,IAAI,CAACC,SAAS,GAAG,CAAC;EAC/F,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACQU,qBAAqB,WAAAA,sBAACC,EAAqB,EAAiB;IAAA,IAAAC,KAAA;IAAA,WAAAC,kBAAA,CAAAC,OAAA,gBAAAC,YAAA,CAAAD,OAAA,CAAAE,IAAA,UAAAC,QAAA;MAAA,OAAAF,YAAA,CAAAD,OAAA,CAAAI,IAAA,UAAAC,SAAAC,QAAA;QAAA,kBAAAA,QAAA,CAAAC,IAAA,GAAAD,QAAA,CAAAE,IAAA;UAAA;YAAA,OAAAF,QAAA,CAAAG,MAAA,WACzD,IAAAC,QAAA,CAAAV,OAAA,CAAY,UAACW,OAAO,EAAEC,MAAM,EAAK;cACtC,IAAIC,IAAI,GAAG,KAAK;cAEhBf,KAAI,CAACb,SAAS,GAAG,CAAC,CAAC;cACnBa,KAAI,CAACZ,SAAS,GAAG,CAAC,CAAC;cACnBY,KAAI,CAACX,SAAS,GAAG,CAAC,CAAC;cACnBW,KAAI,CAACV,SAAS,GAAG,CAAC,CAAC;cACnB,IAAM0B,SAAS,GAAGC,WAAW,CAACC,GAAG,CAAC,CAAC;cAEnC,IAAMC,0BAA0B,GAAG,SAA7BA,0BAA0BA,CAAA,EAAS;gBACvC,IAAIJ,IAAI,EAAE;kBACR;gBACF;gBACAA,IAAI,GAAG,IAAI;gBAEXf,KAAI,CAACV,SAAS,GAAG2B,WAAW,CAACC,GAAG,CAAC,CAAC,GAAGF,SAAS;gBAE9CH,OAAO,CAAC,CAAC;cACX,CAAC;cAEDd,EAAE,CAACqB,cAAc,GAAG,UAACC,KAAK,EAAK;gBAAA,IAAAC,gBAAA;gBAC7B,KAAAA,gBAAA,GAAID,KAAK,CAACE,SAAS,cAAAD,gBAAA,eAAfA,gBAAA,CAAiBE,OAAO,EAAE;kBAC5B,IAAIH,KAAK,CAACE,SAAS,CAACC,OAAO,CAACC,QAAQ,CAAC,QAAQ,CAAC,EAAE;oBAC9C;oBACA,IAAIzB,KAAI,CAACX,SAAS,KAAK,CAAC,CAAC,EAAE;sBACzBW,KAAI,CAACX,SAAS,GAAG4B,WAAW,CAACC,GAAG,CAAC,CAAC,GAAGF,SAAS;oBAChD;kBACF,CAAC,MAAM,IAAIK,KAAK,CAACE,SAAS,CAACC,OAAO,CAACE,QAAQ,CAAC,GAAG,CAAC,EAAE;oBAChD,IAAI1B,KAAI,CAACZ,SAAS,KAAK,CAAC,CAAC,EAAE;sBACzBY,KAAI,CAACZ,SAAS,GAAG6B,WAAW,CAACC,GAAG,CAAC,CAAC,GAAGF,SAAS;oBAChD;kBACF,CAAC,MAAM,IAAIhB,KAAI,CAACb,SAAS,KAAK,CAAC,CAAC,EAAE;oBAChCa,KAAI,CAACb,SAAS,GAAG8B,WAAW,CAACC,GAAG,CAAC,CAAC,GAAGF,SAAS;kBAChD;kBAEA,IAAIhB,KAAI,CAACb,SAAS,IAAI,CAAC,IAAIa,KAAI,CAACZ,SAAS,IAAI,CAAC,EAAE;oBAC9C;oBACAyB,OAAO,CAAC,CAAC;kBACX;gBACF,CAAC,MAAM,IAAIQ,KAAK,CAACE,SAAS,KAAK,IAAI,EAAE;kBACnCJ,0BAA0B,CAAC,CAAC;gBAC9B;cACF,CAAC;cAEDpB,EAAE,CAAC4B,yBAAyB,GAAG,YAAM;gBACnC,IAAI5B,EAAE,CAAC6B,iBAAiB,KAAK,UAAU,EAAE;kBACvCT,0BAA0B,CAAC,CAAC;gBAC9B;cACF,CAAC;cAEDpB,EAAE,CAAC8B,iBAAiB,CAAC,MAAM,CAAC;cAE5B9B,EAAE,CAAC+B,WAAW,CAAC,CAAC,CACbC,IAAI,CAAC,UAACC,KAAK;gBAAA,OAAKjC,EAAE,CAACkC,mBAAmB,CAACD,KAAK,CAAC;cAAA,EAAC,CAC9CE,KAAK,CAAC,UAACC,CAAC,EAAK;gBACZnC,KAAI,CAACoC,KAAK,CAACC,MAAM,CAACC,KAAK,CAAC,sCAAsC,EAAEH,CAAC,CAAC;gBAClErB,MAAM,CAACqB,CAAC,CAAC;cACX,CAAC,CAAC;YACN,CAAC,CAAC;UAAA;UAAA;YAAA,OAAA3B,QAAA,CAAA+B,IAAA;QAAA;MAAA,GAAAlC,OAAA;IAAA;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACQmC,MAAM,WAAAA,OAAA,EAAG;IAAA,IAAAC,MAAA;IAAA,WAAAxC,kBAAA,CAAAC,OAAA,gBAAAC,YAAA,CAAAD,OAAA,CAAAE,IAAA,UAAAsC,SAAA;MAAA,IAAAC,OAAA,EAAA5C,EAAA;MAAA,OAAAI,YAAA,CAAAD,OAAA,CAAAI,IAAA,UAAAsC,UAAAC,SAAA;QAAA,kBAAAA,SAAA,CAAApC,IAAA,GAAAoC,SAAA,CAAAnC,IAAA;UAAA;YAAAmC,SAAA,CAAApC,IAAA;YAKXV,EAAE,GAAG,IAAI+C,iBAAiB,CAAC,CAAC;YAACD,SAAA,CAAAnC,IAAA;YAAA,OAEb+B,MAAI,CAAC3C,qBAAqB,CAACC,EAAE,CAAC;UAAA;YAA9C4C,OAAO,GAAAE,SAAA,CAAAE,IAAA;UAAA;YAAAF,SAAA,CAAApC,IAAA;YAEPV,EAAE,CAACiD,KAAK,CAAC,CAAC;YAAC,OAAAH,SAAA,CAAAI,MAAA;UAAA;YAAA,OAAAJ,SAAA,CAAAlC,MAAA,WAGNgC,OAAO;UAAA;UAAA;YAAA,OAAAE,SAAA,CAAAN,IAAA;QAAA;MAAA,GAAAG,QAAA;IAAA;EAChB,CAAC;EAAAQ,OAAA;AACH,CAAC,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAlD,OAAA,GAEYrB,iBAAiB"}
1
+ {"version":3,"names":["_webexCore","require","STATE","INITIAL","IN_PROGRESS","IDLE","IpNetworkDetector","WebexPlugin","extend","idAttribute","namespace","props","firstIpV4","firstIpV6","firstMdns","totalTime","state","pendingDetection","undefined","derived","supportsIpV4","deps","fn","receivedOnlyMDnsCandidates","supportsIpV6","gatherLocalCandidates","pc","_this","_asyncToGenerator2","default","_regenerator","mark","_callee","wrap","_callee$","_context","prev","next","abrupt","_promise","resolve","reject","done","startTime","performance","now","doneGatheringIceCandidates","onicecandidate","event","_event$candidate","candidate","address","endsWith","includes","onicegatheringstatechange","iceGatheringState","createDataChannel","createOffer","then","offer","setLocalDescription","catch","e","webex","logger","error","stop","detect","_arguments","arguments","_this2","_callee2","force","results","forceParam","_callee2$","_context2","length","RTCPeerConnection","sent","close","finish","version","_default","exports"],"sources":["ipNetworkDetector.ts"],"sourcesContent":["/*!\n * Copyright (c) 2015-2023 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {WebexPlugin} from '@webex/webex-core';\n\nconst STATE = {\n INITIAL: 'initial',\n IN_PROGRESS: 'in-progress',\n IDLE: 'idle',\n};\n\n/**\n * @class\n */\nconst IpNetworkDetector = WebexPlugin.extend({\n idAttribute: 'IpNetworkDetectorId',\n\n namespace: 'Device',\n\n props: {\n firstIpV4: ['number', true, -1], // time [ms] it took to receive first IPv4 candidate\n firstIpV6: ['number', true, -1], // time [ms] it took to receive first IPv6 candidate\n firstMdns: ['number', true, -1], // time [ms] it took to receive first mDNS candidate\n totalTime: ['number', true, -1], // total time [ms] it took to do the last IP network detection\n state: ['string', true, STATE.INITIAL],\n pendingDetection: ['object', false, undefined],\n },\n\n derived: {\n /**\n * True if we know we're on an IPv4 network,\n * False if we know that we are not on an IPv4 network,\n * undefined if we are not sure\n */\n supportsIpV4: {\n deps: ['firstIpV4', 'firstIpV6', 'firstMdns', 'totalTime'],\n /**\n * Function for calculating the value of supportsIpV4 prop\n * @returns {boolean | undefined}\n */\n fn() {\n if (this.firstIpV4 >= 0) {\n return true;\n }\n if (this.totalTime < 0) {\n // we haven't completed the detection, yet\n return undefined;\n }\n if (this.receivedOnlyMDnsCandidates()) {\n return undefined;\n }\n\n return false;\n },\n },\n /**\n * True if we know we're on an IPv6 network,\n * False if we know that we are not on an IPv6 network,\n * undefined if we are not sure\n */\n supportsIpV6: {\n deps: ['firstIpV4', 'firstIpV6', 'firstMdns', 'totalTime'],\n /**\n * Function for calculating the value of supportsIpV6 prop\n * @returns {boolean | undefined}\n */ fn() {\n if (this.firstIpV6 >= 0) {\n return true;\n }\n if (this.totalTime < 0) {\n // we haven't completed the detection, yet\n return undefined;\n }\n if (this.receivedOnlyMDnsCandidates()) {\n return undefined;\n }\n\n return false;\n },\n },\n },\n\n /**\n * Returns true if we have received only mDNS candidates - browsers usually do that if we don't have any user media permissions\n *\n * @private\n * @returns {boolean}\n */\n receivedOnlyMDnsCandidates() {\n return this.totalTime >= 0 && this.firstMdns >= 0 && this.firstIpV4 < 0 && this.firstIpV6 < 0;\n },\n\n /**\n *\n * @param {RTCPeerConnection} pc Peer connection to use\n * @private\n * @returns {Promise<void>}\n */\n async gatherLocalCandidates(pc: RTCPeerConnection): Promise<void> {\n return new Promise((resolve, reject) => {\n let done = false;\n\n this.firstIpV4 = -1;\n this.firstIpV6 = -1;\n this.firstMdns = -1;\n this.totalTime = -1;\n const startTime = performance.now();\n\n const doneGatheringIceCandidates = () => {\n if (done) {\n return;\n }\n done = true;\n\n this.totalTime = performance.now() - startTime;\n\n resolve();\n };\n\n pc.onicecandidate = (event) => {\n if (event.candidate?.address) {\n if (event.candidate.address.endsWith('.local')) {\n // if we don't have camera/mic permissions, browser just gives us mDNS candidates\n if (this.firstMdns === -1) {\n this.firstMdns = performance.now() - startTime;\n }\n } else if (event.candidate.address.includes(':')) {\n if (this.firstIpV6 === -1) {\n this.firstIpV6 = performance.now() - startTime;\n }\n } else if (this.firstIpV4 === -1) {\n this.firstIpV4 = performance.now() - startTime;\n }\n\n if (this.firstIpV4 >= 0 && this.firstIpV6 >= 0) {\n // if we've got both ipv4 and ipv6 candidates, there is no need to wait for any more candidates, we can resolve now\n resolve();\n }\n } else if (event.candidate === null) {\n doneGatheringIceCandidates();\n }\n };\n\n pc.onicegatheringstatechange = () => {\n if (pc.iceGatheringState === 'complete') {\n doneGatheringIceCandidates();\n }\n };\n\n pc.createDataChannel('data');\n\n pc.createOffer()\n .then((offer) => pc.setLocalDescription(offer))\n .catch((e) => {\n this.webex.logger.error('Failed to detect ip network version:', e);\n reject(e);\n });\n });\n },\n\n /**\n * Detects if we are on IPv4 and/or IPv6 network. Once it resolves, read the\n * supportsIpV4 and supportsIpV6 props to find out the result.\n *\n * @param {boolean} force - if false, the detection will only be done if we haven't managed to get any meaningful results yet\n * @returns {Promise<void>}\n */\n async detect(force = false) {\n let results;\n let pc;\n\n if (this.state === STATE.IN_PROGRESS) {\n this.pendingDetection = {force};\n\n return;\n }\n\n if (!force && this.state !== STATE.INITIAL && !this.receivedOnlyMDnsCandidates()) {\n // we already have the results, no need to do the detection again\n return;\n }\n\n try {\n this.state = STATE.IN_PROGRESS;\n\n pc = new RTCPeerConnection();\n\n results = await this.gatherLocalCandidates(pc);\n } finally {\n pc.close();\n this.state = STATE.IDLE;\n }\n\n if (this.pendingDetection) {\n const {force: forceParam} = this.pendingDetection;\n\n this.pendingDetection = undefined;\n this.detect(forceParam);\n }\n },\n});\n\nexport default IpNetworkDetector;\n"],"mappings":";;;;;;;;;;;AAIA,IAAAA,UAAA,GAAAC,OAAA;AAJA;AACA;AACA;;AAIA,IAAMC,KAAK,GAAG;EACZC,OAAO,EAAE,SAAS;EAClBC,WAAW,EAAE,aAAa;EAC1BC,IAAI,EAAE;AACR,CAAC;;AAED;AACA;AACA;AACA,IAAMC,iBAAiB,GAAGC,sBAAW,CAACC,MAAM,CAAC;EAC3CC,WAAW,EAAE,qBAAqB;EAElCC,SAAS,EAAE,QAAQ;EAEnBC,KAAK,EAAE;IACLC,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAAE;IACjCC,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAAE;IACjCC,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAAE;IACjCC,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAAE;IACjCC,KAAK,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAEd,KAAK,CAACC,OAAO,CAAC;IACtCc,gBAAgB,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAEC,SAAS;EAC/C,CAAC;EAEDC,OAAO,EAAE;IACP;AACJ;AACA;AACA;AACA;IACIC,YAAY,EAAE;MACZC,IAAI,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC;MAC1D;AACN;AACA;AACA;MACMC,EAAE,WAAAA,GAAA,EAAG;QACH,IAAI,IAAI,CAACV,SAAS,IAAI,CAAC,EAAE;UACvB,OAAO,IAAI;QACb;QACA,IAAI,IAAI,CAACG,SAAS,GAAG,CAAC,EAAE;UACtB;UACA,OAAOG,SAAS;QAClB;QACA,IAAI,IAAI,CAACK,0BAA0B,CAAC,CAAC,EAAE;UACrC,OAAOL,SAAS;QAClB;QAEA,OAAO,KAAK;MACd;IACF,CAAC;IACD;AACJ;AACA;AACA;AACA;IACIM,YAAY,EAAE;MACZH,IAAI,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC;MAC1D;AACN;AACA;AACA;MAAUC,EAAE,WAAAA,GAAA,EAAG;QACP,IAAI,IAAI,CAACT,SAAS,IAAI,CAAC,EAAE;UACvB,OAAO,IAAI;QACb;QACA,IAAI,IAAI,CAACE,SAAS,GAAG,CAAC,EAAE;UACtB;UACA,OAAOG,SAAS;QAClB;QACA,IAAI,IAAI,CAACK,0BAA0B,CAAC,CAAC,EAAE;UACrC,OAAOL,SAAS;QAClB;QAEA,OAAO,KAAK;MACd;IACF;EACF,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACEK,0BAA0B,WAAAA,2BAAA,EAAG;IAC3B,OAAO,IAAI,CAACR,SAAS,IAAI,CAAC,IAAI,IAAI,CAACD,SAAS,IAAI,CAAC,IAAI,IAAI,CAACF,SAAS,GAAG,CAAC,IAAI,IAAI,CAACC,SAAS,GAAG,CAAC;EAC/F,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACQY,qBAAqB,WAAAA,sBAACC,EAAqB,EAAiB;IAAA,IAAAC,KAAA;IAAA,WAAAC,kBAAA,CAAAC,OAAA,gBAAAC,YAAA,CAAAD,OAAA,CAAAE,IAAA,UAAAC,QAAA;MAAA,OAAAF,YAAA,CAAAD,OAAA,CAAAI,IAAA,UAAAC,SAAAC,QAAA;QAAA,kBAAAA,QAAA,CAAAC,IAAA,GAAAD,QAAA,CAAAE,IAAA;UAAA;YAAA,OAAAF,QAAA,CAAAG,MAAA,WACzD,IAAAC,QAAA,CAAAV,OAAA,CAAY,UAACW,OAAO,EAAEC,MAAM,EAAK;cACtC,IAAIC,IAAI,GAAG,KAAK;cAEhBf,KAAI,CAACf,SAAS,GAAG,CAAC,CAAC;cACnBe,KAAI,CAACd,SAAS,GAAG,CAAC,CAAC;cACnBc,KAAI,CAACb,SAAS,GAAG,CAAC,CAAC;cACnBa,KAAI,CAACZ,SAAS,GAAG,CAAC,CAAC;cACnB,IAAM4B,SAAS,GAAGC,WAAW,CAACC,GAAG,CAAC,CAAC;cAEnC,IAAMC,0BAA0B,GAAG,SAA7BA,0BAA0BA,CAAA,EAAS;gBACvC,IAAIJ,IAAI,EAAE;kBACR;gBACF;gBACAA,IAAI,GAAG,IAAI;gBAEXf,KAAI,CAACZ,SAAS,GAAG6B,WAAW,CAACC,GAAG,CAAC,CAAC,GAAGF,SAAS;gBAE9CH,OAAO,CAAC,CAAC;cACX,CAAC;cAEDd,EAAE,CAACqB,cAAc,GAAG,UAACC,KAAK,EAAK;gBAAA,IAAAC,gBAAA;gBAC7B,KAAAA,gBAAA,GAAID,KAAK,CAACE,SAAS,cAAAD,gBAAA,eAAfA,gBAAA,CAAiBE,OAAO,EAAE;kBAC5B,IAAIH,KAAK,CAACE,SAAS,CAACC,OAAO,CAACC,QAAQ,CAAC,QAAQ,CAAC,EAAE;oBAC9C;oBACA,IAAIzB,KAAI,CAACb,SAAS,KAAK,CAAC,CAAC,EAAE;sBACzBa,KAAI,CAACb,SAAS,GAAG8B,WAAW,CAACC,GAAG,CAAC,CAAC,GAAGF,SAAS;oBAChD;kBACF,CAAC,MAAM,IAAIK,KAAK,CAACE,SAAS,CAACC,OAAO,CAACE,QAAQ,CAAC,GAAG,CAAC,EAAE;oBAChD,IAAI1B,KAAI,CAACd,SAAS,KAAK,CAAC,CAAC,EAAE;sBACzBc,KAAI,CAACd,SAAS,GAAG+B,WAAW,CAACC,GAAG,CAAC,CAAC,GAAGF,SAAS;oBAChD;kBACF,CAAC,MAAM,IAAIhB,KAAI,CAACf,SAAS,KAAK,CAAC,CAAC,EAAE;oBAChCe,KAAI,CAACf,SAAS,GAAGgC,WAAW,CAACC,GAAG,CAAC,CAAC,GAAGF,SAAS;kBAChD;kBAEA,IAAIhB,KAAI,CAACf,SAAS,IAAI,CAAC,IAAIe,KAAI,CAACd,SAAS,IAAI,CAAC,EAAE;oBAC9C;oBACA2B,OAAO,CAAC,CAAC;kBACX;gBACF,CAAC,MAAM,IAAIQ,KAAK,CAACE,SAAS,KAAK,IAAI,EAAE;kBACnCJ,0BAA0B,CAAC,CAAC;gBAC9B;cACF,CAAC;cAEDpB,EAAE,CAAC4B,yBAAyB,GAAG,YAAM;gBACnC,IAAI5B,EAAE,CAAC6B,iBAAiB,KAAK,UAAU,EAAE;kBACvCT,0BAA0B,CAAC,CAAC;gBAC9B;cACF,CAAC;cAEDpB,EAAE,CAAC8B,iBAAiB,CAAC,MAAM,CAAC;cAE5B9B,EAAE,CAAC+B,WAAW,CAAC,CAAC,CACbC,IAAI,CAAC,UAACC,KAAK;gBAAA,OAAKjC,EAAE,CAACkC,mBAAmB,CAACD,KAAK,CAAC;cAAA,EAAC,CAC9CE,KAAK,CAAC,UAACC,CAAC,EAAK;gBACZnC,KAAI,CAACoC,KAAK,CAACC,MAAM,CAACC,KAAK,CAAC,sCAAsC,EAAEH,CAAC,CAAC;gBAClErB,MAAM,CAACqB,CAAC,CAAC;cACX,CAAC,CAAC;YACN,CAAC,CAAC;UAAA;UAAA;YAAA,OAAA3B,QAAA,CAAA+B,IAAA;QAAA;MAAA,GAAAlC,OAAA;IAAA;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;EACQmC,MAAM,WAAAA,OAAA,EAAgB;IAAA,IAAAC,UAAA,GAAAC,SAAA;MAAAC,MAAA;IAAA,WAAA1C,kBAAA,CAAAC,OAAA,gBAAAC,YAAA,CAAAD,OAAA,CAAAE,IAAA,UAAAwC,SAAA;MAAA,IAAAC,KAAA,EAAAC,OAAA,EAAA/C,EAAA,EAAAgD,UAAA;MAAA,OAAA5C,YAAA,CAAAD,OAAA,CAAAI,IAAA,UAAA0C,UAAAC,SAAA;QAAA,kBAAAA,SAAA,CAAAxC,IAAA,GAAAwC,SAAA,CAAAvC,IAAA;UAAA;YAAfmC,KAAK,GAAAJ,UAAA,CAAAS,MAAA,QAAAT,UAAA,QAAAlD,SAAA,GAAAkD,UAAA,MAAG,KAAK;YAAA,MAIpBE,MAAI,CAACtD,KAAK,KAAKd,KAAK,CAACE,WAAW;cAAAwE,SAAA,CAAAvC,IAAA;cAAA;YAAA;YAClCiC,MAAI,CAACrD,gBAAgB,GAAG;cAACuD,KAAK,EAALA;YAAK,CAAC;YAAC,OAAAI,SAAA,CAAAtC,MAAA;UAAA;YAAA,MAK9B,CAACkC,KAAK,IAAIF,MAAI,CAACtD,KAAK,KAAKd,KAAK,CAACC,OAAO,IAAI,CAACmE,MAAI,CAAC/C,0BAA0B,CAAC,CAAC;cAAAqD,SAAA,CAAAvC,IAAA;cAAA;YAAA;YAAA,OAAAuC,SAAA,CAAAtC,MAAA;UAAA;YAAAsC,SAAA,CAAAxC,IAAA;YAM9EkC,MAAI,CAACtD,KAAK,GAAGd,KAAK,CAACE,WAAW;YAE9BsB,EAAE,GAAG,IAAIoD,iBAAiB,CAAC,CAAC;YAACF,SAAA,CAAAvC,IAAA;YAAA,OAEbiC,MAAI,CAAC7C,qBAAqB,CAACC,EAAE,CAAC;UAAA;YAA9C+C,OAAO,GAAAG,SAAA,CAAAG,IAAA;UAAA;YAAAH,SAAA,CAAAxC,IAAA;YAEPV,EAAE,CAACsD,KAAK,CAAC,CAAC;YACVV,MAAI,CAACtD,KAAK,GAAGd,KAAK,CAACG,IAAI;YAAC,OAAAuE,SAAA,CAAAK,MAAA;UAAA;YAG1B,IAAIX,MAAI,CAACrD,gBAAgB,EAAE;cACXyD,UAAU,GAAIJ,MAAI,CAACrD,gBAAgB,CAA1CuD,KAAK;cAEZF,MAAI,CAACrD,gBAAgB,GAAGC,SAAS;cACjCoD,MAAI,CAACH,MAAM,CAACO,UAAU,CAAC;YACzB;UAAC;UAAA;YAAA,OAAAE,SAAA,CAAAV,IAAA;QAAA;MAAA,GAAAK,QAAA;IAAA;EACH,CAAC;EAAAW,OAAA;AACH,CAAC,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAvD,OAAA,GAEYvB,iBAAiB"}
package/package.json CHANGED
@@ -25,10 +25,10 @@
25
25
  "@webex/eslint-config-legacy": "0.0.0",
26
26
  "@webex/jest-config-legacy": "0.0.0",
27
27
  "@webex/legacy-tools": "0.0.0",
28
- "@webex/test-helper-chai": "3.6.0-next.1",
29
- "@webex/test-helper-mocha": "3.6.0-next.1",
30
- "@webex/test-helper-mock-webex": "3.6.0-next.1",
31
- "@webex/test-helper-test-users": "3.6.0-next.1",
28
+ "@webex/test-helper-chai": "3.6.0-next.3",
29
+ "@webex/test-helper-mocha": "3.6.0-next.3",
30
+ "@webex/test-helper-mock-webex": "3.6.0-next.3",
31
+ "@webex/test-helper-test-users": "3.6.0-next.3",
32
32
  "chai": "^4.3.4",
33
33
  "chai-as-promised": "^7.1.1",
34
34
  "eslint": "^8.24.0",
@@ -36,11 +36,11 @@
36
36
  "sinon": "^9.2.4"
37
37
  },
38
38
  "dependencies": {
39
- "@webex/common": "3.6.0-next.1",
40
- "@webex/common-timers": "3.6.0-next.1",
41
- "@webex/http-core": "3.6.0-next.1",
42
- "@webex/internal-plugin-metrics": "3.6.0-next.1",
43
- "@webex/webex-core": "3.6.0-next.1",
39
+ "@webex/common": "3.6.0-next.3",
40
+ "@webex/common-timers": "3.6.0-next.3",
41
+ "@webex/http-core": "3.6.0-next.3",
42
+ "@webex/internal-plugin-metrics": "3.6.0-next.3",
43
+ "@webex/webex-core": "3.6.0-next.3",
44
44
  "ampersand-collection": "^2.0.2",
45
45
  "ampersand-state": "^5.0.3",
46
46
  "lodash": "^4.17.21"
@@ -54,5 +54,5 @@
54
54
  "test:style": "eslint ./src/**/*.*",
55
55
  "test:unit": "webex-legacy-tools test --unit --runner jest"
56
56
  },
57
- "version": "3.6.0-next.1"
57
+ "version": "3.6.0-next.3"
58
58
  }
@@ -4,6 +4,12 @@
4
4
 
5
5
  import {WebexPlugin} from '@webex/webex-core';
6
6
 
7
+ const STATE = {
8
+ INITIAL: 'initial',
9
+ IN_PROGRESS: 'in-progress',
10
+ IDLE: 'idle',
11
+ };
12
+
7
13
  /**
8
14
  * @class
9
15
  */
@@ -17,6 +23,8 @@ const IpNetworkDetector = WebexPlugin.extend({
17
23
  firstIpV6: ['number', true, -1], // time [ms] it took to receive first IPv6 candidate
18
24
  firstMdns: ['number', true, -1], // time [ms] it took to receive first mDNS candidate
19
25
  totalTime: ['number', true, -1], // total time [ms] it took to do the last IP network detection
26
+ state: ['string', true, STATE.INITIAL],
27
+ pendingDetection: ['object', false, undefined],
20
28
  },
21
29
 
22
30
  derived: {
@@ -155,21 +163,41 @@ const IpNetworkDetector = WebexPlugin.extend({
155
163
  * Detects if we are on IPv4 and/or IPv6 network. Once it resolves, read the
156
164
  * supportsIpV4 and supportsIpV6 props to find out the result.
157
165
  *
158
- * @returns {Promise<Object>}
166
+ * @param {boolean} force - if false, the detection will only be done if we haven't managed to get any meaningful results yet
167
+ * @returns {Promise<void>}
159
168
  */
160
- async detect() {
169
+ async detect(force = false) {
161
170
  let results;
162
171
  let pc;
163
172
 
173
+ if (this.state === STATE.IN_PROGRESS) {
174
+ this.pendingDetection = {force};
175
+
176
+ return;
177
+ }
178
+
179
+ if (!force && this.state !== STATE.INITIAL && !this.receivedOnlyMDnsCandidates()) {
180
+ // we already have the results, no need to do the detection again
181
+ return;
182
+ }
183
+
164
184
  try {
185
+ this.state = STATE.IN_PROGRESS;
186
+
165
187
  pc = new RTCPeerConnection();
166
188
 
167
189
  results = await this.gatherLocalCandidates(pc);
168
190
  } finally {
169
191
  pc.close();
192
+ this.state = STATE.IDLE;
170
193
  }
171
194
 
172
- return results;
195
+ if (this.pendingDetection) {
196
+ const {force: forceParam} = this.pendingDetection;
197
+
198
+ this.pendingDetection = undefined;
199
+ this.detect(forceParam);
200
+ }
173
201
  },
174
202
  });
175
203
 
@@ -3,6 +3,8 @@ import sinon from 'sinon';
3
3
  import IpNetworkDetector from '@webex/internal-plugin-device/src/ipNetworkDetector';
4
4
  import MockWebex from '@webex/test-helper-mock-webex';
5
5
 
6
+ const flushPromises = () => new Promise(setImmediate);
7
+
6
8
  describe('plugin-device', () => {
7
9
  describe('IpNetworkDetector', () => {
8
10
  let webex;
@@ -326,7 +328,7 @@ describe('plugin-device', () => {
326
328
  });
327
329
 
328
330
  // now call detect() again
329
- const promise2 = ipNetworkDetector.detect();
331
+ const promise2 = ipNetworkDetector.detect(true);
330
332
 
331
333
  // everything should have been reset
332
334
  assert.equal(ipNetworkDetector.supportsIpV4, undefined);
@@ -340,6 +342,87 @@ describe('plugin-device', () => {
340
342
  await promise2;
341
343
  });
342
344
 
345
+ it('queues another detect() call if one is already in progress', async () => {
346
+ const promise = ipNetworkDetector.detect();
347
+
348
+ simulateCandidate(50, '192.168.0.1');
349
+
350
+ await flushPromises();
351
+
352
+ assert.calledOnce(fakePeerConnection.createDataChannel);
353
+ assert.calledOnce(fakePeerConnection.createOffer);
354
+ assert.calledOnce(fakePeerConnection.setLocalDescription);
355
+
356
+ // now call detect() again
357
+ ipNetworkDetector.detect(true);
358
+
359
+ // simulate the end of the detection -> another one should be started
360
+ simulateEndOfCandidateGathering(10);
361
+
362
+ await promise;
363
+
364
+ assert.calledTwice(fakePeerConnection.createDataChannel);
365
+ assert.calledTwice(fakePeerConnection.createOffer);
366
+ assert.calledTwice(fakePeerConnection.setLocalDescription);
367
+
368
+ simulateCandidate(50, '2a02:c7c:a0d0:8a00:db9b:d4de:d1f7:4c49');
369
+ simulateEndOfCandidateGathering(10);
370
+
371
+ // results should reflect the last run detection
372
+ checkResults({
373
+ supportsIpV4: false,
374
+ supportsIpV6: true,
375
+ timings: {
376
+ totalTime: 60,
377
+ ipv4: -1,
378
+ ipv6: 50,
379
+ mdns: -1,
380
+ },
381
+ });
382
+
383
+ await flushPromises();
384
+
385
+ // no more detections should be started
386
+ assert.calledTwice(fakePeerConnection.createDataChannel);
387
+ });
388
+
389
+ it.each`
390
+ force | state | receivedOnlyMDnsCandidates | expectedToRunDetection
391
+ ${true} | ${'initial'} | ${false} | ${true}
392
+ ${true} | ${'idle'} | ${false} | ${true}
393
+ ${true} | ${'initial'} | ${true} | ${true}
394
+ ${true} | ${'idle'} | ${true} | ${true}
395
+ ${false} | ${'initial'} | ${false} | ${true}
396
+ ${false} | ${'initial'} | ${true} | ${true}
397
+ ${false} | ${'idle'} | ${true} | ${true}
398
+ ${false} | ${'idle'} | ${false} | ${false}
399
+ `(
400
+ 'force=$force, state=$state, receivedOnlyMDnsCandidates=$receivedOnlyMDnsCandidates => expectedToRunDetection=$expectedToRunDetection',
401
+ async ({force, state, receivedOnlyMDnsCandidates, expectedToRunDetection}) => {
402
+ ipNetworkDetector.state = state;
403
+ sinon
404
+ .stub(ipNetworkDetector, 'receivedOnlyMDnsCandidates')
405
+ .returns(receivedOnlyMDnsCandidates);
406
+
407
+ const result = ipNetworkDetector.detect(force);
408
+
409
+ if (expectedToRunDetection) {
410
+ simulateEndOfCandidateGathering(10);
411
+ }
412
+ await result;
413
+
414
+ if (expectedToRunDetection) {
415
+ assert.calledOnce(fakePeerConnection.createDataChannel);
416
+ assert.calledOnce(fakePeerConnection.createOffer);
417
+ assert.calledOnce(fakePeerConnection.setLocalDescription);
418
+ } else {
419
+ assert.notCalled(fakePeerConnection.createDataChannel);
420
+ assert.notCalled(fakePeerConnection.createOffer);
421
+ assert.notCalled(fakePeerConnection.setLocalDescription);
422
+ }
423
+ }
424
+ );
425
+
343
426
  it('rejects if one of RTCPeerConnection operations fails', async () => {
344
427
  const fakeError = new Error('fake error');
345
428