w3c / gamepad

Gamepad
https://w3c.github.io/gamepad/
Other
138 stars 49 forks source link

Add vendorId, productId, name attributes #202

Open nondebug opened 2 months ago

nondebug commented 2 months ago

Closes #199

The following tasks have been completed:

Implementation commitment:


Preview | Diff

marcoscaceres commented 1 month ago

Filed webkit bug https://bugs.webkit.org/show_bug.cgi?id=273981

marcoscaceres commented 1 month ago

@saschanaz, can you confirm that you and folks on the Gecko side are ok with this addition? We are supportive of it on the WebKit side.

saschanaz commented 1 month ago

So this is "fine" as we already have .id that exposes the same info, but it's still a fingerprinting vector. Why do we need vendor/product/name at all here? Is it for some feature detection that existing methods do not cover well?

nondebug commented 1 month ago

Why do we need vendor/product/name at all here? Is it for some feature detection that existing methods do not cover well?

Vendor/product IDs enable applications to identify the gamepad model which can be useful when trying to show icons that match the labels on the gamepad's buttons. Currently, applications use Gamepad.id for this but it's not a good identifier because the content of ID string is explicitly not specified and there's no guarantee that the value will remain stable over time. The vendor/product IDs come from the device firmware so they're unlikely to change except by firmware update.

It's also used for feature detection when deducing which "extra" buttons are available. We're trying to solve that use case with a GamepadButton.type attribute for identifying buttons that aren't part of the Standard Gamepad: #196

A human-readable name is important because there may be multiple gamepads connected and the application may need to ask the user to identify a connected gamepad. Gamepad.id can also be used for this but it typically includes other information like vendor/product IDs that makes it less human-readable.

Mostly we want to add these attributes so that developers can eliminate browser-specific logic for parsing this information out of the underspecified Gamepad.id string.

saschanaz commented 1 month ago

So three use cases:

  1. Show matching icon for each controller
  2. Feature detection for buttons
  3. Identify each controller

1 may be fun but not sure it's important enough. 2 should be solved by #196. 3 sounds like a workaround rather than actual direct use case of this, how can I identify each controller by name if I have 4 Xbox 360 controllers connected? Should the application instead vibrate each controller for example so that I can know which is which?

It's not adding a new fingerprinting vector, but this still eases use of unnecessarily exposed device specific info that I'd rather discuss removing id to resist fingerprinting and add missing features that this might solve as #196 does. (i.e. I think two feature-equivalent gamepads should be perceived equivalent to Gamepad API even if those are different products. Like how we don't allow differentiating a Logitech mouse and Microsoft mouse.)

nondebug commented 1 month ago

1 may be fun but not sure it's important enough.

Displaying the correct button labels is important for gaming services where players are expected to bring their own gamepad. It's confusing when the game tells you to press the "X button" but you're not sure if it means Xbox X button (buttons[2]), PlayStation Cross button (buttons[0]) or Switch X button (buttons[3]). The gamepad itself doesn't know what the correct labels are so applications need a way to decide which labels to use.

how can I identify each controller by name if I have 4 Xbox 360 controllers connected?

I think it's not necessary for the human-readable identifier to distinguish between devices that can't be distinguished by a human. If the controllers are identical then (in my opinion) it's fine to use the same identifier.

Sometimes the product name is identical but the device itself may provide additional device-specific distinguishing information. For instance, it's possible to query a Switch Joy-Con's color. As specified in this PR it would be acceptable for a user agent to add the color information to the name string as an additional distinguishing detail. However, most gamepads don't provide a programmatic way to distinguish between cosmetic variations of the same product.

On consoles this problem is solved by assigning each connected gamepad to a slot and using light indicators to distinguish slots. There's a separate proposal #143 to allow applications to set the light indicator state which could be used to distinguish otherwise identical gamepads. This approach is limited by the reality that not all gamepads have light indicators, and those that do only have a limited number of distinct configurations for representing slots.

Should the application instead vibrate each controller for example so that I can know which is which?

Applications shouldn't rely on vibration since not all gamepads support vibration. Even gamepads that support the feature may give the user a way to disable it, for instance with a physical on-off switch on the gamepad. We can't assume that sending a vibration command to a gamepad will actually cause it to vibrate in a way the user will notice, but vibration could be useful in conjunction with other signals.

I'd rather discuss removing id to resist fingerprinting and add missing features that this might solve

I don't think removing Gamepad.id is feasible because too many applications already rely on it.

As a fingerprinting mitigation I think it would be reasonable for Gamepad API to offer tiered access to gamepads so that Gamepad.id is safe by default. Perhaps by default a site receives only generic information about connected gamepads similar to how PointerEvents provides almost no information about the connected pointing device. Only the standard buttons/axes are exposed and capabilities like vibration are disabled to resist fingerprinting. After granting a permission, the site would be allowed to access all information about the gamepad, including device IDs. I expect we will need to add a permission model anyway since we want to add support for more powerful gamepad capabilities that wouldn't be appropriate without stronger user consent.

I think two feature-equivalent gamepads should be perceived equivalent to Gamepad API even if those are different products.

I disagree mainly because of the button labels problem. Other capabilities can be automatically detected, but displaying the correct button labels requires device identification because the labels are never provided by the device itself.

