/* -*- 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/. */
usingnamespace mozilla; class nsIComponentLoaderManager;
/* CategoryDatabase contains 0 or more 1-1 mappings of string to Category each Category contains 0 or more 1-1 mappings of string keys to string values
In other words, the CategoryDatabase is a tree, whose root is a hashtable. Internal nodes (or Categories) are hashtables. Leaf nodes are strings.
The leaf strings are allocated in an arena, because we assume they're not going to change much ;)
*/
// // CategoryEnumerator class //
class CategoryEnumerator : public nsSimpleEnumerator, private nsStringEnumeratorBase { public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSISIMPLEENUMERATOR
NS_DECL_NSIUTF8STRINGENUMERATOR
for (constauto& entry : aTable) { // if a category has no entries, we pretend it doesn't exist
CategoryNode* aNode = entry.GetWeak(); if (aNode->Count()) {
enumObj->mArray[enumObj->mCount++] = entry.GetKey();
}
}
return enumObj;
}
class CategoryEntry final : public nsICategoryEntry {
NS_DECL_ISUPPORTS
NS_DECL_NSICATEGORYENTRY
NS_DECL_NSISUPPORTSCSTRING
NS_DECL_NSISUPPORTSPRIMITIVE
void CategoryNode::DeleteLeaf(const nsACString& aEntryName) { // we don't throw any errors, because it normally doesn't matter // and it makes JS a lot cleaner
MutexAutoLock lock(mLock);
// we can just remove the entire hash entry without introspection
mTable.RemoveEntry(PromiseFlatCString(aEntryName).get());
}
size_t CategoryNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) { // We don't measure the strings pointed to by the entries because the // pointers are non-owning.
MutexAutoLock lock(mLock); return mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
}
/* static */
nsCategoryManager* nsCategoryManager::GetSingleton() { if (!gCategoryManager) {
gCategoryManager = new nsCategoryManager();
} return gCategoryManager;
}
/* static */ void nsCategoryManager::Destroy() { // The nsMemoryReporterManager gets destroyed before the nsCategoryManager, // so we don't need to unregister the nsCategoryManager as a memory reporter. // In debug builds we assert that unregistering fails, as a way (imperfect // but better than nothing) of testing the "destroyed before" part.
MOZ_ASSERT(NS_FAILED(UnregisterWeakMemoryReporter(gCategoryManager)));
nsCategoryManager::~nsCategoryManager() { // the hashtable contains entries that must be deleted before the arena is // destroyed, or else you will have PRLocks undestroyed and other Really // Bad Stuff (TM)
mTable.Clear();
}
n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf); for (constauto& data : mTable.Values()) { // We don't measure the key string because it's a non-owning pointer.
n += data->SizeOfExcludingThis(aMallocSizeOf);
}
return n;
}
namespace {
class CategoryNotificationRunnable : public Runnable { public:
CategoryNotificationRunnable(nsISupports* aSubject, constchar* aTopic, const nsACString& aData)
: Runnable("CategoryNotificationRunnable"),
mSubject(aSubject),
mTopic(aTopic),
mData(aData) {}
if (aEntryName.Length()) {
nsCOMPtr<nsISupportsCString> entry =
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID); if (!entry) { return;
}
nsresult rv = entry->SetData(aEntryName); if (NS_FAILED(rv)) { return;
}
r = new CategoryNotificationRunnable(entry, aTopic, aCategoryName);
} else {
r = new CategoryNotificationRunnable(
NS_ISUPPORTS_CAST(nsICategoryManager*, this), aTopic, aCategoryName);
}
// Before we can insert a new entry, we'll need to // find the |CategoryNode| to put it in...
CategoryNode* category;
{
MutexAutoLock lock(mLock);
category = get_category(aCategoryName);
if (!category) { // That category doesn't exist yet; let's make it.
category = mTable
.InsertOrUpdate(
MaybeStrdup(aCategoryName, &mArena),
UniquePtr<CategoryNode>{CategoryNode::Create(&mArena)})
.get();
}
}
NS_IMETHODIMP
nsCategoryManager::DeleteCategory(const nsACString& aCategoryName) { // the categories are arena-allocated, so we don't // actually delete them. We just remove all of the // leaf nodes.
/* * CreateServicesFromCategory() * * Given a category, this convenience functions enumerates the category and * creates a service of every CID or ContractID registered under the category. * If observerTopic is non null and the service implements nsIObserver, * this will attempt to notify the observer with the origin, observerTopic * string as parameter.
*/ void NS_CreateServicesFromCategory(constchar* aCategory, nsISupports* aOrigin, constchar* aObserverTopic, const char16_t* aObserverData) {
nsresult rv;
nsCOMPtr<nsICategoryManager> categoryManager =
do_GetService("@mozilla.org/categorymanager;1"); if (!categoryManager) { return;
}
for (auto& categoryEntry : SimpleEnumerator<nsICategoryEntry>(enumerator)) { // From here on just skip any error we get.
nsAutoCString entryString;
categoryEntry->GetEntry(entryString);
nsCOMPtr<nsISupports> instance = do_GetService(contractID.get()); if (!instance) {
LogMessage( "While creating services from category '%s', could not create " "service for entry '%s', contract ID '%s'",
aCategory, entryString.get(), contractID.get()); continue;
}
if (aObserverTopic) { // try an observer, if it implements it.
nsCOMPtr<nsIObserver> observer = do_QueryInterface(instance); if (observer) {
nsPrintfCString profilerStr("%s (%s)", aObserverTopic,
entryString.get());
AUTO_PROFILER_MARKER_TEXT("Category observer notification", OTHER,
MarkerStack::Capture(), profilerStr);
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE( "Category observer notification -", OTHER, profilerStr);
observer->Observe(aOrigin, aObserverTopic,
aObserverData ? aObserverData : u"");
} else {
LogMessage( "While creating services from category '%s', service for entry " "'%s', contract ID '%s' does not implement nsIObserver.",
aCategory, entryString.get(), contractID.get());
}
}
}
}
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.