diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /widget/android/jni/NativesInlines.h | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | widget/android/jni/NativesInlines.h | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/widget/android/jni/NativesInlines.h b/widget/android/jni/NativesInlines.h new file mode 100644 index 0000000000..858b677715 --- /dev/null +++ b/widget/android/jni/NativesInlines.h @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "Natives.h" + +#include "mozilla/MozPromise.h" + +namespace mozilla::jni { + +namespace details { + +/** + * When a NativeWeakPtr is detached from its owning Java object, the calling + * thread invokes the implementation's OnWeakNonIntrusiveDetach to perform + * cleanup. We complete the remainder of the cleanup sequence on the Gecko + * main thread by expecting OnWeakNonIntrusiveDetach implementations to invoke + * this Runnable before exiting. It will move itself to the main thread if it + * is not already there. + */ +template <typename NativeImpl> +class NativeWeakPtrDetachRunnable final : public Runnable { + public: + NativeWeakPtrDetachRunnable( + already_AddRefed<detail::NativeWeakPtrControlBlock<NativeImpl>> aCtlBlock, + const Object::LocalRef& aOwner, + typename NativeWeakPtrControlBlockStorageTraits<NativeImpl>::Type + aNativeImpl) + : Runnable("mozilla::jni::detail::NativeWeakPtrDetachRunnable"), + mCtlBlock(aCtlBlock), + mOwner(aOwner), + mNativeImpl(std::move(aNativeImpl)), + mHasRun(false) { + MOZ_RELEASE_ASSERT(!!mCtlBlock); + MOZ_RELEASE_ASSERT(!!mNativeImpl); + } + + NS_INLINE_DECL_REFCOUNTING_INHERITED(NativeWeakPtrDetachRunnable, Runnable) + + NS_IMETHOD Run() override { + mHasRun = true; + + if (!NS_IsMainThread()) { + NS_DispatchToMainThread(this); + return NS_OK; + } + + // Get the owner object's native implementation + auto owner = ToLocalRef(mOwner); + auto attachedNativeImpl = NativePtrTraits<NativeImpl>::Get(owner); + MOZ_RELEASE_ASSERT(!!attachedNativeImpl); + + // NativePtrTraits::ClearFinish cleans out the JNIObject's handle, which + // obviously we don't want to attempt unless that handle still points to + // our native implementation. + if (attachedNativeImpl->IsSame(mCtlBlock)) { + NativePtrTraits<NativeImpl>::ClearFinish(owner); + } + + // Now we destroy that native object. + mNativeImpl = nullptr; + mHolder.Resolve(true, __func__); + return NS_OK; + } + + RefPtr<DetachPromise> GetPromise() { return mHolder.Ensure(__func__); } + + private: + ~NativeWeakPtrDetachRunnable() { + // Guard against somebody forgetting to call this runnable. + MOZ_RELEASE_ASSERT(mHasRun, "You must run/dispatch this runnable!"); + } + + private: + RefPtr<detail::NativeWeakPtrControlBlock<NativeImpl>> mCtlBlock; + Object::GlobalRef mOwner; + MozPromiseHolder<DetachPromise> mHolder; + typename NativeWeakPtrControlBlockStorageTraits<NativeImpl>::Type mNativeImpl; + bool mHasRun; +}; + +} // namespace details + +template <typename NativeImpl> +RefPtr<DetachPromise> NativeWeakPtr<NativeImpl>::Detach() { + if (!IsAttached()) { + // Never attached to begin with; no-op + return DetachPromise::CreateAndResolve(true, __func__); + } + + auto native = mCtlBlock->Clear(); + if (!native) { + // Detach already in progress + return DetachPromise::CreateAndResolve(true, __func__); + } + + Object::LocalRef owner(mCtlBlock->GetJavaOwner()); + MOZ_RELEASE_ASSERT(!!owner); + + // Save the raw pointer before we move native into the runnable so that we + // may call OnWeakNonIntrusiveDetach on it even after moving native into + // the runnable. + NativeImpl* rawImpl = + detail::NativeWeakPtrControlBlock<NativeImpl>::StorageTraits::AsRaw( + native); + RefPtr<details::NativeWeakPtrDetachRunnable<NativeImpl>> runnable = + new details::NativeWeakPtrDetachRunnable<NativeImpl>( + mCtlBlock.forget(), owner, std::move(native)); + RefPtr<DetachPromise> promise = runnable->GetPromise(); + rawImpl->OnWeakNonIntrusiveDetach(runnable.forget()); + return promise; +} + +} // namespace mozilla::jni |