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/edk/js/waiting_callback.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "gin/per_context_data.h"
     10 
     11 namespace mojo {
     12 namespace edk {
     13 namespace js {
     14 
     15 namespace {
     16 
     17 v8::Handle<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) {
     18   return v8::Private::ForApi(
     19       isolate, gin::StringToV8(isolate, "::mojo::js::WaitingCallback"));
     20 }
     21 
     22 }  // namespace
     23 
     24 gin::WrapperInfo WaitingCallback::kWrapperInfo = { gin::kEmbedderNativeGin };
     25 
     26 // static
     27 gin::Handle<WaitingCallback> WaitingCallback::Create(
     28     v8::Isolate* isolate,
     29     v8::Handle<v8::Function> callback,
     30     gin::Handle<HandleWrapper> handle_wrapper,
     31     MojoHandleSignals signals,
     32     bool one_shot) {
     33   gin::Handle<WaitingCallback> waiting_callback = gin::CreateHandle(
     34       isolate, new WaitingCallback(isolate, callback, one_shot));
     35   MojoResult result = waiting_callback->watcher_.Start(
     36       handle_wrapper->get(), signals,
     37       base::Bind(&WaitingCallback::OnHandleReady,
     38                  base::Unretained(waiting_callback.get())));
     39 
     40   // The signals may already be unsatisfiable.
     41   if (result == MOJO_RESULT_FAILED_PRECONDITION)
     42     waiting_callback->OnHandleReady(MOJO_RESULT_FAILED_PRECONDITION);
     43 
     44   return waiting_callback;
     45 }
     46 
     47 void WaitingCallback::Cancel() {
     48   if (watcher_.IsWatching())
     49     watcher_.Cancel();
     50 }
     51 
     52 WaitingCallback::WaitingCallback(v8::Isolate* isolate,
     53                                  v8::Handle<v8::Function> callback,
     54                                  bool one_shot)
     55     : one_shot_(one_shot),
     56       weak_factory_(this) {
     57   v8::Handle<v8::Context> context = isolate->GetCurrentContext();
     58   runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr();
     59   GetWrapper(isolate)
     60       ->SetPrivate(context, GetHiddenPropertyName(isolate), callback)
     61       .FromJust();
     62 }
     63 
     64 WaitingCallback::~WaitingCallback() {
     65   Cancel();
     66 }
     67 
     68 void WaitingCallback::OnHandleReady(MojoResult result) {
     69   if (!runner_)
     70     return;
     71 
     72   gin::Runner::Scope scope(runner_.get());
     73   v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
     74 
     75   v8::Handle<v8::Value> hidden_value =
     76       GetWrapper(isolate)
     77           ->GetPrivate(runner_->GetContextHolder()->context(),
     78                        GetHiddenPropertyName(isolate))
     79           .ToLocalChecked();
     80   v8::Handle<v8::Function> callback;
     81   CHECK(gin::ConvertFromV8(isolate, hidden_value, &callback));
     82 
     83   v8::Handle<v8::Value> args[] = { gin::ConvertToV8(isolate, result) };
     84   runner_->Call(callback, runner_->global(), 1, args);
     85 
     86   if (one_shot_ || result == MOJO_RESULT_CANCELLED) {
     87     runner_.reset();
     88     Cancel();
     89   }
     90 }
     91 
     92 }  // namespace js
     93 }  // namespace edk
     94 }  // namespace mojo
     95