Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor getDevices into requestDevice #289

Merged
merged 6 commits into from
Oct 20, 2017
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 38 additions & 33 deletions explainer.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,43 +42,47 @@ VR provides an interesting canvas for artists looking to explore the possibiliti

The basic steps any WebVR application will go through are:

1. Request a list of the available VR devices.
2. Checks to see if the desired device supports the presentation modes the application needs.
3. If so, application advertises VR functionality to the user.
4. User performs an action that indicates they want to enter VR mode.
5. Request a VR session to present VR content with.
6. Begin a render loop that produces graphical frames to be displayed on the VR device.
7. Continue producing frames until the user indicates that they wish to exit VR mode.
8. End the VR session.
1. Request a VR device.
1. If a device is available, application advertises VR functionality to the user.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mentioning availability is good, but what about permission? want to make a mention here?

1. Request a VR session from the device in response to a [user-activation event](https://html.spec.whatwg.org/multipage/interaction.html#activation).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are user-activation events now also required for non-exclusive sessions?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the verbiage just got confusing after applying some suggested edits. I was kind of viewing this list as the steps of a "basic" VR experience, which is mostly about getting the exclusive session running. I've made some tweaks to try and clarify.

1. Use the session to run a render loop that produces graphical frames to be displayed on the VR device.
1. Continue producing frames until the user indicates that they wish to exit VR mode.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“producing” -> “sending”?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d say “user activation” again here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to mention anything about navigation here? IMO, it deserves a tiny mention

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to briefly mention the case of hardware error? the cases in which frames can not be send and/or not performantly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

admittedly, this probably isn’t the right place to get verbose, but an additional question I’d have upon reading this is, “What happens when the user takes off the VR device?”

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm working on rewording this a bit, but I think this is the core of it: This section is to give a quick overview of the expected API use pattern, so it should favor brevity. I'll try to apply these suggestions throughout the rest of the doc, though. (Possibly as a follow up PR for clarity?)

1. End the VR session.

### Device enumeration
### Acquiring a Device

The first thing that any VR-enabled page will want to do is enumerate the available VR hardware and, if present, advertise VR functionality to the user.
The first thing that any VR-enabled page will want to do is request a `VRDevice` and, if one is available, advertise VR functionality to the user. (For example, by adding a button to the page that the user can click to start VR content.)

`navigator.vr.getDevices` returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that resolves to a list of available devices. Each `VRDevice` represents a physical unit of VR hardware that can present imagery to the user somehow, referred to here as a "VR hardware device". On desktop clients this will usually be a headset peripheral; on mobile clients it may represent the mobile device itself in conjunction with a viewer harness (e.g., Google Cardboard or Samsung Gear VR). It may also represent devices without stereo presentation capabilities but more advanced tracking, such as Tango devices.
`navigator.vr.requestDevice` returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that resolves to a `VRDevice` if one is available. If no `VRDevice` is available, it will resolve to null. The promise will be rejected if an error occurs, such as the the page not having the appropriate permissions to access VR capabilities.

A `VRDevice` represents a physical unit of VR hardware that can present imagery to the user somehow, referred to here as a "VR hardware device". On desktop clients this will usually be a headset peripheral; on mobile clients it may represent the mobile device itself in conjunction with a viewer harness (e.g., Google Cardboard/Daydream or Samsung GearVR). It may also represent devices without stereo-presentation capabilities but with more advanced tracking, such as ARCore/ARKit-compatible devices.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 thanks

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nittiest nit: GearVR -> Gear VR


```js
let vrDevice = null;
function checkForVR() {
navigator.vr.requestDevice().then(device => {
if (device) {
onVRAvailable(device);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good 👍

}
}, err => {
// An error occurred while requesting a VRDevice.
console.error('Unable to request a VR device:', err);
});
}
```

navigator.vr.getDevices().then(devices => {
if (devices.length > 0) {
// Use the first device in the array if one is available. If multiple
// devices are present, you may want to provide the user a way of choosing
// which device to use.
vrDevice = devices[0];
onVRAvailable();
} else {
// Could not find any VR hardware connected.
}
}, err => {
// An error occurred querying VR hardware. May be the result of blocked
// permissions by a parent frame.
});
Future revisions of the API may add filter criteria to `navigator.vr.requestDevice`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be nice to add links/references (I assume that can come in the spec)


> **Non-normative Note:** If there are multiple VR devices available, the UA will need to pick which one to return. The UA is allowed to use any criteria it wishes to select which device is returned, including settings UI that allows users to manage device priority. Calling `navigator.vr.requestDevice` should not trigger device selection UI, however, as this would cause many sites to display VR-specific dialogs early in the document lifecycle without and user activation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: device selection UI -> device-selection UI

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: without and


It's possible that even if no VR device is available initially, one may become available while the application is running, or that a previously available device becomes unavailable. This will be most common with PC peripherals that can be connected or disconnected at any time. Pages can listen to the `devicechange` event emitted on `navigator.vr` to respond to changes in device availability after the page loads. (VR devices already available when the page loads will not cause a `devicechange` event to be fired.)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for adding the last sentence - it’s helpful


```js
navigator.vr.addEventListener('devicechange', checkForVR);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will devicechange always fire when a document loads and a VR device is detected? or in the presence of an event listener on navigator.vr? what's the trigger?

if so, when? in relation to DOMContentLoaded, load, etc.?

```

### Sessions

A `VRDevice` indicates the presence of a VR hardware device but provides very little information about it outside of a name that could be used to select it from a list. In order to do anything that involves the hardware's presentation or tracking capabilities the application will need to request a `VRSession` from the `VRDevice`.
A `VRDevice` indicates only the availability of a VR device. In order to do anything that involves the device's presentation or tracking capabilities, the application will need to request a `VRSession` from the `VRDevice`.

Sessions can be created with one of two levels of access:

Expand All @@ -93,7 +97,11 @@ If a `VRDevice` is available and able to create an exclusive session, the applic
In the following examples we will focus on using exclusive sessions, and cover non-exclusive session use in the [`Advanced Functionality`](#non-exclusive-sessions-magic-windows) section. With that in mind, we ask here if the `VRDevice` supports sessions with `exclusive` access (the default), since we want the ability to display imagery on the headset.

```js
async function onVRAvailable() {
let vrDevice = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do without the global variable?


async function onVRAvailable(device) {
vrDevice = device;

// Most (but not all) VRDevices are capable of granting exclusive access to
// the device, which is necessary to show imagery in a headset. If the device
// has that capability the page will want to add an "Enter VR" button (similar
Expand Down Expand Up @@ -623,18 +631,15 @@ partial interface Navigator {
};

[SecureContext, Exposed=Window] interface VR : EventTarget {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have this (and others) exposed on (Window,Worker)? or do you feel that warrants a separate issue and discussion?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely want to get there, but I do feel it's worth having it's own issue. I don't expect it to be controversial, but any conversation that does crop up around it deserves its own space rather than being intermixed with this change.

attribute EventHandler ondeviceconnect;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will documentation be updated to reflect the removal of these in a separate PR? can you file an issue to track?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which documentation are you referring to in this case? There's not much in the way of docs for the 2.0 API yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I had read a passage on these events - but I was wrong. I was thinking of the spec.

this is fine 👍

attribute EventHandler ondevicedisconnect;

Promise<sequence<VRDevice>> getDevices();
attribute EventHandler ondevicechange;
Promise<VRDevice> requestDevice();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are there other APIs with similar property naming? the reason I ask is because like with the Permissions API, navigator.permissions.query(…) is what you call to get a Promise back of the permissions state. request to me can be ambiguous; without reading the IDL here that says Promise<VRDevice> or the explainer text above, as a web developer, I could see myself getting confused thinking it’s going to return the availability of a VR Device or begin requesting VR presentation.

that all make sense?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you be opposed to getAvailableDevice? (borrowing a bit from the Remote Playback API which is making its way to CR - which obviously doesn't mean it has absolutely the best spec API but it's probably a good signal.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both WebUSB and WebBluetooth use getDevice. (navigator.usb.getDevice and navigator.bluetooth.getDevice respectively.) As a result I'd really like to carry that verbiage through to this API to reinforce the sense that this is part of the same Web API family.

};

//
// Device
//

[SecureContext, Exposed=Window] interface VRDevice : EventTarget {
readonly attribute DOMString deviceName;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this need to be removed? I assume that this is to avoid fingerprinting? without the ability to query or filter VR devices, this seems to perhaps be a premature change. I don’t have metrics in front of me (nor do I think it’d be easy to inspect existing WebVR content to determine), but I can see this complicating content.

I know there’s an issue on file to handle fingerprinting. do you want to handle that in a separate PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I see you mention in the PR description that this change is to satisfy Apple’s fingerprinting concerns. I suppose this doesn’t completely. and if anything, hopefully the removal of this encourages developers to not sniff and exclude particular headsets (à la the abuse of User-Agent response headers and navigator.userAgent).

after having thought about it, I think this change is acceptable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would understand the impact to developer on making "responsive" webvr apps cross HMDs. I mean webvr apps are able to check the devcieName and load corresponding assets, let's say different complexity of models, different size of textures etc., to deliver best experience for that HMD. Are there any other ways to do this without deviceName?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a great answer for you, unfortunately. (This is something that WebGL in general struggles with.) But I can say with confidence that scaling scene complexity based on the device name is a bad idea. At the very least it would mean that you'd have to update your code every time a new device hit the market, and it's very easy to get wrong (Not only would browser possibly expose different names but developers might check for, say, the string "Vive" and load high-end assets not realizing that HTC has plans to use the Vive branding for standalone devices as well.)

There's a variety of methods out there to determine if you're on a mobile device or not, so that could be used as a baseline performance differentiator. Beyond that you could ask users to pick a detail level (high, medium, low) or try to scale it dynamically as your experience runs.

I wish I had a better answer, but this is a problem that extends well beyond WebVR and we wouldn't be doing the platform any favors by encouraging another form of user agent sniffing.

readonly attribute boolean isExternal;

Promise<void> supportsSession(optional VRSessionCreationOptions parameters);
Expand Down