1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2014 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/js/drain_data.h" 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stddef.h> 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdint.h> 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/bind.h" 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "gin/array_buffer.h" 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "gin/converter.h" 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "gin/dictionary.h" 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "gin/per_context_data.h" 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "gin/per_isolate_data.h" 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/public/cpp/system/core.h" 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo { 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace edk { 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace js { 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezDrainData::DrainData(v8::Isolate* isolate, mojo::Handle handle) 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : isolate_(isolate), handle_(DataPipeConsumerHandle(handle.value())) { 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v8::Handle<v8::Context> context(isolate_->GetCurrentContext()); 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr(); 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez WaitForData(); 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezv8::Handle<v8::Value> DrainData::GetPromise() { 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(resolver_.IsEmpty()); 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v8::Handle<v8::Promise::Resolver> resolver( 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v8::Promise::Resolver::New(isolate_)); 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez resolver_.Reset(isolate_, resolver); 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return resolver->GetPromise(); 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezDrainData::~DrainData() { 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez resolver_.Reset(); 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid DrainData::WaitForData() { 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handle_watcher_.Start( 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::Bind(&DrainData::DataReady, base::Unretained(this))); 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid DrainData::DataReady(MojoResult result) { 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (result != MOJO_RESULT_OK) { 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DeliverData(result); 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez while (result == MOJO_RESULT_OK) { 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result = ReadData(); 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (result == MOJO_RESULT_SHOULD_WAIT) 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez WaitForData(); 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else if (result != MOJO_RESULT_OK) 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DeliverData(result); 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMojoResult DrainData::ReadData() { 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const void* buffer; 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint32_t num_bytes = 0; 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoResult result = BeginReadDataRaw( 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handle_.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (result != MOJO_RESULT_OK) 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return result; 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* p = static_cast<const char*>(buffer); 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DataBuffer* data_buffer = new DataBuffer(p, p + num_bytes); 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez data_buffers_.push_back(data_buffer); 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return EndReadDataRaw(handle_.get(), num_bytes); 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid DrainData::DeliverData(MojoResult result) { 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!runner_) { 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez delete this; 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t total_bytes = 0; 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (unsigned i = 0; i < data_buffers_.size(); i++) 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez total_bytes += data_buffers_[i]->size(); 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Create a total_bytes length ArrayBuffer return value. 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez gin::Runner::Scope scope(runner_.get()); 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v8::Handle<v8::ArrayBuffer> array_buffer = 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v8::ArrayBuffer::New(isolate_, total_bytes); 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez gin::ArrayBuffer buffer; 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ConvertFromV8(isolate_, array_buffer, &buffer); 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK_EQ(total_bytes, buffer.num_bytes()); 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Copy the data_buffers into the ArrayBuffer. 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez char* array_buffer_ptr = static_cast<char*>(buffer.bytes()); 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t offset = 0; 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (size_t i = 0; i < data_buffers_.size(); i++) { 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t num_bytes = data_buffers_[i]->size(); 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (num_bytes == 0) 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez continue; 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* data_buffer_ptr = &((*data_buffers_[i])[0]); 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez memcpy(array_buffer_ptr + offset, data_buffer_ptr, num_bytes); 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez offset += num_bytes; 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The "settled" value of the promise always includes all of the data 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // that was read before either an error occurred or the remote pipe handle 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // was closed. The latter is indicated by MOJO_RESULT_FAILED_PRECONDITION. 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v8::Handle<v8::Promise::Resolver> resolver( 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v8::Local<v8::Promise::Resolver>::New(isolate_, resolver_)); 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez gin::Dictionary dictionary = gin::Dictionary::CreateEmpty(isolate_); 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez dictionary.Set("result", result); 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez dictionary.Set("buffer", array_buffer); 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v8::Handle<v8::Value> settled_value(ConvertToV8(isolate_, dictionary)); 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (result == MOJO_RESULT_FAILED_PRECONDITION) 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez resolver->Resolve(settled_value); 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez resolver->Reject(settled_value); 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez delete this; 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace js 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace edk 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace mojo 128