MaybeDiscarded.h (4430B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_MaybeDiscarded_h 8 #define mozilla_dom_MaybeDiscarded_h 9 10 #include "mozilla/RefPtr.h" 11 12 namespace mozilla::dom { 13 14 // Wrapper type for a WindowContext or BrowsingContext instance which may be 15 // discarded, and thus unavailable in the current process. This type is used to 16 // pass WindowContext and BrowsingContext instances over IPC, as they may be 17 // discarded in the receiving process. 18 // 19 // A MaybeDiscarded can generally be implicitly converted to from a 20 // BrowsingContext* or WindowContext*, but requires an explicit check of 21 // |IsDiscarded| and call to |get| to read from. 22 template <typename T> 23 class MaybeDiscarded { 24 public: 25 MaybeDiscarded() = default; 26 MaybeDiscarded(MaybeDiscarded<T>&&) = default; 27 MaybeDiscarded(const MaybeDiscarded<T>&) = default; 28 29 // Construct from raw pointers and |nullptr|. 30 MOZ_IMPLICIT MaybeDiscarded(T* aRawPtr) 31 : mId(aRawPtr ? aRawPtr->Id() : 0), mPtr(aRawPtr) {} 32 MOZ_IMPLICIT MaybeDiscarded(decltype(nullptr)) {} 33 34 // Construct from |RefPtr<I>| 35 template <typename I, 36 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>> 37 MOZ_IMPLICIT MaybeDiscarded(RefPtr<I>&& aPtr) 38 : mId(aPtr ? aPtr->Id() : 0), mPtr(std::move(aPtr)) {} 39 template <typename I, 40 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>> 41 MOZ_IMPLICIT MaybeDiscarded(const RefPtr<I>& aPtr) 42 : mId(aPtr ? aPtr->Id() : 0), mPtr(aPtr) {} 43 44 // Basic assignment operators. 45 MaybeDiscarded<T>& operator=(const MaybeDiscarded<T>&) = default; 46 MaybeDiscarded<T>& operator=(MaybeDiscarded<T>&&) = default; 47 MaybeDiscarded<T>& operator=(decltype(nullptr)) { 48 mId = 0; 49 mPtr = nullptr; 50 return *this; 51 } 52 MaybeDiscarded<T>& operator=(T* aRawPtr) { 53 mId = aRawPtr ? aRawPtr->Id() : 0; 54 mPtr = aRawPtr; 55 return *this; 56 } 57 template <typename I> 58 MaybeDiscarded<T>& operator=(const RefPtr<I>& aRhs) { 59 mId = aRhs ? aRhs->Id() : 0; 60 mPtr = aRhs; 61 return *this; 62 } 63 template <typename I> 64 MaybeDiscarded<T>& operator=(RefPtr<I>&& aRhs) { 65 mId = aRhs ? aRhs->Id() : 0; 66 mPtr = std::move(aRhs); 67 return *this; 68 } 69 70 // Validate that the value is neither discarded nor null. 71 bool IsNullOrDiscarded() const { return !mPtr || mPtr->IsDiscarded(); } 72 bool IsDiscarded() const { return IsNullOrDiscarded() && !IsNull(); } 73 bool IsNull() const { return mId == 0; } 74 75 explicit operator bool() const { return !IsNullOrDiscarded(); } 76 77 // Extract the wrapped |T|. Must not be called on a discarded |T|. 78 T* get() const { 79 MOZ_DIAGNOSTIC_ASSERT(!IsDiscarded()); 80 return mPtr.get(); 81 } 82 already_AddRefed<T> forget() { 83 MOZ_DIAGNOSTIC_ASSERT(!IsDiscarded()); 84 return mPtr.forget(); 85 } 86 87 T* operator->() const { 88 MOZ_ASSERT(!IsNull()); 89 return get(); 90 } 91 92 // Like "get", but gets the "Canonical" version of the type. This method may 93 // only be called in the parent process. 94 auto get_canonical() const -> decltype(get()->Canonical()) { 95 if (get()) { 96 return get()->Canonical(); 97 } else { 98 return nullptr; 99 } 100 } 101 102 // The ID for the context wrapped by this MaybeDiscarded. This ID comes from a 103 // remote process, and should generally only be used for logging. A 104 // BrowsingContext with this ID may not exist in the current process. 105 uint64_t ContextId() const { return mId; } 106 107 // Tries to get the wrapped value, disregarding discarded status. 108 // This may return |nullptr| for a non-null |MaybeDiscarded|, in the case that 109 // the target is no longer available in this process. 110 T* GetMaybeDiscarded() const { return mPtr.get(); } 111 112 // Clear the value to a discarded state with the given ID. 113 void SetDiscarded(uint64_t aId) { 114 mId = aId; 115 mPtr = nullptr; 116 } 117 118 // Comparison operators required by IPDL 119 bool operator==(const MaybeDiscarded<T>& aRhs) const { 120 return mId == aRhs.mId && mPtr == aRhs.mPtr; 121 } 122 bool operator!=(const MaybeDiscarded<T>& aRhs) const { 123 return !operator==(aRhs); 124 } 125 126 private: 127 uint64_t mId = 0; 128 RefPtr<T> mPtr; 129 }; 130 131 } // namespace mozilla::dom 132 133 #endif // mozilla_dom_MaybeDiscarded_h