UniqueContentParentKeepAlive.cpp (4751B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/UniqueContentParentKeepAlive.h" 8 9 #include "mozilla/dom/ContentParent.h" 10 11 namespace mozilla::dom { 12 13 // const reference to please some libstdc++ trait that requires the deleter to 14 // be callable on a const pointer. We still need a reference though because of 15 // the comment below. 16 void ContentParentKeepAliveDeleter::operator()(ContentParent* const& aProcess) { 17 AssertIsOnMainThread(); 18 if (RefPtr<ContentParent> process = dont_AddRef(aProcess)) { 19 // Nullify aProcess otherwise RemoveKeepAlive may end up visiting this 20 // object while it's being destroyed. 21 const_cast<ContentParent*&>(aProcess) = nullptr; 22 process->RemoveKeepAlive(mBrowserId); 23 } 24 } 25 26 void ContentParentKeepAliveDeleter::operator()( 27 ThreadsafeContentParentHandle* const& aHandle) { 28 if (RefPtr<ThreadsafeContentParentHandle> handle = dont_AddRef(aHandle)) { 29 // Nullify aHandle otherwise RemoveKeepAlive may end up visiting this 30 // object while it's being destroyed. 31 const_cast<ThreadsafeContentParentHandle*&>(aHandle) = nullptr; 32 NS_DispatchToMainThread(NS_NewRunnableFunction( 33 "ThreadsafeContentParentKeepAliveDeleter", 34 [handle = std::move(handle), browserId = mBrowserId]() { 35 AssertIsOnMainThread(); 36 if (RefPtr<ContentParent> process = handle->GetContentParent()) { 37 process->RemoveKeepAlive(browserId); 38 } 39 })); 40 } 41 } 42 43 UniqueContentParentKeepAlive UniqueContentParentKeepAliveFromThreadsafe( 44 UniqueThreadsafeContentParentKeepAlive&& aKeepAlive) { 45 AssertIsOnMainThread(); 46 if (aKeepAlive) { 47 uint64_t browserId = aKeepAlive.get_deleter().mBrowserId; 48 RefPtr<ThreadsafeContentParentHandle> handle = 49 dont_AddRef(aKeepAlive.release()); 50 RefPtr<ContentParent> process = handle->GetContentParent(); 51 return UniqueContentParentKeepAlive{process.forget().take(), 52 {.mBrowserId = browserId}}; 53 } 54 return nullptr; 55 } 56 57 UniqueThreadsafeContentParentKeepAlive UniqueContentParentKeepAliveToThreadsafe( 58 UniqueContentParentKeepAlive&& aKeepAlive) { 59 AssertIsOnMainThread(); 60 if (aKeepAlive) { 61 uint64_t browserId = aKeepAlive.get_deleter().mBrowserId; 62 RefPtr<ContentParent> process = dont_AddRef(aKeepAlive.release()); 63 RefPtr<ThreadsafeContentParentHandle> handle = process->ThreadsafeHandle(); 64 return UniqueThreadsafeContentParentKeepAlive{handle.forget().take(), 65 {.mBrowserId = browserId}}; 66 } 67 return nullptr; 68 } 69 70 namespace { 71 72 class XpcomContentParentKeepAlive final : public nsIContentParentKeepAlive { 73 public: 74 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 75 NS_DECL_CYCLE_COLLECTION_CLASS(XpcomContentParentKeepAlive) 76 77 explicit XpcomContentParentKeepAlive( 78 UniqueContentParentKeepAlive&& aKeepAlive) 79 : mKeepAlive(std::move(aKeepAlive)) {} 80 81 NS_IMETHOD GetDomProcess(nsIDOMProcessParent** aResult) override { 82 nsCOMPtr<nsIDOMProcessParent> process = mKeepAlive.get(); 83 process.forget(aResult); 84 return NS_OK; 85 } 86 87 NS_IMETHOD InvalidateKeepAlive() override { 88 mKeepAlive = nullptr; 89 return NS_OK; 90 } 91 92 private: 93 ~XpcomContentParentKeepAlive() = default; 94 95 UniqueContentParentKeepAlive mKeepAlive; 96 }; 97 98 NS_IMPL_CYCLE_COLLECTING_ADDREF(XpcomContentParentKeepAlive) 99 NS_IMPL_CYCLE_COLLECTING_RELEASE(XpcomContentParentKeepAlive) 100 101 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XpcomContentParentKeepAlive) 102 NS_INTERFACE_MAP_ENTRY(nsIContentParentKeepAlive) 103 NS_INTERFACE_MAP_ENTRY(nsISupports) 104 NS_INTERFACE_MAP_END 105 106 NS_IMPL_CYCLE_COLLECTION_CLASS(XpcomContentParentKeepAlive) 107 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XpcomContentParentKeepAlive) 108 tmp->mKeepAlive = nullptr; 109 NS_IMPL_CYCLE_COLLECTION_UNLINK_END 110 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XpcomContentParentKeepAlive) 111 // NOTE: We traverse through mKeepAlive as it is acting as a non-copyable 112 // `RefPtr<ContentParent>`. 113 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mKeepAlive.get()) 114 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 115 116 } // namespace 117 118 already_AddRefed<nsIContentParentKeepAlive> WrapContentParentKeepAliveForJS( 119 UniqueContentParentKeepAlive&& aKeepAlive) { 120 if (!aKeepAlive) { 121 return nullptr; 122 } 123 124 MOZ_ASSERT(!aKeepAlive->IsLaunching(), 125 "Cannot expose still-launching ContentParent to JS"); 126 return MakeAndAddRef<XpcomContentParentKeepAlive>(std::move(aKeepAlive)); 127 } 128 129 } // namespace mozilla::dom