Webrtc-pc: What happens to the peer connection when the laptop lid closes?

Created on 11 Mar 2020  路  17Comments  路  Source: w3c/webrtc-pc

Questions raised at https://crbug.com/1060547 and related to discussions over at #1883.

If I read the spec correctly, the only way to close a pc is with pc.close().

Action at a distance does not cause close(): E.g. if the remote endpoint performs close(), while this may cause other events to fire due to network signals (track.onmute, dc.onclose, dtlsTransport.onstatechange), there is no event specific to "pc.close()". And in any case, these do not close the local pc.

In Chrome M80 and prior, if you close the laptop lid (at least on a MacBook Pro, not sure about other OS/hardware) this will cause the web page to get suspended, and suspending the web page will cause the RTCPeerConnection to close. This is being looked at now because in M81 there will be a regression here (unless we fix and backmerge).

The regression means we can no longer use pc.onsignalingstatechange to infer that the laptop lid is closing. pc.onsignalingstatechange was almost certainly not intended as an API for detecting laptop lid closing, but it begs the question:

  • Should there be any way to close the pc other than with pc.close()?
  • What should we do when the web page gets suspended? If the laptop lid closes?

Update/Clarification: In Chrome, the web page actually doesn't get suspended (other JS is running), but the peer connection gets closed. In both M80 and M81 it closes, but in M81 it closes without firing the associated event.

Most helpful comment

You close the lid and think you're out but people can hear you?

Hopefully capture and media playback should be suspended.

All 17 comments

@jan-ivar PTAL

I don't know if suspending a page has a spec definition, but I wonder if Location.reload() may be used as a substitute in tests?

I wonder if Location.reload() may be used as a substitute in tests?

No, that's different. Location.reload() triggers a pagehide event in all browsers, a sign of navigation. This doesn't.

From what I can tell Chrome 80 does not do that when I close the lid, nor does it "suspend" the page (it keeps observably running on my MBP as verified by the output when I reopen the lid and re-enter my credentials. However, it _does_ close peer connections.

I find no spec support for Chrome closing peer connections here. Firefox does not.

  • Should there be any way to close the pc other than with pc.close()?

Maybe, but not in this particular case I don't think. Firefox does "close" peer connections internally on unload I believe. But I'm not sure this is observable to the page since we disable BFCache for peer connections (though I believe Safari does not, or are thinking about not doing so. @youennf?)

What should we do when the web page gets suspended? If the laptop lid closes?

I'm not seeing the page being suspended here. Maybe if I wait longer, the laptop enters a deeper sleep?

Firefox does "close" peer connections internally on unload I believe.

I've tested closing 1 of 2 peer tabs, & only Firefox fires close on the other peer's datachannel:

onclose: closed

I think that might be useful to specify.

only Firefox fires close on the other peer's datachannel:

Looks like it works in Chrome 82 (just not 80)! 馃檪

With regards to Chrome's current implementation - not whether or not closing makes sense:

From what I can tell Chrome 80 does not do that when I close the lid, nor does it "suspend" the page (it keeps observably running on my MBP as verified by the output when I reopen the lid and re-enter my credentials. However, it _does_ close peer connections.

Maybe it depends on machine or OS version? I have a MacBook Pro and if I close the lid, open and log in again, I see "closed" in the logs in M80.

In M81 I no longer see it. With a fix that has not landed yet I see it again.

Polling also seems to fix the M81 regression: https://jsfiddle.net/g7as1hbu/3/

I find no spec support for Chrome closing peer connections here. Firefox does not.

Agreed.

if I close the lid, open and log in again, I see "closed" in the logs in M80.

You mean from peer connection? yes I see that also, as I mentioned:

However, it _does_ close peer connections.

Some take aways from today's discussion:

  1. Permanently terminating the pc is wrong because suspending is something you can recover from. (Other applications might want reconnect with ICE restarts, assuming it disconnected.)
  2. It turns out that closing the lid doesn't even suspend the page, at least not immediately - other JS code keeps running. This seems inconsistent.
  3. This seem to behave differently on different OSes and devices.
  4. Detecting lid close is potentially a privacy issue.
  5. Even if we want a "lid is closing API", pc.onsignalingstatechange is an odd API surface for something like this.
  6. This is currently causing cross-browser compatibility issues (other browsers don't do this).

That being said, if a video conference keeps running even after lid close but before suspending that would surprise the user and have privacy issues. You close the lid and think you're out but people can hear you?

You close the lid and think you're out but people can hear you?

Hopefully capture and media playback should be suspended.

if a video conference keeps running even after lid close but before suspending that would surprise the user and have privacy issues

That sounds like a media capture issue. This mediaRecorder fiddle shows both Chrome and Firefox turn off (or at least seize recording) the camera and mic when the lid is shut, and right back on when the lid is reopened.

I've verified this is a feature of the camera & mic (and not mediaRecorder) using a webrtc room (https://whereby.com) and a separate machine.

In Firefox, when I close the lid, the call stays connected AFAICT with silence and a space-gray freeze-frame presumably of my laptop's trackpad. The other party sees audio and video resume once I reopen the lid (probably within some timeout window I imagine). It's a bit disconcerting it happens even on the login screen, so I've filed an issue on that in firefox and chrome.

In Chrome, when I close the lid, the peerconnection ended, even in 82 (I don't think it should end).

Update on Chrome's side:

  • The regression in M81 was reverted. This means that "laptop lid" will continue to cause close _for now_, and the onsignalingstatechange will continue to fire to reflect this.
  • In M82 I plan to make the event only fire if close happens asynchronously due to this lid thing, but to make it not fire when close() is explicitly called. When we know what to do spec-wise, we should stop closing the peer connection when the lid closed.
  • Chrome is not consistent: Laptop lid on Mac causes close, but laptop lid closing on Windows or Linux does not close the peer connection according to manual testing.

Related issue: When we suspend, there will be no audio or video. So it's logical to mute any audio and video tracks. But we still don't know whether Javascript is supposed to get control before suspend or not.

As Dom pointed out in the other thread, there is this WICG spec which looks relevant: https://wicg.github.io/page-lifecycle/

To me it seems that:
1) formalism: since this is a very new thing, let's not refer to it in webrtc-pc. Let's refer to it in webrtc-extensions.
2) the event we're looking for seems to be the "change the frozenness" event, triggered at https://wicg.github.io/page-lifecycle/#frozenness-state
4) in frozen state, we have to assume that no packets arrive or depart. I'm not sure it makes sense to send anything on the network to announce this transition.
5) there is no chance for JS to gain control between frozen and discarded state.
6) when returning to a discarded context, there will be a "discarded" boolean - but I don't think anything else from the previous context survives? We shouldn't specify anything here, I think.

What else?

That seems backwards to me, when that doc refers back to webrtc as a heuristic _not_ to freeze.

IMHO we can define the behaviors we want irrespective of exposure of some new JS API.

We seem to be mixing things. To recap observations in this thread:

  1. Closing a laptop lid is _not_ the same as freezing. It may _trigger_ it, but was observed not to.
  2. It's a physical act that (sans external display) seizes display, audio output, mic & cam capture.
  3. It should have no direct impact on a peer connection.

So what happens to the peer connection when the laptop lid closes? Nothing.

What happens to the peer connection when the page suspends? Please open a new issue.

Was this page helpful?
0 / 5 - 0 ratings