Allow a manifest to register contracts and cids in any order, by deferring processing of contracts until the manifest is completely parsed. This is needed for extension author sanity, and also because jar.mn packaging doesn't place registration lines in order by default.

This commit is contained in:
Benjamin Smedberg 2010-06-25 08:19:48 -04:00
parent 5ab65cc447
commit 77282b6432
4 changed files with 83 additions and 5 deletions

View File

@ -84,6 +84,8 @@ struct ManifestDirective
(nsChromeRegistry::ManifestProcessingContext& cx,
int lineno, char *const *argv,
bool platform, bool contentaccessible);
bool isContract;
};
static const ManifestDirective kParsingTable[] = {
{ "binary-component", 1, true, false, false,
@ -91,7 +93,7 @@ static const ManifestDirective kParsingTable[] = {
{ "component", 2, true, false, false,
&nsComponentManagerImpl::ManifestComponent, NULL },
{ "contract", 2, true, false, false,
&nsComponentManagerImpl::ManifestContract, NULL },
&nsComponentManagerImpl::ManifestContract, NULL, true},
{ "category", 3, true, false, false,
&nsComponentManagerImpl::ManifestCategory, NULL },
{ "content", 2, true, true, true,
@ -331,6 +333,16 @@ CheckVersionFlag(const nsString& aFlag, const nsString& aData,
return true;
}
namespace {
struct CachedDirective
{
int lineno;
char* argv[4];
};
} // anonymous namespace
void
ParseManifest(NSLocationType aType, nsILocalFile* aFile, char* buf,
bool aChromeOnly)
@ -393,6 +405,10 @@ ParseManifest(NSLocationType aType, nsILocalFile* aFile, char* buf,
gtk_minor_version);
#endif
// Because contracts must be registered after CIDs, we save and process them
// at the end.
nsTArray<CachedDirective> contracts;
char *token;
char *newline = buf;
PRUint32 line = 0;
@ -479,8 +495,22 @@ ParseManifest(NSLocationType aType, nsILocalFile* aFile, char* buf,
(nsChromeRegistry::gChromeRegistry->*(directive->regfunc))
(chromecx, line, argv, platform, contentAccessible);
}
else if (!aChromeOnly)
(nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc))
(mgrcx, line, argv);
else if (!aChromeOnly) {
if (directive->isContract) {
CachedDirective* cd = contracts.AppendElement();
cd->lineno = line;
cd->argv[0] = argv[0];
cd->argv[1] = argv[1];
}
else
(nsComponentManagerImpl::gComponentManager->*(directive->mgrfunc))
(mgrcx, line, argv);
}
}
for (PRInt32 i = 0; i < contracts.Length(); ++i) {
CachedDirective& d = contracts[i];
nsComponentManagerImpl::gComponentManager->ManifestContract
(mgrcx, d.lineno, d.argv);
}
}

View File

@ -235,6 +235,20 @@ _PlatformDeinitProfiler()
//-----------------------------------------------------------------------------
class ScopedLogging
{
public:
ScopedLogging()
{
NS_LogInit();
}
~ScopedLogging()
{
NS_LogTerm();
}
};
class ScopedXPCOM : public nsIDirectoryServiceProvider2
{
public:

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -44,6 +44,7 @@
#include "nsCOMArray.h"
#include "nsArrayEnumerator.h"
#include "nsXULAppAPI.h"
#include "nsIComponentRegistrar.h"
#define SERVICE_A_CONTRACT_ID "@mozilla.org/RegTestServiceA;1"
#define SERVICE_B_CONTRACT_ID "@mozilla.org/RegTestServiceB;1"
@ -132,6 +133,30 @@ nsresult TestRegular()
kCoreServiceA_CID, kExtServiceA_CID);
}
bool TestContractFirst()
{
nsCOMPtr<nsIComponentRegistrar> r;
NS_GetComponentRegistrar(getter_AddRefs(r));
nsCID* cid = NULL;
nsresult rv = r->ContractIDToCID("@mozilla.org/RegTestOrderC;1", &cid);
if (NS_FAILED(rv)) {
fail("RegTestOrderC: contract not registered");
return false;
}
nsCID goodcid;
goodcid.Parse("{ada15884-bb89-473c-8b50-dcfbb8447ff4}");
if (!goodcid.Equals(*cid)) {
fail("RegTestOrderC: CID doesn't match");
return false;
}
passed("RegTestOrderC");
return true;
}
static already_AddRefed<nsILocalFile>
GetRegDirectory(const char* basename, const char* dirname)
{
@ -145,6 +170,8 @@ GetRegDirectory(const char* basename, const char* dirname)
return f.forget();
}
int main(int argc, char** argv)
{
if (argc < 2)
@ -153,6 +180,7 @@ int main(int argc, char** argv)
return 1;
}
ScopedLogging logging;
const char *regPath = argv[1];
XRE_AddComponentLocation(NS_COMPONENT_LOCATION,
@ -167,5 +195,8 @@ int main(int argc, char** argv)
if (NS_FAILED(TestRegular()))
rv = 1;
if (!TestContractFirst())
rv = 1;
return rv;
}

View File

@ -1,2 +1,5 @@
component {56ab1cd4-ac44-4f86-8104-171f8b8f2fc7} component.js
contract @mozilla.org/RegTestServiceA;1 {56ab1cd4-ac44-4f86-8104-171f8b8f2fc7}
contract @mozilla.org/RegTestOrderC;1 {ada15884-bb89-473c-8b50-dcfbb8447ff4}
component {ada15884-bb89-473c-8b50-dcfbb8447ff4} missing.js