Problemas para detectar Internet Explorer 11 y cómo solucionarlos

Post original en JASoft.org: http://www.jasoft.org/Blog/post/Problemas-para-detectar-Internet-Explorer-11-y-como-solucionarlos.aspx

BrowserDetection 

Con la reciente Preview de la siguiente versión de Windows 8 (Windows 8.1) se ha incluido también un avance de la próxima versión del navegador de Microsoft, Internet Explorer 11.

Nota: Si quieres instalar Windows 8.1 puedes hacerlo desde aquí. Si no quieres instalarlo en una máquina real puedes usar Virtual Box para ello. He escrito un pequeño post (en inglés, lo siento) explicando cómo puedes conseguirlo aunque de entrada no esté soportado por VirtualBox).

Con IE11 Microsoft está cada vez más cerca de conseguir el nivel de compatibilidad con los estándares de la W3C (HTML5 y CSS3) que tienen otros navegadores de la competencia.

De hecho, parece que quieren parecerse tanto a los competidores que han hecho más difícil el poder identificar al navegador, por lo que mucho código viejo puede que llegue a confundirse.

Generalmente se utilizan dos técnicas para distinguir al navegador actual, dependiendo de si lo estamos haciendo en el lado servidor o en el lado cliente.

Detección en el lado servidor

En el lado servidor se utiliza la Cadena de Agente de Usuario (UAS), que es una cadena de texto que todos los navegadores envían al servidor con cada petición y que los identifica de manera única.

Por ejemplo, esta es la cadena de agente de usuario que envía Internet Explorer 10 en un sistema con Windows 7 de 64 bits:

5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MS-RTC LM 8)

Fíjate en lo fácil que es distinguir que el navegador es Internet Explorer: lo dice directamente con la palabra “MSIE” (Microsoft Internet Explorer) y además añade la versión a continuación. Podemos ver también que es Windows 7 porque nos dice que es “Windows NT 6.1” que es la versión real del sistema operativo. Finalmente, otra buena pista, es que incluye la palabra “Trident” seguida del número de versión. Trident es el motor de renderizado de IE, como ya he explicado en otras ocasiones en este blog.

Si utilizamos Internet Explorer 11 desde Windows 8.1, las cadenas de agente de usuario que devuelve ahora son estas:

5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko – Escritorio
5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko – Versión “Modern”

5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; .NET4.0E; .NET4.0C; Touch; rv:11.0) like Gecko – Escritorio en equipo táctil
5.0 (Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; Touch; rv:11.0) like Gecko – Versión “Modern” en equipo táctil

¿Por qué es importante esto?

Pues porque, hasta la fecha, todas las versiones de Internet Explorer incluían la palabra “MSIE” en su agente de usuario. Por ello, la mayor parte de las funciones de lado servidor para detectar a IE buscan dicha cadena, seguida del número de versión. Si tienes una de esas funciones en algunas de tus aplicaciones, ya puedes empezar a cambiarla. No hay más “MSIE” en la cadena de agente de usuario, así que hay que utilizar otro criterio.

Por ejemplo, un buen candidato sería localizar la cadena “Trident/” que sigue apareciendo y que indica que se usa el motor de renderizado de IE, lo cual debería ser suficiente. Podemos localizar la versión exacta del navegador bien a partir de la  versión de Trident (al final lo que nos importa es cómo se renderizan las páginas, y eso depende del motor de renderizado), o bien localizar la cadena “rv: dd.dd”)  para ver el número de versión del navegador.

Lo malo de esta manera de localizar el navegador, es que la cadena “Trident” sólo se incluye a partir de Internet Explorer 9. Así que no llega con eso si queremos localizar versiones más antiguas. Por lo tanto el sistema debe utilizar una doble detección: si contiene las cadenas “MSIE” o “Trident” entonces es Internet Explorer.

Por cierto, fíjate que puedes detectar si el navegador se está usando en un sistema de pantalla táctil buscando la cadena “Touch” (que he resaltado en rojo), lo cual puede ser útil para mostrar interfaces más apropiadas para manejar con el dedo.

Otro detalle importante es la inclusión de la frase “like Gecko” al final. Es sorprendente que la hayan puesto, ya que Gecko es el nombre del motor de render original de Netscape/Mozilla, es decir, es el motor de Firefox, y el primero en poner eso en su UAS fue Chrome para indicar que es compatible con Gecko.

Si observamos la cadena de agente de usuario de Firefox:

Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0

vemos que lleva el motor “Gecko” indicado, y de hecho se parece mucho a la nueva cadena de IE11.

La UAS de Chrome también lo lleva:

Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36

En realidad la de Chrome refleja una personalidad múltiple, porque incluye también Safari y KHTML (el motor de KDE en el que se basa Webkit). Es más, la versión 28 que se ve en este UAS en realidad ya utiliza el nuevo motor Blink, y no Webkit, pero no ha cambiado el UAS respecto a versiones anteriores (sólo el número de versión).

Parece que, para acabar de liar las cosas más, todos los navegadores hoy en día quieren tener personalidad múltiple, y cada vez complican más el detectarlos por su cadena de usuario. Si quieres conocer un poco la historia que hay detrás de la evolución de las cadenas de agente de usuario y porqué están tan liadas hoy en día, te recomiendo que leas este artículo que lo explica muy bien.

Detección en el lado cliente

Lo cierto es que raramente deberías realizar una detección de navegador y versión en el lado cliente. El motivo es que, dada la amplia variedad de características que contemplan los navegadores en la actualidad, la disparidad de soportes que hay para las mismas en cada uno, y la velocidad con la que se lanzan nuevas versiones, lo natural no es detectar un navegador y una versión sino realizar comprobaciones de características concretas.

De todos modos, una de las maneras más habituales de determinar si nos encontramos ante Internet Explorer es verificar si existe la colección document.all, algo así:

   1: if (document.all) {

   2:     //Es IE

   3: } else {

   4:     //No es IE

   5: }

Esta colección se introdujo hace muchos años en versiones viejas de IE (creo que en la versión 4, en el año ‘97, sino me equivoco) como una manera de acceder a cualquier elemento de la página mediante JavaScript. Eso fue antes de la existencia de los métodos estándar getElementById y similares. Desde entonces lo ha venido soportando por compatibilidad hacia atrás, y por lo tanto era una buena manera de ver si el navegador actual era Internet Explorer o no.

En IE11 han hecho un cambio en el soporte de esta característica: la siguen soportando y el código que use document.all funcionará, pero la comprobación en un condicional devolverá false, así que el if del código anterior no servirá y siempre devolverá false.. Es un primer paso para dejar de utilizar estas estructuras obsoletas 🙂

Conclusión

En el lado servidor deberás cambiar la lógica de detección de las cadenas de usuario para buscar la palabra “Trident” además de “MSIE”. De todos modos deberías tratar de evitarlo en la medida de lo posible y generar código HTML,CSS y JavaScript lo más estándar posible y usar detección de soporte de características en el lado cliente.

Y por eso, en el lado cliente, no detectes el navegador o su versión concreta (es mala idea) sino que deberás hacer detección individual de características concretas. Más allá de que IE11 haya cambiado algunas cosas como la detección de document.all, se trata de una buena práctica que en cualquier caso ya deberías estar siguiendo.

¡Espero que te sea útil!