tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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