Re: Preferred Method for Gating Access to Features

0 views
Skip to first unread message

Jeremy Roman

unread,
Apr 6, 2017, 8:23:44 PM4/6/17
to Reilly Grant, platform-architecture-dev, WebUSB, platform-predictability
+platform-predictability-dev

This strikes me as more of a platform predictability or spec issue.

In my view, the advantage of "feature not present" == missing property is that it means there are fewer cases to consider: the "feature disabled" case is equivalent to "this is a browser that never implemented the feature".

On Thu, Apr 6, 2017 at 8:19 PM, Reilly Grant <rei...@chromium.org> wrote:
One more thing:

When a method like getDevices() returns a Promise should it throw a SecurityError synchronously or reject the Promise?

On Thu, Apr 6, 2017 at 5:17 PM Reilly Grant <rei...@chromium.org> wrote:
We have developed a number of methods to gate access to feature: [SecureContext], Origin Trials, Feature Policy and possibly more that I do not know about. The question is, when one of these methods indicates that a feature should be unavailable how do we expose that state to the developer? Let's take WebUSB as an example. It has the following (simplified) WebIDL:

[SecureContext]
partial interface Navigator {
  readonly attribute USB usb;
};

interface USB : EventTarget {
  attribute EventHandler onconnect;
  attribute EventHandler ondisconnect;
  Promise<sequence<USBDevice>> getDevices();
};

The current behavior of [SecureContext] is to not expose the usb attribute at all in an insecure context. This achieves the goal but is not developer-friendly because it gives no indication why an attribute that should be present on the Navigator object is not. Origin Trials implement the same behavior and highlight the problem because token expiration is a frequent event and yet difficult to debug because it generates an opaque "cannot read property of undefined" error message. There was also discussion of the cost of performing these checks for every conditionally activated feature when the V8 context is created.

Let's consider what would happen if we pushed these checks down through the various layers. If the usb attribute getter threw an exception it would help the developer friendliness problem but cause trouble for feature detection because now if (navigator.usb) { ... } would throw.

Checking inside the implementation of each method in the USB interface would preserve the ability to do feature detection but now increases the burden on Blink developers to ensure that correct checks are added to all methods. It would be nice to do this in the generated bindings layer. The EventHandler attributes and addEventListener method pose an interesting additional challenge. In this case it makes sense to allow adding an event listener but it will never be called. The preferred behavior for other attributes may be different.

Thoughts?

--
You received this message because you are subscribed to the Google Groups "platform-architecture-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-architecture-dev+unsub...@chromium.org.
To post to this group, send email to platform-architecture-dev@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CAEmk%3DMYY2tvpyn1RBWzi557XF6NbyAb_kaLfF4uPYMnMNWDQOg%40mail.gmail.com.

Reilly Grant

unread,
Apr 6, 2017, 8:34:06 PM4/6/17
to Jeremy Roman, platform-architecture-dev, WebUSB, platform-predictability, Ian Clelland
Another thing I forgot to mention is that as currently implemented Feature Policy cannot be used to disable a feature by not installing its bindings because the feature policy itself has not been installed at that point. This is perhaps resolvable but is beyond my knowledge of the systems involved. It also runs up against the earlier discussions over adding an ever increasing amount of logic to installConditionalFeaturesForModules().

To unsubscribe from this group and stop receiving emails from it, send an email to platform-architect...@chromium.org.
To post to this group, send email to platform-arc...@chromium.org.
--
You received this message because you are subscribed to the Google Groups "WebUSB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webusb+un...@chromium.org.
To post to this group, send email to web...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/webusb/CACuR13cepKk%2B%2B4QTFEA9EkDNQ%3DkfsB3iqqa%3DKvMLi65Jme02hg%40mail.gmail.com.

Kentaro Hara

unread,
Apr 6, 2017, 11:42:18 PM4/6/17
to Reilly Grant, Jeremy Roman, platform-architecture-dev, WebUSB, platform-predictability, Ian Clelland
In my view, the advantage of "feature not present" == missing property is that it means there are fewer cases to consider: the "feature disabled" case is equivalent to "this is a browser that never implemented the feature".

Yeah, currently this is our assumption.

If the feature is disabled, the DOM attribute/operation does not exist in the first place. In other words:

  Object.getOwnPropertyDescriptor(navigator, "usb");

returns undefined. Since the DOM attribute/operation does not exist, there's nothing we can do in the generated code or Blink. The generated code is never called back.

We discussed this behavior when we implemented Origin Trials. There was an idea to define navigator.usb but let it return undefined when the feature is disabled. Then developers can distinguish the two cases:

a) The DOM attribute/operation is not supported
b) The DOM attribute/operation is disabled for some reason

At that time the conclusion was that we want the behavior a). If the behavior is not developer-friendly, it would be worth revisiting the discussion.



On Fri, Apr 7, 2017 at 9:33 AM, Reilly Grant <rei...@chromium.org> wrote:
Another thing I forgot to mention is that as currently implemented Feature Policy cannot be used to disable a feature by not installing its bindings because the feature policy itself has not been installed at that point. This is perhaps resolvable but is beyond my knowledge of the systems involved. It also runs up against the earlier discussions over adding an ever increasing amount of logic to installConditionalFeaturesForModules().

On Thu, Apr 6, 2017 at 5:23 PM Jeremy Roman <jbr...@chromium.org> wrote:
+platform-predictability-dev

This strikes me as more of a platform predictability or spec issue.

In my view, the advantage of "feature not present" == missing property is that it means there are fewer cases to consider: the "feature disabled" case is equivalent to "this is a browser that never implemented the feature".

On Thu, Apr 6, 2017 at 8:19 PM, Reilly Grant <rei...@chromium.org> wrote:
One more thing:

When a method like getDevices() returns a Promise should it throw a SecurityError synchronously or reject the Promise?

On Thu, Apr 6, 2017 at 5:17 PM Reilly Grant <rei...@chromium.org> wrote:
We have developed a number of methods to gate access to feature: [SecureContext], Origin Trials, Feature Policy and possibly more that I do not know about. The question is, when one of these methods indicates that a feature should be unavailable how do we expose that state to the developer? Let's take WebUSB as an example. It has the following (simplified) WebIDL:

[SecureContext]
partial interface Navigator {
  readonly attribute USB usb;
};

interface USB : EventTarget {
  attribute EventHandler onconnect;
  attribute EventHandler ondisconnect;
  Promise<sequence<USBDevice>> getDevices();
};

The current behavior of [SecureContext] is to not expose the usb attribute at all in an insecure context. This achieves the goal but is not developer-friendly because it gives no indication why an attribute that should be present on the Navigator object is not. Origin Trials implement the same behavior and highlight the problem because token expiration is a frequent event and yet difficult to debug because it generates an opaque "cannot read property of undefined" error message. There was also discussion of the cost of performing these checks for every conditionally activated feature when the V8 context is created.

Let's consider what would happen if we pushed these checks down through the various layers. If the usb attribute getter threw an exception it would help the developer friendliness problem but cause trouble for feature detection because now if (navigator.usb) { ... } would throw.

Checking inside the implementation of each method in the USB interface would preserve the ability to do feature detection but now increases the burden on Blink developers to ensure that correct checks are added to all methods. It would be nice to do this in the generated bindings layer. The EventHandler attributes and addEventListener method pose an interesting additional challenge. In this case it makes sense to allow adding an event listener but it will never be called. The preferred behavior for other attributes may be different.

Thoughts?

--
You received this message because you are subscribed to the Google Groups "platform-architecture-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-architecture-dev+unsub...@chromium.org.
To post to this group, send email to platform-architecture-dev@chromium.org.
You received this message because you are subscribed to the Google Groups "WebUSB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webusb+unsubscribe@chromium.org.

--
You received this message because you are subscribed to the Google Groups "platform-architecture-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-architecture-dev+unsub...@chromium.org.
To post to this group, send email to platform-architecture-dev@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/platform-architecture-dev/CAEmk%3DMad88ySX-atY55Eo83bg97VOY4ii6hAQ71_JBDpdUtEfA%40mail.gmail.com.



--
Kentaro Hara, Tokyo, Japan

Kentaro Hara

unread,
Apr 6, 2017, 11:50:06 PM4/6/17
to Reilly Grant, Jeremy Roman, platform-architecture-dev, WebUSB, platform-predictability, Ian Clelland
On Fri, Apr 7, 2017 at 12:41 PM, Kentaro Hara <har...@chromium.org> wrote:
In my view, the advantage of "feature not present" == missing property is that it means there are fewer cases to consider: the "feature disabled" case is equivalent to "this is a browser that never implemented the feature".

Yeah, currently this is our assumption.

If the feature is disabled, the DOM attribute/operation does not exist in the first place. In other words:

  Object.getOwnPropertyDescriptor(navigator, "usb");

returns undefined. Since the DOM attribute/operation does not exist, there's nothing we can do in the generated code or Blink. The generated code is never called back.

We discussed this behavior when we implemented Origin Trials. There was an idea to define navigator.usb but let it return undefined when the feature is disabled. Then developers can distinguish the two cases:

a) The DOM attribute/operation is not supported
b) The DOM attribute/operation is disabled for some reason

At that time the conclusion was that we want the behavior a). If the behavior is not developer-friendly, it would be worth revisiting the discussion.

Sorry, this sentence was confusing. Correction:

At that time the conclusion was that we don't want to distinguish the two cases. That's what we have today. If the behavior is not developer-friendly, it would be worth revisiting the discussion.





On Fri, Apr 7, 2017 at 9:33 AM, Reilly Grant <rei...@chromium.org> wrote:
Another thing I forgot to mention is that as currently implemented Feature Policy cannot be used to disable a feature by not installing its bindings because the feature policy itself has not been installed at that point. This is perhaps resolvable but is beyond my knowledge of the systems involved. It also runs up against the earlier discussions over adding an ever increasing amount of logic to installConditionalFeaturesForModules().

On Thu, Apr 6, 2017 at 5:23 PM Jeremy Roman <jbr...@chromium.org> wrote:
+platform-predictability-dev

This strikes me as more of a platform predictability or spec issue.

In my view, the advantage of "feature not present" == missing property is that it means there are fewer cases to consider: the "feature disabled" case is equivalent to "this is a browser that never implemented the feature".

On Thu, Apr 6, 2017 at 8:19 PM, Reilly Grant <rei...@chromium.org> wrote:
One more thing:

When a method like getDevices() returns a Promise should it throw a SecurityError synchronously or reject the Promise?

On Thu, Apr 6, 2017 at 5:17 PM Reilly Grant <rei...@chromium.org> wrote:
We have developed a number of methods to gate access to feature: [SecureContext], Origin Trials, Feature Policy and possibly more that I do not know about. The question is, when one of these methods indicates that a feature should be unavailable how do we expose that state to the developer? Let's take WebUSB as an example. It has the following (simplified) WebIDL:

[SecureContext]
partial interface Navigator {
  readonly attribute USB usb;
};

interface USB : EventTarget {
  attribute EventHandler onconnect;
  attribute EventHandler ondisconnect;
  Promise<sequence<USBDevice>> getDevices();
};

The current behavior of [SecureContext] is to not expose the usb attribute at all in an insecure context. This achieves the goal but is not developer-friendly because it gives no indication why an attribute that should be present on the Navigator object is not. Origin Trials implement the same behavior and highlight the problem because token expiration is a frequent event and yet difficult to debug because it generates an opaque "cannot read property of undefined" error message. There was also discussion of the cost of performing these checks for every conditionally activated feature when the V8 context is created.

Let's consider what would happen if we pushed these checks down through the various layers. If the usb attribute getter threw an exception it would help the developer friendliness problem but cause trouble for feature detection because now if (navigator.usb) { ... } would throw.

Checking inside the implementation of each method in the USB interface would preserve the ability to do feature detection but now increases the burden on Blink developers to ensure that correct checks are added to all methods. It would be nice to do this in the generated bindings layer. The EventHandler attributes and addEventListener method pose an interesting additional challenge. In this case it makes sense to allow adding an event listener but it will never be called. The preferred behavior for other attributes may be different.

Thoughts?

--
You received this message because you are subscribed to the Google Groups "platform-architecture-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-architecture-dev+unsubsc...@chromium.org.

To post to this group, send email to platform-architecture-dev@chromium.org.
You received this message because you are subscribed to the Google Groups "WebUSB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webusb+un...@chromium.org.

--
You received this message because you are subscribed to the Google Groups "platform-architecture-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-architecture-dev+unsubsc...@chromium.org.

To post to this group, send email to platform-architecture-dev@chromium.org.
--
Kentaro Hara, Tokyo, Japan

Yuki Shiino

unread,
Apr 7, 2017, 8:15:22 AM4/7/17
to Kentaro Hara, Reilly Grant, Jeremy Roman, platform-architecture-dev, WebUSB, platform-predictability, Ian Clelland
2017-04-07 9:19 GMT+09:00 Reilly Grant <rei...@chromium.org>:
One more thing:

