mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-28 12:19:54 +00:00
android, desktop: support old Android WebViews (up to 69) (#4953)
* android, desktop: support old Android WebViews (up to 69) * refactor * WebView 70 * comment
This commit is contained in:
parent
ab034e626f
commit
15ca662805
5 changed files with 100 additions and 17 deletions
|
@ -737,7 +737,11 @@ fun WebRTCView(callCommand: SnapshotStateList<WCallCommand>, onResponse: (WVAPIM
|
|||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error initializing WebView: ${e.stackTraceToString()}")
|
||||
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error), generalGetString(MR.strings.error_initializing_web_view).format(e.stackTraceToString()))
|
||||
if (e.stackTraceToString().contains("/lib64")) {
|
||||
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error), generalGetString(MR.strings.error_initializing_web_view_wrong_arch).format(e.stackTraceToString()))
|
||||
} else {
|
||||
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error), generalGetString(MR.strings.error_initializing_web_view).format(e.stackTraceToString()))
|
||||
}
|
||||
return@AndroidView View(androidAppContext)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -989,6 +989,7 @@
|
|||
<string name="audio_device_wired_headphones">Headphones</string>
|
||||
<string name="audio_device_bluetooth">Bluetooth</string>
|
||||
<string name="error_initializing_web_view">Error initializing WebView. Update your system to the new version. Please contact developers.\nError: %s</string>
|
||||
<string name="error_initializing_web_view_wrong_arch">Error initializing WebView. Make sure you have WebView installed and it\'s supported architecture is arm64.\nError: %s</string>
|
||||
|
||||
<!-- SimpleXInfo -->
|
||||
<string name="next_generation_of_private_messaging">The next generation\nof private messaging</string>
|
||||
|
|
|
@ -76,6 +76,8 @@ const processCommand = (function () {
|
|||
iceCandidatePoolSize: 10,
|
||||
encodedInsertableStreams,
|
||||
iceTransportPolicy: relay ? "relay" : "all",
|
||||
// needed for Android WebView >= 69 && <= 72 where default was "plan-b" which is incompatible with transceivers
|
||||
sdpSemantics: "unified-plan",
|
||||
},
|
||||
iceCandidates: {
|
||||
delay: 750,
|
||||
|
@ -202,7 +204,12 @@ const processCommand = (function () {
|
|||
localOrPeerMediaSourcesChanged(call);
|
||||
await setupMediaStreams(call);
|
||||
let connectionTimeout = setTimeout(connectionHandler, answerTimeout);
|
||||
pc.addEventListener("connectionstatechange", connectionStateChange);
|
||||
if (pc.connectionState) {
|
||||
pc.addEventListener("connectionstatechange", connectionStateChange);
|
||||
}
|
||||
else {
|
||||
pc.addEventListener("iceconnectionstatechange", connectionStateChange);
|
||||
}
|
||||
return call;
|
||||
async function connectionStateChange() {
|
||||
// "failed" means the second party did not answer in time (15 sec timeout in Chrome WebView)
|
||||
|
@ -211,26 +218,38 @@ const processCommand = (function () {
|
|||
connectionHandler();
|
||||
}
|
||||
async function connectionHandler() {
|
||||
var _a;
|
||||
sendMessageToNative({
|
||||
resp: {
|
||||
type: "connection",
|
||||
state: {
|
||||
connectionState: pc.connectionState,
|
||||
connectionState: (_a = pc.connectionState) !== null && _a !== void 0 ? _a : (pc.iceConnectionState != "completed" && pc.iceConnectionState != "checking"
|
||||
? pc.iceConnectionState
|
||||
: pc.iceConnectionState == "completed"
|
||||
? "connected"
|
||||
: "connecting") /* webView 69-70 doesn't have connectionState yet */,
|
||||
iceConnectionState: pc.iceConnectionState,
|
||||
iceGatheringState: pc.iceGatheringState,
|
||||
signalingState: pc.signalingState,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (pc.connectionState == "disconnected" || pc.connectionState == "failed") {
|
||||
if (pc.connectionState == "disconnected" ||
|
||||
pc.connectionState == "failed" ||
|
||||
(!pc.connectionState && (pc.iceConnectionState == "disconnected" || pc.iceConnectionState == "failed"))) {
|
||||
clearConnectionTimeout();
|
||||
pc.removeEventListener("connectionstatechange", connectionStateChange);
|
||||
if (pc.connectionState) {
|
||||
pc.removeEventListener("connectionstatechange", connectionStateChange);
|
||||
}
|
||||
else {
|
||||
pc.removeEventListener("iceconnectionstatechange", connectionStateChange);
|
||||
}
|
||||
if (activeCall) {
|
||||
setTimeout(() => sendMessageToNative({ resp: { type: "ended" } }), 0);
|
||||
}
|
||||
endCall();
|
||||
}
|
||||
else if (pc.connectionState == "connected") {
|
||||
else if (pc.connectionState == "connected" || (!pc.connectionState && pc.iceConnectionState == "connected")) {
|
||||
clearConnectionTimeout();
|
||||
const stats = (await pc.getStats());
|
||||
for (const stat of stats.values()) {
|
||||
|
@ -355,7 +374,7 @@ const processCommand = (function () {
|
|||
activeCall = await initializeCall(getCallConfig(!!aesKey, iceServers, relay), media, aesKey);
|
||||
const pc = activeCall.connection;
|
||||
// console.log("offer remoteIceCandidates", JSON.stringify(remoteIceCandidates))
|
||||
await pc.setRemoteDescription(new RTCSessionDescription(offer));
|
||||
await pc.setRemoteDescription(new RTCSessionDescription(!webView69Or70() ? offer : adaptSdpToOldWebView(offer)));
|
||||
// setting up local stream only after setRemoteDescription in order to have transceivers set
|
||||
await setupLocalStream(false, activeCall);
|
||||
setupEncryptionForLocalStream(activeCall);
|
||||
|
@ -397,7 +416,7 @@ const processCommand = (function () {
|
|||
const answer = parse(command.answer);
|
||||
const remoteIceCandidates = parse(command.iceCandidates);
|
||||
// console.log("answer remoteIceCandidates", JSON.stringify(remoteIceCandidates))
|
||||
await pc.setRemoteDescription(new RTCSessionDescription(answer));
|
||||
await pc.setRemoteDescription(new RTCSessionDescription(!webView69Or70() ? answer : adaptSdpToOldWebView(answer)));
|
||||
adaptToOldVersion(pc.getTransceivers()[2].currentDirection == "sendonly", activeCall);
|
||||
addIceCandidates(pc, remoteIceCandidates);
|
||||
addIceCandidates(pc, afterCallInitializedCandidates);
|
||||
|
@ -934,6 +953,7 @@ const processCommand = (function () {
|
|||
});
|
||||
}
|
||||
if (inboundStatsId) {
|
||||
// even though MSDN site says `packetsReceived` is available in WebView 80+, in reality it's available even in 69
|
||||
const packets = (_a = stats.get(inboundStatsId)) === null || _a === void 0 ? void 0 : _a.packetsReceived;
|
||||
if (packets <= lastPacketsReceived) {
|
||||
mutedSeconds++;
|
||||
|
@ -1156,6 +1176,22 @@ const processCommand = (function () {
|
|||
}
|
||||
}
|
||||
}
|
||||
function webView69Or70() {
|
||||
return !isDesktop && (navigator.userAgent.includes("Chrome/69.") || navigator.userAgent.includes("Chrome/70."));
|
||||
}
|
||||
// Adding `a=extmap-allow-mixed` causes exception on old WebViews
|
||||
// https://groups.google.com/a/chromium.org/g/blink-dev/c/7z3uvp0-ZAc/m/8Z7qpp71BgAJ
|
||||
function adaptSdpToOldWebView(desc) {
|
||||
var _a;
|
||||
const res = [];
|
||||
(_a = desc.sdp) === null || _a === void 0 ? void 0 : _a.split("\n").forEach((line) => {
|
||||
// Chrome has a bug related to SDP parser in old web view versions
|
||||
if (!line.includes("a=extmap-allow-mixed")) {
|
||||
res.push(line);
|
||||
}
|
||||
});
|
||||
return { sdp: res.join("\n"), type: desc.type };
|
||||
}
|
||||
return processCommand;
|
||||
})();
|
||||
function toggleRemoteVideoFitFill() {
|
||||
|
|
|
@ -1 +1 @@
|
|||
var LZString=function(){function o(o,r){if(!t[o]){t[o]={};for(var n=0;n<o.length;n++)t[o][o.charAt(n)]=n}return t[o][r]}var r=String.fromCharCode,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",t={},i={compressToBase64:function(o){if(null==o)return"";var r=i._compress(o,6,function(o){return n.charAt(o)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(r){return null==r?"":""==r?null:i._decompress(r.length,32,function(e){return o(n,r.charAt(e))})},compressToUTF16:function(o){return null==o?"":i._compress(o,15,function(o){return r(o+32)})+" "},decompressFromUTF16:function(o){return null==o?"":""==o?null:i._decompress(o.length,16384,function(r){return o.charCodeAt(r)-32})},compressToUint8Array:function(o){for(var r=i.compress(o),n=new Uint8Array(2*r.length),e=0,t=r.length;t>e;e++){var s=r.charCodeAt(e);n[2*e]=s>>>8,n[2*e+1]=s%256}return n},decompressFromUint8Array:function(o){if(null===o||void 0===o)return i.decompress(o);for(var n=new Array(o.length/2),e=0,t=n.length;t>e;e++)n[e]=256*o[2*e]+o[2*e+1];var s=[];return n.forEach(function(o){s.push(r(o))}),i.decompress(s.join(""))},compressToEncodedURIComponent:function(o){return null==o?"":i._compress(o,6,function(o){return e.charAt(o)})},decompressFromEncodedURIComponent:function(r){return null==r?"":""==r?null:(r=r.replace(/ /g,"+"),i._decompress(r.length,32,function(n){return o(e,r.charAt(n))}))},compress:function(o){return i._compress(o,16,function(o){return r(o)})},_compress:function(o,r,n){if(null==o)return"";var e,t,i,s={},p={},u="",c="",a="",l=2,f=3,h=2,d=[],m=0,v=0;for(i=0;i<o.length;i+=1)if(u=o.charAt(i),Object.prototype.hasOwnProperty.call(s,u)||(s[u]=f++,p[u]=!0),c=a+u,Object.prototype.hasOwnProperty.call(s,c))a=c;else{if(Object.prototype.hasOwnProperty.call(p,a)){if(a.charCodeAt(0)<256){for(e=0;h>e;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a]}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++),s[c]=f++,a=String(u)}if(""!==a){if(Object.prototype.hasOwnProperty.call(p,a)){if(a.charCodeAt(0)<256){for(e=0;h>e;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a]}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++)}for(t=2,e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;for(;;){if(m<<=1,v==r-1){d.push(n(m));break}v++}return d.join("")},decompress:function(o){return null==o?"":""==o?null:i._decompress(o.length,32768,function(r){return o.charCodeAt(r)})},_decompress:function(o,n,e){var t,i,s,p,u,c,a,l,f=[],h=4,d=4,m=3,v="",w=[],A={val:e(0),position:n,index:1};for(i=0;3>i;i+=1)f[i]=i;for(p=0,c=Math.pow(2,2),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(t=p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 2:return""}for(f[3]=l,s=l,w.push(l);;){if(A.index>o)return"";for(p=0,c=Math.pow(2,m),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(l=p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 2:return w.join("")}if(0==h&&(h=Math.pow(2,m),m++),f[l])v=f[l];else{if(l!==d)return null;v=s+s.charAt(0)}w.push(v),f[d++]=s+v.charAt(0),h--,s=v,0==h&&(h=Math.pow(2,m),m++)}}};return i}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module&&(module.exports=LZString);
|
||||
var LZString=function(){var r=String.fromCharCode,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",e={};function t(r,o){if(!e[r]){e[r]={};for(var n=0;n<r.length;n++)e[r][r.charAt(n)]=n}return e[r][o]}var i={compressToBase64:function(r){if(null==r)return"";var n=i._compress(r,6,function(r){return o.charAt(r)});switch(n.length%4){default:case 0:return n;case 1:return n+"===";case 2:return n+"==";case 3:return n+"="}},decompressFromBase64:function(r){return null==r?"":""==r?null:i._decompress(r.length,32,function(n){return t(o,r.charAt(n))})},compressToUTF16:function(o){return null==o?"":i._compress(o,15,function(o){return r(o+32)})+" "},decompressFromUTF16:function(r){return null==r?"":""==r?null:i._decompress(r.length,16384,function(o){return r.charCodeAt(o)-32})},compressToUint8Array:function(r){for(var o=i.compress(r),n=new Uint8Array(2*o.length),e=0,t=o.length;e<t;e++){var s=o.charCodeAt(e);n[2*e]=s>>>8,n[2*e+1]=s%256}return n},decompressFromUint8Array:function(o){if(null==o)return i.decompress(o);for(var n=new Array(o.length/2),e=0,t=n.length;e<t;e++)n[e]=256*o[2*e]+o[2*e+1];var s=[];return n.forEach(function(o){s.push(r(o))}),i.decompress(s.join(""))},compressToEncodedURIComponent:function(r){return null==r?"":i._compress(r,6,function(r){return n.charAt(r)})},decompressFromEncodedURIComponent:function(r){return null==r?"":""==r?null:(r=r.replace(/ /g,"+"),i._decompress(r.length,32,function(o){return t(n,r.charAt(o))}))},compress:function(o){return i._compress(o,16,function(o){return r(o)})},_compress:function(r,o,n){if(null==r)return"";var e,t,i,s={},u={},a="",p="",c="",l=2,f=3,h=2,d=[],m=0,v=0;for(i=0;i<r.length;i+=1)if(a=r.charAt(i),Object.prototype.hasOwnProperty.call(s,a)||(s[a]=f++,u[a]=!0),p=c+a,Object.prototype.hasOwnProperty.call(s,p))c=p;else{if(Object.prototype.hasOwnProperty.call(u,c)){if(c.charCodeAt(0)<256){for(e=0;e<h;e++)m<<=1,v==o-1?(v=0,d.push(n(m)),m=0):v++;for(t=c.charCodeAt(0),e=0;e<8;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;e<h;e++)m=m<<1|t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=c.charCodeAt(0),e=0;e<16;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}0==--l&&(l=Math.pow(2,h),h++),delete u[c]}else for(t=s[c],e=0;e<h;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;0==--l&&(l=Math.pow(2,h),h++),s[p]=f++,c=String(a)}if(""!==c){if(Object.prototype.hasOwnProperty.call(u,c)){if(c.charCodeAt(0)<256){for(e=0;e<h;e++)m<<=1,v==o-1?(v=0,d.push(n(m)),m=0):v++;for(t=c.charCodeAt(0),e=0;e<8;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;e<h;e++)m=m<<1|t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=c.charCodeAt(0),e=0;e<16;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}0==--l&&(l=Math.pow(2,h),h++),delete u[c]}else for(t=s[c],e=0;e<h;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;0==--l&&(l=Math.pow(2,h),h++)}for(t=2,e=0;e<h;e++)m=m<<1|1&t,v==o-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;for(;;){if(m<<=1,v==o-1){d.push(n(m));break}v++}return d.join("")},decompress:function(r){return null==r?"":""==r?null:i._decompress(r.length,32768,function(o){return r.charCodeAt(o)})},_decompress:function(o,n,e){var t,i,s,u,a,p,c,l=[],f=4,h=4,d=3,m="",v=[],g={val:e(0),position:n,index:1};for(t=0;t<3;t+=1)l[t]=t;for(s=0,a=Math.pow(2,2),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;switch(s){case 0:for(s=0,a=Math.pow(2,8),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;c=r(s);break;case 1:for(s=0,a=Math.pow(2,16),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;c=r(s);break;case 2:return""}for(l[3]=c,i=c,v.push(c);;){if(g.index>o)return"";for(s=0,a=Math.pow(2,d),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;switch(c=s){case 0:for(s=0,a=Math.pow(2,8),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;l[h++]=r(s),c=h-1,f--;break;case 1:for(s=0,a=Math.pow(2,16),p=1;p!=a;)u=g.val&g.position,g.position>>=1,0==g.position&&(g.position=n,g.val=e(g.index++)),s|=(u>0?1:0)*p,p<<=1;l[h++]=r(s),c=h-1,f--;break;case 2:return v.join("")}if(0==f&&(f=Math.pow(2,d),d++),l[c])m=l[c];else{if(c!==h)return null;m=i+i.charAt(0)}v.push(m),l[h++]=i+m.charAt(0),i=m,0==--f&&(f=Math.pow(2,d),d++)}}};return i}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module?module.exports=LZString:"undefined"!=typeof angular&&null!=angular&&angular.module("LZString",[]).factory("LZString",function(){return LZString});
|
|
@ -311,8 +311,12 @@ const processCommand = (function () {
|
|||
encodedInsertableStreams: boolean
|
||||
}
|
||||
|
||||
type RTCConfigurationWithSdpSemantics = RTCConfiguration & {
|
||||
sdpSemantics: string
|
||||
}
|
||||
|
||||
interface CallConfig {
|
||||
peerConnectionConfig: RTCConfigurationWithEncryption
|
||||
peerConnectionConfig: RTCConfigurationWithEncryption & RTCConfigurationWithSdpSemantics
|
||||
iceCandidates: {
|
||||
delay: number
|
||||
extrasInterval: number
|
||||
|
@ -334,6 +338,8 @@ const processCommand = (function () {
|
|||
iceCandidatePoolSize: 10,
|
||||
encodedInsertableStreams,
|
||||
iceTransportPolicy: relay ? "relay" : "all",
|
||||
// needed for Android WebView >= 69 && <= 72 where default was "plan-b" which is incompatible with transceivers
|
||||
sdpSemantics: "unified-plan",
|
||||
},
|
||||
iceCandidates: {
|
||||
delay: 750,
|
||||
|
@ -458,7 +464,11 @@ const processCommand = (function () {
|
|||
localOrPeerMediaSourcesChanged(call)
|
||||
await setupMediaStreams(call)
|
||||
let connectionTimeout: number | undefined = setTimeout(connectionHandler, answerTimeout)
|
||||
pc.addEventListener("connectionstatechange", connectionStateChange)
|
||||
if (pc.connectionState) {
|
||||
pc.addEventListener("connectionstatechange", connectionStateChange)
|
||||
} else {
|
||||
pc.addEventListener("iceconnectionstatechange", connectionStateChange)
|
||||
}
|
||||
return call
|
||||
|
||||
async function connectionStateChange() {
|
||||
|
@ -472,21 +482,35 @@ const processCommand = (function () {
|
|||
resp: {
|
||||
type: "connection",
|
||||
state: {
|
||||
connectionState: pc.connectionState,
|
||||
connectionState:
|
||||
pc.connectionState ??
|
||||
(pc.iceConnectionState != "completed" && pc.iceConnectionState != "checking"
|
||||
? pc.iceConnectionState
|
||||
: pc.iceConnectionState == "completed"
|
||||
? "connected"
|
||||
: "connecting") /* webView 69-70 doesn't have connectionState yet */,
|
||||
iceConnectionState: pc.iceConnectionState,
|
||||
iceGatheringState: pc.iceGatheringState,
|
||||
signalingState: pc.signalingState,
|
||||
},
|
||||
},
|
||||
})
|
||||
if (pc.connectionState == "disconnected" || pc.connectionState == "failed") {
|
||||
if (
|
||||
pc.connectionState == "disconnected" ||
|
||||
pc.connectionState == "failed" ||
|
||||
(!pc.connectionState && (pc.iceConnectionState == "disconnected" || pc.iceConnectionState == "failed"))
|
||||
) {
|
||||
clearConnectionTimeout()
|
||||
pc.removeEventListener("connectionstatechange", connectionStateChange)
|
||||
if (pc.connectionState) {
|
||||
pc.removeEventListener("connectionstatechange", connectionStateChange)
|
||||
} else {
|
||||
pc.removeEventListener("iceconnectionstatechange", connectionStateChange)
|
||||
}
|
||||
if (activeCall) {
|
||||
setTimeout(() => sendMessageToNative({resp: {type: "ended"}}), 0)
|
||||
}
|
||||
endCall()
|
||||
} else if (pc.connectionState == "connected") {
|
||||
} else if (pc.connectionState == "connected" || (!pc.connectionState && pc.iceConnectionState == "connected")) {
|
||||
clearConnectionTimeout()
|
||||
const stats = (await pc.getStats()) as Map<string, any>
|
||||
for (const stat of stats.values()) {
|
||||
|
@ -613,7 +637,7 @@ const processCommand = (function () {
|
|||
activeCall = await initializeCall(getCallConfig(!!aesKey, iceServers, relay), media, aesKey)
|
||||
const pc = activeCall.connection
|
||||
// console.log("offer remoteIceCandidates", JSON.stringify(remoteIceCandidates))
|
||||
await pc.setRemoteDescription(new RTCSessionDescription(offer))
|
||||
await pc.setRemoteDescription(new RTCSessionDescription(!webView69Or70() ? offer : adaptSdpToOldWebView(offer)))
|
||||
// setting up local stream only after setRemoteDescription in order to have transceivers set
|
||||
await setupLocalStream(false, activeCall)
|
||||
setupEncryptionForLocalStream(activeCall)
|
||||
|
@ -654,7 +678,7 @@ const processCommand = (function () {
|
|||
const remoteIceCandidates: RTCIceCandidateInit[] = parse(command.iceCandidates)
|
||||
// console.log("answer remoteIceCandidates", JSON.stringify(remoteIceCandidates))
|
||||
|
||||
await pc.setRemoteDescription(new RTCSessionDescription(answer))
|
||||
await pc.setRemoteDescription(new RTCSessionDescription(!webView69Or70() ? answer : adaptSdpToOldWebView(answer)))
|
||||
adaptToOldVersion(pc.getTransceivers()[2].currentDirection == "sendonly", activeCall!)
|
||||
addIceCandidates(pc, remoteIceCandidates)
|
||||
addIceCandidates(pc, afterCallInitializedCandidates)
|
||||
|
@ -1219,6 +1243,7 @@ const processCommand = (function () {
|
|||
})
|
||||
}
|
||||
if (inboundStatsId) {
|
||||
// even though MSDN site says `packetsReceived` is available in WebView 80+, in reality it's available even in 69
|
||||
const packets = (stats as any).get(inboundStatsId)?.packetsReceived
|
||||
if (packets <= lastPacketsReceived) {
|
||||
mutedSeconds++
|
||||
|
@ -1447,6 +1472,23 @@ const processCommand = (function () {
|
|||
}
|
||||
}
|
||||
|
||||
function webView69Or70(): boolean {
|
||||
return !isDesktop && (navigator.userAgent.includes("Chrome/69.") || navigator.userAgent.includes("Chrome/70."))
|
||||
}
|
||||
|
||||
// Adding `a=extmap-allow-mixed` causes exception on old WebViews
|
||||
// https://groups.google.com/a/chromium.org/g/blink-dev/c/7z3uvp0-ZAc/m/8Z7qpp71BgAJ
|
||||
function adaptSdpToOldWebView(desc: RTCSessionDescriptionInit): RTCSessionDescriptionInit {
|
||||
const res: string[] = []
|
||||
desc.sdp?.split("\n").forEach((line) => {
|
||||
// Chrome has a bug related to SDP parser in old web view versions
|
||||
if (!line.includes("a=extmap-allow-mixed")) {
|
||||
res.push(line)
|
||||
}
|
||||
})
|
||||
return {sdp: res.join("\n"), type: desc.type}
|
||||
}
|
||||
|
||||
return processCommand
|
||||
})()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue