Jdlrobson has submitted this change and it was merged. Change subject: Device type rewrite ......................................................................
Device type rewrite * Use regexes only if necessary, in most cases strpos() is enough. * Since there's now no difference between 'capable' and 'html' (jQuery support is irrelevant), merge them into 'generic' * Order the checks approximately in the order of popularity per http://stats.wikimedia.org/wikimedia/squids/SquidReportClients.htm to reduce the average number of regexes run per request. * Simplify non-default iPhone browser handling. * Reduce the worst-case number of regexes. * Remove unused firefox.css, neither Fennec is supported nor it's a proper way to fix such problems. * Make 'ie' cover all IE Mobile versions. * Kill 'wap2', 'wii' and 'psp'. * Removed a couple of mobileness detection rules covered by MIDP. * Sort rules. Change-Id: I79401aee6ec91eeda19a2ff5f010c4406f568c9b --- M includes/DeviceDetection.php D stylesheets/devices/firefox.css M tests/DeviceDetectionTest.php 3 files changed, 123 insertions(+), 173 deletions(-) Approvals: Jdlrobson: Verified; Looks good to me, approved diff --git a/includes/DeviceDetection.php b/includes/DeviceDetection.php index 9a495fb..64b2c7c 100644 --- a/includes/DeviceDetection.php +++ b/includes/DeviceDetection.php @@ -108,53 +108,51 @@ $patterns = array( 'mobi', - 'phone', - 'android', - 'ipod', - 'webos', - 'palm', - 'opera.m', - 'semc-browser', - 'playstation', - 'nintendo', - 'blackberry', - 'bada', - 'meego', - 'vodafone', - 'docomo', - 'samsung', - 'alcatel', - 'motor', - 'huawei', - 'audiovox', - 'philips', - 'mot-', - 'cdm-', - 'sagem-', - 'htc[-_]', - 'ngm_', - 'mmp\/', - 'up.browser', - 'symbian', - 'midp', - 'kindle', - 'softbank', - 'sec-', '240x240', '240x320', '320x320', - 'ericsson', - 'panasonic', - 'hiptop', - 'portalmmm', - 'kddi-', + 'alcatel', + 'android', + 'audiovox', + 'bada', 'benq', + 'blackberry', + 'cdm-', 'compal-', - 'sanyo', - 'sharp', - 'teleca', + 'docomo', + 'ericsson', + 'hiptop', + 'htc[-_]', + 'huawei', + 'ipod', + 'kddi-', + 'kindle', + 'meego', + 'midp', 'mitsu', + 'mmp\/', + 'mot-', + 'motor', + 'ngm_', + 'nintendo', + 'opera.m', + 'palm', + 'panasonic', + 'philips', + 'phone', + 'playstation', + 'portalmmm', + 'sagem-', + 'samsung', + 'sanyo', + 'sec-', 'sendo', + 'sharp', + 'softbank', + 'symbian', + 'teleca', + 'up.browser', + 'webos', ); $patternsStart = array( 'lg-', @@ -204,6 +202,11 @@ class DeviceDetection implements IDeviceDetector { private static $formats = array ( + 'generic' => array ( + 'view_format' => 'html', + 'css_file_name' => '', + ), + 'android' => array ( 'view_format' => 'html', 'css_file_name' => '', @@ -211,18 +214,6 @@ 'blackberry' => array ( 'view_format' => 'html', 'css_file_name' => 'blackberry', - ), - 'blackberry-lt5' => array ( - 'view_format' => 'html', - 'css_file_name' => 'blackberry', - ), - 'capable' => array ( - 'view_format' => 'html', - 'css_file_name' => '', - ), - 'html' => array ( - 'view_format' => 'html', - 'css_file_name' => '', ), 'ie' => array ( 'view_format' => 'html', @@ -233,10 +224,6 @@ 'css_file_name' => 'iphone', ), 'kindle' => array ( - 'view_format' => 'html', - 'css_file_name' => 'kindle', - ), - 'kindle2' => array ( 'view_format' => 'html', 'css_file_name' => 'kindle', ), @@ -260,25 +247,9 @@ 'view_format' => 'html', 'css_file_name' => '', ), - 'ps3' => array ( - 'view_format' => 'html', - 'css_file_name' => 'simple', - ), - 'psp' => array ( - 'view_format' => 'html', - 'css_file_name' => 'psp', - ), - 'wap2' => array ( - 'view_format' => 'html', - 'css_file_name' => 'simple', - ), 'webkit' => array ( 'view_format' => 'html', 'css_file_name' => '', - ), - 'wii' => array ( - 'view_format' => 'html', - 'css_file_name' => 'wii', ), 'wml' => array ( 'view_format' => 'wml', @@ -317,14 +288,10 @@ * @return IDeviceProperties */ public function getDeviceProperties( $deviceName, $userAgent ) { - if ( isset( self::$formats[$deviceName] ) ) { - return new DeviceProperties( self::$formats[$deviceName], $userAgent ); - } else { - return new DeviceProperties( array( - 'view_format' => 'html', - 'css_file_name' => '', - ), $userAgent ); + if ( !isset( self::$formats[$deviceName] ) ) { + $deviceName = 'generic'; } + return new DeviceProperties( self::$formats[$deviceName], $userAgent ); } /** @@ -336,79 +303,53 @@ wfProfileIn( __METHOD__ ); $deviceName = ''; - if ( preg_match( '/Android/', $userAgent ) ) { - $deviceName = 'android'; - if ( strpos( $userAgent, 'Opera Mini' ) !== false ) { - $deviceName = 'operamini'; - } elseif ( strpos( $userAgent, 'Opera Mobi' ) !== false ) { - $deviceName = 'operamobile'; - } - } elseif ( preg_match( '/MSIE (8|9|1\d)\./', $userAgent ) ) { - $deviceName = 'ie'; - } elseif( preg_match( '/MSIE/', $userAgent ) ) { - $deviceName = 'html'; - } elseif ( strpos( $userAgent, 'Opera Mobi' ) !== false ) { - $deviceName = 'operamobile'; - } elseif ( preg_match( '/iPad.* Safari/', $userAgent ) ) { - $deviceName = 'iphone'; - } elseif ( preg_match( '/iPhone.* Safari/', $userAgent ) ) { - $deviceName = 'iphone'; - } elseif ( preg_match( '/iPhone/', $userAgent ) ) { - if ( strpos( $userAgent, 'Opera' ) !== false ) { - $deviceName = 'operamini'; - } else { - $deviceName = 'capable'; - } - } elseif ( preg_match( '/WebKit/', $userAgent ) ) { - if ( preg_match( '/Series60/', $userAgent ) ) { + + // These regexes come roughly in order of popularity per + // http://stats.wikimedia.org/wikimedia/squids/SquidReportClients.htm + // to reduce the average number of regexes per user-agent. + if ( strpos( $userAgent, 'Safari' ) !== false ) { + if ( strpos( $userAgent, 'iPhone' ) !== false + || strpos( $userAgent, 'iPad' ) !== false + ) { + $deviceName = 'iphone'; + } elseif ( strpos( $userAgent, 'Android' ) !== false ) { + $deviceName = 'android'; + } elseif ( strpos( $userAgent, 'Series60' ) !== false ) { $deviceName = 'nokia'; - } elseif ( preg_match( '/webOS/', $userAgent ) ) { + } elseif ( strpos( $userAgent, 'webOS' ) !== false ) { $deviceName = 'palm_pre'; } else { $deviceName = 'webkit'; } - } elseif ( preg_match( '/Opera/', $userAgent ) ) { - if ( strpos( $userAgent, 'Nintendo Wii' ) !== false ) { - $deviceName = 'wii'; - } elseif ( strpos( $userAgent, 'Opera Mini' ) !== false ) { + } elseif ( strpos( $userAgent, 'Opera/' ) !== false ) { + if ( strpos( $userAgent, 'Opera Mini' ) !== false ) { $deviceName = 'operamini'; - } else { + } elseif ( strpos( $userAgent, 'Opera Mobi' ) !== false ) { $deviceName = 'operamobile'; - } - } elseif ( preg_match( '/Kindle\/1.0/', $userAgent ) ) { - $deviceName = 'kindle'; - } elseif ( preg_match( '/Kindle\/2.0/', $userAgent ) ) { - $deviceName = 'kindle2'; - } elseif ( preg_match( '/Firefox|Maemo Browser|Fennec/', $userAgent ) ) { - $deviceName = 'capable'; - } elseif ( preg_match( '/NetFront/', $userAgent ) ) { - $deviceName = 'netfront'; - } elseif ( preg_match( '/SEMC-Browser/', $userAgent ) ) { - $deviceName = 'wap2'; - } elseif ( preg_match( '/Series60/', $userAgent ) ) { - $deviceName = 'wap2'; - } elseif ( preg_match( '/PlayStation Portable/', $userAgent ) ) { - $deviceName = 'psp'; - } elseif ( preg_match( '/PLAYSTATION 3/', $userAgent ) ) { - $deviceName = 'ps3'; - } elseif ( preg_match( '/SAMSUNG/', $userAgent ) ) { - $deviceName = 'capable'; - } elseif ( preg_match( '/BlackBerry/', $userAgent ) ) { - if( preg_match( '/BlackBerry[^\/]*\/[1-4]\./', $userAgent ) ) { - $deviceName = 'blackberry-lt5'; + } elseif ( strpos( $userAgent, 'Wii' ) !== false ) { + $deviceName = 'operamobile'; } else { - $deviceName = 'blackberry'; + $deviceName = 'generic'; // Desktop Opera } + } elseif ( strpos( $userAgent, 'BlackBerry' ) !== false ) { + $deviceName = 'blackberry'; + } elseif ( strpos( $userAgent, 'NetFront' ) !== false ) { + if ( strpos( $userAgent, 'Kindle' ) !== false ) { + $deviceName = 'kindle'; + } else { + $deviceName = 'netfront'; + } + } elseif ( strpos( $userAgent, 'MSIE' ) !== false ) { + $deviceName = 'ie'; } if ( $deviceName === '' ) { if ( strpos( $acceptHeader, 'application/vnd.wap.xhtml+xml' ) !== false ) { - // Should be wap2 - $deviceName = 'html'; + $deviceName = 'generic'; } elseif ( strpos( $acceptHeader, 'vnd.wap.wml' ) !== false ) { $deviceName = 'wml'; } else { - $deviceName = 'html'; + $deviceName = 'generic'; } } wfProfileOut( __METHOD__ ); diff --git a/stylesheets/devices/firefox.css b/stylesheets/devices/firefox.css deleted file mode 100644 index b8d5944..0000000 --- a/stylesheets/devices/firefox.css +++ /dev/null @@ -1,7 +0,0 @@ -/* avoid float issues in fennec caused by MediaWiki:Common.css definition */ -div.tright, -div.floatright, -table.floatright { - clear: none !important; - float: none !important; -} diff --git a/tests/DeviceDetectionTest.php b/tests/DeviceDetectionTest.php index 412df45..1869657 100644 --- a/tests/DeviceDetectionTest.php +++ b/tests/DeviceDetectionTest.php @@ -8,9 +8,9 @@ /** * @dataProvider provideTestFormatName */ - public function testFormatName( $format, $userAgent ) { + public function testFormatName( $format, $userAgent, $acceptHeader = '' ) { $detector = new DeviceDetection(); - $this->assertEquals( $format, $detector->detectDeviceName( $userAgent ) ); + $this->assertEquals( $format, $detector->detectDeviceName( $userAgent, $acceptHeader ) ); } public function provideTestFormatName() { @@ -19,7 +19,7 @@ return array_merge( $mobileDevices, array( array( 'ie', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' ), array( 'ie', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)' ), - array( 'capable', 'Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1' ), + array( 'generic', 'Mozilla/5.0 (X11; Linux i686; rv:2.0.1) Gecko/20100101 Firefox/4.0.1' ), ) ); } @@ -27,29 +27,46 @@ private function mobileDevices() { return array( // Firefox OS (bug 40919) - array( 'capable', 'Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0' ), + array( 'generic', 'Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0' ), + array( 'generic', 'Mozilla/5.0 (Android; Mobile; rv:20.0) Gecko/20.0 Firefox/20.0' ), // Blackberry 10 (bug 40513) array( 'webkit', 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.3+ (KHTML, like Gecko) Version/10.0.9.386 Mobile Safari/537.3+' ), + array( 'webkit', 'Mozilla/5.0 (BlackBerry; U; BlackBerry 9850; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.254 Mobile Safari/534.11+' ), // Windows Phone 8 / IE 10 (bug 41517) array( 'ie', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; ARM; Touch; IEMobile/10.0; <Manufacturer>; <Device> [;<Operator>])' ), // Others - array( 'android', 'Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17' ), - array( 'iphone', 'Mozilla/5.0 (ipod: U;CPU iPhone OS 2_2 like Mac OS X: es_es) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.0 Mobile/3B48b Safari/419.3' ), - array( 'iphone', 'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3B48b Safari/419.3' ), - array( 'nokia', 'Mozilla/5.0 (SymbianOS/9.1; U; [en]; SymbianOS/91 Series60/3.0) AppleWebKit/413 (KHTML, like Gecko) Safari/413' ), - array( 'palm_pre', 'Mozilla/5.0 (webOS/1.0; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/1.0' ), - array( 'wii', 'Opera/9.00 (Nintendo Wii; U; ; 1309-9; en)' ), - array( 'operamini', 'Opera/9.50 (J2ME/MIDP; Opera Mini/4.0.10031/298; U; en)' ), - array( 'operamobile', 'Opera/9.51 Beta (Microsoft Windows; PPC; Opera Mobi/1718; U; en)' ), - array( 'kindle', 'Mozilla/4.0 (compatible; Linux 2.6.10) NetFront/3.3 Kindle/1.0 (screen 600x800)' ), - array( 'kindle2', 'Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.0 (screen 824x1200; rotate)' ), - array( 'netfront', 'Mozilla/4.08 (Windows; Mobile Content Viewer/1.0) NetFront/3.2' ), - array( 'wap2', 'SonyEricssonK608i/R2L/SN356841000828910 Browser/SEMC-Browser/4.2 Profile/MIDP-2.0 Configuration/CLDC-1.1' ), - array( 'wap2', 'NokiaN73-2/3.0-630.0.2 Series60/3.0 Profile/MIDP-2.0 Configuration/CLDC-1.1' ), - array( 'psp', 'Mozilla/4.0 (PSP (PlayStation Portable); 2.00)' ), - array( 'ps3', 'Mozilla/5.0 (PLAYSTATION 3; 1.00)' ), - array( 'blackberry', 'BlackBerry9300/5.0.0.716 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/133' ), - array( 'blackberry-lt5', 'BlackBerry7250/4.0.0 Profile/MIDP-2.0 Configuration/CLDC-1.1' ), + array( 'android', 'Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17' ), + array( 'iphone', 'Mozilla/5.0 (ipod: U;CPU iPhone OS 2_2 like Mac OS X: es_es) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.0 Mobile/3B48b Safari/419.3' ), + array( 'iphone', 'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3B48b Safari/419.3' ), + array( 'nokia', 'Mozilla/5.0 (SymbianOS/9.1; U; [en]; SymbianOS/91 Series60/3.0) AppleWebKit/413 (KHTML, like Gecko) Safari/413' ), + array( 'palm_pre', 'Mozilla/5.0 (webOS/1.0; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/1.0' ), + // Opera + array( 'operamobile', 'Opera/9.00 (Nintendo Wii; U; ; 1309-9; en)' ), + array( 'operamini', 'Opera/9.50 (J2ME/MIDP; Opera Mini/4.0.10031/298; U; en)' ), + array( 'operamini', 'Opera/9.80 (iPhone; Opera Mini/7.0.4/28.2555; U; fr) Presto/2.8.119 Version/11.10' ), + array( 'operamobile', 'Opera/9.51 Beta (Microsoft Windows; PPC; Opera Mobi/1718; U; en)' ), + array( 'operamobile', 'Opera/9.80 (Android 4.1.1; Linux; Opera Mobi/ADR-1301080958) Presto/2.11.355 Version/12.10' ), + array( 'kindle', 'Mozilla/4.0 (compatible; Linux 2.6.10) NetFront/3.3 Kindle/1.0 (screen 600x800)' ), + array( 'kindle', 'Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.0 (screen 824x1200; rotate)' ), + // Later Kindles use WebKit + array( 'webkit', 'Mozilla/5.0 (Linux; U; en-US) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) Version/4.0 Kindle/3.0 (screen 600X800; rotate)' ), + array( 'netfront', 'Mozilla/4.08 (Windows; Mobile Content Viewer/1.0) NetFront/3.2' ), + array( 'generic', 'SonyEricssonK608i/R2L/SN356841000828910 Browser/SEMC-Browser/4.2 Profile/MIDP-2.0 Configuration/CLDC-1.1' ), + array( 'generic', 'NokiaN73-2/3.0-630.0.2 Series60/3.0 Profile/MIDP-2.0 Configuration/CLDC-1.1' ), + array( 'generic', 'Mozilla/4.0 (PSP (PlayStation Portable); 2.00)' ), + array( 'generic', 'Mozilla/5.0 (PLAYSTATION 3; 1.00)' ), + // Blackberry + array( 'blackberry', 'BlackBerry9300/5.0.0.716 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/133' ), + array( 'blackberry', 'BlackBerry7250/4.0.0 Profile/MIDP-2.0 Configuration/CLDC-1.1' ), + // https://bugzilla.wikimedia.org/show_bug.cgi?id=30827 + array( 'generic', 'SAMSUNG-S8000/S800MXEJA1 SHP/VPP/R5 Jasmine/1.0 Nextreaming SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1 SS-Widget/S8000-FM', + 'text/html, application/xml, image/vnd.wap.wbmp, image/png, image/jpeg, image/gif, image/bmp, application/vnd.wap.xhtml+xml, application/xhtml+xml, application/vnd.wap.multipart.mixed, multipart/mixed, text/vnd.wap.wml, application/vnd.wap.wmlc, application/vnd.oma.dd+xml, text/vnd.sun.j2me.app-descriptor, application/java-archive, */*' + ), + // @todo: + // Chrome browser + //array( 'webkit', 'Mozilla/5.0 (Linux; Android 4.1.1; Galaxy Nexus Build/JRO03C) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19' ), + //array( 'operamobile', 'Opera/9.80 (Android 2.3.7; Linux; Opera Tablet/35779; U; en) Presto/2.10.254 Version/12.00' ), + //array( 'generic', 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.7; en-US; rv:1.9.2.1pre) Gecko/20100126 Namoroka/3.6.1pre Fennec/1.0pre)' ), ); } @@ -67,19 +84,12 @@ array( 'webkit', '' ), array( 'android', '' ), array( 'palm_pre', '' ), - array( 'html', '' ), - array( 'capable', '' ), + array( 'generic', '' ), array( 'ie', 'mobile.device.ie' ), array( 'iphone', 'mobile.device.iphone' ), array( 'kindle', 'mobile.device.kindle' ), - array( 'kindle2', 'mobile.device.kindle' ), array( 'blackberry', 'mobile.device.blackberry' ), - array( 'blackberry-lt5', 'mobile.device.blackberry' ), array( 'netfront', 'mobile.device.simple' ), - array( 'wap2', 'mobile.device.simple' ), - array( 'psp', 'mobile.device.psp' ), - array( 'ps3', 'mobile.device.simple' ), - array( 'wii', 'mobile.device.wii' ), array( 'operamini', 'mobile.device.operamini' ), array( 'operamobile', 'mobile.device.operamobile' ), array( 'nokia', 'mobile.device.nokia' ), @@ -99,9 +109,15 @@ public function provideTestIsMobileDevice() { // Borrow mobile user agent strings from another test... $input = $this->mobileDevices(); - // ...and add some desktop ones return array_merge( $input, array( + // add more obscure mobile devices + array( true, 'Vodafone/1.0/LG-KU990/V10iBrowser/Obigo-Q05A/3.6 MMS/LG-MMS-V1.0/1.2 Java/ASVM/1.0 Profile/MIDP-2.0Configuration/CLDC-1.1' ), + array( true, 'Vodafone/1.0/0Vodafone543/ V010 05/MIDP-2.0 Configuration/CLDC-1.1 ObigoInternetBrowser/Q03C' ), + array( true, 'DoCoMo/2.0 P07A3(c500;TB;W24H15)' ), + array( true, 'KDDI-HI31 UP.Browser/6.2.0.5 (GUI) MMP/2.0' ), + array( true, 'Mozilla/4.0 (compatible; MSIE 6.0; KDDI-SA39) Opera 8.60 [ja]' ), + // ...and some desktop browsers array( false, 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.7) Gecko/20060928 (Debian|Debian-1.8.0.7-1) Epiphany/2.14' ), array( false, 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)' ), array( false, 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' ), -- To view, visit https://gerrit.wikimedia.org/r/61942 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I79401aee6ec91eeda19a2ff5f010c4406f568c9b Gerrit-PatchSet: 12 Gerrit-Project: mediawiki/extensions/MobileFrontend Gerrit-Branch: master Gerrit-Owner: MaxSem <[email protected]> Gerrit-Reviewer: Jdlrobson <[email protected]> Gerrit-Reviewer: MaxSem <[email protected]> Gerrit-Reviewer: awjrichards <[email protected]> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