When a method like getDevices() returns a Promise should it throw a SecurityError synchronously or reject the Promise?

Just FYI, promise-returning functions cannot actually throw an exception.  If you throw an exception inside a promise-returning function, the exception will be magically converted into a reject promise with that exception.

- 1. If op has a return type that is a promise type, then:
- - 1. Let reject be the initial value of %Promise%.reject.
- - 2. Return the result of calling reject with %Promise% as the this object and the exception as the single argument value.

If the question is whether the reject promise should be made from a SecurityError or other things, I don't know.

Cheers,
Yuki Shiino


To unsubscribe from this group and stop receiving emails from it, send an email to platform-architecture-dev+unsub...@chromium.org.

To post to this group, send email to platform-architecture-dev@chromium.org.

Ian Clelland

unread,
Apr 7, 2017, 8:56:36 AM4/7/17
to Kentaro Hara, Reilly Grant, Jeremy Roman, platform-architecture-dev, WebUSB, platform-predictability, Ian Clelland
On Thu, Apr 6, 2017 at 11:49 PM, Kentaro Hara <har...@chromium.org> wrote:
On Fri, Apr 7, 2017 at 12:41 PM, Kentaro Hara <har...@chromium.org> wrote:
In my view, the advantage of "feature not present" == missing property is that it means there are fewer cases to consider: the "feature disabled" case is equivalent to "this is a browser that never implemented the feature".

Yeah, currently this is our assumption.

If the feature is disabled, the DOM attribute/operation does not exist in the first place. In other words:

  Object.getOwnPropertyDescriptor(navigator, "usb");

returns undefined. Since the DOM attribute/operation does not exist, there's nothing we can do in the generated code or Blink. The generated code is never called back.

We discussed this behavior when we implemented Origin Trials. There was an idea to define navigator.usb but let it return undefined when the feature is disabled. Then developers can distinguish the two cases:

a) The DOM attribute/operation is not supported
b) The DOM attribute/operation is disabled for some reason

At that time the conclusion was that we want the behavior a). If the behavior is not developer-friendly, it would be worth revisiting the discussion.

Sorry, this sentence was confusing. Correction:

At that time the conclusion was that we don't want to distinguish the two cases. That's what we have today. If the behavior is not developer-friendly, it would be worth revisiting the discussion.

The original implementations of origin trials did just that, and it ended up being a problem, as I recall -- returning an explicit 'undefined' meant that a developer trying to do feature detection with an expression like

  if (navigator.usb) { ... }

would succeed, but if they used

  if ("usb" in navigator) { ... }

then they would always detect that the feature was available. That was deemed to be confusing enough, and contrary to developer expectations, that we changed how the attributes were bound at run-time.

Ojan Vafai

unread,
Apr 7, 2017, 4:57:27 PM4/7/17
to Ian Clelland, Kentaro Hara, icle...@google.com, Reilly Grant, Jeremy Roman, platform-architecture-dev, WebUSB, platform-predictability
TL;DR: I think there should be two classes of gating access to features. 1) The FeaturePolicy/iframe-sandbox class and 2) the SecureContext/OriginTrials class. I don't think we can merge those two, but we should make sure we don't add a third class.

We thought we might be able to make FeaturePolicy behave the same as OriginTrials at first (i.e. don't expose the API), but it just didn't work out in practice because disabling a feature would often break content that didn't know to feature detect because you didn't use to have to feature detect it.

For FeaturePolicy and sandbox, we're taking it on a case-by-case basis whether the API silently fails, denies a permission, or throws an exception. For the vibrate API, it returns a false value when it fails. For permissions, the permission request is denied. We don't currently have any cases that silently fail, but we have some speculative ones in mind.

For detecting the policy, we're planning on exposing a first class API to see what policy is currently applied to your document. Details of the shape of the API are TBD. +Ian Clelland you had written up a proposal somewhere, right?

See also this related discussion about providing this guidance in a format the TAG could use instead of something chromium-specific. I'd love a volunteer to draft a one-pager outlining all of this (Reilly?). Doesn't need to be polished or accurate...just a starting point that we can iterate on. :)

