-
Notifications
You must be signed in to change notification settings - Fork 19
Linking between VR web pages #22
Comments
From what I understood, once there has been a user interaction to start presenting in the HMD, you can move to different VR capable sites without having to take the headset off. |
So how does the destination web page know that it's already presenting when it starts running? And what happens if that destination web page doesn't know how to handle VR? |
Last summer, we prototyped a standalone VR backwards-compatible browser based on Firefox's Graphene project (which is Desktop B2G, similar to Electron). You have an app manifest, an Check out this short video demoing our Horizon prototype browser. À la the Unlike the And you want to know which type of experience it is before you render the next page. Do you project a non-VR site as a 2D plane? That's what we did with Horizon. That isn't doable in content with pure WebGL in Chrome, however. We looked into the Navigation Transitions spec (good critique blog post here) or writing an extension or chrome-level code in Firefox that would allow a kind of hijacking/pausing of the navigation. Navigation Transitions isn't fully spec'd or implemented in Chrome nor Firefox, so that seemed premature to count on that. Chrome versions 31-38 used to rely on Anyway, Chrome for Android 39 stopped using the That's when I proposed using the Web App Manifest for VR-specific metadata. It seems like a good idea because you can reference a single manifest for all documents on your server (e.g., suppose you have a VR world that contains a different document per level). Huge plus would be not having to propose and invent a new Example: Michael Blix at Samsung had proposed a Since the Web App Manifest spec has a non-normative section suggesting to use proprietary keys, the browser could use that information to identify the viewmode of the site and then figure out the projection. Or if a 2D page is encountered, the user agent could decide to open that in a new tab and display a notification message in the headset. It's really up to the user agent to decide how to handle "legacy" content. But parts of this probably ought to be spec'd, at the very least as non-normative text in the spec. The Manifest spec is explicit that manifests should be If you're interested in some of the pros/cons of the approaches the Mozilla VR was doing WebVR prototyping and prepping for the WebVR API overhaul for v1.0, check out this Google Doc. And, heh, I just found a short summary I wrote a few months ago that mostly summarises what I said above. Anyway, we stopped working on our Horizon browser prototype because of a bunch of technical limitations:
We should loop in @caseyyee from the Mozilla VR team who has done a lot of thinking with me on the browser and link traversal UX prototyping. Also, we should loop in @mkeblx from Samsung. The Samsung Internet Browser for Gear VR has to handle all of these things in the very near future, as they're looking to support first-class legacy 2D and WebVR experiences. |
This probably belongs as non-normative text, as the behavior can vary from one browser to another without affecting the WebVR API, but I can share our design related to link traversal and permissions: Calling Navigator.GetVRDisplays triggers the UX prompts for requesting entering VR...
|
I assume in this case it resolves with the devices, right? I'm still not clear on how this solves the problem. Assuming my site has been linked from another VR site and is already presenting, how do I know that so I can start rendering in stereo? When that promise resolves very quickly with a list of devices, how can I tell the difference between being already in VR and the user having selected "accept always"? |
Would a flag living along side VRDisplay.IsPresenting and VRDisplay.IsConnected help here? I suppose it would need to be something that returns "true" in this case. |
Yes, I imagine something like that would work. I'd want to try it out to be
|
Can you clarify thoughts in regards to prompt display in case of third bullet point above. Any site calling getVRDisplays to query WebVR capabilities would show dialog right at page load potentially, even if no immediate intent to present/enter fullscreen. Is there a good way for site being able to determine if any vrdisplay connected (without getting data access) without calling getVRDisplays and having prompt displayed? Would ideally like to avoid that for just that one piece of info. |
@mkeblx à la should definitely spec that soon. |
I don't understand why we need UX prompts for entering VR. and calling IMO, we should talk to @marcoscaceres, et. al. about adding WebVR to the Permissions API enum so we can use that API. and until the Permissions API is supported, in the meantime, follow the same security model used by Pop-ups, Pointer Lock, Fullscreen API, etc. - that is, require an "engagement gesture" on the first entering of VR: |
Great, forgot about those, that'd work. Will comment on issue for specing out. I think permission prompt on getVRDisplays more to do with tracking data a la geolocation API, etc. so does make sense there in cases where will return a VRDisplay. But only when actually at point of requesting that access (or ahead of time with Permissions API). Or should we view pose data as same as same as device orientation data w.r.t. permissions? Or are there two different permissions: data access, and ability to present/go fullscreen? |
in Chrome, Geolocation permissions (since 43) have been controlled by the Permissions API. see https://developers.google.com/web/updates/2015/04/permissions-api-for-the-web and https://googlechrome.github.io/samples/permissions/ Firefox implementation isn't done yet, but we should plan on using the Permissions API regardless.
FWIW, thoughts? |
full pseudo-code example would go something like this: var canQueryDisplays = false;
var canRequestPresent = false; // Can enter VR based on a user-initiated gesture (e.g., `click`).
var canRequestPresentOnLoad = false; // Can enter VR immediately on document load (see `NOTE` below).
var vrDisplay;
/*
// If you want to test for the permissions explicitly …
navigator.permissions.query({name: 'vr', queryDisplays: true}).then(function (result) {
canQueryDisplays = this.state === 'granted';
result.onchange = function () {
canQueryDisplays = this.state === 'granted';
};
});
navigator.permissions.query({name: 'vr', requestPresent: true}).then(function (result) {
canRequestPresent = this.state === 'granted';
result.onchange = function () {
canRequestPresent = this.state === 'granted';
};
});
// NOTE: We may not ever want this to be a toggleable permission.
navigator.permissions.query({name: 'vr', requestPresentOnLoad: true}).then(function (result) {
canRequestPresentOnLoad = this.state === 'granted';
result.onchange = function () {
canRequestPresentOnLoad = this.state === 'granted';
};
});
*/
function successQueryDisplays (displays) {
console.log('`navigator.getVRDisplays` access granted');
if (displays) {
vrDisplay = displays[0];
console.log('VR display found and using:', vrDisplay);
}
return vrDisplay;
}
function errorQueryDisplays (err) {
console.warn('`navigator.getVRDisplays` was blocked for this reason: %s', err);
}
function requestPresent (vrDisplay) {
return vrDisplay.requestPresent({source: webglCanvas});
}
function errorRequestPresent (err) {
console.warn('`VRDisplay.requestPresent` was blocked for this reason: %s', err);
}
function successEnterVR () {
enterVRButton.style.display = 'none';
console.log('`VRDisplay.requestPresent` access granted and entered VR on document load:', vrDisplay);
}
function errorEnterVR (err) {
enterVRButton.style.display = 'block';
console.log('Could not enter VR for this reason: %s', err);
}
window.addEventListener('vrdisplaypresentchange', function () {
if (vrDisplay && vrDisplay.isPresenting) {
enterVRButton.style.display = 'none';
} else {
enterVRButton.style.display = 'block';
}
});
// Query for a VR display.
navigator.getVRDisplays().then(successQueryDisplays, errorQueryDisplays)
// Try to enter VR immediately if we can.
.then(requestPresent, errorRequestPresent)
.then(successEnterVR, errorEnterVR);
enterVRButton.addEventListener('click', function () {
if (!vrDisplay) {
console.warn('Cannot enter VR because no displays found');
return;
}
if (vrDisplay.isPresenting) {
console.warn('Cannot reenter VR because already presenting');
return;
}
requestPresent(vrDisplay).then(successEnterVR, errorRequestPresent).catch(errorEnterVR);
}); |
Permission API makes sense, plus pseudo code LGTM. |
Is queryDisplays permission required? One one hand it definitely is exploitable tracking data, on other hand so is mouse position data. Also lets page determine if and what model of device you own. You can also imagine other exploits when system/chome UI is showing. Obviously it would simplify things if not required. |
Also currently spec Security Concerns says:
This could be clarified unless intend no permission required (just user gesture required perhaps). I kind of don't like having two permissions. (And anyway if did would probably have a UA setting to ignore for all sites for one/both). |
I vote no to introducing a permission to query the displays (i.e., to call
That was my initial suggestion. Introducing a permission (in the Permissions API sense) seems a bit much, introduces a dependency on the Permissions API (which only Chrome has shipped to release), and introduces a ton of user experience implications that I don't think we've properly thought through with link traversal. Once we add it, it's going to be next to impossible to remove. Per my earlier comment, I vote for this simpler approach to gate on a user gesture for the initial user request of entering VR:
|
FWIW I also vote no on introducing a permission here, but ultimately that will be up to the security/privacy people on the Chrome team and not me. :( In the meantime I won't add one voluntarily and I'll push back if one is requested. |
Moved to immersive-web/webxr#30 |
I seem to recall some discussion of enabling linking directly from one VR web site to another without having to stop presenting. The spec as it is doesn't seem to handle that.
This is a potentially tricky case, so I understand wanting to hold off on implementation until more progress is made in the field. But has there been any discussion about what this might look like in an API? Are we confident that the API as it currently stands leaves room for that in the future?
The text was updated successfully, but these errors were encountered: