Home | History | Annotate | Download | only in js
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "mojo/bindings/js/waiting_callback.h"
      6 
      7 #include "gin/per_context_data.h"
      8 #include "mojo/public/cpp/environment/environment.h"
      9 
     10 namespace mojo {
     11 namespace js {
     12 
     13 namespace {
     14 
     15 v8::Handle<v8::String> GetHiddenPropertyName(v8::Isolate* isolate) {
     16   return gin::StringToSymbol(isolate, "::mojo::js::WaitingCallback");
     17 }
     18 
     19 }  // namespace
     20 
     21 gin::WrapperInfo WaitingCallback::kWrapperInfo = { gin::kEmbedderNativeGin };
     22 
     23 // static
     24 gin::Handle<WaitingCallback> WaitingCallback::Create(
     25     v8::Isolate* isolate,
     26     v8::Handle<v8::Function> callback,
     27     gin::Handle<gin::HandleWrapper> handle_wrapper,
     28     MojoHandleSignals signals) {
     29   gin::Handle<WaitingCallback> waiting_callback = gin::CreateHandle(
     30       isolate, new WaitingCallback(isolate, callback, handle_wrapper));
     31   waiting_callback->wait_id_ = Environment::GetDefaultAsyncWaiter()->AsyncWait(
     32       handle_wrapper->get().value(),
     33       signals,
     34       MOJO_DEADLINE_INDEFINITE,
     35       &WaitingCallback::CallOnHandleReady,
     36       waiting_callback.get());
     37   return waiting_callback;
     38 }
     39 
     40 void WaitingCallback::Cancel() {
     41   if (!wait_id_)
     42     return;
     43 
     44   handle_wrapper_->RemoveCloseObserver(this);
     45   handle_wrapper_ = NULL;
     46   Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_);
     47   wait_id_ = 0;
     48 }
     49 
     50 WaitingCallback::WaitingCallback(v8::Isolate* isolate,
     51                                  v8::Handle<v8::Function> callback,
     52                                  gin::Handle<gin::HandleWrapper> handle_wrapper)
     53     : wait_id_(0), handle_wrapper_(handle_wrapper.get()) {
     54   handle_wrapper_->AddCloseObserver(this);
     55   v8::Handle<v8::Context> context = isolate->GetCurrentContext();
     56   runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr();
     57   GetWrapper(isolate)->SetHiddenValue(GetHiddenPropertyName(isolate), callback);
     58 }
     59 
     60 WaitingCallback::~WaitingCallback() {
     61   Cancel();
     62 }
     63 
     64 // static
     65 void WaitingCallback::CallOnHandleReady(void* closure, MojoResult result) {
     66   static_cast<WaitingCallback*>(closure)->OnHandleReady(result);
     67 }
     68 
     69 void WaitingCallback::OnHandleReady(MojoResult result) {
     70   wait_id_ = 0;
     71   handle_wrapper_->RemoveCloseObserver(this);
     72   handle_wrapper_ = NULL;
     73 
     74   if (!runner_)
     75     return;
     76 
     77   gin::Runner::Scope scope(runner_.get());
     78   v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
     79 
     80   v8::Handle<v8::Value> hidden_value =
     81       GetWrapper(isolate)->GetHiddenValue(GetHiddenPropertyName(isolate));
     82   v8::Handle<v8::Function> callback;
     83   CHECK(gin::ConvertFromV8(isolate, hidden_value, &callback));
     84 
     85   v8::Handle<v8::Value> args[] = { gin::ConvertToV8(isolate, result) };
     86   runner_->Call(callback, runner_->global(), 1, args);
     87 }
     88 
     89 void WaitingCallback::OnWillCloseHandle() {
     90   Environment::GetDefaultAsyncWaiter()->CancelWait(wait_id_);
     91   OnHandleReady(MOJO_RESULT_INVALID_ARGUMENT);
     92 }
     93 
     94 }  // namespace js
     95 }  // namespace mojo
     96