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