Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(606)

Unified Diff: mojo/bindings/js/drain_data.cc

Issue 577733002: Mojo JS bindings: draining a DataPipe (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Revised the way the TaskObserver is managed Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/bindings/js/drain_data.cc
diff --git a/mojo/bindings/js/drain_data.cc b/mojo/bindings/js/drain_data.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1a207d62c200f9a538597c59c3efc797b8e56006
--- /dev/null
+++ b/mojo/bindings/js/drain_data.cc
@@ -0,0 +1,125 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/bindings/js/drain_data.h"
+
+#include "gin/array_buffer.h"
+#include "gin/converter.h"
+#include "gin/dictionary.h"
+#include "gin/per_context_data.h"
+#include "gin/per_isolate_data.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+namespace js {
+
+DrainData::DrainData(v8::Isolate* isolate, mojo::Handle handle)
+ : isolate_(isolate),
+ handle_(DataPipeConsumerHandle(handle.value())),
+ wait_id_(0) {
+
+ v8::Handle<v8::Context> context(isolate_->GetCurrentContext());
+ runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr();
+
+ WaitForData();
+}
+
+v8::Handle<v8::Value> DrainData::GetPromise() {
+ CHECK(resolver_.IsEmpty());
+ v8::Handle<v8::Promise::Resolver> resolver(
+ v8::Promise::Resolver::New(isolate_));
+ resolver_.Reset(isolate_, resolver);
+ return resolver->GetPromise();
+}
+
+DrainData::~DrainData() {
+ if (wait_id_)
+ Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_);
+ resolver_.Reset();
+}
+
+void DrainData::WaitForData() {
+ wait_id_ = Environment::GetDefaultAsyncWaiter()->AsyncWait(
+ handle_.get().value(),
+ MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_DEADLINE_INDEFINITE,
+ &DrainData::WaitCompleted,
+ this);
+}
+
+void DrainData::DataReady(MojoResult result) {
+ wait_id_ = 0;
+ if (result != MOJO_RESULT_OK) {
+ DeliverData(result);
+ return;
+ }
+ while(result == MOJO_RESULT_OK) {
Matt Perry 2014/09/24 00:39:42 space before (
hansmuller 2014/09/24 17:47:53 Done.
+ result = ReadData();
+ if (result == MOJO_RESULT_SHOULD_WAIT)
+ WaitForData();
+ else if (result != MOJO_RESULT_OK)
+ DeliverData(result);
+ }
+}
+
+MojoResult DrainData::ReadData() {
+ const void* buffer;
+ uint32_t num_bytes = 0;
+ MojoResult result = BeginReadDataRaw(
+ handle_.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+ if (result != MOJO_RESULT_OK)
+ return result;
+ const char* p = static_cast<const char*>(buffer);
+ DataBuffer data_buffer(p, p + num_bytes);
+ data_buffers_.push_back(data_buffer);
Matt Perry 2014/09/24 00:39:41 This will make an extra copy of the data. Alternat
hansmuller 2014/09/24 17:47:53 Good point, I've done that.
+ return EndReadDataRaw(handle_.get(), num_bytes);
+}
+
+void DrainData::DeliverData(MojoResult result) {
+ if (!runner_) {
+ delete this;
+ return;
+ }
+
+ uint32_t total_bytes = 0;
+ for (unsigned i = 0; i < data_buffers_.size(); i++)
+ total_bytes += data_buffers_[i].size();
+
+ // Create a total_bytes length ArrayBuffer return value.
+ gin::Runner::Scope scope(runner_.get());
+ v8::Handle<v8::ArrayBuffer> array_buffer =
+ v8::ArrayBuffer::New(isolate_, total_bytes);
Matt Perry 2014/09/24 00:39:42 indent +2
hansmuller 2014/09/24 17:47:53 Done.
+ gin::ArrayBuffer buffer;
+ ConvertFromV8(isolate_, array_buffer, &buffer);
+ CHECK_EQ(total_bytes, buffer.num_bytes());
+
+ // Copy the data_buffers into the ArrayBuffer.
+ char* array_buffer_ptr = static_cast<char*>(buffer.bytes());
+ unsigned offset = 0;
+ for (unsigned i = 0; i < data_buffers_.size(); i++) {
+ uint32_t num_bytes = data_buffers_[i].size();
+ if (!num_bytes)
Matt Perry 2014/09/24 00:39:41 compare to 0 rather than check for logical false
hansmuller 2014/09/24 17:47:53 Done.
+ continue;
+ const char* data_buffer_ptr = &(data_buffers_[i][0]);
+ memcpy(array_buffer_ptr + offset, data_buffer_ptr, num_bytes);
Matt Perry 2014/09/24 00:39:41 It's a shame we have to copy the data again here.
hansmuller 2014/09/24 17:47:53 We don't know how much data is coming, so there is
+ offset += num_bytes;
+ }
+
+ v8::Handle<v8::Promise::Resolver> resolver(
+ v8::Local<v8::Promise::Resolver>::New(isolate_, resolver_));
+ if (result == MOJO_RESULT_FAILED_PRECONDITION) {
Matt Perry 2014/09/24 00:39:41 So the promise never resolves if there's an error?
hansmuller 2014/09/24 17:47:53 Sorry, that's my mistake! There's should be an els
+ gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate_);
+ dictionary.Set("result", result);
+ dictionary.Set("buffer", array_buffer);
+ resolver->Resolve(ConvertToV8(isolate_, dictionary));
+ }
+
+ delete this;
+}
+
+
+} // namespace js
+} // namespace mojo
+

Powered by Google App Engine
This is Rietveld 408576698