Browser Basics: User Gestures

The Web Platform offers a great deal of power, and unfortunately evil websites go to great lengths to abuse it. One of the weakest (but simplest to implement) protections against such abuse is to block actions that were not preceded by a “User Gesture.” Such gestures (sometimes more precisely called User Activations) include a variety of simple actions, from clicking the mouse to typing a key; each interpreted as “The user tried to do something in this web content.”

A single user gesture can unlock any of a surprisingly wide array of privileged (“gated”) actions:

So, when you see a site show a UI like this:

…chances are good that what they’re really trying to do is trick you into performing a gesture (mouse click) so they can perform a privileged action– in this case, open a popup ad in a new tab.

In terms of which actions can cause a gesture, the list is surprisingly limited, and includes mousedown (but not mouseup/click):

// Returns |true| if |type| is the kind of user input that should trigger user interaction observers.
bool IsUserInteractionInputType(blink::WebInputEvent::Typetype) {
// Ideally, this list would be based more off of
// return type ==
blink::WebInputEvent::Type::kMouseDown ||
type == blink::WebInputEvent::Type::kGestureScrollBegin ||
type == blink::WebInputEvent::Type::kTouchStart ||
type == blink::WebInputEvent::Type::kRawKeyDown; }

Some gestures are considered “consumable”, meaning that a single user action allows only one privileged action; subsequent privileged actions require another gesture. Web Developers do not have unlimited time to consume the action: In Chrome, when you click in a web page, the browser considers this “User Activation” valid for five seconds (as of Februrary 2019) before it expires. Here’s a simple test.

Unfortunately, even this weak protection is subject to both false positives (an unwanted granting of privilege) and false negatives (an action is unexpectedly blocked).

You can learn more about this topic (and the complexity of dealing with nested frames, etc) in the original Chromium User Activation v2 spec, and the User-Activation section of HTML5.


PS: Some discussion of Safari’s behavior, and a blog post from the WebKit team about Safari’s implementation of the User Activation API.

Published by ericlaw

Impatient optimist. Dad. Author/speaker. Created Fiddler & SlickRun. PM @ Microsoft 2001-2012, and 2018-2022, working on Office, IE, and Edge. Now a SWE on Microsoft Defender Web Protection. My words are my own, I do not speak for any other entity.

2 thoughts on “Browser Basics: User Gestures

  1. Note that the “user activation v2” changes were merged into the HTML Standard in, so now the best source of information is actually the HTML Standard itself:

    I also would suggest avoiding the Chromium-specific term “user gesture” in favor of “user activation”. In particular, there are a variety of gestures that do not cause activation, such as the scroll gesture.

    1. Thanks for the HTML reference. The term “user gesture” precedes Chrome by decades, used in both browsers and operating systems.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: