Bug 1486182: Part 1 - Include both category names and values in category enumerator. r=froydnj

Nearly all of the consumers of category enumerators require the entry value,
either along with or instead of the name. Including both by default simplifies
things considerably for most consumers, and allows us to remove the XPCOMUtils
wrapper that JS callers typically use to enumerate category entries.

Differential Revision: https://phabricator.services.mozilla.com/D4277

--HG--
extra : rebase_source : 1efe0434e150f08bb9f4d8a4c6f6e993efebf8d8
This commit is contained in:
Kris Maglione 2018-08-24 22:22:07 -07:00
Родитель 367cf770e4
Коммит 92b452df94
4 изменённых файлов: 150 добавлений и 160 удалений

Просмотреть файл

@ -13,6 +13,7 @@
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
#include "nsIStringEnumerator.h"
#include "mozilla/SimpleEnumerator.h"
#include "nsCOMPtr.h"
#include "mozilla/ModuleUtils.h"
@ -45,6 +46,8 @@
#define NS_COMMANDLINE_CID \
{ 0x23bcc750, 0xdc20, 0x460b, { 0xb2, 0xd4, 0x74, 0xd8, 0xf5, 0x8d, 0x36, 0x15 } }
using mozilla::SimpleEnumerator;
class nsCommandLine final : public nsICommandLineRunner
{
public:
@ -506,22 +509,15 @@ nsCommandLine::EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClo
getter_AddRefs(entenum));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIUTF8StringEnumerator> strenum (do_QueryInterface(entenum));
NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED);
nsAutoCString entry;
bool hasMore;
while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) {
strenum->GetNext(entry);
nsCString contractID;
rv = catman->GetCategoryEntry("command-line-handler", entry,
contractID);
if (NS_FAILED(rv))
continue;
for (auto& categoryEntry : SimpleEnumerator<nsICategoryEntry>(entenum)) {
nsAutoCString contractID;
categoryEntry->GetValue(contractID);
nsCOMPtr<nsICommandLineHandler> clh(do_GetService(contractID.get()));
if (!clh) {
nsCString entry;
categoryEntry->GetEntry(entry);
LogConsoleMessage(u"Contract ID '%s' was registered as a command line handler for entry '%s', but could not be created.",
contractID.get(), entry.get());
continue;
@ -554,16 +550,9 @@ nsCommandLine::EnumerateValidators(EnumerateValidatorsCallback aCallback, void *
nsCOMPtr<nsIUTF8StringEnumerator> strenum (do_QueryInterface(entenum));
NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED);
nsAutoCString entry;
bool hasMore;
while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) {
strenum->GetNext(entry);
nsCString contractID;
rv = catman->GetCategoryEntry("command-line-validator",
entry, contractID);
if (contractID.IsVoid())
continue;
for (auto& categoryEntry : SimpleEnumerator<nsICategoryEntry>(entenum)) {
nsAutoCString contractID;
categoryEntry->GetValue(contractID);
nsCOMPtr<nsICommandLineValidator> clv(do_GetService(contractID.get()));
if (!clv)

Просмотреть файл

@ -6,6 +6,7 @@
#include "nsIObserverService.h"
#include "mozilla/Services.h"
#include "mozilla/SimpleEnumerator.h"
#include "nsISupportsPrimitives.h"
#include "nsIStringEnumerator.h"
@ -13,6 +14,8 @@
#include "nsCategoryCache.h"
using mozilla::SimpleEnumerator;
nsCategoryObserver::nsCategoryObserver(const nsACString& aCategory)
: mCategory(aCategory)
, mCallback(nullptr)
@ -34,21 +37,15 @@ nsCategoryObserver::nsCategoryObserver(const nsACString& aCategory)
return;
}
nsCOMPtr<nsIUTF8StringEnumerator> strings = do_QueryInterface(enumerator);
MOZ_ASSERT(strings);
for (auto& categoryEntry : SimpleEnumerator<nsICategoryEntry>(enumerator)) {
nsAutoCString entryValue;
categoryEntry->GetValue(entryValue);
bool more;
while (NS_SUCCEEDED(strings->HasMore(&more)) && more) {
nsAutoCString entryName;
strings->GetNext(entryName);
if (nsCOMPtr<nsISupports> service = do_GetService(entryValue.get())) {
nsAutoCString entryName;
categoryEntry->GetEntry(entryName);
nsCString entryValue;
rv = catMan->GetCategoryEntry(aCategory, entryName, entryValue);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsISupports> service = do_GetService(entryValue.get());
if (service) {
mHash.Put(entryName, service);
}
mHash.Put(entryName, service);
}
}

Просмотреть файл

@ -9,6 +9,7 @@
#include "prio.h"
#include "prlock.h"
#include "nsArrayEnumerator.h"
#include "nsCOMPtr.h"
#include "nsTHashtable.h"
#include "nsClassHashtable.h"
@ -27,6 +28,7 @@
#include "mozilla/ArenaAllocatorExtensions.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Services.h"
#include "mozilla/SimpleEnumerator.h"
#include "ManifestParser.h"
#include "nsSimpleEnumerator.h"
@ -47,10 +49,10 @@ class nsIComponentLoaderManager;
*/
//
// BaseStringEnumerator is subclassed by EntryEnumerator and
// CategoryEnumerator
// CategoryEnumerator class
//
class BaseStringEnumerator
class CategoryEnumerator
: public nsSimpleEnumerator
, private nsIUTF8StringEnumerator
{
@ -64,11 +66,11 @@ public:
return NS_GET_IID(nsISupportsCString);
}
protected:
// Callback function for NS_QuickSort to sort mArray
static int SortCallback(const void*, const void*, void*);
static CategoryEnumerator* Create(nsClassHashtable<nsDepCharHashKey,
CategoryNode>& aTable);
BaseStringEnumerator()
protected:
CategoryEnumerator()
: mArray(nullptr)
, mCount(0)
, mSimpleCurItem(0)
@ -76,27 +78,22 @@ protected:
{
}
// A virtual destructor is needed here because subclasses of
// BaseStringEnumerator do not implement their own Release() method.
virtual ~BaseStringEnumerator()
~CategoryEnumerator() override
{
delete [] mArray;
}
void Sort();
const char** mArray;
uint32_t mCount;
uint32_t mSimpleCurItem;
uint32_t mStringCurItem;
};
NS_IMPL_ISUPPORTS_INHERITED(BaseStringEnumerator, nsSimpleEnumerator,
NS_IMPL_ISUPPORTS_INHERITED(CategoryEnumerator, nsSimpleEnumerator,
nsIUTF8StringEnumerator)
NS_IMETHODIMP
BaseStringEnumerator::HasMoreElements(bool* aResult)
CategoryEnumerator::HasMoreElements(bool* aResult)
{
*aResult = (mSimpleCurItem < mCount);
@ -104,7 +101,7 @@ BaseStringEnumerator::HasMoreElements(bool* aResult)
}
NS_IMETHODIMP
BaseStringEnumerator::GetNext(nsISupports** aResult)
CategoryEnumerator::GetNext(nsISupports** aResult)
{
if (mSimpleCurItem >= mCount) {
return NS_ERROR_FAILURE;
@ -121,7 +118,7 @@ BaseStringEnumerator::GetNext(nsISupports** aResult)
}
NS_IMETHODIMP
BaseStringEnumerator::HasMore(bool* aResult)
CategoryEnumerator::HasMore(bool* aResult)
{
*aResult = (mStringCurItem < mCount);
@ -129,7 +126,7 @@ BaseStringEnumerator::HasMore(bool* aResult)
}
NS_IMETHODIMP
BaseStringEnumerator::GetNext(nsACString& aResult)
CategoryEnumerator::GetNext(nsACString& aResult)
{
if (mStringCurItem >= mCount) {
return NS_ERROR_FAILURE;
@ -139,59 +136,120 @@ BaseStringEnumerator::GetNext(nsACString& aResult)
return NS_OK;
}
int
BaseStringEnumerator::SortCallback(const void* aE1, const void* aE2,
void* /*unused*/)
CategoryEnumerator*
CategoryEnumerator::Create(nsClassHashtable<nsDepCharHashKey, CategoryNode>&
aTable)
{
char const* const* s1 = reinterpret_cast<char const* const*>(aE1);
char const* const* s2 = reinterpret_cast<char const* const*>(aE2);
return strcmp(*s1, *s2);
}
void
BaseStringEnumerator::Sort()
{
NS_QuickSort(mArray, mCount, sizeof(mArray[0]), SortCallback, nullptr);
}
//
// EntryEnumerator is the wrapper that allows nsICategoryManager::EnumerateCategory
//
class EntryEnumerator
: public BaseStringEnumerator
{
public:
static EntryEnumerator* Create(nsTHashtable<CategoryLeaf>& aTable);
};
EntryEnumerator*
EntryEnumerator::Create(nsTHashtable<CategoryLeaf>& aTable)
{
auto* enumObj = new EntryEnumerator();
auto* enumObj = new CategoryEnumerator();
if (!enumObj) {
return nullptr;
}
enumObj->mArray = new char const* [aTable.Count()];
enumObj->mArray = new const char* [aTable.Count()];
if (!enumObj->mArray) {
delete enumObj;
return nullptr;
}
for (auto iter = aTable.Iter(); !iter.Done(); iter.Next()) {
CategoryLeaf* leaf = iter.Get();
if (leaf->value) {
enumObj->mArray[enumObj->mCount++] = leaf->GetKey();
// if a category has no entries, we pretend it doesn't exist
CategoryNode* aNode = iter.UserData();
if (aNode->Count()) {
enumObj->mArray[enumObj->mCount++] = iter.Key();
}
}
enumObj->Sort();
return enumObj;
}
class CategoryEntry final : public nsICategoryEntry
{
NS_DECL_ISUPPORTS
NS_DECL_NSICATEGORYENTRY
NS_DECL_NSISUPPORTSCSTRING
NS_DECL_NSISUPPORTSPRIMITIVE
CategoryEntry(const char* aKey, const char* aValue)
: mKey(aKey)
, mValue(aValue)
{}
const char* Key() const { return mKey; }
static CategoryEntry* Cast(nsICategoryEntry* aEntry)
{
return static_cast<CategoryEntry*>(aEntry);
}
private:
~CategoryEntry() = default;
const char* mKey;
const char* mValue;
};
NS_IMPL_ISUPPORTS(CategoryEntry, nsICategoryEntry, nsISupportsCString)
nsresult
CategoryEntry::ToString(char** aResult)
{
*aResult = moz_xstrdup(mKey);
return NS_OK;
}
nsresult
CategoryEntry::GetType(uint16_t* aType)
{
*aType = TYPE_CSTRING;
return NS_OK;
}
nsresult
CategoryEntry::GetData(nsACString& aData)
{
aData = mKey;
return NS_OK;
}
nsresult
CategoryEntry::SetData(const nsACString& aData)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
CategoryEntry::GetEntry(nsACString& aEntry)
{
aEntry = mKey;
return NS_OK;
}
nsresult
CategoryEntry::GetValue(nsACString& aValue)
{
aValue = mValue;
return NS_OK;
}
static nsresult
CreateEntryEnumerator(nsTHashtable<CategoryLeaf>& aTable,
nsISimpleEnumerator** aResult)
{
nsCOMArray<nsICategoryEntry> entries(aTable.Count());
for (auto iter = aTable.Iter(); !iter.Done(); iter.Next()) {
CategoryLeaf* leaf = iter.Get();
if (leaf->value) {
entries.AppendElement(new CategoryEntry(leaf->GetKey(), leaf->value));
}
}
entries.Sort([](nsICategoryEntry* aA, nsICategoryEntry* aB, void*) {
return strcmp(CategoryEntry::Cast(aA)->Key(), CategoryEntry::Cast(aB)->Key());
}, nullptr);
return NS_NewArrayEnumerator(aResult, entries, NS_GET_IID(nsICategoryEntry));
}
//
// CategoryNode implementations
@ -284,20 +342,8 @@ CategoryNode::DeleteLeaf(const nsACString& aEntryName)
nsresult
CategoryNode::Enumerate(nsISimpleEnumerator** aResult)
{
if (NS_WARN_IF(!aResult)) {
return NS_ERROR_INVALID_ARG;
}
MutexAutoLock lock(mLock);
EntryEnumerator* enumObj = EntryEnumerator::Create(mTable);
if (!enumObj) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aResult = enumObj;
NS_ADDREF(*aResult);
return NS_OK;
return CreateEntryEnumerator(mTable, aResult);
}
size_t
@ -308,45 +354,6 @@ CategoryNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf)
return mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
}
//
// CategoryEnumerator class
//
class CategoryEnumerator
: public BaseStringEnumerator
{
public:
static CategoryEnumerator* Create(nsClassHashtable<nsDepCharHashKey,
CategoryNode>& aTable);
};
CategoryEnumerator*
CategoryEnumerator::Create(nsClassHashtable<nsDepCharHashKey, CategoryNode>&
aTable)
{
auto* enumObj = new CategoryEnumerator();
if (!enumObj) {
return nullptr;
}
enumObj->mArray = new const char* [aTable.Count()];
if (!enumObj->mArray) {
delete enumObj;
return nullptr;
}
for (auto iter = aTable.Iter(); !iter.Done(); iter.Next()) {
// if a category has no entries, we pretend it doesn't exist
CategoryNode* aNode = iter.UserData();
if (aNode->Count()) {
enumObj->mArray[enumObj->mCount++] = iter.Key();
}
}
return enumObj;
}
//
// nsCategoryManager implementations
//
@ -745,26 +752,13 @@ NS_CreateServicesFromCategory(const char* aCategory,
return;
}
nsCOMPtr<nsIUTF8StringEnumerator> senumerator =
do_QueryInterface(enumerator);
if (!senumerator) {
NS_WARNING("Category enumerator doesn't support nsIUTF8StringEnumerator.");
return;
}
bool hasMore;
while (NS_SUCCEEDED(senumerator->HasMore(&hasMore)) && hasMore) {
for (auto& categoryEntry : SimpleEnumerator<nsICategoryEntry>(enumerator)) {
// From here on just skip any error we get.
nsAutoCString entryString;
if (NS_FAILED(senumerator->GetNext(entryString))) {
continue;
}
categoryEntry->GetEntry(entryString);
nsCString contractID;
rv = categoryManager->GetCategoryEntry(category, entryString, contractID);
if (NS_FAILED(rv)) {
continue;
}
nsAutoCString contractID;
categoryEntry->GetValue(contractID);
nsCOMPtr<nsISupports> instance = do_GetService(contractID.get());
if (!instance) {

Просмотреть файл

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "nsISupportsPrimitives.idl"
interface nsISimpleEnumerator;
@ -15,6 +16,14 @@ interface nsISimpleEnumerator;
* nsICategoryManager
*/
[scriptable, uuid(de021d54-57a3-4025-ae63-4c8eedbe74c0)]
interface nsICategoryEntry : nsISupportsCString
{
readonly attribute ACString entry;
readonly attribute ACString value;
};
[builtinclass, scriptable, uuid(3275b2cd-af6d-429a-80d7-f0c5120342ac)]
interface nsICategoryManager : nsISupports
{
@ -58,10 +67,11 @@ interface nsICategoryManager : nsISupports
* Enumerate the entries in a category.
* @param aCategory The category to be enumerated.
* @return a simple enumerator, each result QIs to
* nsISupportsCString.
* nsICategoryEntry.
*/
nsISimpleEnumerator enumerateCategory(in ACString aCategory);
/**
* Enumerate all existing categories
* @param aCategory The category to be enumerated.