Re: Overlap between StreamReader and FileReader

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
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)

- pause: pause the stream, do not send eof

- 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 
> <mailto: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, 23 October 2013 14:43:21 UTC