Add API to get GeckoView's User-Agent string

RESOLVED FIXED in Firefox 64

Status

enhancement
P2
normal
RESOLVED FIXED
Last year
7 months ago

People

(Reporter: ekager, Assigned: agi)

Tracking

unspecified
mozilla64

Firefox Tracking Flags

(firefox-esr52 wontfix, firefox-esr60 wontfix, firefox61 wontfix, firefox62 wontfix, firefox63 wontfix, firefox64 fixed)

Details

(Whiteboard: [geckoview:klar:p2])

Attachments

(1 attachment)

Know we have discussed this but couldn't find past bug so wanted to make sure it was filed. We should be able to get (and maybe set) the user agent with GV.
Priority: -- → P2
I hope we would have the setter either. For example, Firefox Reality project wanna add a token, "FirefoxReality", at the end of the UA string.
Altering the `User-Agent` string has grave implications for user fingerprinting, and in the case of improper/unneeded UA sniffing, sites could start accidentally or intentionally block Firefox Reality. 

To achieve the desired outcome and evaluate the best strategy, what do we expect or need from altering the `User-Agent`?

GeckoView could be accidentally or maliciously blacklisted by sites could accidentally (by including some popular library) or maliciously (adding custom code to their web pages or servers) to blacklist.

Off the top of my head:

Pros:
- analytics can be filtered more easily (without requesting third-party services adjust accordingly)

