Closed Bug 1564451 Opened 6 years ago Closed 5 years ago

Camera remains active when the app is in background or the phone is locked

Categories

(GeckoView :: General, defect, P1)

67 Branch
Unspecified
Android
defect

Tracking

(firefox-esr60 wontfix, firefox-esr68 wontfix, firefox68 wontfix, firefox69 wontfix, firefox70 wontfix, firefox82 fixed)

RESOLVED FIXED
82 Branch
Tracking Status
firefox-esr60 --- wontfix
firefox-esr68 --- wontfix
firefox68 --- wontfix
firefox69 --- wontfix
firefox70 --- wontfix
firefox82 --- fixed

People

(Reporter: trishul.goel, Assigned: agi)

References

(Regression)

Details

(Keywords: privacy, regression, reporter-external, Whiteboard: [geckoview:m82][fenix:p1])

Attachments

(1 file)

Steps to reproduce

  1. Open any video chat application on Firefox for android (say https://appear.in/trishul)
  2. Connect to same chat room from other device (say FF desktop)
  3. Ensure there is a proper video chat stream setup.
  4. Now put FF for android in background.
  5. You will find video still streaming.
  6. Now lock your mobile phone
  7. The video stream is still active 😲

Expected results:
The video stream(both camera and microphone) capture should stop immediately when phone is locked

Note: Chrome for Android behaves in expected way.

Flags: sec-bounty?

David: I suspect fixing this is more in the Android front-end than anything jya (triage owner) works on. Can you help find someone to own this and maybe a better component if necessary?

Flags: needinfo?(dbolter)

Jna-Ivar is this something which needs to get fixed in the camera platform code or in the Fennec/Fenix frontend code?

Flags: needinfo?(jib)

Is GV susceptible?

Flags: needinfo?(dbolter) → needinfo?(kbrosnan)

(In reply to Nils Ohlmeier [:drno] from comment #2)

Jan-Ivar is this something which needs to get fixed in the camera platform code or in the Fennec/Fenix frontend code?

It sounds like it. I would say that the existing behavior is intended to the extent that no-one has thought about it as a problem before. For instance, someone might specifically want this behavior to record a situation. That said, I agree it is not what most users would expect, and is therefore problematic, because users may accidentally record themselves when they think they are not. Doubly so when similar phone browsers work differently in this regard. This privacy concern seems to trump any use case for this feature, and I agree the Chrome behavior seems desirable here.

I'm not aware of any spec language around this, so I suggest we look at Chrome, whether it mutes the tracks or fires the ended event (Firefox turns off the camera/mic devices & any hardware lights in either case). We can then guide the android team to trigger this, either muting the tracks or revoking permission, respectively.

I've also pinged some DOM permission folks to see if this has come up before with other "powerful features" or features in Firefox where termination on phone lock is of consideration, or if this is a problem is unique to camera and microphone. If there's a precedent, we may want to follow that.

Flags: needinfo?(jib) → needinfo?(jhofmann)

(In reply to Trishul from comment #0)

Expected results:
The video stream(both camera and microphone) capture should stop immediately when phone is locked

Note: Chrome for Android behaves in expected way.

Before we move on this... Those results do not match what I see in Chrome (73 and 75) on my Samsung S8 (Android 9):

When I use Chrome for Android to connect w/appear.in to my desktop and then lock my phone, it's true the video freezes, but the audio keeps recording (I've muted the mic on desktop and I still hear audio being recorded by my phone's mic). I also keep hearing the call on my phone (when I unmute my desktop). When I unlock my phone, the video resumes. Importantly, the call is still going; I have to unlock my phone and leave the call or kill the Chrome app to terminate the call.

Do others experience different results?

It's not clear to me whether Chrome muting the video here is a bug or a feature. In either case, it makes me question what the desired behavior should be. Should we drop the call? Likely not. That might not be what users want either. Maybe mute both camera and microphone, but otherwise keep the call going? I think I vote for the latter. Some android apps like YouTube have switched to keep playing audio on phone lock, so that seems to be the direction.

It's not clear to me this qualifies as a sec bug.

For comparison I tried the video chat app "Zoom". When put into the background the video stops immediately but the audio continues. When the app is refocused the video picks up again. When I locked the phone, again the audio continues but the video recording stops. This very much follows the model of a phone call on the same device. Like a phone call there's a "Zoom meeting in progress" notification/icon at the top of the screen and on the lock screen.

Like Zoom and the phone there's a notification that Firefox is recording video at the top of the screen when unlocked, and on the lock screen. Unlike Zoom video keeps recording in addition to audio. There is notice, but it's subtle. There's also a good question about whether this is useful. Sometimes, maybe you're broadcasting, but the camerawork is likely crappy if you're filming without feedback. Given the behavior of other apps it may be more of a surprise and waste of bandwidth to people. It could be an option, but not the default? Our competitors may have done user studies about this and we can learn from their fairly consistent choices. In any case, consistent behavior amongst other apps makes ours being different even more of a surprise to users, and likely an unpleasant surprise since there's no compelling "win" (user benefit) from doing it this way.

The audio continuing makes sense. I often will put a phone or video meeting in the background while looking something up in another app, or listen on headphones while walking/driving with the phone locked. The fact that I also hear all the other participants is a clue I might also be recorded if I didn't mute myself. This behavior is consistent in different apps and is less likely to be an unpleasant surprise.

For testing, https://appr.tc/ doesn't require creating an account to try out webrtc on a browser.

Keywords: privacy
Summary: Camera/microphone remains active and still captures video when the FF is in background or the phone is locked → Camera/microphone remains active when FF is in background or the phone is locked

Killing the connection when the phone locked infuriated me with when we used the Vidyo app. If we do decide to change the behavior then we should have Firefox keep the screen awake when on a webRTC call. We have some code for that when dealing with fullscreen video.

I can reproduce this behavior in Reference Browser.

Flags: needinfo?(kbrosnan)

Agreed. Despite the reporter's expectation, other browsers and analogous apps keep the connection and audio going even when the phone is locked. I'm removing microphone from the bug summary. If Trishul really wants that they can argue in a separate bug (which will almost certainly be WONTFIXed).

The camera thing is worth discussing. Continuing to take video while the camera is locked is pointless (what are you filming if you don't know where the camera is pointing?), wastes bandwidth, and could be a surprise privacy violation. The only thing it seems useful for is as a secret remote camera (privacy violation as a feature). For most of our users turning off the camera is the right choice, and there are dedicated spy cameras (with better battery performance!) for the snoops.

Summary: Camera/microphone remains active when FF is in background or the phone is locked → Camera remains active when FF is in background or the phone is locked
Group: mobile-core-security

I don't expect we will change the behavior in Firefox for Android as it has started the ESR process. Should this be a GV bug or should the frontend app or AC own solving this?

Flags: needinfo?(cpeterson)

(In reply to Kevin Brosnan [:kbrosnan] from comment #9)

I don't expect we will change the behavior in Firefox for Android as it has started the ESR process. Should this be a GV bug or should the frontend app or AC own solving this?

Good question. We should probably fix this GV so every GV-powered app does the right thing. I'll send this bug to GV triage for now.

Component: Audio/Video → General
Flags: needinfo?(cpeterson)
OS: Unspecified → Android
Product: Firefox for Android → GeckoView
Version: Firefox 67 → 67 Branch

Andreas, GV notifies the app when (Gecko tells GV) the camera is activated. We need Product input on whether GV should pause or turn off camera recording (when the screen turns off, the phone is locked, or the app is backgrounded) or whether GV should just notify the app and the app is responsible for turning off the camera. This could be a security issue that every GV-powered app will need to solve correctly, but if GV turns off the camera itself, then apps that want uninterrupted camera recording would either be impossible to implement with GV or would need a new GV API to opt-out of turning the camera off.

Does GV hold the proper screen wakelock to keep the screen on and phone unlocked while the camera is active? That would avoid accidentally turning off the camera, bu wouldn't solve the scenario where the user manually turns off the screen or locks the phone.

Sorry for the delayed response, I think you folks are on a good track and I don't think this should have any implications on the permissions state of the website (which I guess it what I'm needinfo'd for). :) I'm also in favor of turning off the camera in some way while keeping audio recording working.

Flags: needinfo?(jhofmann)

(In reply to Daniel Veditz [:dveditz] from comment #8)

Agreed. Despite the reporter's expectation, other browsers and analogous apps keep the connection and audio going even when the phone is locked. I'm removing microphone from the bug summary. If Trishul really wants that they can argue in a separate bug (which will almost certainly be WONTFIXed).

The camera thing is worth discussing. Continuing to take video while the camera is locked is pointless (what are you filming if you don't know where the camera is pointing?), wastes bandwidth, and could be a surprise privacy violation. The only thing it seems useful for is as a secret remote camera (privacy violation as a feature). For most of our users turning off the camera is the right choice, and there are dedicated spy cameras (with better battery performance!) for the snoops.

I see keeping microphone active has still valid use-cases, and I assume its fine.
Turning camera off when locked is the thing I really want to push.

I also agree on the direction here. Luckily, Firefox already turns off its camera when a track is temporary disabled, so a temporary pause should suffice to also turn off any camera hardware (light).

There's some platform work here since the spec says to fire events in this case: "Muted is out of control for the application, but can be observed by the application by reading the muted attribute and listening to the associated events mute and unmute. There can be several reasons for a MediaStreamTrack to be muted: the user pushing a physical mute button on the microphone, the user toggling a control in the operating system, the user clicking a mute button in the browser chrome, the User Agent (on behalf of the user) mutes, etc."

I checked Chrome for Android, and it fires these events only for video, not audio, which supports Chrome's behavior being intentional (open this fiddle, share camera/mic, then turn your phone screen off and back on):

local video mute
local video unmute

Firefox for Android does not emit these events (Firefox Preview didn't work, NotAllowedError, wot?)

In fact, simply pushing the Chrome app to the background and returning to it, emits these events. which suggests Chrome pauses video even then. This perhaps suggests we may be able to do this solely in the platform, by listening for loss of focus on Android—or would that sometimes be wrong? Would the android folks rather have explicit methods for this?

Sorry for not thinking to look for these events earlier.

I see keeping microphone active has still valid use-cases, and I assume its fine. Turning camera off when locked is the thing I really want to push.

I agree with this direction.

then apps that want uninterrupted camera recording would either be impossible to implement with GV

I think that is OK. And in case it turns out there is a real use case for it, we can reconsider it as it occurs.

Flags: needinfo?(abovens)

Fenix shows a camera icon in the system notification bar, so the user is not totally unaware that the camera is on when the app is backgrounded or locked. The notification icon obviously doesn't help when the screen is off. :)

Priority: -- → P3
Summary: Camera remains active when FF is in background or the phone is locked → Camera remains active when the app is in background or the phone is locked

This is not a remote attack of the sort our bounty program is looking for. It sounds like a reasonable privacy improvement.

Flags: sec-bounty? → sec-bounty-

Removing priority so we can retriage.

Priority: P3 → --

This is an action that the app should take.

But! There currently is no GV API to allow the app to revoke camera permissions when the app goes into the background. This may need to be added. This probably also needs some UX assistance to figure out what the behaviour on the app side should be.

Flags: needinfo?(agi)
Priority: -- → P2

Note that muting is temporary, whereas revoking permission permanently ends those video tracks, leaving the page unable to resume without re-asking for permission when it comes back into foreground, which will be denied until the page is navigated/reloaded.

I think there are three things we should do here:

  1. Temporarily mute/unmute camera's video track(s) when app goes into/out of background, for parity with Chrome for Android. Test it here.
  2. When users click on the "📹 Firefox Nightly: Camera and microphone are on" notification, take them to the (first) offending tab (like Desktop does in response to clicks on our privacy indicators somewhere on the user's desktop),
  3. 2 + when users click on the "📹 Firefox Nightly: Camera and microphone are on" notification, pop up page info UX for the tab the user is taken to (e.g. like clicking 🔒 in url on Desktop) where they can quickly revoke that page's camera+mic permissions.

For #1 we need to expose a platform API to mute/unmute all camera tracks, since nothing does that yet AFAIK.
For #3 can we reuse the platform API Desktop uses to revoke permission (which uses this) from 🔒 in the url bar?

Much of 2 and 3 are Android components or app behavior.

  1. works as you described in Fenix
  2. is already built Settings -> Site Permissions -> Exceptions in Fenix
Rank: 1
Whiteboard: [geckoview:m81][fenix:p1]
  1. works as you described in Fenix

Doesn't work for me. I'm using Firefox Nightly 200713 06:47 (Build #21950658) Monday 7/13 @ 6:57 from Google Play store on a Samsung S8.

STRs:

  1. Open https://jan-ivar.github.io/dummy/gum_events.html and allow camera + mic
  2. In a new tab, open a random site e.g. https://stackoverflow.com/
  3. Go to a different app or the Android home screen.
  4. Drag down notification bar and click on "📹 Firefox Nightly: Camera and microphone are on"

Expected result:

Actual result:

Flags: needinfo?(kbrosnan)
  1. is already built Settings -> Site Permissions -> Exceptions in Fenix

That's different: it doesn't show temporary permissions of the current document, only permissions persisted to its origin.

In contrast, Desktop's pageinfo dropdown lists active permissions for the current page with an ✖ that not only revokes permission but terminates active capture.

This means Desktop users can: click on Firefox camera indicator on the desktop -> get taken to the offending tab with its pageinfo dropdown opened -> click on ✖ in "Use the camera ... Allowed Temporarily ✖" — to revoke permission in two clicks.

If Fenix had something similar, my suggestion in #3 was to have a similar workflow except s/indicator/notification/

I can confirm it is broken on the new tab navigation step. I had tested switching to an existing tab. Opened Fenix issue 12574 and added it to the team triage list.

I opened issue 12578 for displaying temporarily granted permissions.

Flags: needinfo?(kbrosnan)

jib: Could the rtc code in Gecko stop the video stream when the app is in background (listening to application-background)?

Flags: needinfo?(agi) → needinfo?(jib)

Stopping isn't desired behavior. We're adding mute in bug 1652884 for this, still ironing out lots of little sharp edges around it that are unrelated to how we'd detect when muting is desired. This should let fenix mute/unmute when it needs to (e.g. during application-background). Thank you for your patience.

Flags: needinfo?(jib)

Ah gotcha, so this is waiting on Bug 1652884, I completely missed the dependency. Thank you.

Moving to m82 as we're still waiting on the above bug.

Whiteboard: [geckoview:m81][fenix:p1] → [geckoview:m82][fenix:p1]

(In reply to Agi Sferro | :agi | ⏰ PST | he/him from comment #25)

jib: Could the rtc code in Gecko stop the video stream when the app is in background (listening to [application-background][1])?

Giving this a try in https://phabricator.services.mozilla.com/D87539. PTAL. If it works, maybe we can still get it in under the wire for 81.

Flags: needinfo?(agi)
Depends on: 1660049
Flags: needinfo?(agi)

I think the only problem with this is that we forgot to add the observer to application-{background,foreground} here: https://searchfox.org/mozilla-central/rev/eb9d5c97927aea75f0c8e38bbc5b5d288099e687/dom/media/MediaManager.cpp#2058 😅 patch incoming.

This is a refuse from Bug 1652884, the feature works as intended.

Assignee: nobody → agi
Status: NEW → ASSIGNED

So this was fixed in Bug 1652884, but then Bug 1658353 regressed it shortly thereafter (see the patch).

Regressed by: 1658353
Keywords: regression
Pushed by asferro@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/6496bb7f8a14 Add missing AddObserver calls for application-{background,foreground} r=pehrsons
Status: ASSIGNED → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → 82 Branch
Has Regression Range: --- → yes
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: