// 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/edk/js/waiting_callback.h" #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "gin/per_context_data.h" namespace mojo { namespace edk { namespace js { namespace { v8::Handle<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) { return v8::Private::ForApi( isolate, gin::StringToV8(isolate, "::mojo::js::WaitingCallback")); } } // namespace gin::WrapperInfo WaitingCallback::kWrapperInfo = { gin::kEmbedderNativeGin }; // static gin::Handle<WaitingCallback> WaitingCallback::Create( v8::Isolate* isolate, v8::Handle<v8::Function> callback, gin::Handle<HandleWrapper> handle_wrapper, MojoHandleSignals signals, bool one_shot) { gin::Handle<WaitingCallback> waiting_callback = gin::CreateHandle( isolate, new WaitingCallback(isolate, callback, one_shot)); MojoResult result = waiting_callback->watcher_.Start( handle_wrapper->get(), signals, base::Bind(&WaitingCallback::OnHandleReady, base::Unretained(waiting_callback.get()))); // The signals may already be unsatisfiable. if (result == MOJO_RESULT_FAILED_PRECONDITION) waiting_callback->OnHandleReady(MOJO_RESULT_FAILED_PRECONDITION); return waiting_callback; } void WaitingCallback::Cancel() { if (watcher_.IsWatching()) watcher_.Cancel(); } WaitingCallback::WaitingCallback(v8::Isolate* isolate, v8::Handle<v8::Function> callback, bool one_shot) : one_shot_(one_shot), weak_factory_(this) { v8::Handle<v8::Context> context = isolate->GetCurrentContext(); runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr(); GetWrapper(isolate) ->SetPrivate(context, GetHiddenPropertyName(isolate), callback) .FromJust(); } WaitingCallback::~WaitingCallback() { Cancel(); } void WaitingCallback::OnHandleReady(MojoResult result) { if (!runner_) return; gin::Runner::Scope scope(runner_.get()); v8::Isolate* isolate = runner_->GetContextHolder()->isolate(); v8::Handle<v8::Value> hidden_value = GetWrapper(isolate) ->GetPrivate(runner_->GetContextHolder()->context(), GetHiddenPropertyName(isolate)) .ToLocalChecked(); v8::Handle<v8::Function> callback; CHECK(gin::ConvertFromV8(isolate, hidden_value, &callback)); v8::Handle<v8::Value> args[] = { gin::ConvertToV8(isolate, result) }; runner_->Call(callback, runner_->global(), 1, args); if (one_shot_ || result == MOJO_RESULT_CANCELLED) { runner_.reset(); Cancel(); } } } // namespace js } // namespace edk } // namespace mojo