diff options
Diffstat (limited to 'dom/ipc/MaybeDiscarded.h')
-rw-r--r-- | dom/ipc/MaybeDiscarded.h | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/dom/ipc/MaybeDiscarded.h b/dom/ipc/MaybeDiscarded.h new file mode 100644 index 0000000000..32c0dde3b9 --- /dev/null +++ b/dom/ipc/MaybeDiscarded.h @@ -0,0 +1,133 @@ +/* -*- 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/. */ + +#ifndef mozilla_dom_MaybeDiscarded_h +#define mozilla_dom_MaybeDiscarded_h + +#include "mozilla/RefPtr.h" + +namespace mozilla::dom { + +// Wrapper type for a WindowContext or BrowsingContext instance which may be +// discarded, and thus unavailable in the current process. This type is used to +// pass WindowContext and BrowsingContext instances over IPC, as they may be +// discarded in the receiving process. +// +// A MaybeDiscarded can generally be implicitly converted to from a +// BrowsingContext* or WindowContext*, but requires an explicit check of +// |IsDiscarded| and call to |get| to read from. +template <typename T> +class MaybeDiscarded { + public: + MaybeDiscarded() = default; + MaybeDiscarded(MaybeDiscarded<T>&&) = default; + MaybeDiscarded(const MaybeDiscarded<T>&) = default; + + // Construct from raw pointers and |nullptr|. + MOZ_IMPLICIT MaybeDiscarded(T* aRawPtr) + : mId(aRawPtr ? aRawPtr->Id() : 0), mPtr(aRawPtr) {} + MOZ_IMPLICIT MaybeDiscarded(decltype(nullptr)) {} + + // Construct from |RefPtr<I>| + template <typename I, + typename = std::enable_if_t<std::is_convertible_v<I*, T*>>> + MOZ_IMPLICIT MaybeDiscarded(RefPtr<I>&& aPtr) + : mId(aPtr ? aPtr->Id() : 0), mPtr(std::move(aPtr)) {} + template <typename I, + typename = std::enable_if_t<std::is_convertible_v<I*, T*>>> + MOZ_IMPLICIT MaybeDiscarded(const RefPtr<I>& aPtr) + : mId(aPtr ? aPtr->Id() : 0), mPtr(aPtr) {} + + // Basic assignment operators. + MaybeDiscarded<T>& operator=(const MaybeDiscarded<T>&) = default; + MaybeDiscarded<T>& operator=(MaybeDiscarded<T>&&) = default; + MaybeDiscarded<T>& operator=(decltype(nullptr)) { + mId = 0; + mPtr = nullptr; + return *this; + } + MaybeDiscarded<T>& operator=(T* aRawPtr) { + mId = aRawPtr ? aRawPtr->Id() : 0; + mPtr = aRawPtr; + return *this; + } + template <typename I> + MaybeDiscarded<T>& operator=(const RefPtr<I>& aRhs) { + mId = aRhs ? aRhs->Id() : 0; + mPtr = aRhs; + return *this; + } + template <typename I> + MaybeDiscarded<T>& operator=(RefPtr<I>&& aRhs) { + mId = aRhs ? aRhs->Id() : 0; + mPtr = std::move(aRhs); + return *this; + } + + // Validate that the value is neither discarded nor null. + bool IsNullOrDiscarded() const { return !mPtr || mPtr->IsDiscarded(); } + bool IsDiscarded() const { return IsNullOrDiscarded() && !IsNull(); } + bool IsNull() const { return mId == 0; } + + explicit operator bool() const { return !IsNullOrDiscarded(); } + + // Extract the wrapped |T|. Must not be called on a discarded |T|. + T* get() const { + MOZ_DIAGNOSTIC_ASSERT(!IsDiscarded()); + return mPtr.get(); + } + already_AddRefed<T> forget() { + MOZ_DIAGNOSTIC_ASSERT(!IsDiscarded()); + return mPtr.forget(); + } + + T* operator->() const { + MOZ_ASSERT(!IsNull()); + return get(); + } + + // Like "get", but gets the "Canonical" version of the type. This method may + // only be called in the parent process. + auto get_canonical() const -> decltype(get()->Canonical()) { + if (get()) { + return get()->Canonical(); + } else { + return nullptr; + } + } + + // The ID for the context wrapped by this MaybeDiscarded. This ID comes from a + // remote process, and should generally only be used for logging. A + // BrowsingContext with this ID may not exist in the current process. + uint64_t ContextId() const { return mId; } + + // Tries to get the wrapped value, disregarding discarded status. + // This may return |nullptr| for a non-null |MaybeDiscarded|, in the case that + // the target is no longer available in this process. + T* GetMaybeDiscarded() const { return mPtr.get(); } + + // Clear the value to a discarded state with the given ID. + void SetDiscarded(uint64_t aId) { + mId = aId; + mPtr = nullptr; + } + + // Comparison operators required by IPDL + bool operator==(const MaybeDiscarded<T>& aRhs) const { + return mId == aRhs.mId && mPtr == aRhs.mPtr; + } + bool operator!=(const MaybeDiscarded<T>& aRhs) const { + return !operator==(aRhs); + } + + private: + uint64_t mId = 0; + RefPtr<T> mPtr; +}; + +} // namespace mozilla::dom + +#endif // mozilla_dom_MaybeDiscarded_h |