зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
367cf770e4
Коммит
92b452df94
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче