Choose user agent for Firefox for iOS

VERIFIED FIXED

Status

()

Firefox for iOS
General
VERIFIED FIXED
3 years ago
3 years ago

People

(Reporter: bnicholson, Assigned: bnicholson)

Tracking

unspecified
All
iOS 8
Dependency tree / graph

Firefox Tracking Flags

(fennec+)

Details

Attachments

(1 attachment)

(Assignee)

Description

3 years ago
We can set a UA by throwing this line in AppDelegate:

NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent": userAgent])

The hard part: now we get to figure out what we want that user agent to be. For parity with Android, we should make this process as confusing and awkward as possible.
There's a parallel discussion (sort of) happening in Servo-land that may be useful to consider here: https://github.com/servo/servo/issues/4331. But an iOS browser will have different compat constraints than a new browser.

Chrome on iOS jams in a `CriOS/19.0.1084.60` token in the Safari UA string:

> Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3

If we assume Google did the compat research here we could do something similar with `FirefoxiOS/1.0`:

> Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) FirefoxiOS/1.0 Mobile/9B206 Safari/7534.48.3
It may be useful to run that kind of UA string through some device detection libs (cf. http://miketaylr.github.io/arewedetectableyet/) to see if the "Firefox" string is picked up as Gecko.

If that's the case, maybe using "FxiOS/1.0" would be better.

Comment 3

3 years ago
Let me know if it would be useful to replicate some of the work that was done for other UA decisions in the past, eg here https://bugzilla.mozilla.org/show_bug.cgi?id=588909#c46
The choice of UA depends on how different our browser is going to be from Safari. Given that we are using their rendering engine, I suspect it will behave pretty similarly - is that fair to say? 

In which case, I suspect that Chrome's approach is the right one, which is to use the Safari UA string almost as-is but add Yet Another Token which notes that it's Chrome, but without using the word "Chrome" to avoid confusion with actual real Chrome. If we add "Firefox" to the string, we'll probably get some bad detections because people will think we are real Gecko.

Can we determine the UA string Safari is using programmatically, so we can always match it (with our addition)? Or would we need to hard-code something and update it regularly?

NI lmandel for his thoughts.

Gerv
Flags: needinfo?(lmandel)
Summary: Set a custom user agent for the browser → Choose user agent for Firefox for iOS
(In reply to Gervase Markham [:gerv] from comment #4)
> The choice of UA depends on how different our browser is going to be from
> Safari. Given that we are using their rendering engine, I suspect it will
> behave pretty similarly - is that fair to say? 

Correct

> In which case, I suspect that Chrome's approach is the right one, which is
> to use the Safari UA string almost as-is but add Yet Another Token which
> notes that it's Chrome, but without using the word "Chrome" to avoid
> confusion with actual real Chrome. If we add "Firefox" to the string, we'll
> probably get some bad detections because people will think we are real Gecko.
> 
> Can we determine the UA string Safari is using programmatically, so we can
> always match it (with our addition)? Or would we need to hard-code something
> and update it regularly?

Brian can test to see if we can "get" the current UA before attempting to "set" a modified version. I agree with your line of thought:

1. Base it on Safari's UA
2. Add a unique token
3. Make sure the new token does not trigger "this is firefox" and suddenly break pages

NI Brian for the test
Flags: needinfo?(bnicholson)
There are a couple of use cases that I think we want to satisfy with the UA:
1. Get the right Web content
2. Ensure Firefox on iOS can be differentiated for usage stats

I think the Safari plus a unique token should satisfy these requests. I expect that the "firefox" token will result in Gecko/Moz specific content as "firefox" + "mobile" is used to differentiate content for Fennec.
Flags: needinfo?(lmandel)
This:

    WKWebView *webView = [WKWebView new];
    [self.view addSubview: webView];
    [webView evaluateJavaScript: @"navigator.userAgent" completionHandler:^(id obj, NSError *error) {
        NSLog(@"%@", obj);
    }];
    [webView removeFromSuperview];

Gives me:

    Mozilla/5.0 (iPad; CPU OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12B466

We can do this at app startup and see if it has changed because of iOS updates. And then configure a custom UA with whatever extra token we want in there.
Based on the webview UA from Comment 7, we'd need to add both our own unique token, in addition to Safari at the end.

I'll do some manual testing right now with "Mozilla/5.0 (iPad; CPU OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 dMobile/12B466 Safari/7534.48.3" with the device detection libs I have on hand and report back.
(without the obvious "dMobile" typo)
"Mobile" is not supposed to be a token unique to us. I think that most detection libs would detect the Safari UA as mobile without us needing to say "Mobile".

And where did "12B466" come from? :-)

Gerv
> "Mobile" is not supposed to be a token unique to us.

It's not. It's in the Safari UA string. It would be silly to remove it, IMO.

> And where did "12B466" come from? :-)

Dunno, ask Apple. :) I'm assuming it's a hex that represents... something. ¯\_(ツ)_/¯
Oh, sorry - I misread comment 8 as "both our own unique token_s_", assumed this Mobile thing was the other one, and got very confused!

Gerv
Here's my quick (manual) results:

I grabbed 6 existing JS device detection frameworks and 5 popular server modules/service, using 

"Mozilla/5.0 (iPhone; CPU OS 8_1_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/10A5355d Safari/8536.25"

detect.js -> mobile safari
detectizr -> mobile safari
device.js -> mobile iOS iphone
isMobile -> mobile apple phone
platform.js -> mobile safari
ua-parser -> mobile safari

http://detectmobilebrowsers.com -> mobile
Apache Mobile Filter -> is_mobile true, device_is_touch true
51Degrees -> Apple iPhone
Device Atlas -> Apple iPhone, mobile safari
WURFL -> Apple iPhone

Every single one classified it as mobile Safari, which is what we want. And then we have "FxiOS/$Version" for stat counters.
(Assignee)

Comment 14

3 years ago
Looks like my NI request was answered by comment 7 and comment 13.
Flags: needinfo?(bnicholson)
Lets move with this!
tracking-fennec: ? → +
(Assignee)

Comment 16

3 years ago
Created attachment 8587762 [details] [review]
Pull request

Testing Safari on the phone and on my Mac, I found that the Safari version is always the same as the WebKit version. Here's the UA from desktop Safari:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.4.10 (KHTML, like Gecko) Version/8.0.4 Safari/600.4.10

Since that's what Safari does, it seems reasonable for us to do the same -- especially since there's no way that I know of to query for the Safari app version.

Here's the UA with this commit applied:
Mozilla/5.0 (iPhone; CPU iPhone OS 10_10_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12D508 Safari/600.1.4
Assignee: nobody → bnicholson
Status: NEW → ASSIGNED
Attachment #8587762 - Flags: review?(sarentz)
One nit: would it be wise for it currently to say FxiOS/0.1 or similar, and switch to 1.0 when we actually ship?

Gerv
This looks good, I am just worried about taking the UA value from UIWebView instead of WKWebView. Specially since UIWebView uses WebKit1 while WKWebView uses WebKit2.
Attachment #8587762 - Flags: review?(sarentz) → review+
(Assignee)

Comment 19

3 years ago
(In reply to Gervase Markham [:gerv] from comment #17)
> One nit: would it be wise for it currently to say FxiOS/0.1 or similar, and
> switch to 1.0 when we actually ship?

This commit just pulls the appVersion, which is set to 1.0. Stefan, would it make sense to change this to something else while we're still in pre-release stages? It might be too late since we're already making builds.
Flags: needinfo?(sarentz)
I don't think it really matters much what version number we have in there now. You could add the build number, also in the info.plist, there. Like 1.0b6 .. would that help?

Not sure what problem we are trying to solve :-)
Flags: needinfo?(sarentz)
Merely not announcing something as a 1.0 before it's a 1.0.

Don't go adding b6 and all that stuff; there's no need to increase the fingerprintability above what's needed.

Gerv
(Assignee)

Comment 22

3 years ago
Merged.
Status: ASSIGNED → RESOLVED
Last Resolved: 3 years ago
Resolution: --- → FIXED
Mozilla/5.0 (iPhone; CPU iPhone OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12D508 Safari/600.1.4
Status: RESOLVED → VERIFIED
It is also possible to set the user agent per webView instead of globally.

webView.setValue("MyFancyUserAgent" forKeyPath: "customUserAgent")

This can also be called multiple times, so this could be used for Desktop Mode for example.

This is not entirely private, since it is well documented in WebKit, and it has landed months ago. But, we may want to be cautious and not try to use this for our first release.

See http://trac.webkit.org/changeset/176340
You need to log in before you can comment on or make changes to this bug.