| Index: mojo/android/system/watcher_impl.cc
|
| diff --git a/mojo/android/system/watcher_impl.cc b/mojo/android/system/watcher_impl.cc
|
| index a363a595bed0dad451da9c38ce2970bf8843d61c..b9dc2065d0df187d4520e67db7aee1a1517b4e0f 100644
|
| --- a/mojo/android/system/watcher_impl.cc
|
| +++ b/mojo/android/system/watcher_impl.cc
|
| @@ -13,6 +13,7 @@
|
| #include "base/android/library_loader/library_loader_hooks.h"
|
| #include "base/android/scoped_java_ref.h"
|
| #include "base/bind.h"
|
| +#include "base/message_loop/message_loop.h"
|
| #include "jni/WatcherImpl_jni.h"
|
| #include "mojo/public/cpp/system/handle.h"
|
| #include "mojo/public/cpp/system/watcher.h"
|
| @@ -24,25 +25,85 @@ using base::android::JavaParamRef;
|
|
|
| namespace {
|
|
|
| -class JavaWatcherCallback {
|
| +class WatcherWithMessageLoopObserver
|
| + : public base::MessageLoop::DestructionObserver {
|
| public:
|
| - JavaWatcherCallback(JNIEnv* env, const JavaParamRef<jobject>& java_watcher) {
|
| - java_watcher_.Reset(env, java_watcher);
|
| + WatcherWithMessageLoopObserver() {}
|
| +
|
| + ~WatcherWithMessageLoopObserver() override { StopObservingIfNecessary(); }
|
| +
|
| + jint Start(JNIEnv* env,
|
| + const JavaParamRef<jobject>& jcaller,
|
| + jint mojo_handle,
|
| + jint signals) {
|
| + if (!is_observing_) {
|
| + is_observing_ = true;
|
| + base::MessageLoop::current()->AddDestructionObserver(this);
|
| + }
|
| +
|
| + java_watcher_.Reset(env, jcaller);
|
| +
|
| + auto ready_callback = base::Bind(
|
| + &WatcherWithMessageLoopObserver::OnHandleReady, base::Unretained(this));
|
| +
|
| + MojoResult result =
|
| + watcher_.Start(mojo::Handle(static_cast<MojoHandle>(mojo_handle)),
|
| + static_cast<MojoHandleSignals>(signals), ready_callback);
|
| +
|
| + if (result != MOJO_RESULT_OK) {
|
| + StopObservingIfNecessary();
|
| + java_watcher_.Reset();
|
| + }
|
| +
|
| + return result;
|
| }
|
|
|
| - void OnHandleReady(MojoResult result) {
|
| - Java_WatcherImpl_onHandleReady(base::android::AttachCurrentThread(),
|
| - java_watcher_, result);
|
| + void Cancel() {
|
| + StopObservingIfNecessary();
|
| + java_watcher_.Reset();
|
| + watcher_.Cancel();
|
| }
|
|
|
| private:
|
| + void OnHandleReady(MojoResult result) {
|
| + DCHECK(!java_watcher_.is_null());
|
| +
|
| + base::android::ScopedJavaGlobalRef<jobject> java_watcher_preserver;
|
| + if (result == MOJO_RESULT_CANCELLED) {
|
| + StopObservingIfNecessary();
|
| + java_watcher_preserver = std::move(java_watcher_);
|
| + }
|
| +
|
| + Java_WatcherImpl_onHandleReady(
|
| + base::android::AttachCurrentThread(),
|
| + java_watcher_.is_null() ? java_watcher_preserver : java_watcher_,
|
| + result);
|
| + }
|
| +
|
| + // base::MessageLoop::DestructionObserver:
|
| + void WillDestroyCurrentMessageLoop() override {
|
| + StopObservingIfNecessary();
|
| + OnHandleReady(MOJO_RESULT_ABORTED);
|
| + }
|
| +
|
| + void StopObservingIfNecessary() {
|
| + if (is_observing_) {
|
| + is_observing_ = false;
|
| + base::MessageLoop::current()->RemoveDestructionObserver(this);
|
| + }
|
| + }
|
| +
|
| + bool is_observing_ = false;
|
| + Watcher watcher_;
|
| base::android::ScopedJavaGlobalRef<jobject> java_watcher_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(WatcherWithMessageLoopObserver);
|
| };
|
|
|
| } // namespace
|
|
|
| static jlong CreateWatcher(JNIEnv* env, const JavaParamRef<jobject>& jcaller) {
|
| - return reinterpret_cast<jlong>(new Watcher);
|
| + return reinterpret_cast<jlong>(new WatcherWithMessageLoopObserver);
|
| }
|
|
|
| static jint Start(JNIEnv* env,
|
| @@ -50,24 +111,20 @@ static jint Start(JNIEnv* env,
|
| jlong watcher_ptr,
|
| jint mojo_handle,
|
| jint signals) {
|
| - Watcher* watcher = reinterpret_cast<Watcher*>(watcher_ptr);
|
| - return watcher->Start(
|
| - mojo::Handle(static_cast<MojoHandle>(mojo_handle)),
|
| - static_cast<MojoHandleSignals>(signals),
|
| - base::Bind(&JavaWatcherCallback::OnHandleReady,
|
| - base::Owned(new JavaWatcherCallback(env, jcaller))));
|
| + auto watcher = reinterpret_cast<WatcherWithMessageLoopObserver*>(watcher_ptr);
|
| + return watcher->Start(env, jcaller, mojo_handle, signals);
|
| }
|
|
|
| static void Cancel(JNIEnv* env,
|
| const JavaParamRef<jobject>& jcaller,
|
| jlong watcher_ptr) {
|
| - reinterpret_cast<Watcher*>(watcher_ptr)->Cancel();
|
| + reinterpret_cast<WatcherWithMessageLoopObserver*>(watcher_ptr)->Cancel();
|
| }
|
|
|
| static void Delete(JNIEnv* env,
|
| const JavaParamRef<jobject>& jcaller,
|
| jlong watcher_ptr) {
|
| - delete reinterpret_cast<Watcher*>(watcher_ptr);
|
| + delete reinterpret_cast<WatcherWithMessageLoopObserver*>(watcher_ptr);
|
| }
|
|
|
| bool RegisterWatcherImpl(JNIEnv* env) {
|
|
|