Skip to content

Instantly share code, notes, and snippets.

@dSalieri
Last active August 17, 2022 17:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dSalieri/0a249dbd00d2e094a77b9458ca42e7a6 to your computer and use it in GitHub Desktop.
Save dSalieri/0a249dbd00d2e094a77b9458ca42e7a6 to your computer and use it in GitHub Desktop.
Tracking user activation (whatwg)

Этот текст был составлен как проблема и помощь в понимании некоторых вещей по спецификации whatwg. Текст проблемы не был принят во внимание и проигнорирован, а мое объяснение было посоветовано разместить в своем блоге.

Текст ниже является объясняющей частью (можете воспользоваться переводчиком, перевод будет сносным, я смотрел). Не удалять же мне эти интересные находки, может кому-то это будет полезным.

I noticed that Chrome APIs gives ~5000ms for APIs that using transient activation in their algorithms for successfull completion

/// measuring only for Chrome
(() => {
    let timerId = null;
    let start = null;
    const data = navigator.userActivation;
    document.documentElement.addEventListener("pointerdown", (e) => {
        if(timerId !== null && data.isActive) {
            clearTimeout(timerId);
        } else if(timerId === null){
            console.log("isActive", data.isActive);
            start = performance.now();
        }
        timerId = setInterval(() => {
            if(!data.isActive){
                console.log("isActive", data.isActive);
                console.log("Your transient activation interval: ", performance.now() - start);
                clearInterval(timerId);
                timerId = null;
            }
        })
    })
})()

What I could find for every example of APIs gated by user activation:

  • Sticky activation-gated APIs You may came across to this case when you're closing your tab having event beforeunload that will cause popup message. In Chrome you can track it with navigator.userActivation.hasBeenActive if it gives true value that means you'll see popup, otherwise you won't see. Also it appears in history API

  • Transient activation-gated APIs This case you can meet for example in using document.documentElement.requestFullscreen or input.showPicker APIs.

    /// open a blank tab and perform this in console
    let newEl = document.createElement("input");
    newEl.setAttribute("type", "color");
    document.body.append(newEl);
    newEl.showPicker();

    In the Firefox you will get the following message of error: Uncaught DOMException: HTMLInputElement.showPicker: Call was blocked due to lack of user activation.. That's because performing code in the console won't cause activation triggering input event that I see correct by spec. In the same time Chrome won't cause the error such as Firefox, because it thinks that this is activation triggering input event.

    Also if you run in console this code:

    document.documentElement.addEventListener("pointerdown", () => {
      setTimeout(() => document.documentElement.requestFullscreen(), 5000)
    })

    and commit click within document area, you will see how fullscreen activated, but if you will increase timeout you will have gotten error with notification (in Chrome) and error message (everywhere) that requestFullscreen can't be aplied due with expired transient activation.

    And the last one:

    /// Transient activation-consuming API and Transient activation-gated API
    const newEl = document.createElement("input");
    newEl.setAttribute("type", "color");
    document.body.append(newEl);
    document.documentElement.addEventListener("pointerdown", () => {
      window.open();
      newEl.showPicker();
    })

    Using window.open API switch our transient activation to inactive status, that means if any other API that needing in that transient activation can't be perfomed successfully.

  • Transient activation-consuming APIs This case appears when you are using such API as window.open. In Chrome if you open new tab and in console of the dev-tools write window.open() and after navigator.userActivation.isActive, you will get new opened tab and false value in the opener window, that will be mean that window.open uses transient activation. Also you can write in console window.open(); window.open();(in one moment) that opens two tabs, that shows that window.open API doesn't check transient activation for its action.

  • Transient activation-gated APIs and Transient activation-consuming APIs This case appears when API uses two concept together

    document.documentElement.addEventListener("pointerdown", async () => {
      await document.documentElement.requestFullscreen();
      document.exitFullscreen();
      document.documentElement.requestFullscreen();
    })

    At the first time requestFullscreen checks transient activation, if it is active then perform successufully its algorithm and after toggle transient activation to inactive. At the second time falls into fail because transient activation has been toggled in state of transient activation when it is not active.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment