- From: Takeshi Yoshino <tyoshino@google.com>
- Date: Wed, 30 Oct 2013 20:14:13 +0900
- To: Aymeric Vitte <vitteaymeric@gmail.com>
- Cc: Kenneth Russell <kbr@google.com>, Isaac Schlueter <i@izs.me>, Jonas Sicking <jonas@sicking.cc>, Austin William Wright <aaa@bzfx.net>, Domenic Denicola <domenic@domenicdenicola.com>, "public-webapps@w3.org" <public-webapps@w3.org>
- Message-ID: <CAH9hSJYL_e+qpQvo=EMxkOL_t0sEZfqSVrWAkKKvwhJryK1oZA@mail.gmail.com>
On Wed, Oct 23, 2013 at 11:42 PM, Aymeric Vitte <vitteaymeric@gmail.com>wrote:
> Your filter idea seems to be equivalent to a createStream that I
> suggested some time ago (like node), what about:
>
> var encryptionPromise = crypto.subtle.encrypt(aesAlgorithmEncrypt, aesKey,
> sourceStream).createStream();
>
> So you don't need to modify the APIs where you can not specify the
> responseType.
>
> I was thinking to add stop/resume and pause/unpause:
>
> - stop: insert eof in the stream
>
close() does this.
> Example : finalize the hash when eof is received
>
> - resume: restart from where the stream stopped
> Example : restart the hash from the state the operation was before
> receiving eof (related to Issue22 in WebCrypto that was closed without any
> solution, might imply to clone the state of the operation)
>
>
Should it really be a part of Streams API? How about just making the filter
(not Stream itself) returned by WebCrypto reusable and add some method to
recycle it?
> - pause: pause the stream, do not send eof
>
>
Sorry, what will be paused? Output?
> - unpause: restart the stream
>
> And flow control should be back and explicit, not sure right now how to
> define it but I think it's impossible for a js app to do a precise flow
> control, and for existing APIs like WebSockets it's not easy to control the
> flow and avoid in some situations to overload the UA.
>
> Regards,
>
> Aymeric
>
> Le 21/10/2013 13:14, Takeshi Yoshino a écrit :
>
> Sorry for blank of ~2 weeks.
>
> On Fri, Oct 4, 2013 at 5:57 PM, Aymeric Vitte <vitteaymeric@gmail.com>wrote:
>
>> I am still not very familiar with promises, but if I take your
>> preceeding example:
>>
>>
>> var sourceStream = xhr.response;
>> var resultStream = new Stream();
>> var fileWritingPromise = fileWriter.write(resultStream);
>> var encryptionPromise = crypto.subtle.encrypt(aesAlgorithmEncrypt,
>> aesKey, sourceStream, resultStream);
>> Promise.all(fileWritingPromise, encryptionPromise).then(
>> ...
>> );
>>
>
> I made a mistake. The argument of Promise.all should be an Array. So,
> [fileWritingPromise, encryptionPromise].
>
>
>>
>>
>> shoud'nt it be more something like:
>>
>> var sourceStream = xhr.response;
>> var encryptionPromise = crypto.subtle.encrypt(aesAlgorithmEncrypt,
>> aesKey);
>> var resultStream=sourceStream.pipe(encryptionPromise);
>> var fileWritingPromise = fileWriter.write(resultStream);
>> Promise.all(fileWritingPromise, encryptionPromise).then(
>> ...
>> );
>>
>
> Promises just tell the user completion of each operation with some value
> indicating the result of the operation. It's not destination of data.
>
> Do you think it's good to create objects representing each encrypt
> operation? So, some objects called "filter" is introduced and the code
> would be like:
>
> var pipeToFilterPromise;
>
> var encryptionFilter;
> var fileWriter;
>
> xhr.onreadystatechange = function() {
> ...
> } else if (this.readyState == this.LOADING) {
> if (this.status != 200) {
> ...
> }
>
> var sourceStream = xhr.response;
>
> encryptionFilter =
> crypto.subtle.createEncryptionFilter(aesAlgorithmEncrypt, aesKey);
> // Starts the filter.
> var encryptionPromise = encryptionFilter.encrypt();
> // Also starts pouring data but separately from promise creation.
> pipeToFilterPromise = sourceStream.pipe(encryptionFilter);
>
> fileWriter = ...;
> // encryptionFilter works as data producer for FileWriter.
> var fileWritingPromise = fileWriter.write(encryptionFilter);
>
> // Set only handler for rejection now.
> pipeToFilterPromise.catch(
> function(result) {
> xhr.abort();
> encryptionFilter.abort();
> fileWriter.abort();
> }
> );
>
> encryptionPromise.catch(
> function(result) {
> xhr.abort();
> fileWriter.abort();
> }
> );
>
> fileWritingPromise.catch(
> function(result) {
> xhr.abort();
> encryptionFilter.abort();
> }
> );
>
> // As encryptionFilter will be (successfully) closed only
> // when XMLHttpRequest and pipe() are both successful.
> // So, it's ok to set handler for fulfillment now.
> Promise.all([encryptionPromise, fileWritingPromise]).then(
> function(result) {
> // Done everything successfully!
> // We come here only when encryptionFilter is close()-ed.
> fileWriter.close();
> processFile();
> }
> );
> } else if (this.readyState == this.DONE) {
> if (this.status != 200) {
> encryptionFilter.abort();
> fileWriter.abort();
> } else {
> // Now we know that XHR was successful.
> // Let's close() the filter to finish encryption
> // successfully.
> pipeToFilterPromise.then(
> function(result) {
> // XMLHttpRequest closes sourceStream but pipe()
> // resolves pipeToFilterPromise without closing
> // encryptionFilter.
> encryptionFilter.close();
> }
> );
> }
> }
> };
> xhr.send();
>
> encryptionFilter has the same interface as normal stream but encrypts
> piped data. Encrypted data is readable from it. It has special methods,
> encrypt() and abort().
>
> processFile() is hypothetical function must be called only when all of
> loading, encryption and saving to file were successful.
>
>
>>
>> or
>>
>> var sourceStream = xhr.response;
>> var encryptionPromise = crypto.subtle.encrypt(aesAlgorithmEncrypt,
>> aesKey);
>> var hashPromise = crypto.subtle.digest(hash);
>> var resultStream = sourceStream.pipe([encryptionPromise,hashPromise]);
>> var fileWritingPromise = fileWriter.write(resultStream);
>> Promise.all([fileWritingPromise, resultStream]).then(
>> ...
>> );
>>
>>
> and this should be:
>
> var sourceStream = xhr.response;
>
> encryptionFilter =
> crypto.subtle.createEncryptionFilter(aesAlgorithmEncrypt, aesKey);
> var encryptionPromise = encryptionFilter.crypt();
>
> hashFilter = crypto.subtle.createDigestFilter(hash);
> var hashPromise = hashFilter.digest();
>
> pipeToFiltersPromise = sourceStream.pipe([encryptionFilter, hashFilter]);
>
> var encryptedDataWritingPromise = fileWriter.write(encryptionFilter);
>
> var hashWritingPromise =
> Promise.all([encryptionPromise, encryptedDataWritingPromise]).then(
> function(result) {
> return fileWriter.write(hashFilter)
> },
> ...
> );
>
> Promise.all([hashPromise, hashWritingPromise]).then(
> function(result) {
> fileWriter.close();
> processFile();
> },
> ...
> );
>
> Or, we can also choose to let the writer API to create a special object
> that has the Stream interface for receiving input and then let
> encryptionFilter and hashFilter to pipe() to it.
>
> ...
> pipeToFiltersPromise = sourceStream.pipe([encryptionFilter, hashFilter]);
> var streamForFileWrite = fileWriter.createStreamForWrite(encryptionFilter);
> var encryptedDataWritingPromise =
> encryptionFilter.pipe(streamForFileWrite);
> var hashWritingPromise =
> Promise.all([encryptionPromise, encryptedDataWritingPromise]).then(
> function(result) {
> return hashFilter.pipe(streamForWrite);
> },
> ...
> );
>
>
>
> --
> Peersm : http://www.peersm.com
> node-Tor : https://www.github.com/Ayms/node-Tor
> GitHub : https://www.github.com/Ayms
>
>
Received on Wednesday, 30 October 2013 11:15:06 UTC