From c8e8a88211c58787fe8b23c2c39848dcc36e34ff Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Thu, 26 Apr 2012 13:11:45 +0000 Subject: [PATCH] Functions for reporting Android and iOS version (#8716) svn changeset:23642/svn branch:6.8 --- .../terminal/gwt/client/BrowserInfo.java | 15 +++ .../terminal/gwt/client/VBrowserDetails.java | 79 ++++++++++++++++ .../TestVBrowserDetailsUserAgentParser.java | 93 +++++++++++++++++-- 3 files changed, 181 insertions(+), 6 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java index a2e5bffe39..8ec610c089 100644 --- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java +++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java @@ -456,4 +456,19 @@ public class BrowserInfo { return false; } + /** + * Tests if this is an Android devices with a broken scrollTop + * implementation + * + * @return true if scrollTop cannot be trusted on this device, false + * otherwise + */ + public boolean isAndroidWithBrokenScrollTop() { + return isAndroid() + && (getOperatingSystemMajorVersion() == 3 || getOperatingSystemMajorVersion() == 4); + } + + private int getOperatingSystemMajorVersion() { + return browserDetails.getOperatingSystemMajorVersion(); + } } diff --git a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java index fa5fdc6d47..1212447a65 100644 --- a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java +++ b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java @@ -38,6 +38,9 @@ public class VBrowserDetails implements Serializable { private int browserMajorVersion = -1; private int browserMinorVersion = -1; + private int osMajorVersion = -1; + private int osMinorVersion = -1; + /** * Create an instance based on the given user agent. * @@ -121,6 +124,7 @@ public class VBrowserDetails implements Serializable { } else if (userAgent.contains("linux")) { if (userAgent.contains("android")) { os = OperatingSystem.ANDROID; + parseAndroidVersion(userAgent); } else { os = OperatingSystem.LINUX; @@ -131,12 +135,67 @@ public class VBrowserDetails implements Serializable { if (userAgent.contains("ipad") || userAgent.contains("ipod") || userAgent.contains("iphone")) { os = OperatingSystem.IOS; + parseIOSVersion(userAgent); } else { os = OperatingSystem.MACOSX; } } } + private void parseAndroidVersion(String userAgent) { + // Android 5.1; + if (!userAgent.contains("android")) { + return; + } + + String osVersionString = safeSubstring(userAgent, + userAgent.indexOf("android ") + "android ".length(), + userAgent.length()); + osVersionString = safeSubstring(osVersionString, 0, + osVersionString.indexOf(";")); + String[] parts = osVersionString.split("\\."); + parseOsVersion(parts); + } + + private void parseIOSVersion(String userAgent) { + // OS 5_1 like Mac OS X + if (!userAgent.contains("os ") || !userAgent.contains(" like mac")) { + return; + } + + String osVersionString = safeSubstring(userAgent, + userAgent.indexOf("os ") + 3, userAgent.indexOf(" like mac")); + String[] parts = osVersionString.split("_"); + parseOsVersion(parts); + } + + private void parseOsVersion(String[] parts) { + osMajorVersion = -1; + osMinorVersion = -1; + + if (parts.length >= 1) { + try { + osMajorVersion = Integer.parseInt(parts[0]); + } catch (Exception e) { + } + } + if (parts.length >= 2) { + try { + osMinorVersion = Integer.parseInt(parts[1]); + } catch (Exception e) { + } + // Some Androids report version numbers as "2.1-update1" + if (osMinorVersion == -1 && parts[1].contains("-")) { + try { + osMinorVersion = Integer.parseInt(parts[1].substring(0, + parts[1].indexOf('-'))); + } catch (Exception ee) { + } + } + } + + } + private void parseVersionString(String versionString) { int idx = versionString.indexOf('.'); if (idx < 0) { @@ -332,4 +391,24 @@ public class VBrowserDetails implements Serializable { return os == OperatingSystem.IOS; } + /** + * Returns the major version of the operating system. Currently only + * supported for mobile devices (iOS/Android) + * + * @return The major version or -1 if unknown + */ + public int getOperatingSystemMajorVersion() { + return osMajorVersion; + } + + /** + * Returns the minor version of the operating system. Currently only + * supported for mobile devices (iOS/Android) + * + * @return The minor version or -1 if unknown + */ + public int getOperatingSystemMinorVersion() { + return osMinorVersion; + } + } diff --git a/tests/client-side/com/vaadin/terminal/gwt/client/TestVBrowserDetailsUserAgentParser.java b/tests/client-side/com/vaadin/terminal/gwt/client/TestVBrowserDetailsUserAgentParser.java index 98159775bd..fedce98ecf 100644 --- a/tests/client-side/com/vaadin/terminal/gwt/client/TestVBrowserDetailsUserAgentParser.java +++ b/tests/client-side/com/vaadin/terminal/gwt/client/TestVBrowserDetailsUserAgentParser.java @@ -36,8 +36,14 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { private static final String SAFARI4_MAC = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; en-us) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7"; private static final String IPHONE_IOS_5_1 = "Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B179 Safari/7534.48.3"; + private static final String IPHONE_IOS_4_0 = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7"; private static final String IPAD_IOS_4_3_1 = "Mozilla/5.0 (iPad; U; CPU OS 4_3_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8G4 Safari/6533.18.5"; + private static final String ANDROID_HTC_2_1 = "Mozilla/5.0 (Linux; U; Android 2.1-update1; en-us; ADR6300 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17"; + private static final String ANDROID_GOOGLE_NEXUS_2_2 = "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"; + private static final String ANDROID_MOTOROLA_3_0 = "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13"; + private static final String ANDROID_GALAXY_NEXUS_4_0_4_CHROME = "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19"; + public void testSafari3() { VBrowserDetails bd = new VBrowserDetails(SAFARI3_WINDOWS); assertWebKit(bd); @@ -65,8 +71,17 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertBrowserMajorVersion(bd, 5); assertBrowserMinorVersion(bd, 1); assertEngineVersion(bd, 534f); - assertMacOSX(bd); - assertIOS(bd); + assertIOS(bd, 5, 1); + } + + public void testIPhoneIOS4() { + VBrowserDetails bd = new VBrowserDetails(IPHONE_IOS_4_0); + assertWebKit(bd); + assertSafari(bd); + assertBrowserMajorVersion(bd, 4); + assertBrowserMinorVersion(bd, 0); + assertEngineVersion(bd, 532f); + assertIOS(bd, 4, 0); } public void testIPadIOS4() { @@ -76,8 +91,57 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertBrowserMajorVersion(bd, 5); assertBrowserMinorVersion(bd, 0); assertEngineVersion(bd, 533f); - assertMacOSX(bd); - assertIOS(bd); + assertIOS(bd, 4, 3); + } + + public void testAndroid21() { + VBrowserDetails bd = new VBrowserDetails(ANDROID_HTC_2_1); + assertWebKit(bd); + assertSafari(bd); + assertBrowserMajorVersion(bd, 4); + assertBrowserMinorVersion(bd, 0); + assertEngineVersion(bd, 530f); + assertAndroid(bd, 2, 1); + + } + + public void testAndroid22() { + VBrowserDetails bd = new VBrowserDetails(ANDROID_GOOGLE_NEXUS_2_2); + assertWebKit(bd); + assertSafari(bd); + assertBrowserMajorVersion(bd, 4); + assertBrowserMinorVersion(bd, 0); + assertEngineVersion(bd, 533f); + assertAndroid(bd, 2, 2); + } + + public void testAndroid30() { + VBrowserDetails bd = new VBrowserDetails(ANDROID_MOTOROLA_3_0); + assertWebKit(bd); + assertSafari(bd); + assertBrowserMajorVersion(bd, 4); + assertBrowserMinorVersion(bd, 0); + assertEngineVersion(bd, 534f); + assertAndroid(bd, 3, 0); + } + + public void testAndroid40Chrome() { + VBrowserDetails bd = new VBrowserDetails( + ANDROID_GALAXY_NEXUS_4_0_4_CHROME); + assertWebKit(bd); + assertChrome(bd); + assertBrowserMajorVersion(bd, 18); + assertBrowserMinorVersion(bd, 0); + assertEngineVersion(bd, 535f); + assertAndroid(bd, 4, 0); + } + + private void assertOSMajorVersion(VBrowserDetails bd, int i) { + assertEquals(i, bd.getOperatingSystemMajorVersion()); + } + + private void assertOSMinorVersion(VBrowserDetails bd, int i) { + assertEquals(i, bd.getOperatingSystemMinorVersion()); } public void testChrome3() { @@ -378,12 +442,28 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertFalse(browserDetails.isAndroid()); } - private void assertIOS(VBrowserDetails browserDetails) { + private void assertAndroid(VBrowserDetails browserDetails, + int majorVersion, int minorVersion) { assertFalse(browserDetails.isLinux()); assertFalse(browserDetails.isWindows()); - assertTrue(browserDetails.isMacOSX()); + assertFalse(browserDetails.isMacOSX()); + assertFalse(browserDetails.isIOS()); + assertTrue(browserDetails.isAndroid()); + + assertOSMajorVersion(browserDetails, majorVersion); + assertOSMinorVersion(browserDetails, minorVersion); + } + + private void assertIOS(VBrowserDetails browserDetails, int majorVersion, + int minorVersion) { + assertFalse(browserDetails.isLinux()); + assertFalse(browserDetails.isWindows()); + assertFalse(browserDetails.isMacOSX()); assertTrue(browserDetails.isIOS()); assertFalse(browserDetails.isAndroid()); + + assertOSMajorVersion(browserDetails, majorVersion); + assertOSMinorVersion(browserDetails, minorVersion); } private void assertWindows(VBrowserDetails browserDetails) { @@ -399,6 +479,7 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertFalse(browserDetails.isWindows()); assertFalse(browserDetails.isMacOSX()); assertFalse(browserDetails.isIOS()); + assertFalse(browserDetails.isAndroid()); } } -- 2.39.5