/* -*- 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/cache/StreamList.h" #include "mozilla/dom/cache/CacheStreamControlParent.h" #include "mozilla/dom/cache/Context.h" #include "mozilla/dom/cache/Manager.h" #include "nsIInputStream.h" namespace mozilla { namespace dom { namespace cache { StreamList::StreamList(Manager* aManager, Context* aContext) : mManager(aManager) , mContext(aContext) , mCacheId(INVALID_CACHE_ID) , mStreamControl(nullptr) , mActivated(false) { MOZ_DIAGNOSTIC_ASSERT(mManager); mContext->AddActivity(this); } Manager* StreamList::GetManager() const { MOZ_DIAGNOSTIC_ASSERT(mManager); return mManager; } bool StreamList::ShouldOpenStreamFor(const nsID& aId) const { NS_ASSERT_OWNINGTHREAD(StreamList); for (auto entry : mList) { if (entry.mId == aId) { return true; } } return false; } void StreamList::SetStreamControl(CacheStreamControlParent* aStreamControl) { NS_ASSERT_OWNINGTHREAD(StreamList); MOZ_DIAGNOSTIC_ASSERT(aStreamControl); // For cases where multiple streams are serialized for a single list // then the control will get passed multiple times. This is ok, but // it should be the same control each time. if (mStreamControl) { MOZ_DIAGNOSTIC_ASSERT(aStreamControl == mStreamControl); return; } mStreamControl = aStreamControl; mStreamControl->SetStreamList(this); } void StreamList::RemoveStreamControl(CacheStreamControlParent* aStreamControl) { NS_ASSERT_OWNINGTHREAD(StreamList); MOZ_DIAGNOSTIC_ASSERT(mStreamControl); MOZ_DIAGNOSTIC_ASSERT(mStreamControl == aStreamControl); mStreamControl = nullptr; } void StreamList::Activate(CacheId aCacheId) { NS_ASSERT_OWNINGTHREAD(StreamList); MOZ_DIAGNOSTIC_ASSERT(!mActivated); MOZ_DIAGNOSTIC_ASSERT(mCacheId == INVALID_CACHE_ID); mActivated = true; mCacheId = aCacheId; mManager->AddRefCacheId(mCacheId); mManager->AddStreamList(this); for (uint32_t i = 0; i < mList.Length(); ++i) { mManager->AddRefBodyId(mList[i].mId); } } void StreamList::Add(const nsID& aId, nsCOMPtr&& aStream) { // All streams should be added on IO thread before we set the stream // control on the owning IPC thread. MOZ_DIAGNOSTIC_ASSERT(!mStreamControl); mList.AppendElement(Entry(aId, Move(aStream))); } already_AddRefed StreamList::Extract(const nsID& aId) { NS_ASSERT_OWNINGTHREAD(StreamList); for (uint32_t i = 0; i < mList.Length(); ++i) { if (mList[i].mId == aId) { return mList[i].mStream.forget(); } } return nullptr; } void StreamList::NoteClosed(const nsID& aId) { NS_ASSERT_OWNINGTHREAD(StreamList); for (uint32_t i = 0; i < mList.Length(); ++i) { if (mList[i].mId == aId) { mList.RemoveElementAt(i); mManager->ReleaseBodyId(aId); break; } } if (mList.IsEmpty() && mStreamControl) { mStreamControl->Shutdown(); } } void StreamList::NoteClosedAll() { NS_ASSERT_OWNINGTHREAD(StreamList); for (uint32_t i = 0; i < mList.Length(); ++i) { mManager->ReleaseBodyId(mList[i].mId); } mList.Clear(); if (mStreamControl) { mStreamControl->Shutdown(); } } void StreamList::Close(const nsID& aId) { NS_ASSERT_OWNINGTHREAD(StreamList); if (mStreamControl) { mStreamControl->Close(aId); } } void StreamList::CloseAll() { NS_ASSERT_OWNINGTHREAD(StreamList); if (mStreamControl) { mStreamControl->CloseAll(); } } void StreamList::Cancel() { NS_ASSERT_OWNINGTHREAD(StreamList); CloseAll(); } bool StreamList::MatchesCacheId(CacheId aCacheId) const { NS_ASSERT_OWNINGTHREAD(StreamList); return aCacheId == mCacheId; } StreamList::~StreamList() { NS_ASSERT_OWNINGTHREAD(StreamList); MOZ_DIAGNOSTIC_ASSERT(!mStreamControl); if (mActivated) { mManager->RemoveStreamList(this); for (uint32_t i = 0; i < mList.Length(); ++i) { mManager->ReleaseBodyId(mList[i].mId); } mManager->ReleaseCacheId(mCacheId); } mContext->RemoveActivity(this); } } // namespace cache } // namespace dom } // namespace mozilla