| Index: mojo/edk/js/waiting_callback.cc
|
| diff --git a/mojo/edk/js/waiting_callback.cc b/mojo/edk/js/waiting_callback.cc
|
| index af34d87ef801c3fcd1a5d2331595b040de975b70..ef702c8a28bfbdcea86a54e03dee34e7fd26ed9d 100644
|
| --- a/mojo/edk/js/waiting_callback.cc
|
| +++ b/mojo/edk/js/waiting_callback.cc
|
| @@ -28,31 +28,57 @@ gin::Handle<WaitingCallback> WaitingCallback::Create(
|
| v8::Isolate* isolate,
|
| v8::Handle<v8::Function> callback,
|
| gin::Handle<HandleWrapper> handle_wrapper,
|
| - MojoHandleSignals signals) {
|
| + MojoHandleSignals signals,
|
| + bool one_shot) {
|
| gin::Handle<WaitingCallback> waiting_callback = gin::CreateHandle(
|
| - isolate, new WaitingCallback(isolate, callback, handle_wrapper));
|
| -
|
| - waiting_callback->handle_watcher_.Start(
|
| - handle_wrapper->get(), signals, MOJO_DEADLINE_INDEFINITE,
|
| - base::Bind(&WaitingCallback::OnHandleReady,
|
| - base::Unretained(waiting_callback.get())));
|
| + isolate,
|
| + new WaitingCallback(isolate, callback, handle_wrapper, one_shot));
|
| +
|
| + if (one_shot) {
|
| + waiting_callback->handle_watcher_.Start(
|
| + handle_wrapper->get(), signals, MOJO_DEADLINE_INDEFINITE,
|
| + base::Bind(&WaitingCallback::OnHandleReady,
|
| + base::Unretained(waiting_callback.get())));
|
| + } else {
|
| + waiting_callback->watcher_.Start(
|
| + handle_wrapper->get(), signals,
|
| + base::Bind(&WaitingCallback::OnHandleReady,
|
| + base::Unretained(waiting_callback.get())));
|
| + }
|
| return waiting_callback;
|
| }
|
|
|
| void WaitingCallback::Cancel() {
|
| - if (!handle_watcher_.is_watching())
|
| + if (!handle_watcher_.is_watching() && !watcher_.IsWatching())
|
| return;
|
|
|
| - RemoveHandleCloseObserver();
|
| - handle_watcher_.Stop();
|
| + if (handle_watcher_.is_watching()) {
|
| + DCHECK(one_shot_);
|
| + DCHECK(!watcher_.IsWatching());
|
| + RemoveHandleCloseObserver();
|
| + handle_watcher_.Stop();
|
| + } else {
|
| + DCHECK(!one_shot_);
|
| + DCHECK(watcher_.IsWatching());
|
| + watcher_.Cancel();
|
| + handle_wrapper_ = nullptr;
|
| + }
|
| }
|
|
|
| WaitingCallback::WaitingCallback(v8::Isolate* isolate,
|
| v8::Handle<v8::Function> callback,
|
| - gin::Handle<HandleWrapper> handle_wrapper)
|
| - : handle_wrapper_(handle_wrapper.get()),
|
| + gin::Handle<HandleWrapper> handle_wrapper,
|
| + bool one_shot)
|
| + : one_shot_(one_shot),
|
| + handle_wrapper_(handle_wrapper.get()),
|
| weak_factory_(this) {
|
| - handle_wrapper_->AddCloseObserver(this);
|
| + if (one_shot_) {
|
| + // We need to manually signal cancellation if the handle is closed while
|
| + // waiting in one-shot mode. When using non-one-shot mode this cancellation
|
| + // behavior is already provided for us.
|
| + handle_wrapper_->AddCloseObserver(this);
|
| + }
|
| +
|
| v8::Handle<v8::Context> context = isolate->GetCurrentContext();
|
| runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr();
|
| GetWrapper(isolate)
|
| @@ -65,18 +91,27 @@ WaitingCallback::~WaitingCallback() {
|
| }
|
|
|
| void WaitingCallback::RemoveHandleCloseObserver() {
|
| + DCHECK(one_shot_);
|
| handle_wrapper_->RemoveCloseObserver(this);
|
| handle_wrapper_ = nullptr;
|
| }
|
|
|
| void WaitingCallback::OnHandleReady(MojoResult result) {
|
| - RemoveHandleCloseObserver();
|
| + if (one_shot_)
|
| + RemoveHandleCloseObserver();
|
| +
|
| CallCallback(result);
|
| }
|
|
|
| void WaitingCallback::CallCallback(MojoResult result) {
|
| - DCHECK(!handle_watcher_.is_watching());
|
| - DCHECK(!handle_wrapper_);
|
| + DCHECK(
|
| + // Either this is a one-shot callback and its HandleWatcher should have been
|
| + // stopped already...
|
| + (one_shot_ && !handle_wrapper_ && !handle_watcher_.is_watching()) ||
|
| + // Or it's not a one-shot callback and the Watcher is either still active or
|
| + // was implicitly cancelled and this is a notification of that fact.
|
| + (!one_shot_ && handle_wrapper_ &&
|
| + (watcher_.IsWatching() || result == MOJO_RESULT_CANCELLED)));
|
|
|
| if (!runner_)
|
| return;
|
| @@ -97,6 +132,8 @@ void WaitingCallback::CallCallback(MojoResult result) {
|
| }
|
|
|
| void WaitingCallback::OnWillCloseHandle() {
|
| + DCHECK(one_shot_);
|
| +
|
| handle_watcher_.Stop();
|
|
|
| // This may be called from GC, so we can't execute Javascript now, call
|
| @@ -105,7 +142,7 @@ void WaitingCallback::OnWillCloseHandle() {
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| base::Bind(&WaitingCallback::CallCallback, weak_factory_.GetWeakPtr(),
|
| - MOJO_RESULT_INVALID_ARGUMENT));
|
| + MOJO_RESULT_CANCELLED));
|
| }
|
|
|
| } // namespace js
|
|
|