Xojo2024R1: Browser and BrowserType equivalent needed

This should be easy to resolve for experts, unfortunately I can’t figure this out.
I need the equivalent of WebSession.Browser, WebSession.BrowserVersion and WebSession.BrowserType (these were used in Xojo2018).

Can anyone please help?

For several reasons, Web 2.0 no longer includes a feature to assume the browser. Developers can’t rely on the User-Agent these days. Safari for iOS straight up lies about what platform it is in an effort to protect user privacy. Most browsers also allow the user to input anything they want.

The User-Agent string should not be relied upon to be accurate and should not be used for important features.

That said, you can access this unreliable information with Session.Header(“User-Agent”)

1 Like

Tim,
Thank you. I tried ChatGPT but it wasn’t clear to me how to use “UserAgent”. I think I have for now what I need.

Use

var userAgent as String = Session.Header("User-Agent")

AlbertoD;
Thanks. If only this could be also made part of the online help then I am sure it would make life easier :wink:

Below is what I use to identify the browser, with the old technique commented out below:

Protected Function getBrowserInfoWAD(Type As String) As String
  Var UserAgent As String = Session.Header("User-Agent") 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML,like Gecko) Version/13.1.1 Safari/605.1.15
  
  Var VersionNumber As String
  
  Select Case Type
  Case "Cookie"
    Return Session.Header("Cookie")
    
  Case "Host"
    Return Session.Header("Host")
    
  Case "Accept"
    Return Session.Header("Accept")
    
  Case "Accept-Language"
    Return Session.Header("Accept-Language")
    
  Case "Accept-Encoding"
    Return Session.Header("Accept-Encoding")
    
  Case "Connection"
    Return Session.Header("Connection")
    
  Case "HTTPS"
    Return Session.Header("HTTPS")
    
  Case "SCRIPT_NAME"
    Return Session.Header("SCRIPT_NAME")
    
  Case "Browser"
    If UserAgent.IndexOf("Android") >= 0 Then
      Return "Android"
    ElseIf UserAgent.IndexOf("Blackberry") >= 0 Then
      Return "Blackberry"
    ElseIf UserAgent.IndexOf("Chrome") >= 0 Then
      Return "Chrome"
    ElseIf UserAgent.IndexOf("ChromeOS") >= 0 Then
      Return "ChromeOS"
    ElseIf UserAgent.IndexOf("Firefox") >= 0 Then
      Return "Firefox"
    ElseIf UserAgent.IndexOf("Internet Explorer") >= 0 Then
      Return "Internet Explorer"
    ElseIf UserAgent.IndexOf("Opera") >= 0 Then
      Return "Opera"
    ElseIf UserAgent.IndexOf("Opera Mini") >= 0 Then
      Return "Opera Mini"
    ElseIf UserAgent.IndexOf("Safari") >= 0 Then
      Return "Safari"
    ElseIf UserAgent.IndexOf("Safari Mobile") >= 0 Then
      Return "Safari Mobile"
    ElseIf UserAgent.IndexOf("Unknown") >= 0 Then
      Return "Unknown"
    Else
      Return "Unknown"
    End If
    
  Case "SmallScreen" 'check if on a small screen device device
    If UserAgent.IndexOf("Android") >= 0 Or UserAgent.IndexOf("Blackberry") >= 0 Or UserAgent.IndexOf("Opera Mini") >= 0 Or UserAgent.IndexOf("Safari Mobile") >= 0 Then
      Return "True"
    Else
      Return ""
    End If
    
    If UserAgent.IndexOf("Phone") >= 0 Or UserAgent.IndexOf("iPhone") >= 0 Or UserAgent.IndexOf("iPod") >= 0 Then 'iPod Touch
      Return "True"
    Else
      Return ""
    End If
    
  Case "Mobile" 'check if on a mobile device
    If UserAgent.IndexOf("Android") >= 0 Or UserAgent.IndexOf("Blackberry") >= 0 Or UserAgent.IndexOf("Opera Mini") >= 0 Or UserAgent.IndexOf("Mobile") >= 0 Then 'Safari Mobile
      Return "True"
    Else
      Return ""
    End If
    
    If UserAgent.IndexOf("Phone") >= 0 Or UserAgent.IndexOf("iPhone") >= 0 Or UserAgent.IndexOf("iPod") >= 0 Or UserAgent.IndexOf("iPad") >= 0 Or UserAgent.IndexOf("Tablet") >= 0 Then
      Return "True"
    Else
      Return ""
    End If
    
  Case "Platform"
    If UserAgent.IndexOf("Android") >= 0 And UserAgent.IndexOf("Phone") >= 0 Then
      Return "AndroidPhone"
    ElseIf UserAgent.IndexOf("Android") >= 0 And UserAgent.IndexOf("Tablet") >= 0 Then
      Return "AndroidTablet"
    ElseIf UserAgent.IndexOf("Blackberry") >= 0 Then
      Return "Blackberry"
    ElseIf UserAgent.IndexOf("iPad") >= 0 Then
      Return "iPad"
    ElseIf UserAgent.IndexOf("iPhone") >= 0 Then
      Return "iPhone"
    ElseIf UserAgent.IndexOf("iPod") >= 0 Then
      Return "iPodTouch"
    ElseIf UserAgent.IndexOf("Linux") >= 0 Then
      Return "Linux"
    ElseIf UserAgent.IndexOf("Macintosh") >= 0 Then
      Return "macOS"
    ElseIf UserAgent.IndexOf("PS3") >= 0 Then
      Return "PS3"
    ElseIf UserAgent.IndexOf("WebOS") >= 0 Then
      Return "WebOS"
    ElseIf UserAgent.IndexOf("Wii") >= 0 Then
      Return "Wii"
    ElseIf UserAgent.IndexOf("Windows") >= 0 Then
      Return "Windows"
    ElseIf UserAgent.IndexOf("Unknown") >= 0 Then
      Return "Unknown"
    Else
      Return "Unknown"
    End If
    
  Case "RenderingEngine"
    If UserAgent.IndexOf("Gecko") >= 0 Then
      Return "Gecko"
    ElseIf UserAgent.IndexOf("Presto") >= 0 Then
      Return "Presto"
    ElseIf UserAgent.IndexOf("Trident") >= 0 Then
      Return "Trident"
    ElseIf UserAgent.IndexOf("WebKit") >= 0 Then
      Return "WebKit"
    ElseIf UserAgent.IndexOf("Unknown") >= 0 Then
      Return "Unknown"
    Else
      Return "Unknown"
    End If
    
  Case "Version" 'Version/13.1.1 Safari/605.1.15
    VersionNumber = UserAgent.NthField("Version", 2) 'get from Version on
    VersionNumber = VersionNumber.NthField(" ", 1) 'remove excess after space
    VersionNumber = ReplaceAll(VersionNumber, "/", "").Trim 'remove any leading or trailing slashes and spaces
    
    Return VersionNumber
  End Select
  
  Return ""
  
  'Select Case Type
  'Case "Browser"
  'Select Case Session.Browser
  'Case WebSession.BrowserType.Android
  'Return "Android"
  'Case WebSession.BrowserType.Blackberry
  'Return "Blackberry"
  'Case WebSession.BrowserType.Chrome
  'Return "Chrome"
  'Case WebSession.BrowserType.ChromeOS
  'Return "ChromeOS"
  'Case WebSession.BrowserType.Firefox
  'Return "Firefox"
  'Case WebSession.BrowserType.InternetExplorer
  'Return "Internet Explorer"
  'Case WebSession.BrowserType.Opera
  'Return "Opera"
  'Case WebSession.BrowserType.OperaMini
  'Return "Opera Mini"
  'Case WebSession.BrowserType.Safari
  'Return "Safari"
  'Case WebSession.BrowserType.SafariMobile
  'Return "Safari Mobile"
  'Case WebSession.BrowserType.Unknown
  'Return "Unknown"
  'Case Else
  'Return "Unknown"
  'End Select
  '
  'Case "SmallScreen" 'check if on a small screen device device
  'Select Case Session.Browser
  'Case WebSession.BrowserType.Android, WebSession.BrowserType.Blackberry, WebSession.BrowserType.OperaMini, WebSession.BrowserType.SafariMobile
  'Return "True"
  'End Select
  'Select Case Session.Platform
  'Case WebSession.PlatformType.AndroidPhone, WebSession.PlatformType.Blackberry, WebSession.PlatformType.iPhone, WebSession.PlatformType.iPodTouch
  'Return "True"
  'Case Else
  'Return ""
  'End Select
  '
  'Case "Mobile" 'check if on a mobile device
  'Select Case Session.Browser
  'Case WebSession.BrowserType.Android, WebSession.BrowserType.Blackberry, WebSession.BrowserType.OperaMini, WebSession.BrowserType.SafariMobile
  'Return "True"
  'End Select
  'Select Case Session.Platform
  'Case WebSession.PlatformType.AndroidPhone, WebSession.PlatformType.AndroidTablet, WebSession.PlatformType.Blackberry, WebSession.PlatformType.iPad, WebSession.PlatformType.iPhone, WebSession.PlatformType.iPodTouch
  'Return "True"
  'Case Else
  'Return ""
  'End Select
  '
  'Case "Platform"
  'Select Case Session.Platform
  'Case WebSession.PlatformType.AndroidPhone
  'Return "AndroidPhone"
  'Case WebSession.PlatformType.AndroidTablet
  'Return "AndroidTablet"
  'Case WebSession.PlatformType.Blackberry
  'Return "Blackberry"
  'Case WebSession.PlatformType.iPad
  'Return "iPad"
  'Case WebSession.PlatformType.iPhone
  'Return "iPhone"
  'Case WebSession.PlatformType.iPodTouch
  'Return "iPodTouch"
  'Case WebSession.PlatformType.Linux
  'Return "Linux"
  'Case WebSession.PlatformType.Macintosh
  'Return "Macintosh"
  'Case WebSession.PlatformType.PS3
  'Return "PS3"
  'Case WebSession.PlatformType.Unknown
  'Return "Unknown"
  'Case WebSession.PlatformType.WebOS
  'Return "WebOS"
  'Case WebSession.PlatformType.Wii
  'Return "Wii"
  'Case WebSession.PlatformType.Windows
  'Return "Windows"
  'Case Else
  'Return "Unknown"
  'End Select
  '
  'Case "RenderingEngine"
  'Select Case Session.RenderingEngine
  'Case WebSession.EngineType.Gecko
  'Return "Gecko"
  'Case WebSession.EngineType.Presto
  'Return "Presto"
  'Case WebSession.EngineType.Trident
  'Return "Trident"
  'Case WebSession.EngineType.Unknown
  'Return "Unknown"
  'Case WebSession.EngineType.WebKit
  'Return "WebKit"
  'Case Else
  'Return "Unknown"
  'End Select
  '
  'Case "Version"
  'Return Session.BrowserVersion
  '
  'End Select
  
  'Return ""
    
