File: UniqueContentParentKeepAlive.cpp

package info (click to toggle)
firefox 143.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,617,328 kB
  • sloc: cpp: 7,478,492; javascript: 6,417,157; ansic: 3,720,058; python: 1,396,372; xml: 627,523; asm: 438,677; java: 186,156; sh: 63,477; makefile: 19,171; objc: 13,059; perl: 12,983; yacc: 4,583; cs: 3,846; pascal: 3,405; lex: 1,720; ruby: 1,003; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 53; csh: 10
file content (129 lines) | stat: -rw-r--r-- 4,751 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* -*- 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 "mozilla/dom/UniqueContentParentKeepAlive.h"

#include "mozilla/dom/ContentParent.h"

namespace mozilla::dom {

// const reference to please some libstdc++ trait that requires the deleter to
// be callable on a const pointer. We still need a reference though because of
// the comment below.
void ContentParentKeepAliveDeleter::operator()(ContentParent* const& aProcess) {
  AssertIsOnMainThread();
  if (RefPtr<ContentParent> process = dont_AddRef(aProcess)) {
    // Nullify aProcess otherwise RemoveKeepAlive may end up visiting this
    // object while it's being destroyed.
    const_cast<ContentParent*&>(aProcess) = nullptr;
    process->RemoveKeepAlive(mBrowserId);
  }
}

void ContentParentKeepAliveDeleter::operator()(
    ThreadsafeContentParentHandle* const& aHandle) {
  if (RefPtr<ThreadsafeContentParentHandle> handle = dont_AddRef(aHandle)) {
    // Nullify aHandle otherwise RemoveKeepAlive may end up visiting this
    // object while it's being destroyed.
    const_cast<ThreadsafeContentParentHandle*&>(aHandle) = nullptr;
    NS_DispatchToMainThread(NS_NewRunnableFunction(
        "ThreadsafeContentParentKeepAliveDeleter",
        [handle = std::move(handle), browserId = mBrowserId]() {
          AssertIsOnMainThread();
          if (RefPtr<ContentParent> process = handle->GetContentParent()) {
            process->RemoveKeepAlive(browserId);
          }
        }));
  }
}

UniqueContentParentKeepAlive UniqueContentParentKeepAliveFromThreadsafe(
    UniqueThreadsafeContentParentKeepAlive&& aKeepAlive) {
  AssertIsOnMainThread();
  if (aKeepAlive) {
    uint64_t browserId = aKeepAlive.get_deleter().mBrowserId;
    RefPtr<ThreadsafeContentParentHandle> handle =
        dont_AddRef(aKeepAlive.release());
    RefPtr<ContentParent> process = handle->GetContentParent();
    return UniqueContentParentKeepAlive{process.forget().take(),
                                        {.mBrowserId = browserId}};
  }
  return nullptr;
}

UniqueThreadsafeContentParentKeepAlive UniqueContentParentKeepAliveToThreadsafe(
    UniqueContentParentKeepAlive&& aKeepAlive) {
  AssertIsOnMainThread();
  if (aKeepAlive) {
    uint64_t browserId = aKeepAlive.get_deleter().mBrowserId;
    RefPtr<ContentParent> process = dont_AddRef(aKeepAlive.release());
    RefPtr<ThreadsafeContentParentHandle> handle = process->ThreadsafeHandle();
    return UniqueThreadsafeContentParentKeepAlive{handle.forget().take(),
                                                  {.mBrowserId = browserId}};
  }
  return nullptr;
}

namespace {

class XpcomContentParentKeepAlive final : public nsIContentParentKeepAlive {
 public:
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_CLASS(XpcomContentParentKeepAlive)

  explicit XpcomContentParentKeepAlive(
      UniqueContentParentKeepAlive&& aKeepAlive)
      : mKeepAlive(std::move(aKeepAlive)) {}

  NS_IMETHOD GetDomProcess(nsIDOMProcessParent** aResult) override {
    nsCOMPtr<nsIDOMProcessParent> process = mKeepAlive.get();
    process.forget(aResult);
    return NS_OK;
  }

  NS_IMETHOD InvalidateKeepAlive() override {
    mKeepAlive = nullptr;
    return NS_OK;
  }

 private:
  ~XpcomContentParentKeepAlive() = default;

  UniqueContentParentKeepAlive mKeepAlive;
};

NS_IMPL_CYCLE_COLLECTING_ADDREF(XpcomContentParentKeepAlive)
NS_IMPL_CYCLE_COLLECTING_RELEASE(XpcomContentParentKeepAlive)

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XpcomContentParentKeepAlive)
  NS_INTERFACE_MAP_ENTRY(nsIContentParentKeepAlive)
  NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END

NS_IMPL_CYCLE_COLLECTION_CLASS(XpcomContentParentKeepAlive)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XpcomContentParentKeepAlive)
  tmp->mKeepAlive = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XpcomContentParentKeepAlive)
  // NOTE: We traverse through mKeepAlive as it is acting as a non-copyable
  // `RefPtr<ContentParent>`.
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mKeepAlive.get())
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

}  // namespace

already_AddRefed<nsIContentParentKeepAlive> WrapContentParentKeepAliveForJS(
    UniqueContentParentKeepAlive&& aKeepAlive) {
  if (!aKeepAlive) {
    return nullptr;
  }

  MOZ_ASSERT(!aKeepAlive->IsLaunching(),
             "Cannot expose still-launching ContentParent to JS");
  return MakeAndAddRef<XpcomContentParentKeepAlive>(std::move(aKeepAlive));
}

}  // namespace mozilla::dom