123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556 |
- /*
- * Copyright 2000-2014 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
- package com.vaadin.shared;
-
- import java.io.Serializable;
-
- /**
- * Class that parses the user agent string from the browser and provides
- * information about the browser. Used internally by
- * {@link com.vaadin.client.BrowserInfo} and
- * {@link com.vaadin.server.WebBrowser}. Should not be used directly.
- *
- * @author Vaadin Ltd.
- * @since 6.3
- */
- public class VBrowserDetails implements Serializable {
-
- private boolean isGecko = false;
- private boolean isWebKit = false;
- private boolean isPresto = false;
- private boolean isTrident = false;
-
- private boolean isChromeFrameCapable = false;
- private boolean isChromeFrame = false;
-
- private boolean isSafari = false;
- private boolean isChrome = false;
- private boolean isFirefox = false;
- private boolean isOpera = false;
- private boolean isIE = false;
- private boolean isPhantomJS = false;
-
- private boolean isWindowsPhone;
- private boolean isIPad;
- private boolean isIPhone;
-
- private OperatingSystem os = OperatingSystem.UNKNOWN;
-
- public enum OperatingSystem {
- UNKNOWN, WINDOWS, MACOSX, LINUX, IOS, ANDROID;
- }
-
- private float browserEngineVersion = -1;
- 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.
- *
- * @param userAgent
- * User agent as provided by the browser.
- */
- public VBrowserDetails(String userAgent) {
- userAgent = userAgent.toLowerCase();
-
- // browser engine name
- isGecko = userAgent.indexOf("gecko") != -1
- && userAgent.indexOf("webkit") == -1
- && userAgent.indexOf("trident/") == -1;
- isPresto = userAgent.indexOf(" presto/") != -1;
- isTrident = userAgent.indexOf("trident/") != -1;
- isWebKit = !isTrident && userAgent.indexOf("applewebkit") != -1;
-
- // browser name
- isChrome = userAgent.indexOf(" chrome/") != -1;
- isOpera = userAgent.indexOf("opera") != -1;
- isIE = userAgent.indexOf("msie") != -1 && !isOpera
- && (userAgent.indexOf("webtv") == -1);
- // IE 11 no longer contains MSIE in the user agent
- isIE = isIE || isTrident;
-
- isSafari = !isChrome && !isIE && userAgent.indexOf("safari") != -1;
- isFirefox = userAgent.indexOf(" firefox/") != -1;
- isPhantomJS = userAgent.indexOf("phantomjs/") != -1;
-
- // chromeframe
- isChromeFrameCapable = userAgent.indexOf("chromeframe") != -1;
- isChromeFrame = isChromeFrameCapable && !isChrome;
-
- // Rendering engine version
- try {
- if (isGecko) {
- int rvPos = userAgent.indexOf("rv:");
- if (rvPos >= 0) {
- String tmp = userAgent.substring(rvPos + 3);
- tmp = tmp.replaceFirst("(\\.[0-9]+).+", "$1");
- browserEngineVersion = Float.parseFloat(tmp);
- }
- } else if (isWebKit) {
- String tmp = userAgent
- .substring(userAgent.indexOf("webkit/") + 7);
- tmp = tmp.replaceFirst("([0-9]+)[^0-9].+", "$1");
- browserEngineVersion = Float.parseFloat(tmp);
- } else if (isIE) {
- int tridentPos = userAgent.indexOf("trident/");
- if (tridentPos >= 0) {
- String tmp = userAgent.substring(tridentPos
- + "Trident/".length());
- tmp = tmp.replaceFirst("([0-9]+\\.[0-9]+).*", "$1");
- browserEngineVersion = Float.parseFloat(tmp);
- }
- }
- } catch (Exception e) {
- // Browser engine version parsing failed
- System.err.println("Browser engine version parsing failed for: "
- + userAgent);
- }
-
- // Browser version
- try {
- if (isIE) {
- if (userAgent.indexOf("msie") == -1) {
- // IE 11+
- int rvPos = userAgent.indexOf("rv:");
- if (rvPos >= 0) {
- String tmp = userAgent.substring(rvPos + 3);
- tmp = tmp.replaceFirst("(\\.[0-9]+).+", "$1");
- parseVersionString(tmp);
- }
- } else {
- String ieVersionString = userAgent.substring(userAgent
- .indexOf("msie ") + 5);
- ieVersionString = safeSubstring(ieVersionString, 0,
- ieVersionString.indexOf(";"));
- parseVersionString(ieVersionString);
- }
- } else if (isFirefox) {
- int i = userAgent.indexOf(" firefox/") + 9;
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- } else if (isChrome) {
- int i = userAgent.indexOf(" chrome/") + 8;
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- } else if (isSafari) {
- int i = userAgent.indexOf(" version/") + 9;
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- } else if (isOpera) {
- int i = userAgent.indexOf(" version/");
- if (i != -1) {
- // Version present in Opera 10 and newer
- i += 9; // " version/".length
- } else {
- i = userAgent.indexOf("opera/") + 6;
- }
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- }
- } catch (Exception e) {
- // Browser version parsing failed
- System.err.println("Browser version parsing failed for: "
- + userAgent);
- }
-
- // Operating system
- if (userAgent.contains("windows ")) {
- os = OperatingSystem.WINDOWS;
- isWindowsPhone = userAgent.contains("windows phone");
- } else if (userAgent.contains("android")) {
- os = OperatingSystem.ANDROID;
- parseAndroidVersion(userAgent);
- } else if (userAgent.contains("linux")) {
- os = OperatingSystem.LINUX;
- } else if (userAgent.contains("macintosh")
- || userAgent.contains("mac osx")
- || userAgent.contains("mac os x")) {
- isIPad = userAgent.contains("ipad");
- isIPhone = userAgent.contains("iphone");
- if (isIPad || userAgent.contains("ipod") || isIPhone) {
- 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) {
- idx = versionString.length();
- }
- browserMajorVersion = Integer.parseInt(safeSubstring(versionString, 0,
- idx));
-
- int idx2 = versionString.indexOf('.', idx + 1);
- if (idx2 < 0) {
- idx2 = versionString.length();
- }
- try {
- browserMinorVersion = Integer.parseInt(safeSubstring(versionString,
- idx + 1, idx2).replaceAll("[^0-9].*", ""));
- } catch (NumberFormatException e) {
- // leave the minor version unmodified (-1 = unknown)
- }
- }
-
- private String safeSubstring(String string, int beginIndex, int endIndex) {
- if (beginIndex < 0) {
- beginIndex = 0;
- }
- if (endIndex < 0 || endIndex > string.length()) {
- endIndex = string.length();
- }
- return string.substring(beginIndex, endIndex);
- }
-
- /**
- * Tests if the browser is Firefox.
- *
- * @return true if it is Firefox, false otherwise
- */
- public boolean isFirefox() {
- return isFirefox;
- }
-
- /**
- * Tests if the browser is using the Gecko engine
- *
- * @return true if it is Gecko, false otherwise
- */
- public boolean isGecko() {
- return isGecko;
- }
-
- /**
- * Tests if the browser is using the WebKit engine
- *
- * @return true if it is WebKit, false otherwise
- */
- public boolean isWebKit() {
- return isWebKit;
- }
-
- /**
- * Tests if the browser is using the Presto engine
- *
- * @return true if it is Presto, false otherwise
- */
- public boolean isPresto() {
- return isPresto;
- }
-
- /**
- * Tests if the browser is using the Trident engine
- *
- * @since 7.1.7
- * @return true if it is Trident, false otherwise
- */
- public boolean isTrident() {
- return isTrident;
- }
-
- /**
- * Tests if the browser is Safari.
- *
- * @return true if it is Safari, false otherwise
- */
- public boolean isSafari() {
- return isSafari;
- }
-
- /**
- * Tests if the browser is Chrome.
- *
- * @return true if it is Chrome, false otherwise
- */
- public boolean isChrome() {
- return isChrome;
- }
-
- /**
- * Tests if the browser is capable of running ChromeFrame.
- *
- * @return true if it has ChromeFrame, false otherwise
- */
- public boolean isChromeFrameCapable() {
- return isChromeFrameCapable;
- }
-
- /**
- * Tests if the browser is running ChromeFrame.
- *
- * @return true if it is ChromeFrame, false otherwise
- */
- public boolean isChromeFrame() {
- return isChromeFrame;
- }
-
- /**
- * Tests if the browser is Opera.
- *
- * @return true if it is Opera, false otherwise
- */
- public boolean isOpera() {
- return isOpera;
- }
-
- /**
- * Tests if the browser is Internet Explorer.
- *
- * @return true if it is Internet Explorer, false otherwise
- */
- public boolean isIE() {
- return isIE;
- }
-
- /**
- * Tests if the browser is PhantomJS.
- *
- * @return true if it is PhantomJS, false otherwise
- */
- public boolean isPhantomJS() {
- return isPhantomJS;
- }
-
- /**
- * Returns the version of the browser engine. For WebKit this is an integer
- * e.g., 532.0. For gecko it is a float e.g., 1.8 or 1.9.
- *
- * @return The version of the browser engine
- */
- public float getBrowserEngineVersion() {
- return browserEngineVersion;
- }
-
- /**
- * Returns the browser major version e.g., 3 for Firefox 3.5, 4 for Chrome
- * 4, 8 for Internet Explorer 8.
- * <p>
- * Note that Internet Explorer 8 and newer will return the document mode so
- * IE8 rendering as IE7 will return 7.
- * </p>
- *
- * @return The major version of the browser.
- */
- public final int getBrowserMajorVersion() {
- return browserMajorVersion;
- }
-
- /**
- * Returns the browser minor version e.g., 5 for Firefox 3.5.
- *
- * @see #getBrowserMajorVersion()
- *
- * @return The minor version of the browser, or -1 if not known/parsed.
- */
- public final int getBrowserMinorVersion() {
- return browserMinorVersion;
- }
-
- /**
- * Sets the version for IE based on the documentMode. This is used to return
- * the correct the correct IE version when the version from the user agent
- * string and the value of the documentMode property do not match.
- *
- * @param documentMode
- * The current document mode
- */
- public void setIEMode(int documentMode) {
- browserMajorVersion = documentMode;
- browserMinorVersion = 0;
- }
-
- /**
- * Tests if the browser is run on Windows.
- *
- * @return true if run on Windows, false otherwise
- */
- public boolean isWindows() {
- return os == OperatingSystem.WINDOWS;
- }
-
- /**
- * Tests if the browser is run on Windows Phone.
- *
- * @return true if run on Windows Phone, false otherwise
- * @since 7.3.2
- */
- public boolean isWindowsPhone() {
- return isWindowsPhone;
- }
-
- /**
- * Tests if the browser is run on Mac OSX.
- *
- * @return true if run on Mac OSX, false otherwise
- */
- public boolean isMacOSX() {
- return os == OperatingSystem.MACOSX;
- }
-
- /**
- * Tests if the browser is run on Linux.
- *
- * @return true if run on Linux, false otherwise
- */
- public boolean isLinux() {
- return os == OperatingSystem.LINUX;
- }
-
- /**
- * Tests if the browser is run on Android.
- *
- * @return true if run on Android, false otherwise
- */
- public boolean isAndroid() {
- return os == OperatingSystem.ANDROID;
- }
-
- /**
- * Tests if the browser is run in iOS.
- *
- * @return true if run in iOS, false otherwise
- */
- public boolean isIOS() {
- return os == OperatingSystem.IOS;
- }
-
- /**
- * Tests if the browser is run on iPhone.
- *
- * @return true if run on iPhone, false otherwise
- * @since 7.3.3
- */
- public boolean isIPhone() {
- return isIPhone;
- }
-
- /**
- * Tests if the browser is run on iPad.
- *
- * @return true if run on iPad, false otherwise
- * @since 7.3.3
- */
- public boolean isIPad() {
- return isIPad;
- }
-
- /**
- * 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;
- }
-
- /**
- * Checks if the browser is so old that it simply won't work with a Vaadin
- * application. NOTE that the browser might still be capable of running
- * Crome Frame, so you might still want to check
- * {@link #isChromeFrameCapable()} if this returns true.
- *
- * @return true if the browser won't work, false if not the browser is
- * supported or might work
- */
- public boolean isTooOldToFunctionProperly() {
- // Check Trident version to detect compatibility mode
- if (isIE() && getBrowserMajorVersion() < 8
- && getBrowserEngineVersion() < 4) {
- return true;
- }
- // Webkit 533 in Safari 4.1+, Android 2.2+, iOS 4+
- if (isSafari() && getBrowserEngineVersion() < 533) {
- return true;
- }
- if (isFirefox() && getBrowserMajorVersion() < 4) {
- return true;
- }
- if (isOpera() && getBrowserMajorVersion() < 11) {
- return true;
- }
-
- return false;
- }
-
- }
|