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
646 lines
15 KiB
C++
646 lines
15 KiB
C++
/* 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 "nsICommandLineRunner.h"
|
|
|
|
#include "nsICategoryManager.h"
|
|
#include "nsICommandLineHandler.h"
|
|
#include "nsICommandLineValidator.h"
|
|
#include "nsIConsoleService.h"
|
|
#include "nsIClassInfoImpl.h"
|
|
#include "nsIDOMWindow.h"
|
|
#include "nsIFile.h"
|
|
#include "nsISimpleEnumerator.h"
|
|
#include "nsIStringEnumerator.h"
|
|
#include "mozilla/SimpleEnumerator.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
#include "mozilla/ModuleUtils.h"
|
|
#include "nsISupportsImpl.h"
|
|
#include "nsNativeCharsetUtils.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsIFileProtocolHandler.h"
|
|
#include "nsIURI.h"
|
|
#include "nsUnicharUtils.h"
|
|
#include "nsTArray.h"
|
|
#include "nsTextFormatter.h"
|
|
#include "nsXPCOMCID.h"
|
|
#include "plstr.h"
|
|
#include "mozilla/Attributes.h"
|
|
|
|
#ifdef MOZ_WIDGET_COCOA
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
#include "nsILocalFileMac.h"
|
|
#elif defined(XP_WIN)
|
|
#include <windows.h>
|
|
#include <shlobj.h>
|
|
#elif defined(XP_UNIX)
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#ifdef DEBUG_bsmedberg
|
|
#define DEBUG_COMMANDLINE
|
|
#endif
|
|
|
|
#define NS_COMMANDLINE_CID \
|
|
{ 0x23bcc750, 0xdc20, 0x460b, { 0xb2, 0xd4, 0x74, 0xd8, 0xf5, 0x8d, 0x36, 0x15 } }
|
|
|
|
using mozilla::SimpleEnumerator;
|
|
|
|
class nsCommandLine final : public nsICommandLineRunner
|
|
{
|
|
public:
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSICOMMANDLINE
|
|
NS_DECL_NSICOMMANDLINERUNNER
|
|
|
|
nsCommandLine();
|
|
|
|
protected:
|
|
~nsCommandLine() = default;
|
|
|
|
typedef nsresult (*EnumerateHandlersCallback)(nsICommandLineHandler* aHandler,
|
|
nsICommandLine* aThis,
|
|
void *aClosure);
|
|
typedef nsresult (*EnumerateValidatorsCallback)(nsICommandLineValidator* aValidator,
|
|
nsICommandLine* aThis,
|
|
void *aClosure);
|
|
|
|
void appendArg(const char* arg);
|
|
MOZ_MUST_USE nsresult resolveShortcutURL(nsIFile* aFile, nsACString& outURL);
|
|
nsresult EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure);
|
|
nsresult EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure);
|
|
|
|
nsTArray<nsString> mArgs;
|
|
uint32_t mState;
|
|
nsCOMPtr<nsIFile> mWorkingDir;
|
|
nsCOMPtr<nsIDOMWindow> mWindowContext;
|
|
bool mPreventDefault;
|
|
};
|
|
|
|
nsCommandLine::nsCommandLine() :
|
|
mState(STATE_INITIAL_LAUNCH),
|
|
mPreventDefault(false)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
NS_IMPL_CLASSINFO(nsCommandLine, nullptr, 0, NS_COMMANDLINE_CID)
|
|
NS_IMPL_ISUPPORTS_CI(nsCommandLine,
|
|
nsICommandLine,
|
|
nsICommandLineRunner)
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::GetLength(int32_t *aResult)
|
|
{
|
|
*aResult = int32_t(mArgs.Length());
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::GetArgument(int32_t aIndex, nsAString& aResult)
|
|
{
|
|
NS_ENSURE_ARG_MIN(aIndex, 0);
|
|
NS_ENSURE_ARG_MAX(aIndex, int32_t(mArgs.Length() - 1));
|
|
|
|
aResult = mArgs[aIndex];
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::FindFlag(const nsAString& aFlag, bool aCaseSensitive, int32_t *aResult)
|
|
{
|
|
NS_ENSURE_ARG(!aFlag.IsEmpty());
|
|
|
|
nsDefaultStringComparator caseCmp;
|
|
nsCaseInsensitiveStringComparator caseICmp;
|
|
nsStringComparator& c = aCaseSensitive ?
|
|
static_cast<nsStringComparator&>(caseCmp) :
|
|
static_cast<nsStringComparator&>(caseICmp);
|
|
|
|
for (uint32_t f = 0; f < mArgs.Length(); f++) {
|
|
const nsString &arg = mArgs[f];
|
|
|
|
if (arg.Length() >= 2 && arg.First() == char16_t('-')) {
|
|
if (aFlag.Equals(Substring(arg, 1), c)) {
|
|
*aResult = f;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
*aResult = -1;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::RemoveArguments(int32_t aStart, int32_t aEnd)
|
|
{
|
|
NS_ENSURE_ARG_MIN(aStart, 0);
|
|
NS_ENSURE_ARG_MAX(uint32_t(aEnd) + 1, mArgs.Length());
|
|
|
|
for (int32_t i = aEnd; i >= aStart; --i) {
|
|
mArgs.RemoveElementAt(i);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::HandleFlag(const nsAString& aFlag, bool aCaseSensitive,
|
|
bool *aResult)
|
|
{
|
|
nsresult rv;
|
|
|
|
int32_t found;
|
|
rv = FindFlag(aFlag, aCaseSensitive, &found);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (found == -1) {
|
|
*aResult = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
*aResult = true;
|
|
RemoveArguments(found, found);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::HandleFlagWithParam(const nsAString& aFlag, bool aCaseSensitive,
|
|
nsAString& aResult)
|
|
{
|
|
nsresult rv;
|
|
|
|
int32_t found;
|
|
rv = FindFlag(aFlag, aCaseSensitive, &found);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
if (found == -1) {
|
|
aResult.SetIsVoid(true);
|
|
return NS_OK;
|
|
}
|
|
|
|
if (found == int32_t(mArgs.Length()) - 1) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
++found;
|
|
|
|
{ // scope for validity of |param|, which RemoveArguments call invalidates
|
|
const nsString& param = mArgs[found];
|
|
if (!param.IsEmpty() && param.First() == '-') {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
aResult = param;
|
|
}
|
|
|
|
RemoveArguments(found - 1, found);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::GetState(uint32_t *aResult)
|
|
{
|
|
*aResult = mState;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::GetPreventDefault(bool *aResult)
|
|
{
|
|
*aResult = mPreventDefault;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::SetPreventDefault(bool aValue)
|
|
{
|
|
mPreventDefault = aValue;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::GetWorkingDirectory(nsIFile* *aResult)
|
|
{
|
|
NS_ENSURE_TRUE(mWorkingDir, NS_ERROR_NOT_INITIALIZED);
|
|
|
|
NS_ADDREF(*aResult = mWorkingDir);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::GetWindowContext(nsIDOMWindow* *aResult)
|
|
{
|
|
NS_IF_ADDREF(*aResult = mWindowContext);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::SetWindowContext(nsIDOMWindow* aValue)
|
|
{
|
|
mWindowContext = aValue;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::ResolveFile(const nsAString& aArgument, nsIFile* *aResult)
|
|
{
|
|
NS_ENSURE_TRUE(mWorkingDir, NS_ERROR_NOT_INITIALIZED);
|
|
|
|
// This is some seriously screwed-up code. nsIFile.appendRelativeNativePath
|
|
// explicitly does not accept .. or . path parts, but that is exactly what we
|
|
// need here. So we hack around it.
|
|
|
|
nsresult rv;
|
|
|
|
#if defined(MOZ_WIDGET_COCOA)
|
|
nsCOMPtr<nsILocalFileMac> lfm (do_QueryInterface(mWorkingDir));
|
|
NS_ENSURE_TRUE(lfm, NS_ERROR_NO_INTERFACE);
|
|
|
|
nsCOMPtr<nsILocalFileMac> newfile (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
|
|
NS_ENSURE_TRUE(newfile, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
CFURLRef baseurl;
|
|
rv = lfm->GetCFURL(&baseurl);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString path;
|
|
NS_CopyUnicodeToNative(aArgument, path);
|
|
|
|
CFURLRef newurl =
|
|
CFURLCreateFromFileSystemRepresentationRelativeToBase(nullptr, (const UInt8*) path.get(),
|
|
path.Length(),
|
|
true, baseurl);
|
|
|
|
CFRelease(baseurl);
|
|
|
|
rv = newfile->InitWithCFURL(newurl);
|
|
CFRelease(newurl);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
newfile.forget(aResult);
|
|
return NS_OK;
|
|
|
|
#elif defined(XP_UNIX)
|
|
nsCOMPtr<nsIFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
|
|
NS_ENSURE_TRUE(lf, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
if (aArgument.First() == '/') {
|
|
// absolute path
|
|
rv = lf->InitWithPath(aArgument);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
NS_ADDREF(*aResult = lf);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsAutoCString nativeArg;
|
|
NS_CopyUnicodeToNative(aArgument, nativeArg);
|
|
|
|
nsAutoCString newpath;
|
|
mWorkingDir->GetNativePath(newpath);
|
|
|
|
newpath.Append('/');
|
|
newpath.Append(nativeArg);
|
|
|
|
rv = lf->InitWithNativePath(newpath);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = lf->Normalize();
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
lf.forget(aResult);
|
|
return NS_OK;
|
|
|
|
#elif defined(XP_WIN32)
|
|
nsCOMPtr<nsIFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
|
|
NS_ENSURE_TRUE(lf, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
rv = lf->InitWithPath(aArgument);
|
|
if (NS_FAILED(rv)) {
|
|
// If it's a relative path, the Init is *going* to fail. We use string magic and
|
|
// win32 _fullpath. Note that paths of the form "\Relative\To\CurDrive" are
|
|
// going to fail, and I haven't figured out a way to work around this without
|
|
// the PathCombine() function, which is not available in plain win95/nt4
|
|
|
|
nsAutoString fullPath;
|
|
mWorkingDir->GetPath(fullPath);
|
|
|
|
fullPath.Append('\\');
|
|
fullPath.Append(aArgument);
|
|
|
|
WCHAR pathBuf[MAX_PATH];
|
|
if (!_wfullpath(pathBuf, fullPath.get(), MAX_PATH))
|
|
return NS_ERROR_FAILURE;
|
|
|
|
rv = lf->InitWithPath(nsDependentString(pathBuf));
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
lf.forget(aResult);
|
|
return NS_OK;
|
|
|
|
#else
|
|
#error Need platform-specific logic here.
|
|
#endif
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::ResolveURI(const nsAString& aArgument, nsIURI* *aResult)
|
|
{
|
|
nsresult rv;
|
|
|
|
// First, we try to init the argument as an absolute file path. If this doesn't
|
|
// work, it is an absolute or relative URI.
|
|
|
|
nsCOMPtr<nsIIOService> io = do_GetIOService();
|
|
NS_ENSURE_TRUE(io, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
nsCOMPtr<nsIURI> workingDirURI;
|
|
if (mWorkingDir) {
|
|
io->NewFileURI(mWorkingDir, getter_AddRefs(workingDirURI));
|
|
}
|
|
|
|
nsCOMPtr<nsIFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
|
|
rv = lf->InitWithPath(aArgument);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
lf->Normalize();
|
|
nsAutoCString url;
|
|
// Try to resolve the url for .url files.
|
|
rv = resolveShortcutURL(lf, url);
|
|
if (NS_SUCCEEDED(rv) && !url.IsEmpty()) {
|
|
return io->NewURI(url,
|
|
nullptr,
|
|
workingDirURI,
|
|
aResult);
|
|
}
|
|
|
|
return io->NewFileURI(lf, aResult);
|
|
}
|
|
|
|
return io->NewURI(NS_ConvertUTF16toUTF8(aArgument),
|
|
nullptr,
|
|
workingDirURI,
|
|
aResult);
|
|
}
|
|
|
|
void
|
|
nsCommandLine::appendArg(const char* arg)
|
|
{
|
|
#ifdef DEBUG_COMMANDLINE
|
|
printf("Adding XP arg: %s\n", arg);
|
|
#endif
|
|
|
|
nsAutoString warg;
|
|
#ifdef XP_WIN
|
|
CopyUTF8toUTF16(nsDependentCString(arg), warg);
|
|
#else
|
|
NS_CopyNativeToUnicode(nsDependentCString(arg), warg);
|
|
#endif
|
|
|
|
mArgs.AppendElement(warg);
|
|
}
|
|
|
|
nsresult
|
|
nsCommandLine::resolveShortcutURL(nsIFile* aFile, nsACString& outURL)
|
|
{
|
|
nsCOMPtr<nsIFileProtocolHandler> fph;
|
|
nsresult rv = NS_GetFileProtocolHandler(getter_AddRefs(fph));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
rv = fph->ReadURLFile(aFile, getter_AddRefs(uri));
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
return uri->GetSpec(outURL);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::Init(int32_t argc, const char* const* argv, nsIFile* aWorkingDir,
|
|
uint32_t aState)
|
|
{
|
|
NS_ENSURE_ARG_MAX(aState, 2);
|
|
|
|
int32_t i;
|
|
|
|
mWorkingDir = aWorkingDir;
|
|
|
|
// skip argv[0], we don't want it
|
|
for (i = 1; i < argc; ++i) {
|
|
const char* curarg = argv[i];
|
|
|
|
#ifdef DEBUG_COMMANDLINE
|
|
printf("Testing native arg %i: '%s'\n", i, curarg);
|
|
#endif
|
|
#if defined(XP_WIN)
|
|
if (*curarg == '/') {
|
|
char* dup = PL_strdup(curarg);
|
|
if (!dup) return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
*dup = '-';
|
|
char* colon = PL_strchr(dup, ':');
|
|
if (colon) {
|
|
*colon = '\0';
|
|
appendArg(dup);
|
|
appendArg(colon+1);
|
|
} else {
|
|
appendArg(dup);
|
|
}
|
|
PL_strfree(dup);
|
|
continue;
|
|
}
|
|
#endif
|
|
if (*curarg == '-') {
|
|
if (*(curarg+1) == '-') ++curarg;
|
|
|
|
char* dup = PL_strdup(curarg);
|
|
if (!dup) return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
char* eq = PL_strchr(dup, '=');
|
|
if (eq) {
|
|
*eq = '\0';
|
|
appendArg(dup);
|
|
appendArg(eq + 1);
|
|
} else {
|
|
appendArg(dup);
|
|
}
|
|
PL_strfree(dup);
|
|
continue;
|
|
}
|
|
|
|
appendArg(curarg);
|
|
}
|
|
|
|
mState = aState;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
template<typename ...T>
|
|
static void
|
|
LogConsoleMessage(const char16_t* fmt, T... args)
|
|
{
|
|
nsString msg;
|
|
nsTextFormatter::ssprintf(msg, fmt, args...);
|
|
|
|
nsCOMPtr<nsIConsoleService> cs = do_GetService("@mozilla.org/consoleservice;1");
|
|
if (cs)
|
|
cs->LogStringMessage(msg.get());
|
|
}
|
|
|
|
nsresult
|
|
nsCommandLine::EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsICategoryManager> catman
|
|
(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
|
|
NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED);
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> entenum;
|
|
rv = catman->EnumerateCategory("command-line-handler",
|
|
getter_AddRefs(entenum));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
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;
|
|
}
|
|
|
|
rv = (aCallback)(clh, this, aClosure);
|
|
if (rv == NS_ERROR_ABORT)
|
|
break;
|
|
|
|
rv = NS_OK;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsCommandLine::EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsICategoryManager> catman
|
|
(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
|
|
NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED);
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> entenum;
|
|
rv = catman->EnumerateCategory("command-line-validator",
|
|
getter_AddRefs(entenum));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIUTF8StringEnumerator> strenum (do_QueryInterface(entenum));
|
|
NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED);
|
|
|
|
for (auto& categoryEntry : SimpleEnumerator<nsICategoryEntry>(entenum)) {
|
|
nsAutoCString contractID;
|
|
categoryEntry->GetValue(contractID);
|
|
|
|
nsCOMPtr<nsICommandLineValidator> clv(do_GetService(contractID.get()));
|
|
if (!clv)
|
|
continue;
|
|
|
|
rv = (aCallback)(clv, this, aClosure);
|
|
if (rv == NS_ERROR_ABORT)
|
|
break;
|
|
|
|
rv = NS_OK;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
static nsresult
|
|
EnumValidate(nsICommandLineValidator* aValidator, nsICommandLine* aThis, void*)
|
|
{
|
|
return aValidator->Validate(aThis);
|
|
}
|
|
|
|
static nsresult
|
|
EnumRun(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void*)
|
|
{
|
|
return aHandler->Handle(aThis);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::Run()
|
|
{
|
|
nsresult rv;
|
|
|
|
rv = EnumerateValidators(EnumValidate, nullptr);
|
|
if (rv == NS_ERROR_ABORT)
|
|
return rv;
|
|
|
|
rv = EnumerateHandlers(EnumRun, nullptr);
|
|
if (rv == NS_ERROR_ABORT)
|
|
return rv;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
static nsresult
|
|
EnumHelp(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void* aClosure)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCString text;
|
|
rv = aHandler->GetHelpInfo(text);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
NS_ASSERTION(text.Length() == 0 || text.Last() == '\n',
|
|
"Help text from command line handlers should end in a newline.");
|
|
|
|
nsACString* totalText = reinterpret_cast<nsACString*>(aClosure);
|
|
totalText->Append(text);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsCommandLine::GetHelpText(nsACString& aResult)
|
|
{
|
|
EnumerateHandlers(EnumHelp, &aResult);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCommandLine)
|
|
|
|
NS_DEFINE_NAMED_CID(NS_COMMANDLINE_CID);
|
|
|
|
static const mozilla::Module::CIDEntry kCommandLineCIDs[] = {
|
|
{ &kNS_COMMANDLINE_CID, false, nullptr, nsCommandLineConstructor },
|
|
{ nullptr }
|
|
};
|
|
|
|
static const mozilla::Module::ContractIDEntry kCommandLineContracts[] = {
|
|
{ "@mozilla.org/toolkit/command-line;1", &kNS_COMMANDLINE_CID },
|
|
{ nullptr }
|
|
};
|
|
|
|
static const mozilla::Module kCommandLineModule = {
|
|
mozilla::Module::kVersion,
|
|
kCommandLineCIDs,
|
|
kCommandLineContracts
|
|
};
|
|
|
|
NSMODULE_DEFN(CommandLineModule) = &kCommandLineModule;
|