WebIDL usage for Algorithms

TL;DR: Usage of Dictionary inheritance for Algorithms is broken.  Should
use WebIDL object type or callback interfaces instead.

BACKGROUND:
In the current spec, algorithm identifiers and parameters are passed to
encrypt(), decrypt(), etc. using dictionaries that inherit from Algorithm,
which is itself a dictionary type.  For example:
  dictionary Algorithm { DOMString name; }
  dictionary AesCbcParams : Algorithm { CryptoOperationData iv; }
  typedef (Algorithm or DOMString) AlgorithmIdentifier;
  Promise<any> encrypt(AlgorithmIdentifier algorithm, ... )

PROBLEM:
According to the WebIDL spec for handling of dictionary types, the
implementation is required to create the dictionary object by copying out
of the source object the fields specified in the type definition.
http://www.w3.org/TR/WebIDL/#es-dictionary

For WebCrypto, this means that polymorphism via inheritance of dictionaries
doesn't work.  If someone creates a dictionary that matches AesCbcParams
and passes it to encrypt(), then the WebIDL implementation will only store
the "name" field, and throw everything else away.  Anything using the
WebIDL object will not be able to see the "iv" parameter.

As far as implementation: I discovered this bug while trying to implement
using the Firefox WebIDL implementation, so clearly Firefox has this
problem :)  It appears that Chromium is internally treating "algorithm"
arguments as generic objects (not following the WebIDL spec for
dictionaries), then using a "parseAlgorithm" method to pull out relevant
information.

PROPOSED RESOLUTION:
It seems to me that we have a couple of options here.

1. "typedef object Algorithm" - Don't have the WebIDL handle any of the
internal structure of Algorithm objects, but instead lay this out in the
text of the spec.  In this case, there's no inheritance to speak of, just
lists of what parameters must be present in each use of Algorithm.  We
would need to specify at what point in the process values are extracted
from the object.

2. "callback interface Algorithm" - This would use inheritance and have the
expected behavior, since callback interfaces keep around a copy of the
provided JS object.  However, there might be some weird behaviors if people
pass in exotic objects, e.g., side-effects or changing values.  Also, the
spec would need to carefully define exactly when the properties are
accessed, and all per-spec access to the properties would need to be done
on the main thread, since it needs to be able to run script.

I have a slight preference for (2).  It continues to delegate most of the
work to WebIDL, and it seems unlikely that people will do exotic enough
things to cause trouble, given that the way WebCrypto uses these objects is
fairly straightforward.

--Richard

Received on Monday, 10 March 2014 23:11:54 UTC