Haz que la activación del usuario sea coherente en todas las APIs

Mustaq Ahmed
Joe Medley
Joe Medley

Para evitar que secuencias de comandos maliciosas abusen de APIs sensibles, como las ventanas emergentes, pantalla completa, etc., los navegadores controlan el acceso a esas APIs a través del activación. La activación del usuario es el estado de una sesión de navegación con respecto a a las acciones del usuario: un estado "activo" estado suele implicar que el usuario está está interactuando actualmente con la página o completó una interacción desde que la página de carga de trabajo. Gesto del usuario es un término popular pero engañoso para la misma idea. Para ejemplo, un gesto de deslizar o girar el dedo por parte de un usuario no activa una página y, por lo tanto, no es, desde el punto de vista de una secuencia de comandos, una activación del usuario.

En la actualidad, los principales navegadores muestran comportamientos muy divergentes con respecto a cómo la activación del usuario controla las APIs con acceso de activación. En Chrome, la implementación se basó en un modelo basado en tokens que resultó ser demasiado complejo para definir un de seguridad en todas las APIs con activación restringidas. Por ejemplo, Chrome ha sido lo que permite el acceso incompleto a APIs con acceso a la activación mediante postMessage() y llamadas de setTimeout(); y la activación del usuario no fue compatible con promesas, XHR, Interacción con el control de mando, etc. Ten en cuenta que algunas de estas son insectos populares pero de larga data.

En la versión 72, Chrome incluye Activación de usuarios v2, que hace Se completó la disponibilidad de activación para todas las APIs con acceso restringido. Esto resuelve las inconsistencias mencionadas anteriormente (y algunas más, como MessageChannels), que creemos que facilitaría el uso de desarrollo en torno a la activación del usuario. Además, la nueva implementación proporciona una implementación de referencia para una propuesta nueva especificación que busca unir a todos los navegadores a largo plazo.

¿Cómo funciona User Activation v2?

La nueva API mantiene un estado de activación del usuario de dos bits en cada objeto window. en la jerarquía de fotogramas: un bit persistente para el estado histórico de activación del usuario (si un haya visto una activación del usuario), y un bit transitorio para el estado actual (si un fotograma detectó una activación del usuario en aproximadamente un segundo). La parte pegajosa nunca se restablece durante la vida útil del fotograma después de configurarlo. El bit transitorio se configura en cada interacción del usuario y se restablece después del vencimiento intervalo (alrededor de un segundo) o mediante una llamada a una API que consuma mucha activación (p.ej., window.open()).

Ten en cuenta que las distintas APIs con acceso restringido se basan en la activación del usuario maneras; la nueva API no cambiará ninguno de estos comportamientos específicos de la API. P.ej., Solo se permite una ventana emergente por activación del usuario porque window.open() consume la activación del usuario como antes, Navigator.prototype.vibrate() continúa será eficaz si un fotograma (o cualquiera de sus submarcos) alguna vez sufrió acciones del usuario etcétera.

¿Cuáles son los cambios?

  • User Activation v2 formaliza la noción de visibilidad de la activación del usuario a lo largo de los límites de los fotogramas: una interacción del usuario con un fotograma en particular activar todos los fotogramas que los contienen (y solo aquellos), independientemente de su origen. (En Chrome 72, tenemos una solución temporal para expandir visibilidad a todos los marcos del mismo origen. Eliminaremos esta solución alternativa cuando tener una manera de pasar de forma explícita la activación del usuario a los submarcos).
  • Cuando se llama a una API con acceso restringido desde un marco activado, pero desde fuera del código del controlador de eventos, funcionará siempre y cuando la activación del usuario el estado es "activo" (p.ej., no venció ni se consumió). Antes del usuario Activación v2, fallaría incondicionalmente.
  • Se fusionan varias interacciones de usuarios sin usar dentro del intervalo de tiempo de vencimiento en una sola activación que corresponde a la última interacción.

Ejemplos de coherencia en APIs con acceso de activación

Aquí tienes dos ejemplos con ventanas emergentes (que se abren con window.open()) que mostrar cómo User Activation v2 hace que el comportamiento de las APIs restringidas por activación coherentes.

setTimeout() llamadas encadenadas

Este ejemplo proviene de nuestra demostración de setTimeout(). Si un controlador click intenta abrir una ventana emergente en un segundo, se espera que triunfar sin importar cómo se "componga" el código la demora. La v2 de activación de usuarios cumple esta expectativa, por lo que cada uno de los siguientes controladores de eventos abre una ventana emergente en un click (con un retraso de 100 ms):

function popupAfter100ms() {
  setTimeout(callWindowOpen, 100);
}

function asyncPopupAfter100ms() {
  setTimeout(popupAfter100ms, 0);
}

someButton.addEventListener('click', popupAfter100ms);
someButton.addEventListener('click', asyncPopupAfter100ms);

Sin User Activation v2, el segundo controlador de eventos falla en todos los navegadores y cómo se entrenó y probó el modelo. (Incluso falla el primero) en algunos casos).

Llamadas multidominio a postMessage()

Aquí hay un ejemplo de nuestra demostración de postMessage(). Supongamos que un controlador click en un submarco de origen cruzado envía dos mensajes directamente al marco superior. El marco superior debería poder abrir una ventana emergente al si recibe alguno de estos mensajes (pero no ambos):

// Parent frame code
window.addEventListener('message', e => {
  if (e.data === 'open_popup' && e.origin === child_origin)
    window.open('about:blank');
});

// Child frame code:
someButton.addEventListener('click', () => {
  parent.postMessage('hi_there', parent_origin);
  parent.postMessage('open_popup', parent_origin);
});

Sin User Activation v2, el marco superior no puede abrir una ventana emergente luego de recibir el segundo mensaje. Incluso el primer mensaje falla si está "encadenado" a otro. trama de origen cruzado (es decir, si el primer receptor reenvía el mensaje a otro).

Esto funciona con User Activation v2, tanto en el formato original como con el el encadenamiento.