blob: 1e84dfdd8bbea65551e73bfae696a6feec79f46c [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.ui.pointerflow;
using fuchsia.ui.views;
using fuchsia.ui.input3;
using zx;
const uint32 MAX_INJECT = 128;
/// A coordination mechanism to clearly define the *injecting* of pointer events
/// into the scene (injection policy, injection context, etc), for *dispatching*
/// pointer events to UI clients (referenced by |fuchsia.ui.views.ViewRef|).
///
/// NOTE WELL! ONLY COMPONENTS IN THE TRUSTED COMPUTING BASE SHOULD BE GRANTED
/// ACCESS TO THIS PROTOCOL.
/// (1) The injector acts with the user's authority. UI clients cannot tell the
/// difference between a real user and an injector.
/// (2) The defined context is self-specified by the injector. An injector that
/// gains access to a sensitive context will operate in that scope.
/// (3) The injected events may be arbitrary. An injector can inject whatever
/// it wants to the clients it can reach.
///
/// This protocol sets up the defined context for an |Injector|, and directs the
/// |Injector| at a target. These parameters are set up in the |InjectorConfig|.
/// An |Injector| may *inject* pointer events on the specified target in the
/// scene, but the *dispatch* of pointer events to UI clients will depend on the
/// dispatch policy and the scene topology.
///
/// An |Injector| operates within a defined context; it serves two purposes:
/// (1) Scoping. It confirms the |Injector|'s ability to inject pointer events
/// on the specified target.
/// (2) Coordinate System. It provides the reference coordinate space to
/// interpret injected pointer events.
///
/// Guarantees. An |Injector| is directed at a specified target in the scene,
/// and such a target is afforded some guarantees against snooping and
/// interference from UI clients outside the target's view tree ("non-target
/// clients"). Non-target clients never have injected events dispatched to
/// them: an |Injector| preserves *confidentiality* for target clients.
/// Non-target clients never block injected events from reaching the target on
/// injection, or from reaching target clients on dispatch: an |Injector|
/// preserves *integrity* and *availability* for target clients. However, the
/// |Injector| itself is subject to disruption by ancestor views of the target
/// (see connectivity invariant, below).
///
/// Note. This protocol, and its policies, are *not* a sufficient guard against
/// UI redress attacks! The confidentiality, integrity, and availability
/// guarantees apply only with respect to non-target clients. Within a
/// target, UI redress attacks can still happen, between target clients.
///
/// Connectivity invariant. An |Injector| operates in a stable view tree that
/// is connected to the root view. When either the target, or both context and
/// target, are disconnected from the view tree by a UI client, the |Injector|
/// channel is closed. If an event stream was in flight, the server dispatches
/// a final CANCEL event following channel closure; this CANCEL event is then
/// propagated according to dispatch policy.
[Discoverable]
protocol InjectorRegistry {
/// Sets up a defined context for an |Injector|, and directs it at a target.
/// These parameters are specified in an |InjectorConfig|.
///
/// If |config| is invalid (e.g., missing important data), the |injector|
/// request will be denied (i.e., the channel will be closed).
///
/// The return event tells the caller that (1) the server has processed the
/// call, and (2) the |injector| is connected.
Register(InjectorConfig config, request<Injector> injector) -> ();
};
/// The channel for injecting pointer events into a target.
/// The associated |InjectorConfig| applies to injected pointer events.
///
/// An |Injector| may *inject* pointer events into a target in the scene, but
/// the *dispatch* of pointer events to UI clients within that target's view
/// tree will depend on the dispatch policy and the scene topology.
protocol Injector {
/// Injects events into a target.
///
/// Batching: The caller is expected to batch-inject all events that share the
/// same timestamp (e.g., multiple finger samples). There may be multiple such
/// batches per injection call.
///
/// Flow control: The caller is allowed at most one in-flight |Inject| call
/// at at time: subsequent |Inject| calls must wait until the acknowledgment
/// returns. Non-compliance results in channel closure.
Inject(vector<Event>:MAX_INJECT events) -> ();
};
/// A specification for an |Injector|.
table InjectorConfig {
/// A specification of the pointer device.
1: DeviceConfig device_config;
/// The scope and coordinate system of the injector.
///
/// Note: To avoid circular injection scenarios, |context| must be a
/// strict ancestor of |target|.
2: InjectorContext context;
/// The region where dispatch is attempted for injected events.
///
/// Note: To avoid circular injection scenarios, |target| must be a strict
/// descendant of |context|.
3: InjectorTarget target;
/// A specification of the UI clients in |target| that may have injected
/// events dispatched to them.
///
/// For example, if |dispatch_policy| is |EXCLUSIVE|, then only |target| may
/// have injected events dispatched to it, regardless of other factors, such
/// as surface occlusion by clients inside and outside of |target|.
4: DispatchPolicy dispatch_policy;
};
/// A specification of the pointer device.
table DeviceConfig {
/// An identifier for the pointer device that issues pointer event streams.
1: uint32 device_id;
/// A characterization of the pointer device.
2: fuchsia.ui.input3.PointerDeviceType device_type;
};
/// The region from which injection is attempted for injected events. As the
/// context, it serves two purposes:
/// (1) Scoping. It confirms the |Injector|'s ability to inject pointer events
/// on the specified target. Specifically, the context must be a view-tree
/// ancestor of the target.
/// (2) Coordinate System. It provides the reference coordinate space to
/// interpret injected pointer events. Specifically, the injector specifies
/// the location of injected events in its own coordinate system (instead of
/// the target's coordinate system).
union InjectorContext {
/// A Scenic view from which injection is attempted for injected events.
/// - This view must be connected to the scene graph for injection.
/// - Injected events are confined to this view and its sub-views.
1: fuchsia.ui.views.ViewRef view;
};
/// The region in which dispatch is attempted for injected events.
/// The particular dispatch policy is specified in |InjectorConfig|.
union InjectorTarget {
/// A Scenic view in which dispatch is attempted for injected events.
/// - This view must be connected to the scene graph for dispatch.
/// - Injected events are confined to this view and its sub-views.
1: fuchsia.ui.views.ViewRef view;
};
/// A specification of the UI clients that may have injected events dispatched
/// to them in an |InjectorTarget|. One is specified in |InjectorConfig|.
///
/// For a given pointer stream, zero or more clients may "latch" onto it: each
/// latched client is eligible to have the entire pointer stream dispatched to
/// it. A "latch attempt" determines which clients are latched, it succeeds when
/// at least one client is latched, and it fails when no clients are latched.
///
/// Note: A client's latch is not a guarantee that the entire pointer stream
/// *will* be dispatched to that client; other mechanisms may prematurely
/// end the pointer stream dispatched to that client.
/// Note: It's possible for a latch attempt to succeed on a hidden surface
/// (i.e., manipulate a surface that is invisible to the user), where the
/// occluding surface is owned by a client outside of |InjectorTarget|.
/// However, occluding clients cannot participate in a latch attempt,
/// because latched clients must be a sub-view of the |InjectorTarget|.
enum DispatchPolicy {
/// A single client may latch onto a pointer stream, where:
/// - the pointer stream starts in the clip region of |InjectorTarget|,
/// - the latch attempt is on the ADD phase of the pointer stream, and
/// - the client is the |InjectorTarget| itself.
///
/// Note: This policy guarantees confidentiality, integrity, and
/// availability of dispatch to the client, but by itself, does *not*
/// confer immunity against UI redress attacks.
/// Note: The client may be told that it owns exclusive dispatch.
EXCLUSIVE = 1;
/// A single client may latch onto a pointer stream, where:
/// - the pointer stream starts in the clip region of |InjectorTarget|,
/// - the latch attempt is on the ADD phase of the pointer stream,
/// - the latch attempt hits one or more surfaces owned by a client,
/// - one of those surfaces is top-most (in Z or paint order) in the view
/// tree rooted at |InjectorTarget|, and
/// - the client is a sub-view of |InjectorTarget| (inclusive).
///
/// Note: It's possible for the latch attempt to fail, by failing to hit any
/// surface in any sub-view of |InjectorTarget|.
TOP_HIT_ONLY = 2;
/// Multiple clients may latch onto a pointer stream, where:
/// - the pointer stream starts in the clip region of |InjectorTarget|,
/// - the latch attempt is on the ADD phase of the pointer stream,
/// - the latch attempt hits one or more surfaces owned by multiple clients,
/// - each client is a sub-view of the |InjectorTarget| (inclusive).
///
/// With multiple latches, a pointer stream is dispatched in parallel to
/// each latched client.
///
/// Note: It's possible for the latch attempt to fail, by failing to hit any
/// surface in any sub-view of |InjectorTarget|.
ALL_HIT_PARALLEL = 3;
};
/// A description of each sampled data point for a pointer device.
table Event {
/// The time when this event happened.
/// Required field.
1: zx.time timestamp;
/// An identifier of the pointer that issued this event.
/// It is unique only to a given pointer device.
/// Required field.
2: uint32 pointer_id;
/// The state of this event in the pointer event stream's state machine.
/// Required field.
3: fuchsia.ui.input3.PointerEventPhase phase;
/// The horizontal position of this event, interpreted in the injector's
/// coordinate system.
/// Required field.
4: float32 position_x;
/// The vertical position of this event, interpreted in the injector's
/// coordinate system.
/// Required field.
5: float32 position_y;
/// An identifier to correlate this event's send/receive occurrence across
/// component boundaries or abstraction layers.
6: uint64 trace_flow_id;
};