End Function
4 Likes

Thanks for sharing David.
I might use that in the Xojo entry client.

There is one issue though, “Safari Mobile” will never be returned.

“Opera Mini” and “ChromeOS” either, no?

1 Like

Just out of curiosity… may I ask why you need this info?

1 Like

In my case, I use a very tight layout on mobile and tablet via custom webSDK controls (the layout is entirely in javascript too). Each control is adjacent to another on mobile, to save space. The problem is that, depending on the browser and platform, the same control can have a slightly different size, so I have a method that readjusts the control margins according to the environment, to avoid the controls overlapping.

I use GitHub - bowser-js/bowser: a browser detector

You are both correct, Safari Mobile must come before Safari, Opera Mini must come before Opera and ChromeOS must come before Chrome:

Case "Browser"
  If UserAgent.IndexOf("Android") >= 0 Then
    Return "Android"
  ElseIf UserAgent.IndexOf("Blackberry") >= 0 Then
    Return "Blackberry"
  ElseIf UserAgent.IndexOf("ChromeOS") >= 0 Then
    Return "ChromeOS"
  ElseIf UserAgent.IndexOf("Chrome") >= 0 Then
    Return "Chrome"
  ElseIf UserAgent.IndexOf("Firefox") >= 0 Then
    Return "Firefox"
  ElseIf UserAgent.IndexOf("Internet Explorer") >= 0 Then
    Return "Internet Explorer"
  ElseIf UserAgent.IndexOf("Opera Mini") >= 0 Then
    Return "Opera Mini"
  ElseIf UserAgent.IndexOf("Opera") >= 0 Then
    Return "Opera"
  ElseIf UserAgent.IndexOf("Safari Mobile") >= 0 Then
    Return "Safari Mobile"
  ElseIf UserAgent.IndexOf("Safari") >= 0 Then
    Return "Safari"
  ElseIf UserAgent.IndexOf("Unknown") >= 0 Then
    Return "Unknown"
  Else
    Return "Unknown"
  End If
1 Like

You might be better off by using Session.ClientWidth (WebSession — Xojo documentation)

Relying on the browser agent is not a great way of doing things… that might lead to more problems in the future.

3 Likes

But that’s precisely what this library does, but with many other parameters too, in order to detect the environment as accurately as possible. There are many experienced people who have been building and maintaining this library for a very long time, trying to combine many parameters (such as screen sizes, testing browser/os specific features and characteristics, etc., and above all by combining them) so as not to rely on declarative things. But perhaps it’s less reliable now.

David;
You are my hero today, thanks a lot for the code snippet. It don’t know what I will all the info use for but I will keep it aside in case need arrives. Thanks.

2 Likes

FWIW, when Web 2.0 was being designed, the common knowledge was to use feature detection instead of relying on user agents to figure out the capabilities of the browser running your app. When I left, the framework was using the current version of Modernizr to check the browser and transmitted some of that information to the app. My point is that

  1. Xojo could add more items to Session if you ask for it
  2. Xojo could expose the raw data
  3. You could write your own SDK control to access the data.

The whole point was that browsers shouldn’t be penalized by user agent detection based on some developer’s idea of what they thought a particular browser could do. By checking for the actual features that you need, as soon as a browser adds that, your feature just works. Otherwise you have a fallback technique or don’t show it at all.

2 Likes
  Case "Browser"
    If UserAgent.IndexOf("Android") >= 0 Then
      Return "Android"
    ElseIf UserAgent.IndexOf("Blackberry") >= 0 Then
      Return "Blackberry"
    ElseIf UserAgent.IndexOf("ChromeOS") >= 0 Then
      Return "ChromeOS"
    ElseIf UserAgent.IndexOf("Chrome") >= 0 Then
      Return "Chrome"
    ElseIf UserAgent.IndexOf("Firefox") >= 0 Then
      Return "Firefox"
    ElseIf UserAgent.IndexOf("Internet Explorer") >= 0 Then
      Return "Internet Explorer"
    ElseIf UserAgent.IndexOf("Opera Mini") >= 0 Then
      Return "Opera Mini"
    ElseIf UserAgent.IndexOf("Opera") >= 0 Then
      Return "Opera"
    ElseIf UserAgent.IndexOf("Safari Mobile") >= 0 Then
      Return "Safari Mobile"
    ElseIf UserAgent.IndexOf("Safari") >= 0 Then
      Return "Safari"
    Else
      Return "Unknown"
    End If