Cons:
- increases surface area of user fingerprinting, decreasing anonymity (see W3C's "Fingerprinting Guidance" doc: https://www.w3.org/TR/fingerprinting-guidance/#bp-summary)
- increases likelihood of developer negligence in favour of proper feature detection (e.g., is a VR device available, what is the media type, is the user in fullscreen mode, is the web site being launched as a Progressive Web App, etc.)

Thanks to Mike Taylor (https://github.com/mozilla-mobile/firefox-tv/issues/257#issuecomment-353539764), I was referred to a bug with a lengthy discussion on this topic, during the Firefox OS TV days: bug 1199592 comment 18.

This topic ought to get the input of the GeckoView team, the various module owners in Firefox, and the WebCompat.com team.

I agree we want to support analytics, crash reports, and third-party aggregators. If there's a way we can do this safely, let's do it. I expect this to be a lengthy discussion. So thanks for everyone's patience in advance :)
Flags: needinfo?(miket)
I'm currently implementing support for Downloads in the Android Components repository and we would like to get the user agent used by GeckoView so that we can pass it to Android's Download Manager which will then use the same UA for downloading.
(In reply to Sebastian Kaspari (:sebastian) from comment #3)
> I'm currently implementing support for Downloads in the Android Components
> repository and we would like to get the user agent used by GeckoView so that
> we can pass it to Android's Download Manager which will then use the same UA
> for downloading.

For our specific use case we could also pass the UA to onExternalResource() (Assuming that the UA could be different for this specific resource, at least with WebExtensions at some point).
See Also: → 1476745
Note that this bug is only about *getting* GV's UA. Focus 7.0 would like to use GV's UA with the Android Download Manager for downloads initiated by Focus:

https://github.com/mozilla-mobile/focus-android/issues/2470

Adding an API to *change* GV's UA is bug 1476745, which we WONTFIX'd for now.
Flags: needinfo?(miket)
Summary: New method request to get the user agent → Add API to get GeckoView's User-Agent string
Whiteboard: [geckoview:klar:p2]
I am curious if we use GV's useragent as the download id in Android Download manager, but there are other apps also develop by GV. They should have the same UA string if bug 1476745 is wontfix. What will happen?
(In reply to Daosheng Mu[:daoshengmu] from comment #6)
> I am curious if we use GV's useragent as the download id in Android Download
> manager, but there are other apps also develop by GV. They should have the
> same UA string if bug 1476745 is wontfix. What will happen?

Sebastian, what is the effect of passing GV's UA to the Android Download Manager? Will using the same GV UA for unrelated GV-based apps (e.g. Focus and Fenix on the same device) cause problems or user confusion in the Android Download Manager?
Flags: needinfo?(s.kaspari)
> Sebastian, what is the effect of passing GV's UA to the Android Download Manager?

We are passing it to Android's Download Manager by using the addRequestHeader() API so that requests from the Download manager will have the same User-Agent header as the rest of the browser:

https://developer.android.com/reference/android/app/DownloadManager.Request.html#addRequestHeader(java.lang.String,%20java.lang.String)

I see two reasons why we would like to do that:

* Not letting Android Download Manger use whatever default it may pick (which potentially may be very "chatty")
* Being a good web citizen and having all "our" requests tagged with the same UA.  

> Will using the same GV UA for unrelated GV-based apps (e.g. Focus and Fenix on the same device) cause problems or user confusion in the Android Download Manager?

Download Manager should only use this for requests so it shouldn't cause any problems.
Flags: needinfo?(s.kaspari)
Thanks. I will leave this bug at priority P2 because we should fix it soon, but it doesn't sound like a Focus+GV release blocker.
I'm wondering if we want an API that provides the userAgent for a specific page load (I'm thinking about per-webpage userAgent overrides, if we have any now or in the future) or just a global API to get the default userAgent for GeckoView.

Any opinions?
(In reply to Agi [:agi] from comment #10)
> I'm wondering if we want an API that provides the userAgent for a specific
> page load (I'm thinking about per-webpage userAgent overrides, if we have
> any now or in the future) or just a global API to get the default userAgent
> for GeckoView.
> 
> Any opinions?

I think we might have some site-specific UA overrides (an internal Gecko system controlled via prefs), but the idea of somehow exposing that via GeckoSessionSettings seems kind of annoying.

IMHO, I think for apps it should be enough to get/set via GeckoSessionSettings. If they want site-specific overrides they can do that themselves by changing the UA in response to onLoadRequest(). We probably need to make sure that actually works, though.
> IMHO, I think for apps it should be enough to get/set via GeckoSessionSettings. If they want site-specific overrides they can do that themselves by changing the UA in response to onLoadRequest(). We probably need to make sure that actually works, though.

That makes sense to me, however Bug 1476745 was WONTFIX'd which makes me think we don't intend to implement the setter? Having a read-only Setting feels a little weird to me, but I can see how it would be helpful.

I also have a question: I was looking at how to get the UserAgent and it looks like this is the way we do it in most places:

    let userAgent = Cc["@mozilla.org/network/protocol;1?name=http"]
           .getService(Ci.nsIHttpProtocolHandler).userAgent;

but as far as I can see HttpProtocolHandler can only be accessed in C++ or Javascript, is that correct?

Right now I have it set up so that it sends a message `GeckoView:GetUserAgent` and when it returns it updates the settings value for USER_AGENT, so that it is `null` at initialization until the callback for `:GetUserAgent` returns. Is there a better / more canonical way of doing this?

The other question I have is whether we think there will be more of these read-only settings, in which case we probably want to add a read-only member in `GeckoSessionSettings.Key`?
(In reply to Agi [:agi] from comment #12)
> > IMHO, I think for apps it should be enough to get/set via GeckoSessionSettings. If they want site-specific overrides they can do that themselves by changing the UA in response to onLoadRequest(). We probably need to make sure that actually works, though.
> 
> That makes sense to me, however Bug 1476745 was WONTFIX'd which makes me
> think we don't intend to implement the setter? Having a read-only Setting
> feels a little weird to me, but I can see how it would be helpful.
> 
> I also have a question: I was looking at how to get the UserAgent and it
> looks like this is the way we do it in most places:
> 
>     let userAgent = Cc["@mozilla.org/network/protocol;1?name=http"]
>            .getService(Ci.nsIHttpProtocolHandler).userAgent;
> 
> but as far as I can see HttpProtocolHandler can only be accessed in C++ or
> Javascript, is that correct?

Right, that's the default UA. For GeckoView, we override it on a per-session basis with a HTTP request observer[0].

> 
> Right now I have it set up so that it sends a message
> `GeckoView:GetUserAgent` and when it returns it updates the settings value
> for USER_AGENT, so that it is `null` at initialization until the callback
> for `:GetUserAgent` returns. Is there a better / more canonical way of doing
> this?

Yeah, I guess this isn't really a very good match for the GeckoSessionSettings API. Right now all of those are settings we push down to Gecko, not things we fetch from Gecko. It seems like getCurrentUserAgent() directly on GeckoSession might be a better fit? You would want to return a GeckResult<String> from that as it will be an async operation.

> 
> The other question I have is whether we think there will be more of these
> read-only settings, in which case we probably want to add a read-only member
> in `GeckoSessionSettings.Key`?

Yeah, I just think a fully read-only thing is not a "setting", so I'd rather put it somewhere else.

[0] https://searchfox.org/mozilla-central/source/mobile/android/modules/geckoview/GeckoViewSettings.jsm#69
(In reply to James Willcox (:snorp) (jwillcox@mozilla.com) from comment #13)
> 
> Yeah, I guess this isn't really a very good match for the
> GeckoSessionSettings API. Right now all of those are settings we push down
> to Gecko, not things we fetch from Gecko. It seems like
> getCurrentUserAgent() directly on GeckoSession might be a better fit? You
> would want to return a GeckResult<String> from that as it will be an async
> operation.

Agreed! I'll do that then. And I guess I should assign this to myself now.
Assignee: nobody → agi
Status: NEW → ASSIGNED
This patch adds a new API to GeckoSession to get the currently used
UserAgent.
Android Try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=9b4b7330a0b9936cfc5df434f68e31a2626df323 (green modulo some intermittents)

I'll land this as soon as I get L3 (in progress).
Attachment #9015323 - Attachment description: Bug 1454444: Add GeckoSession.getUserAgent. r?snorp? → Bug 1454444: Add GeckoSession.getUserAgent. r?snorp,esawin
Pushed by asferro@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/ac0fc3f03029
Add GeckoSession.getUserAgent. r=snorp,esawin
https://hg.mozilla.org/mozilla-central/rev/ac0fc3f03029
Status: ASSIGNED → RESOLVED
Closed: 9 months ago
Resolution: --- → FIXED
Target Milestone: --- → Firefox 64
63=wontfix because we don't need to uplift this UA API for Focus 8.0.
Product: Firefox for Android → GeckoView
Target Milestone: Firefox 64 → mozilla64
You need to log in before you can comment on or make changes to this bug.