* !!! This is an undocumented "private" service !!! * * @name $sniffer * @requires $window * @requires $document * @this * * @property {boolean} history Does the browser support html5 history api ? * @property {boolean} transitions Does the browser support CSS transition events ? * @propert
()
| 20462 | * This is very simple implementation of testing browser's features. |
| 20463 | */ |
| 20464 | function $SnifferProvider() { |
| 20465 | this.$get = ['$window', '$document', function($window, $document) { |
| 20466 | var eventSupport = {}, |
| 20467 | // Chrome Packaged Apps are not allowed to access `history.pushState`. |
| 20468 | // If not sandboxed, they can be detected by the presence of `chrome.app.runtime` |
| 20469 | // (see https://developer.chrome.com/apps/api_index). If sandboxed, they can be detected by |
| 20470 | // the presence of an extension runtime ID and the absence of other Chrome runtime APIs |
| 20471 | // (see https://developer.chrome.com/apps/manifest/sandbox). |
| 20472 | // (NW.js apps have access to Chrome APIs, but do support `history`.) |
| 20473 | isNw = $window.nw && $window.nw.process, |
| 20474 | isChromePackagedApp = |
| 20475 | !isNw && |
| 20476 | $window.chrome && |
| 20477 | ($window.chrome.app && $window.chrome.app.runtime || |
| 20478 | !$window.chrome.app && $window.chrome.runtime && $window.chrome.runtime.id), |
| 20479 | hasHistoryPushState = !isChromePackagedApp && $window.history && $window.history.pushState, |
| 20480 | android = |
| 20481 | toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), |
| 20482 | boxee = /Boxee/i.test(($window.navigator || {}).userAgent), |
| 20483 | document = $document[0] || {}, |
| 20484 | bodyStyle = document.body && document.body.style, |
| 20485 | transitions = false, |
| 20486 | animations = false; |
| 20487 | |
| 20488 | if (bodyStyle) { |
| 20489 | // Support: Android <5, Blackberry Browser 10, default Chrome in Android 4.4.x |
| 20490 | // Mentioned browsers need a -webkit- prefix for transitions & animations. |
| 20491 | transitions = !!('transition' in bodyStyle || 'webkitTransition' in bodyStyle); |
| 20492 | animations = !!('animation' in bodyStyle || 'webkitAnimation' in bodyStyle); |
| 20493 | } |
| 20494 | |
| 20495 | |
| 20496 | return { |
| 20497 | // Android has history.pushState, but it does not update location correctly |
| 20498 | // so let's not use the history API at all. |
| 20499 | // http://code.google.com/p/android/issues/detail?id=17471 |
| 20500 | // https://github.com/angular/angular.js/issues/904 |
| 20501 | |
| 20502 | // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has |
| 20503 | // so let's not use the history API also |
| 20504 | // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined |
| 20505 | history: !!(hasHistoryPushState && !(android < 4) && !boxee), |
| 20506 | hasEvent: function(event) { |
| 20507 | // Support: IE 9-11 only |
| 20508 | // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have |
| 20509 | // it. In particular the event is not fired when backspace or delete key are pressed or |
| 20510 | // when cut operation is performed. |
| 20511 | // IE10+ implements 'input' event but it erroneously fires under various situations, |
| 20512 | // e.g. when placeholder changes, or a form is focused. |
| 20513 | if (event === 'input' && msie) return false; |
| 20514 | |
| 20515 | if (isUndefined(eventSupport[event])) { |
| 20516 | var divElm = document.createElement('div'); |
| 20517 | eventSupport[event] = 'on' + event in divElm; |
| 20518 | } |
| 20519 | |
| 20520 | return eventSupport[event]; |
| 20521 | }, |
nothing calls this directly
no test coverage detected