If we want to hide device IDs from the application then the user agent needs to provide the necessary information to select the correct button labels. I expect the fingerprinting risk of exposing labeling information is roughly equivalent to exposing the vendor/product/name since we expect these values to be highly correlated. If the API is responsible for providing this information then it increases the burden on the user agent proportional to the number of supported gamepads. If the fingerprinting risk is roughly equivalent then I think we should save ourselves the effort and let applications developers build tables of button labels for the devices they care about.

marcoscaceres commented 1 month ago

Just adding that I agree with @nondebug's assessment. On the WebKit side, we see the user interaction requirement as sufficient to mitigate the fingerprinting concerns. At the same time, if users agents want to go beyond that for the productId and vendorId (and sometimes not provide them, or provide generalized identifiers) to provide further anonymity, they are certainly free to do so.

There is limited opportunity for two or more sites to collude to identify an individual because of both the user activation are requirement, and because the set of controllers types out there is expansive, but not super unique per individual (and there's other sadly more effective means to fingerprint).

As such, we might want to make that clear in the spec (that the user agent can lie if it needs to or the user wants it to).

saschanaz commented 1 month ago

Displaying the correct button labels is important for gaming services where players are expected to bring their own gamepad. It's confusing when the game tells you to press the "X button" but you're not sure if it means Xbox X button (buttons[2]), PlayStation Cross button (buttons[0]) or Switch X button (buttons[3]). The gamepad itself doesn't know what the correct labels are so applications need a way to decide which labels to use.

I agree that's a real problem! Still I don't think exposing vendor/product ID is a right solution, as the caller would need a database to tell which ID has which mapping. Fortunately there are a few well-defined button mappings, so wonder we could have a proper API to expose that info, perhaps with an enum. (As you noted later this still would require the mapping from browser side, which I would say okay and is just easier to use.)

I think it's not necessary for the human-readable identifier to distinguish between devices that can't be distinguished by a human. If the controllers are identical then (in my opinion) it's fine to use the same identifier.

But that means having IDs does not really solve the core problem? If it only helps when the user is having different type of controllers, I'm not sure how that would be helpful most of the time.

Again, this is "okay" as it does not expose additional info, but I still does not understand why we want to solve problems with IDs that does not expose any useful device info as-is.

nondebug commented 1 month ago

Fortunately there are a few well-defined button mappings, so wonder we could have a proper API to expose that info, perhaps with an enum.

Button mapping isn't equivalent to deducing button labels. Console gamepads often have the same layout but with different labels. It's important for applications to be able to draw the correct labels even for gamepads with the same button layout and mapping. Suppose the game is trying to tell the player which button opens an options menu and wants the player to press the button mapped to buttons[9] ("right button in center cluster"). It's not enough for the game to know that this gamepad uses a PlayStation layout because the labels will differ depending on if it's a PS3, PS4, or PS5 controller. On DualShock 3 this button is labeled "Start", on DualShock 4 it's "Options", and on DualSense it's a hamburger icon. For the game to draw the correct label, the enum at minimum will need to distinguish between these possibilities. When a new PlayStation gamepad is released, it's likely that the spec would need to be updated with a new enum value.

We should try to avoid building this sort of dependency into the spec where the spec needs to be updated for each new device we want to support. Ideally it should be possible to connect your gamepad to your browser on the day the gamepad is released and have it work correctly without needing to wait for a spec change and a browser update. If we make it the browser's responsibility to maintain button label information then I expect there will be a delay before new gamepads are supported and less popular gamepads may never be supported.

Also, I think we should try to avoid referencing specific vendors or trademarks in the spec. If we added a enum with different values for "well-defined button mappings" then I expect the enum will include many trademarked names by necessity.

But that means having IDs does not really solve the core problem?

The core problem (as I see it) is that applications are relying on the underspecified Gamepad.id attribute for programmatic identification of gamepad models. Applications already maintain mappings of Gamepad.id -> button labels. This makes it difficult to modify the Gamepad.id value for any currently-supported gamepad because it will break applications that rely on that gamepad having a stable Gamepad.id value. The purpose of the name attribute isn't to guarantee distinguishability, it's to provide the same level of human-facing distinguishability currently provided by Gamepad.id without requiring identifier stability.

If it only helps when the user is having different type of controllers, I'm not sure how that would be helpful most of the time.

Do we need to consider whether it's helpful? I agree it's typically not necessary for users to identify a gamepad because usually there's only one connected gamepad, or all the gamepads are the same product model. However, the current API provides a human-facing identifier and application developers sometimes find it useful to present this identifier to users. I think we should assume that a human-facing identifier is helpful to application developers and empower browser implementations to provide the best possible identifier.

marcoscaceres commented 3 weeks ago

Agree with @nondebug on this and on the WebKit side. We think it makes sense to split these up as it's something developers rely on.

At the same time, there is certainly scope for improving the privacy generally here - but I think we should take that up separately.

saschanaz commented 3 weeks ago

Okay, Mozilla is neutral here, given the ID has been being exposed and pages already can extract each ID component by some heuristic. We would be happier without the need to sniff based on ID but also acknowledge that it would be hard to deal with use cases given the hardware reality.