Backed out changeset b462e7b742d8 (bug 1908261) for causing multiple reftest failures...
[gecko.git] / dom / cache / StreamList.cpp
blob00dd3b585fbd6aba95d10525206a87d08144e74b
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/. */
7 #include "mozilla/dom/cache/StreamList.h"
9 #include <algorithm>
10 #include "mozilla/dom/cache/CacheStreamControlParent.h"
11 #include "mozilla/dom/cache/Context.h"
12 #include "mozilla/dom/cache/Manager.h"
13 #include "nsIInputStream.h"
15 namespace mozilla::dom::cache {
17 namespace {
19 auto MatchById(const nsID& aId) {
20 return [aId](const auto& entry) { return entry.mId == aId; };
23 } // namespace
25 StreamList::StreamList(SafeRefPtr<Manager> aManager,
26 SafeRefPtr<Context> aContext)
27 : mManager(std::move(aManager)),
28 mContext(std::move(aContext)),
29 mCacheId(INVALID_CACHE_ID),
30 mStreamControl(nullptr),
31 mActivated(false) {
32 MOZ_DIAGNOSTIC_ASSERT(mManager);
33 mContext->AddActivity(*this);
36 Manager& StreamList::GetManager() const {
37 MOZ_DIAGNOSTIC_ASSERT(mManager);
38 return *mManager;
41 bool StreamList::ShouldOpenStreamFor(const nsID& aId) const {
42 NS_ASSERT_OWNINGTHREAD(StreamList);
44 return std::any_of(mList.cbegin(), mList.cend(), MatchById(aId));
47 void StreamList::SetStreamControl(CacheStreamControlParent* aStreamControl) {
48 NS_ASSERT_OWNINGTHREAD(StreamList);
49 MOZ_DIAGNOSTIC_ASSERT(aStreamControl);
51 // For cases where multiple streams are serialized for a single list
52 // then the control will get passed multiple times. This is ok, but
53 // it should be the same control each time.
54 if (mStreamControl) {
55 MOZ_DIAGNOSTIC_ASSERT(aStreamControl == mStreamControl);
56 return;
59 mStreamControl = aStreamControl;
60 mStreamControl->SetStreamList(SafeRefPtrFromThis());
63 void StreamList::RemoveStreamControl(CacheStreamControlParent* aStreamControl) {
64 NS_ASSERT_OWNINGTHREAD(StreamList);
65 MOZ_DIAGNOSTIC_ASSERT(mStreamControl);
66 MOZ_DIAGNOSTIC_ASSERT(mStreamControl == aStreamControl);
67 mStreamControl = nullptr;
70 void StreamList::Activate(CacheId aCacheId) {
71 NS_ASSERT_OWNINGTHREAD(StreamList);
72 MOZ_DIAGNOSTIC_ASSERT(!mActivated);
73 MOZ_DIAGNOSTIC_ASSERT(mCacheId == INVALID_CACHE_ID);
74 mActivated = true;
75 mCacheId = aCacheId;
76 mManager->AddRefCacheId(mCacheId);
77 mManager->AddStreamList(*this);
79 for (uint32_t i = 0; i < mList.Length(); ++i) {
80 mManager->AddRefBodyId(mList[i].mId);
84 void StreamList::Add(const nsID& aId, nsCOMPtr<nsIInputStream>&& aStream) {
85 // All streams should be added on IO thread before we set the stream
86 // control on the owning IPC thread.
87 MOZ_DIAGNOSTIC_ASSERT(!mStreamControl);
89 // Removal of the stream will be triggered when the stream is closed,
90 // which happens only once, so let's ensure nobody adds us twice.
91 MOZ_ASSERT_DEBUG_OR_FUZZING(
92 std::find_if(mList.begin(), mList.end(), MatchById(aId)) == mList.end());
94 mList.EmplaceBack(aId, std::move(aStream));
97 already_AddRefed<nsIInputStream> StreamList::Extract(const nsID& aId) {
98 NS_ASSERT_OWNINGTHREAD(StreamList);
100 const auto it = std::find_if(mList.begin(), mList.end(), MatchById(aId));
102 // Note that if the stream has not been opened with OpenMode::Eager we will
103 // find it nullptr here and it will have to be opened by the consumer.
105 return it != mList.end() ? it->mStream.forget() : nullptr;
108 void StreamList::NoteClosed(const nsID& aId) {
109 NS_ASSERT_OWNINGTHREAD(StreamList);
111 const auto it = std::find_if(mList.begin(), mList.end(), MatchById(aId));
112 if (it != mList.end()) {
113 MOZ_ASSERT(!it->mStream, "We expect to find mStream already extracted.");
114 mList.RemoveElementAt(it);
115 mManager->ReleaseBodyId(aId);
118 if (mList.IsEmpty() && mStreamControl) {
119 mStreamControl->Shutdown();
123 void StreamList::NoteClosedAll() {
124 NS_ASSERT_OWNINGTHREAD(StreamList);
125 for (uint32_t i = 0; i < mList.Length(); ++i) {
126 mManager->ReleaseBodyId(mList[i].mId);
128 mList.Clear();
130 if (mStreamControl) {
131 mStreamControl->Shutdown();
135 void StreamList::CloseAll() {
136 NS_ASSERT_OWNINGTHREAD(StreamList);
138 if (mStreamControl && mStreamControl->CanSend()) {
139 // CloseAll will kick off everything needed for shutdown.
140 // mStreamControl may go away immediately or async.
141 mStreamControl->CloseAll();
142 } else {
143 // We cannot interact with the child, let's just clear our lists of
144 // streams to unblock shutdown.
145 if (NS_WARN_IF(mStreamControl)) {
146 // TODO: Check if this case is actually possible. We might see a late
147 // delivery of the CSCP::ActorDestroy? What would that mean for CanSend?
148 mStreamControl->LostIPCCleanup(SafeRefPtrFromThis());
149 mStreamControl = nullptr;
150 } else {
151 NoteClosedAll();
156 void StreamList::Cancel() {
157 NS_ASSERT_OWNINGTHREAD(StreamList);
158 CloseAll();
161 bool StreamList::MatchesCacheId(CacheId aCacheId) const {
162 NS_ASSERT_OWNINGTHREAD(StreamList);
163 return aCacheId == mCacheId;
166 void StreamList::DoStringify(nsACString& aData) {
167 aData.Append("StreamList "_ns + kStringifyStartInstance +
169 "List:"_ns +
170 IntToCString(static_cast<uint64_t>(mList.Length())) +
171 kStringifyDelimiter +
173 "Activated:"_ns + IntToCString(mActivated) + ")"_ns +
174 kStringifyDelimiter +
176 "Manager:"_ns + IntToCString(static_cast<bool>(mManager)));
177 if (mManager) {
178 aData.Append(" "_ns);
179 mManager->Stringify(aData);
181 aData.Append(kStringifyDelimiter +
183 "Context:"_ns + IntToCString(static_cast<bool>(mContext)));
184 if (mContext) {
185 aData.Append(" "_ns);
186 mContext->Stringify(aData);
188 aData.Append(kStringifyEndInstance);
191 StreamList::~StreamList() {
192 NS_ASSERT_OWNINGTHREAD(StreamList);
193 MOZ_DIAGNOSTIC_ASSERT(!mStreamControl);
194 if (mActivated) {
195 mManager->RemoveStreamList(*this);
196 for (uint32_t i = 0; i < mList.Length(); ++i) {
197 mManager->ReleaseBodyId(mList[i].mId);
199 mManager->ReleaseCacheId(mCacheId);
201 mContext->RemoveActivity(*this);
204 } // namespace mozilla::dom::cache