diff --git a/lib/classes/useragent.php b/lib/classes/useragent.php index fcc3c6d3601..5ed0c7311bd 100644 --- a/lib/classes/useragent.php +++ b/lib/classes/useragent.php @@ -481,6 +481,52 @@ class core_useragent { return false; } + /** + * Checks the user agent is Edge (of any version). + * + * @return bool true if Edge + */ + public static function is_edge() { + return self::check_edge_version(); + } + + /** + * Check the User Agent for the version of Edge. + * + * @param string|int $version A version to check for, returns true if its equal to or greater than that specified. + * @return bool + */ + public static function check_edge_version($version = null) { + $useragent = self::get_user_agent_string(); + + if ($useragent === false) { + // No User Agent found. + return false; + } + + if (strpos($useragent, 'Edge/') === false) { + // Edge was not found in the UA - this is not Edge. + return false; + } + + if (empty($version)) { + // No version to check. + return true; + } + + // Find the version. + // Edge versions are always in the format: + // Edge/. + preg_match('%Edge/([\d]+)\.(.*)$%', $useragent, $matches); + + // Just to be safe, round the version being tested. + // Edge only uses integer versions - the second component is the OS build number. + $version = round($version); + + // Check whether the version specified is >= the version found. + return version_compare($matches[1], $version, '>='); + } + /** * Checks the user agent is IE (of any version). * @@ -516,6 +562,7 @@ class core_useragent { } else { return false; } + $compatview = false; // IE8 and later versions may pretend to be IE7 for intranet sites, use Trident version instead, // the Trident should always describe the capabilities of IE in any emulation mode. @@ -696,7 +743,9 @@ class core_useragent { // No Apple mobile devices here - editor does not work, course ajax is not touch compatible, etc. return false; } - if (strpos($useragent, 'Chrome')) { // Reject chrome browsers - it needs to be tested explicitly. + if (strpos($useragent, 'Chrome')) { + // Reject chrome browsers - it needs to be tested explicitly. + // This will also reject Edge, which pretends to be both Chrome, and Safari. return false; } diff --git a/lib/tests/useragent_test.php b/lib/tests/useragent_test.php index f0dd54d5052..b81c59aee1f 100644 --- a/lib/tests/useragent_test.php +++ b/lib/tests/useragent_test.php @@ -42,6 +42,68 @@ class core_useragent_testcase extends basic_testcase { // Note: When adding new entries to this list, please ensure that any new browser versions are added to the corresponding list. // This ensures that regression tests are applied to all known user agents. return array( + 'Microsoft Edge for Windows 10 Desktop' => array( + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136', + array( + 'is_edge' => true, + 'check_edge_version' => array( + '12' => true, + ), + + // Edge pretends to be WebKit. + 'is_webkit' => true, + + // Edge pretends to be Chrome. + // Note: Because Edge pretends to be Chrome, it will not be picked up as a Safari browser. + 'is_chrome' => true, + 'check_chrome_version' => array( + '7' => true, + '8' => true, + '10' => true, + '39' => true, + ), + + 'versionclasses' => array( + 'safari', + ), + ), + ), + 'Microsoft Edge for Windows 10 Mobile' => array( + 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; DEVICE INFO) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Edge/12.10136', + array( + 'is_edge' => true, + 'check_edge_version' => array( + '12' => true, + ), + + // Edge pretends to be WebKit. + 'is_webkit' => true, + + // Mobile Edge pretends to be Android. + 'is_webkit_android' => true, + 'check_webkit_android_version' => array( + '525' => true, + '527' => true, + ), + + // Edge pretends to be Chrome. + // Note: Because Edge pretends to be Chrome, it will not be picked up as a Safari browser. + 'is_chrome' => true, + 'check_chrome_version' => array( + '7' => true, + '8' => true, + '10' => true, + '39' => true, + ), + + 'versionclasses' => array( + 'safari', + 'android', + ), + + 'devicetype' => 'mobile', + ), + ), // Windows 98; Internet Explorer 5.0. array( 'Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)', @@ -1338,6 +1400,37 @@ class core_useragent_testcase extends basic_testcase { $this->assertInstanceOf('core_useragent', core_useragent::instance(true)); } + /** + * @dataProvider user_agents_providers + */ + public function test_useragent_edge($useragent, $tests) { + // Setup the core_useragent instance. + core_useragent::instance(true, $useragent); + + // Edge Tests. + if (isset($tests['is_edge']) && $tests['is_edge']) { + $this->assertTrue(core_useragent::is_edge()); + } else { + $this->assertFalse(core_useragent::is_edge()); + } + + $versions = array( + // New versions of should be added here. + '12' => false, + ); + + if (isset($tests['check_edge_version'])) { + // The test provider has overwritten some of the above checks. + // Must use the '+' operator, because array_merge will incorrectly rewrite the array keys for integer-based indexes. + $versions = $tests['check_edge_version'] + $versions; + } + + foreach ($versions as $version => $result) { + $this->assertEquals($result, core_useragent::check_edge_version($version), + "Version incorrectly determined for Edge version '{$version}'"); + } + } + /** * @dataProvider user_agents_providers */