webrtcHacks/adapter

Uncaught DOMException: Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.

hthetiot opened this issue · 13 comments

Please read first!

Please use discuss-webrtc for general technical discussions and questions.

  • I have provided steps to reproduce (e.g. a link to a jsfiddle)
  • I have provided browser name, version and adapter.js version
  • This issue only happens when adapter.js is used

Note: If the checkboxes above are not checked (which you do after the issue is posted), the issue will be closed.

Versions affected

  • Chrome 81.0.4044.129

  • adapter.js from https://webrtc.github.io/adapter/adapter-latest.js

Description

Cause Uncaught DOMException: Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender. when calling peerConnection.removeTrack with RTCRtpSender from getSenders.

Steps to reproduce

var senders = peerConnection.getSenders();
stream.getTracks().forEach((track) => {
    senders.forEach((sender) => {
        if (sender.track === track) {
            peerConnection.removeTrack(sender);
        }
    });
});

Only when https://webrtc.github.io/adapter/adapter-latest.js is loaded.

Expected results

Remove Sender peerConnection from and properly when https://webrtc.github.io/adapter/adapter-latest.js is not loaded.

Actual results

Cause Uncaught DOMException: Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.

Caused by https://webrtc.github.io/adapter/adapter-latest.js:892

    // We can not yet check for sender instanceof RTCRtpSender
    // since we shim RTPSender. So we check if sender._pc is set.
    if (!sender._pc) {
      throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' + 'does not implement interface RTCRtpSender.', 'TypeError');
    }

Note: sender.replaceTrack(null) also fail.

Current workaround:

var senders = peerConnection.getSenders();
stream.getTracks().forEach((track) => {
    senders.forEach((sender) => {
        if (sender.track === track) {
            // Fix Uncaught DOMException: Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.
            if (typeof window.adapter) {
                sender._pc = peerConnection;
            }
            peerConnection.removeTrack(sender);
        }
    });
});

Note: sender.replaceTrack(null) fail to properly remove the track on Chrome 81.0.4044.129

fippo commented

can't reproduce on with https://webrtc.github.io/samples/src/content/peerconnection/pc1/

var senders = pc1.getSenders();
localStream.getTracks().forEach((track) => {
    senders.forEach((sender) => {
        if (sender.track === track) {
            pc1.removeTrack(sender);
        }
    });
});

after making a call. In M81 checking window.RTCPeerConnection.prototype.getSenders should return ƒ getSenders() { [native code] } (i.e. no shimming), does it do that for you?

I confirm I do not reproduce with https://webrtc.github.io/samples/src/content/peerconnection/pc1/ and that window.RTCPeerConnection.prototype.getSenders does return ƒ getSenders() { [native code] } (i.e. no shimming).

I'm not sure I ended up fixing it but I cannot reproduce anymore despite been able to reproduce several time before creating the issue (I did change some of my implementation since then, I think that why) I'm closing for now and will re-open if it append again and I have a full sample not partial to reproduce.

Thank you @fippo

Screen Shot 2020-05-06 at 9 19 04 PM

Ok I got it today again.

This is my PeerConnection config for reference:
Screen Shot 2020-05-06 at 9 25 06 PM

Screen Shot 2020-05-06 at 9 24 13 PM

I can reproduce using https://webrtc.github.io/samples/src/content/peerconnection/pc1/ by selecting Unified-Plan. See capture above. I think yesterday I did not reproduce because I did not select Unified-Plan on the sample. The weird part is on my side I'm not using Unified-Plan but sdpSemantics: plan-b and "bundlePolicy": 'max-compat'.

Do not reproduce on Firefox, just to be sure:

Screen Shot 2020-05-06 at 9 28 42 PM

Updated workaround:

// Using removeStream
if (
    // @ts-ignore
    typeof peerConnection.removeStream === 'function' &&
       typeof window.adapter !== 'undefined' &&
            window.adapter.browserDetails.browser === 'chrome'
) {
    // @ts-ignore
    peerConnection.removeStream(streamObj.stream);

// Using sender removeTrack
} else {
    var senders = peerConnection.getSenders();
    streamObj.stream.getTracks().forEach((track) => {
        senders.forEach((sender) => {
            if (sender.track === track) {
                peerConnection.removeTrack(sender);
            }
        });
    });
}
fippo commented

Still can't reproduce. This looks like it is running into some weird interaction in ħere

Can you step through this and check it runs into this?

It would be interesting to see if the error is the native one or https://github.com/webrtcHacks/adapter/blob/master/src/js/chrome/chrome_shim.js#L633
If its the native one, what is the value of the first argument to the native replaceTrack call?

fippo commented

you have three senders there. And the transport of the sender you're trying to remove is null.
And pc1.removeTrack shows this15 which suggests its https://github.com/webrtc/adapter/blob/gh-pages/adapter-7.5.0.js#L861 which suggests its not running into https://github.com/webrtc/adapter/blob/gh-pages/adapter-7.5.0.js#L689

How does adapter.browserDetails looks like, in particular the version?

Ok I got with your instructions, I was running the console with the device toolbar open without realizing it. That why it came and disappeared wihout trace yesterday,

Screen Shot 2020-05-06 at 10 09 07 PM

Because it is using user agent sniffing instead of features detection it caused bad detection of the browser version.

Screen Shot 2020-05-06 at 10 08 18 PM

This is basicly a false positive I would say. Closing then.

Thank you @fippo for the pointer.

fippo commented

there is probably room for improvement when the detected version is null (from ua sniffing) and it still looks like chrome (from feature detecetion). Interesting 👻

That been said, I wonder what append on all this Chromium based browser with modifed userAgent...

Final dirty workaround for using adapter and the console with the device toolbar using custom userAgent on chrome:

var tryUsingRemoveStream = false;

// Using sender removeTrack
try {
    var senders = peerConnection.getSenders();
    streamObj.stream.getTracks().forEach((track) => {
        senders.forEach((sender) => {
            if (sender.track === track) {
                peerConnection.removeTrack(sender);
            }
        });
    });
} catch (err) {
    if (err.message === 'Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.') {
        tryUsingRemoveStream = true;
    } else {
        throw err;
    }
}

// Using removeStreamx
if (
    // @ts-ignore
    tryUsingRemoveStream && typeof peerConnection.removeStream === 'function'
) {
    // @ts-ignore
    peerConnection.removeStream(streamObj.stream);
}