Spójność aktywacji użytkowników we wszystkich interfejsach API

Mustaq Ahmed
Joe Medley
Joe Medley

Aby złośliwe skrypty nie nadużywały wrażliwych interfejsów API, takich jak wyskakujące okienka, pełnego ekranu itp., przeglądarki kontrolują dostęp do tych interfejsów API za pomocą aktywacji. Aktywacja użytkownika to stan sesji przeglądania w odniesieniu do do działań użytkownika: „aktywne” zwykle oznacza, że użytkownik jest użytkownik obecnie wchodzi w interakcję ze stroną lub zakończył interakcję ze stroną od strony. Gest użytkownika to popularne, ale mylące pojęcie dotyczące tego samego pomysłu. Dla: na przykład przesunięcie lub gest przesunięcia przez użytkownika nie aktywuje strony, nie jest, z punktu widzenia skryptu, aktywacji użytkownika.

Główne przeglądarki wykazują obecnie bardzo rozbieżne w obsłudze sposób aktywacji użytkowników steruje interfejsami API z aktywacją. Implementacja w Chrome opierała się w modelu opartym na tokenach, który okazał się zbyt złożony, aby można było zdefiniować zachowanie we wszystkich interfejsach API z blokadą aktywacyjną. Na przykład Chrome niepełny dostęp do interfejsów API objętych aktywacją postMessage() i Połączenia (setTimeout()); a aktywacja użytkownika nie wspierany przez Promises, XHR, Interakcja na gamepad itp. Pamiętaj, że niektóre z tych są popularnymi, ale jednak występującymi od dawna robakami.

W wersji 72 Chrome wysyła wersję 2 aktywacji użytkownika, dostępność aktywacji wszystkich interfejsów API objętych aktywacją. To rozwiązuje wymienionych powyżej niespójności (i kilku innych, np. MessageChannels), które naszym zdaniem ułatwia korzystanie z internetu. nad aktywacją użytkowników. Ponadto nowa implementacja zapewnia referencyjną implementacji proponowanej nowa specyfikacja który ma na dłuższą metę połączyć wszystkie przeglądarki.

Jak działa Aktywacja użytkowników w wersji 2?

Nowy interfejs API zachowuje 2-bitowy stan aktywacji użytkownika w każdym obiekcie window w hierarchii ramek: przyklejony bit do historycznych stanów aktywacji użytkownika (jeśli w której kiedykolwiek odnotowano aktywację użytkownika) oraz bit tymczasowy dla bieżącego stanu. (jeśli klatka zawiera aktywację użytkownika w ciągu mniej więcej sekundy). Przyklejony element nie jest resetowane przez cały okres istnienia klatki po jej ustawieniu. Bit przejściowa jest ustawiany po każdej interakcji użytkownika i resetowany po wygaśnięciu (około sekundę) lub przez wywołanie interfejsu API, który wymaga aktywacji (np. window.open()).

Pamiętaj, że różne interfejsy API z blokadą aktywacji zależą od aktywacji użytkownika w różnych sposoby; nie zmienia działania charakterystycznego dla tego interfejsu. Na przykład: dozwolone jest tylko jedno wyskakujące okienko na aktywację użytkownika, ponieważ window.open() skorzystał aktywacji użytkowników w dotychczasowy sposób, Navigator.prototype.vibrate() być skuteczne, jeśli klatka (lub którakolwiek z jej ramek podrzędnych) kiedykolwiek była i tak dalej.

Co się zmienia?

  • Aktywacja użytkowników w wersji 2 formalnie nadaje pojęcie widoczności aktywacji użytkowników między granicami klatek: interakcja użytkownika z daną klatką aktywują wszystkie zawierające klatki (i tylko te), niezależnie od ich pochodzeniu danych. (W Chrome 72 oferujemy tymczasowe obejście polegające na rozwinięciu do wszystkich ramek z tej samej domeny. Usuniemy to obejście, gdy mają sposób wyraźnie przekazać aktywację użytkownika do ramek podrzędnych).
  • Gdy interfejs API objęty aktywacją jest wywoływany z aktywowanej ramki, ale z poza kodem modułu obsługi zdarzeń, będzie działać, dopóki nie zostanie aktywowana stan to „Aktywny” (np. nie stracił ważności i nie został wykorzystany). Przed użytkownikiem Aktywacja w wersji 2; bezwarunkowo nie powiodła się.
  • Wiele nieużywanych interakcji użytkownika w ramach przedziału czasowego ważności w jedną aktywację odpowiadającą ostatniej interakcji.

Przykłady spójności w interfejsach API objętych aktywacją

Oto 2 przykłady z wyskakującymi okienkami (otwieranymi za pomocą polecenia window.open()), które pokaż, jak funkcja User Activation w wersji 2 wpływa na działanie interfejsów API objętych aktywacją spójne.

Łańcuch setTimeout() połączeń

Ten przykład pochodzi z: nasza prezentacja (setTimeout()). Jeśli moduł obsługi click spróbuje otworzyć wyskakujące okienko w ciągu sekundy, niezależnie od tego, jak kod „kompozytuje” opóźnienia. Spełnia wymagania Aktywacja użytkownika w wersji 2 więc każdy z poniższych modułów obsługi zdarzeń otwiera wyskakujące okienko click (z opóźnieniem 100 ms):

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

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

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

Bez aktywacji użytkownika w wersji 2 drugi moduł obsługi zdarzeń kończy się niepowodzeniem we wszystkich przeglądarkach, i testowania modelu. (Nie udało się wysłać pierwszej odpowiedzi w niektórych przypadkach).

postMessage() – połączenia między domenami

Oto przykład z: nasza prezentacja (postMessage()). Załóżmy, że moduł obsługi click w ramce podrzędnej z innej domeny wysyła 2 wiadomości bezpośrednio do ramki nadrzędnej. Ramka nadrzędna powinna mieć możliwość otwarcia wyskakującego okienka odbieranie jednej z tych wiadomości (ale nie obu):

// 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);
});

Bez aktywacji użytkownika w wersji 2 ramka nadrzędna nie może otworzyć wyskakującego okienka po otrzymaniu drugą wiadomość. Nawet pierwsza wiadomość nie powiedzie się, jeśli jest „łańcuch” do innego ramka z innej domeny (innymi słowy, jeśli pierwszy odbiorca przekazuje wiadomość do innego).

Ta funkcja działa z funkcją Aktywacja użytkowników w wersji 2, zarówno w oryginalnej postaci, jak i tworzyć łańcuchy.