To unsubscribe from this group and stop receiving emails from it, send an email to platform-architect...@chromium.org.
To post to this group, send email to platform-arc...@chromium.org.
You received this message because you are subscribed to the Google Groups "WebUSB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webusb+un...@chromium.org.
To post to this group, send email to web...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/webusb/CACuR13cepKk%2B%2B4QTFEA9EkDNQ%3DkfsB3iqqa%3DKvMLi65Jme02hg%40mail.gmail.com.

--
You received this message because you are subscribed to the Google Groups "platform-architecture-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-architect...@chromium.org.
To post to this group, send email to platform-arc...@chromium.org.
--
Kentaro Hara, Tokyo, Japan



--
Kentaro Hara, Tokyo, Japan

--
You received this message because you are subscribed to the Google Groups "platform-predictability" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-predicta...@chromium.org.
To post to this group, send email to platform-pr...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/platform-predictability/CAK_TSXLaHHTHqXT8wE5RQ-%3D4v8qJ%3D8W6a_zFuKCqKeV0qjVU7A%40mail.gmail.com.

Ian Clelland

unread,
Apr 7, 2017, 5:58:37 PM4/7/17
to Ojan Vafai, Kentaro Hara, Reilly Grant, Jeremy Roman, platform-architecture-dev, WebUSB, platform-predictability
On Fri, Apr 7, 2017 at 4:57 PM, Ojan Vafai <oj...@chromium.org> wrote:
TL;DR: I think there should be two classes of gating access to features. 1) The FeaturePolicy/iframe-sandbox class and 2) the SecureContext/OriginTrials class. I don't think we can merge those two, but we should make sure we don't add a third class.

We thought we might be able to make FeaturePolicy behave the same as OriginTrials at first (i.e. don't expose the API), but it just didn't work out in practice because disabling a feature would often break content that didn't know to feature detect because you didn't use to have to feature detect it.


That's certainly the case for established web platform features; new APIs like WebUSB and WebVR are in a different place, as developers have never written code that assumes their ubiquity. Even as an origin trial, we promise that the API will go away, and tell developers that they need to code defensively against that. 
 
For FeaturePolicy and sandbox, we're taking it on a case-by-case basis whether the API silently fails, denies a permission, or throws an exception. For the vibrate API, it returns a false value when it fails. For permissions, the permission request is denied. We don't currently have any cases that silently fail, but we have some speculative ones in mind.

For detecting the policy, we're planning on exposing a first class API to see what policy is currently applied to your document. Details of the shape of the API are TBD. +Ian Clelland you had written up a proposal somewhere, right?

To unsubscribe from this group and stop receiving emails from it, send an email to platform-architecture-dev+unsubsc...@chromium.org.
To post to this group, send email to platform-architecture-dev@chromium.org.
You received this message because you are subscribed to the Google Groups "WebUSB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webusb+un...@chromium.org.
To post to this group, send email to web...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/webusb/CACuR13cepKk%2B%2B4QTFEA9EkDNQ%3DkfsB3iqqa%3DKvMLi65Jme02hg%40mail.gmail.com.

--
You received this message because you are subscribed to the Google Groups "platform-architecture-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-architecture-dev+unsubsc...@chromium.org.
To post to this group, send email to platform-architecture-dev@chromium.org.
--
Kentaro Hara, Tokyo, Japan



--
Kentaro Hara, Tokyo, Japan

--
You received this message because you are subscribed to the Google Groups "platform-predictability" group.
To unsubscribe from this group and stop receiving emails from it, send an email to platform-predictability+unsubscr...@chromium.org.
To post to this group, send email to platform-predictability@chromium.org.

Rick Byers

unread,
Apr 10, 2017, 11:55:43 AM4/10/17
to Ian Clelland, Ojan Vafai, Kentaro Hara, Reilly Grant, Jeremy Roman, platform-architecture-dev, WebUSB, platform-predictability
I think the primary principle in this discussion is that we want to minimize the number of different (but conceptually similar) failure modes a developer needs to reason about.  If there's already some reason an API should be expected to commonly fail (eg. permission denied) then re-using that for feature policy probably makes sense.  If a new feature has no other existing failure mode, then perhaps the "API isn't exposed" failure mode is actually the best one to re-use for feature-policy?

To unsubscribe from this group and stop receiving emails from it, send an email to platform-predictability+unsub...@chromium.org.

To post to this group, send email to platform-predictability@chromium.org.
Reply all
Reply to author
Forward
0 new messages