LCOV - code coverage report
Current view: top level - toolkit/components/commandlines - nsCommandLine.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 122 237 51.5 %
Date: 2017-07-14 16:53:18 Functions: 23 34 67.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "nsICommandLineRunner.h"
       6             : 
       7             : #include "nsICategoryManager.h"
       8             : #include "nsICommandLineHandler.h"
       9             : #include "nsICommandLineValidator.h"
      10             : #include "nsIConsoleService.h"
      11             : #include "nsIClassInfoImpl.h"
      12             : #include "nsIDOMWindow.h"
      13             : #include "nsIFile.h"
      14             : #include "nsISimpleEnumerator.h"
      15             : #include "nsIStringEnumerator.h"
      16             : 
      17             : #include "nsCOMPtr.h"
      18             : #include "mozilla/ModuleUtils.h"
      19             : #include "nsISupportsImpl.h"
      20             : #include "nsNativeCharsetUtils.h"
      21             : #include "nsNetUtil.h"
      22             : #include "nsIFileProtocolHandler.h"
      23             : #include "nsIURI.h"
      24             : #include "nsUnicharUtils.h"
      25             : #include "nsTArray.h"
      26             : #include "nsTextFormatter.h"
      27             : #include "nsXPCOMCID.h"
      28             : #include "plstr.h"
      29             : #include "mozilla/Attributes.h"
      30             : 
      31             : #ifdef MOZ_WIDGET_COCOA
      32             : #include <CoreFoundation/CoreFoundation.h>
      33             : #include "nsILocalFileMac.h"
      34             : #elif defined(XP_WIN)
      35             : #include <windows.h>
      36             : #include <shlobj.h>
      37             : #elif defined(XP_UNIX)
      38             : #include <unistd.h>
      39             : #endif
      40             : 
      41             : #ifdef DEBUG_bsmedberg
      42             : #define DEBUG_COMMANDLINE
      43             : #endif
      44             : 
      45             : #define NS_COMMANDLINE_CID \
      46             :   { 0x23bcc750, 0xdc20, 0x460b, { 0xb2, 0xd4, 0x74, 0xd8, 0xf5, 0x8d, 0x36, 0x15 } }
      47             : 
      48             : class nsCommandLine final : public nsICommandLineRunner
      49             : {
      50             : public:
      51             :   NS_DECL_ISUPPORTS
      52             :   NS_DECL_NSICOMMANDLINE
      53             :   NS_DECL_NSICOMMANDLINERUNNER
      54             : 
      55             :   nsCommandLine();
      56             : 
      57             : protected:
      58           0 :   ~nsCommandLine() = default;
      59             : 
      60             :   typedef nsresult (*EnumerateHandlersCallback)(nsICommandLineHandler* aHandler,
      61             :                                         nsICommandLine* aThis,
      62             :                                         void *aClosure);
      63             :   typedef nsresult (*EnumerateValidatorsCallback)(nsICommandLineValidator* aValidator,
      64             :                                         nsICommandLine* aThis,
      65             :                                         void *aClosure);
      66             : 
      67             :   void appendArg(const char* arg);
      68             :   MOZ_MUST_USE nsresult resolveShortcutURL(nsIFile* aFile, nsACString& outURL);
      69             :   nsresult EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure);
      70             :   nsresult EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure);
      71             : 
      72             :   nsTArray<nsString>      mArgs;
      73             :   uint32_t                mState;
      74             :   nsCOMPtr<nsIFile>       mWorkingDir;
      75             :   nsCOMPtr<nsIDOMWindow>  mWindowContext;
      76             :   bool                    mPreventDefault;
      77             : };
      78             : 
      79           1 : nsCommandLine::nsCommandLine() :
      80             :   mState(STATE_INITIAL_LAUNCH),
      81           1 :   mPreventDefault(false)
      82             : {
      83             : 
      84           1 : }
      85             : 
      86             : 
      87           3 : NS_IMPL_CLASSINFO(nsCommandLine, nullptr, 0, NS_COMMANDLINE_CID)
      88         106 : NS_IMPL_ISUPPORTS_CI(nsCommandLine,
      89             :                      nsICommandLine,
      90             :                      nsICommandLineRunner)
      91             : 
      92             : NS_IMETHODIMP
      93           2 : nsCommandLine::GetLength(int32_t *aResult)
      94             : {
      95           2 :   *aResult = int32_t(mArgs.Length());
      96           2 :   return NS_OK;
      97             : }
      98             : 
      99             : NS_IMETHODIMP
     100           1 : nsCommandLine::GetArgument(int32_t aIndex, nsAString& aResult)
     101             : {
     102           1 :   NS_ENSURE_ARG_MIN(aIndex, 0);
     103           1 :   NS_ENSURE_ARG_MAX(aIndex, int32_t(mArgs.Length() - 1));
     104             : 
     105           1 :   aResult = mArgs[aIndex];
     106           1 :   return NS_OK;
     107             : }
     108             : 
     109             : NS_IMETHODIMP
     110          29 : nsCommandLine::FindFlag(const nsAString& aFlag, bool aCaseSensitive, int32_t *aResult)
     111             : {
     112          29 :   NS_ENSURE_ARG(!aFlag.IsEmpty());
     113             : 
     114          29 :   nsDefaultStringComparator caseCmp;
     115          29 :   nsCaseInsensitiveStringComparator caseICmp;
     116             :   nsStringComparator& c = aCaseSensitive ?
     117             :     static_cast<nsStringComparator&>(caseCmp) :
     118          29 :     static_cast<nsStringComparator&>(caseICmp);
     119             : 
     120          58 :   for (uint32_t f = 0; f < mArgs.Length(); f++) {
     121          29 :     const nsString &arg = mArgs[f];
     122             : 
     123          29 :     if (arg.Length() >= 2 && arg.First() == char16_t('-')) {
     124           0 :       if (aFlag.Equals(Substring(arg, 1), c)) {
     125           0 :         *aResult = f;
     126           0 :         return NS_OK;
     127             :       }
     128             :     }
     129             :   }
     130             : 
     131          29 :   *aResult = -1;
     132          29 :   return NS_OK;
     133             : }
     134             : 
     135             : NS_IMETHODIMP
     136           0 : nsCommandLine::RemoveArguments(int32_t aStart, int32_t aEnd)
     137             : {
     138           0 :   NS_ENSURE_ARG_MIN(aStart, 0);
     139           0 :   NS_ENSURE_ARG_MAX(uint32_t(aEnd) + 1, mArgs.Length());
     140             : 
     141           0 :   for (int32_t i = aEnd; i >= aStart; --i) {
     142           0 :     mArgs.RemoveElementAt(i);
     143             :   }
     144             : 
     145           0 :   return NS_OK;
     146             : }
     147             : 
     148             : NS_IMETHODIMP
     149          12 : nsCommandLine::HandleFlag(const nsAString& aFlag, bool aCaseSensitive,
     150             :                           bool *aResult)
     151             : {
     152             :   nsresult rv;
     153             : 
     154             :   int32_t found;
     155          12 :   rv = FindFlag(aFlag, aCaseSensitive, &found);
     156          12 :   NS_ENSURE_SUCCESS(rv, rv);
     157             : 
     158          12 :   if (found == -1) {
     159          12 :     *aResult = false;
     160          12 :     return NS_OK;
     161             :   }
     162             : 
     163           0 :   *aResult = true;
     164           0 :   RemoveArguments(found, found);
     165             : 
     166           0 :   return NS_OK;
     167             : }
     168             : 
     169             : NS_IMETHODIMP
     170          14 : nsCommandLine::HandleFlagWithParam(const nsAString& aFlag, bool aCaseSensitive,
     171             :                                    nsAString& aResult)
     172             : {
     173             :   nsresult rv;
     174             : 
     175             :   int32_t found;
     176          14 :   rv = FindFlag(aFlag, aCaseSensitive, &found);
     177          14 :   NS_ENSURE_SUCCESS(rv, rv);
     178             : 
     179          14 :   if (found == -1) {
     180          14 :     aResult.SetIsVoid(true);
     181          14 :     return NS_OK;
     182             :   }
     183             : 
     184           0 :   if (found == int32_t(mArgs.Length()) - 1) {
     185           0 :     return NS_ERROR_INVALID_ARG;
     186             :   }
     187             : 
     188           0 :   ++found;
     189             : 
     190             :   { // scope for validity of |param|, which RemoveArguments call invalidates
     191           0 :     const nsString& param = mArgs[found];
     192           0 :     if (!param.IsEmpty() && param.First() == '-') {
     193           0 :       return NS_ERROR_INVALID_ARG;
     194             :     }
     195             : 
     196           0 :     aResult = param;
     197             :   }
     198             : 
     199           0 :   RemoveArguments(found - 1, found);
     200             : 
     201           0 :   return NS_OK;
     202             : }
     203             : 
     204             : NS_IMETHODIMP
     205           1 : nsCommandLine::GetState(uint32_t *aResult)
     206             : {
     207           1 :   *aResult = mState;
     208           1 :   return NS_OK;
     209             : }
     210             : 
     211             : NS_IMETHODIMP
     212           1 : nsCommandLine::GetPreventDefault(bool *aResult)
     213             : {
     214           1 :   *aResult = mPreventDefault;
     215           1 :   return NS_OK;
     216             : }
     217             : 
     218             : NS_IMETHODIMP
     219           0 : nsCommandLine::SetPreventDefault(bool aValue)
     220             : {
     221           0 :   mPreventDefault = aValue;
     222           0 :   return NS_OK;
     223             : }
     224             : 
     225             : NS_IMETHODIMP
     226           0 : nsCommandLine::GetWorkingDirectory(nsIFile* *aResult)
     227             : {
     228           0 :   NS_ENSURE_TRUE(mWorkingDir, NS_ERROR_NOT_INITIALIZED);
     229             : 
     230           0 :   NS_ADDREF(*aResult = mWorkingDir);
     231           0 :   return NS_OK;
     232             : }
     233             : 
     234             : NS_IMETHODIMP
     235           0 : nsCommandLine::GetWindowContext(nsIDOMWindow* *aResult)
     236             : {
     237           0 :   NS_IF_ADDREF(*aResult = mWindowContext);
     238           0 :   return NS_OK;
     239             : }
     240             : 
     241             : NS_IMETHODIMP
     242           0 : nsCommandLine::SetWindowContext(nsIDOMWindow* aValue)
     243             : {
     244           0 :   mWindowContext = aValue;
     245           0 :   return NS_OK;
     246             : }
     247             : 
     248             : NS_IMETHODIMP
     249           0 : nsCommandLine::ResolveFile(const nsAString& aArgument, nsIFile* *aResult)
     250             : {
     251           0 :   NS_ENSURE_TRUE(mWorkingDir, NS_ERROR_NOT_INITIALIZED);
     252             : 
     253             :   // This is some seriously screwed-up code. nsIFile.appendRelativeNativePath
     254             :   // explicitly does not accept .. or . path parts, but that is exactly what we
     255             :   // need here. So we hack around it.
     256             : 
     257             :   nsresult rv;
     258             : 
     259             : #if defined(MOZ_WIDGET_COCOA)
     260             :   nsCOMPtr<nsILocalFileMac> lfm (do_QueryInterface(mWorkingDir));
     261             :   NS_ENSURE_TRUE(lfm, NS_ERROR_NO_INTERFACE);
     262             : 
     263             :   nsCOMPtr<nsILocalFileMac> newfile (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
     264             :   NS_ENSURE_TRUE(newfile, NS_ERROR_OUT_OF_MEMORY);
     265             : 
     266             :   CFURLRef baseurl;
     267             :   rv = lfm->GetCFURL(&baseurl);
     268             :   NS_ENSURE_SUCCESS(rv, rv);
     269             : 
     270             :   nsAutoCString path;
     271             :   NS_CopyUnicodeToNative(aArgument, path);
     272             : 
     273             :   CFURLRef newurl =
     274             :     CFURLCreateFromFileSystemRepresentationRelativeToBase(nullptr, (const UInt8*) path.get(),
     275             :                                                           path.Length(),
     276             :                                                           true, baseurl);
     277             : 
     278             :   CFRelease(baseurl);
     279             : 
     280             :   rv = newfile->InitWithCFURL(newurl);
     281             :   CFRelease(newurl);
     282             :   if (NS_FAILED(rv)) return rv;
     283             : 
     284             :   newfile.forget(aResult);
     285             :   return NS_OK;
     286             : 
     287             : #elif defined(XP_UNIX)
     288           0 :   nsCOMPtr<nsIFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
     289           0 :   NS_ENSURE_TRUE(lf, NS_ERROR_OUT_OF_MEMORY);
     290             : 
     291           0 :   if (aArgument.First() == '/') {
     292             :     // absolute path
     293           0 :     rv = lf->InitWithPath(aArgument);
     294           0 :     if (NS_FAILED(rv)) return rv;
     295             : 
     296           0 :     NS_ADDREF(*aResult = lf);
     297           0 :     return NS_OK;
     298             :   }
     299             : 
     300           0 :   nsAutoCString nativeArg;
     301           0 :   NS_CopyUnicodeToNative(aArgument, nativeArg);
     302             : 
     303           0 :   nsAutoCString newpath;
     304           0 :   mWorkingDir->GetNativePath(newpath);
     305             : 
     306           0 :   newpath.Append('/');
     307           0 :   newpath.Append(nativeArg);
     308             : 
     309           0 :   rv = lf->InitWithNativePath(newpath);
     310           0 :   if (NS_FAILED(rv)) return rv;
     311             : 
     312           0 :   rv = lf->Normalize();
     313           0 :   if (NS_FAILED(rv)) return rv;
     314             : 
     315           0 :   lf.forget(aResult);
     316           0 :   return NS_OK;
     317             : 
     318             : #elif defined(XP_WIN32)
     319             :   nsCOMPtr<nsIFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
     320             :   NS_ENSURE_TRUE(lf, NS_ERROR_OUT_OF_MEMORY);
     321             : 
     322             :   rv = lf->InitWithPath(aArgument);
     323             :   if (NS_FAILED(rv)) {
     324             :     // If it's a relative path, the Init is *going* to fail. We use string magic and
     325             :     // win32 _fullpath. Note that paths of the form "\Relative\To\CurDrive" are
     326             :     // going to fail, and I haven't figured out a way to work around this without
     327             :     // the PathCombine() function, which is not available in plain win95/nt4
     328             : 
     329             :     nsAutoString fullPath;
     330             :     mWorkingDir->GetPath(fullPath);
     331             : 
     332             :     fullPath.Append('\\');
     333             :     fullPath.Append(aArgument);
     334             : 
     335             :     WCHAR pathBuf[MAX_PATH];
     336             :     if (!_wfullpath(pathBuf, fullPath.get(), MAX_PATH))
     337             :       return NS_ERROR_FAILURE;
     338             : 
     339             :     rv = lf->InitWithPath(nsDependentString(pathBuf));
     340             :     if (NS_FAILED(rv)) return rv;
     341             :   }
     342             :   lf.forget(aResult);
     343             :   return NS_OK;
     344             : 
     345             : #else
     346             : #error Need platform-specific logic here.
     347             : #endif
     348             : }
     349             : 
     350             : NS_IMETHODIMP
     351           1 : nsCommandLine::ResolveURI(const nsAString& aArgument, nsIURI* *aResult)
     352             : {
     353             :   nsresult rv;
     354             : 
     355             :   // First, we try to init the argument as an absolute file path. If this doesn't
     356             :   // work, it is an absolute or relative URI.
     357             : 
     358           2 :   nsCOMPtr<nsIIOService> io = do_GetIOService();
     359           1 :   NS_ENSURE_TRUE(io, NS_ERROR_OUT_OF_MEMORY);
     360             : 
     361           2 :   nsCOMPtr<nsIURI> workingDirURI;
     362           1 :   if (mWorkingDir) {
     363           1 :     io->NewFileURI(mWorkingDir, getter_AddRefs(workingDirURI));
     364             :   }
     365             : 
     366           2 :   nsCOMPtr<nsIFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
     367           1 :   rv = lf->InitWithPath(aArgument);
     368           1 :   if (NS_SUCCEEDED(rv)) {
     369           0 :     lf->Normalize();
     370           0 :     nsAutoCString url;
     371             :     // Try to resolve the url for .url files.
     372           0 :     rv = resolveShortcutURL(lf, url);
     373           0 :     if (NS_SUCCEEDED(rv) && !url.IsEmpty()) {
     374           0 :       return io->NewURI(url,
     375             :                         nullptr,
     376             :                         workingDirURI,
     377           0 :                         aResult);
     378             :     }
     379             : 
     380           0 :     return io->NewFileURI(lf, aResult);
     381             :   }
     382             : 
     383           3 :   return io->NewURI(NS_ConvertUTF16toUTF8(aArgument),
     384             :                     nullptr,
     385             :                     workingDirURI,
     386           2 :                     aResult);
     387             : }
     388             : 
     389             : void
     390           1 : nsCommandLine::appendArg(const char* arg)
     391             : {
     392             : #ifdef DEBUG_COMMANDLINE
     393             :   printf("Adding XP arg: %s\n", arg);
     394             : #endif
     395             : 
     396           2 :   nsAutoString warg;
     397             : #ifdef XP_WIN
     398             :   CopyUTF8toUTF16(nsDependentCString(arg), warg);
     399             : #else
     400           1 :   NS_CopyNativeToUnicode(nsDependentCString(arg), warg);
     401             : #endif
     402             : 
     403           1 :   mArgs.AppendElement(warg);
     404           1 : }
     405             : 
     406             : nsresult
     407           0 : nsCommandLine::resolveShortcutURL(nsIFile* aFile, nsACString& outURL)
     408             : {
     409           0 :   nsCOMPtr<nsIFileProtocolHandler> fph;
     410           0 :   nsresult rv = NS_GetFileProtocolHandler(getter_AddRefs(fph));
     411           0 :   if (NS_FAILED(rv))
     412           0 :     return rv;
     413             : 
     414           0 :   nsCOMPtr<nsIURI> uri;
     415           0 :   rv = fph->ReadURLFile(aFile, getter_AddRefs(uri));
     416           0 :   if (NS_FAILED(rv))
     417           0 :     return rv;
     418             : 
     419           0 :   return uri->GetSpec(outURL);
     420             : }
     421             : 
     422             : NS_IMETHODIMP
     423           1 : nsCommandLine::Init(int32_t argc, const char* const* argv, nsIFile* aWorkingDir,
     424             :                     uint32_t aState)
     425             : {
     426           1 :   NS_ENSURE_ARG_MAX(aState, 2);
     427             : 
     428             :   int32_t i;
     429             : 
     430           1 :   mWorkingDir = aWorkingDir;
     431             : 
     432             :   // skip argv[0], we don't want it
     433           2 :   for (i = 1; i < argc; ++i) {
     434           1 :     const char* curarg = argv[i];
     435             : 
     436             : #ifdef DEBUG_COMMANDLINE
     437             :     printf("Testing native arg %i: '%s'\n", i, curarg);
     438             : #endif
     439             : #if defined(XP_WIN)
     440             :     if (*curarg == '/') {
     441             :       char* dup = PL_strdup(curarg);
     442             :       if (!dup) return NS_ERROR_OUT_OF_MEMORY;
     443             : 
     444             :       *dup = '-';
     445             :       char* colon = PL_strchr(dup, ':');
     446             :       if (colon) {
     447             :         *colon = '\0';
     448             :         appendArg(dup);
     449             :         appendArg(colon+1);
     450             :       } else {
     451             :         appendArg(dup);
     452             :       }
     453             :       PL_strfree(dup);
     454             :       continue;
     455             :     }
     456             : #endif
     457             : #ifdef XP_UNIX
     458           1 :     if (*curarg == '-' &&
     459           0 :         *(curarg+1) == '-') {
     460           0 :       ++curarg;
     461             : 
     462           0 :       char* dup = PL_strdup(curarg);
     463           0 :       if (!dup) return NS_ERROR_OUT_OF_MEMORY;
     464             : 
     465           0 :       char* eq = PL_strchr(dup, '=');
     466           0 :       if (eq) {
     467           0 :         *eq = '\0';
     468           0 :         appendArg(dup);
     469           0 :         appendArg(eq + 1);
     470             :       } else {
     471           0 :         appendArg(dup);
     472             :       }
     473           0 :       PL_strfree(dup);
     474           0 :       continue;
     475             :     }
     476             : #endif
     477             : 
     478           1 :     appendArg(curarg);
     479             :   }
     480             : 
     481           1 :   mState = aState;
     482             : 
     483           1 :   return NS_OK;
     484             : }
     485             : 
     486             : static void
     487           0 : LogConsoleMessage(const char16_t* fmt, ...)
     488             : {
     489             :   va_list args;
     490           0 :   va_start(args, fmt);
     491           0 :   char16_t* msg = nsTextFormatter::vsmprintf(fmt, args);
     492           0 :   va_end(args);
     493             : 
     494           0 :   nsCOMPtr<nsIConsoleService> cs = do_GetService("@mozilla.org/consoleservice;1");
     495           0 :   if (cs)
     496           0 :     cs->LogStringMessage(msg);
     497             : 
     498           0 :   free(msg);
     499           0 : }
     500             : 
     501             : nsresult
     502           1 : nsCommandLine::EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure)
     503             : {
     504             :   nsresult rv;
     505             : 
     506             :   nsCOMPtr<nsICategoryManager> catman
     507           2 :     (do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
     508           1 :   NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED);
     509             : 
     510           2 :   nsCOMPtr<nsISimpleEnumerator> entenum;
     511           2 :   rv = catman->EnumerateCategory("command-line-handler",
     512           2 :                                  getter_AddRefs(entenum));
     513           1 :   NS_ENSURE_SUCCESS(rv, rv);
     514             : 
     515           2 :   nsCOMPtr<nsIUTF8StringEnumerator> strenum (do_QueryInterface(entenum));
     516           1 :   NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED);
     517             : 
     518           2 :   nsAutoCString entry;
     519             :   bool hasMore;
     520          19 :   while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) {
     521           9 :     strenum->GetNext(entry);
     522             : 
     523          18 :     nsCString contractID;
     524          18 :     rv = catman->GetCategoryEntry("command-line-handler",
     525             :                                   entry.get(),
     526          18 :                                   getter_Copies(contractID));
     527           9 :     if (NS_FAILED(rv))
     528           0 :       continue;
     529             : 
     530          18 :     nsCOMPtr<nsICommandLineHandler> clh(do_GetService(contractID.get()));
     531           9 :     if (!clh) {
     532           0 :       LogConsoleMessage(u"Contract ID '%s' was registered as a command line handler for entry '%s', but could not be created.",
     533           0 :                         contractID.get(), entry.get());
     534           0 :       continue;
     535             :     }
     536             : 
     537           9 :     rv = (aCallback)(clh, this, aClosure);
     538           9 :     if (rv == NS_ERROR_ABORT)
     539           0 :       break;
     540             : 
     541           9 :     rv = NS_OK;
     542             :   }
     543             : 
     544           1 :   return rv;
     545             : }
     546             : 
     547             : nsresult
     548           1 : nsCommandLine::EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure)
     549             : {
     550             :   nsresult rv;
     551             : 
     552             :   nsCOMPtr<nsICategoryManager> catman
     553           2 :     (do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
     554           1 :   NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED);
     555             : 
     556           2 :   nsCOMPtr<nsISimpleEnumerator> entenum;
     557           2 :   rv = catman->EnumerateCategory("command-line-validator",
     558           2 :                                  getter_AddRefs(entenum));
     559           1 :   NS_ENSURE_SUCCESS(rv, rv);
     560             : 
     561           2 :   nsCOMPtr<nsIUTF8StringEnumerator> strenum (do_QueryInterface(entenum));
     562           1 :   NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED);
     563             : 
     564           2 :   nsAutoCString entry;
     565             :   bool hasMore;
     566           3 :   while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) {
     567           1 :     strenum->GetNext(entry);
     568             : 
     569           2 :     nsXPIDLCString contractID;
     570           2 :     rv = catman->GetCategoryEntry("command-line-validator",
     571             :                                   entry.get(),
     572           2 :                                   getter_Copies(contractID));
     573           1 :     if (!contractID)
     574           0 :       continue;
     575             : 
     576           2 :     nsCOMPtr<nsICommandLineValidator> clv(do_GetService(contractID.get()));
     577           1 :     if (!clv)
     578           0 :       continue;
     579             : 
     580           1 :     rv = (aCallback)(clv, this, aClosure);
     581           1 :     if (rv == NS_ERROR_ABORT)
     582           0 :       break;
     583             : 
     584           1 :     rv = NS_OK;
     585             :   }
     586             : 
     587           1 :   return rv;
     588             : }
     589             : 
     590             : static nsresult
     591           1 : EnumValidate(nsICommandLineValidator* aValidator, nsICommandLine* aThis, void*)
     592             : {
     593           1 :   return aValidator->Validate(aThis);
     594             : }
     595             : 
     596             : static nsresult
     597           9 : EnumRun(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void*)
     598             : {
     599           9 :   return aHandler->Handle(aThis);
     600             : }
     601             : 
     602             : NS_IMETHODIMP
     603           1 : nsCommandLine::Run()
     604             : {
     605             :   nsresult rv;
     606             : 
     607           1 :   rv = EnumerateValidators(EnumValidate, nullptr);
     608           1 :   if (rv == NS_ERROR_ABORT)
     609           0 :     return rv;
     610             : 
     611           1 :   rv = EnumerateHandlers(EnumRun, nullptr);
     612           1 :   if (rv == NS_ERROR_ABORT)
     613           0 :     return rv;
     614             : 
     615           1 :   return NS_OK;
     616             : }
     617             : 
     618             : static nsresult
     619           0 : EnumHelp(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void* aClosure)
     620             : {
     621             :   nsresult rv;
     622             : 
     623           0 :   nsCString text;
     624           0 :   rv = aHandler->GetHelpInfo(text);
     625           0 :   if (NS_SUCCEEDED(rv)) {
     626           0 :     NS_ASSERTION(text.Length() == 0 || text.Last() == '\n',
     627             :                  "Help text from command line handlers should end in a newline.");
     628             : 
     629           0 :     nsACString* totalText = reinterpret_cast<nsACString*>(aClosure);
     630           0 :     totalText->Append(text);
     631             :   }
     632             : 
     633           0 :   return NS_OK;
     634             : }
     635             : 
     636             : NS_IMETHODIMP
     637           0 : nsCommandLine::GetHelpText(nsACString& aResult)
     638             : {
     639           0 :   EnumerateHandlers(EnumHelp, &aResult);
     640             : 
     641           0 :   return NS_OK;
     642             : }
     643             : 
     644           2 : NS_GENERIC_FACTORY_CONSTRUCTOR(nsCommandLine)
     645             : 
     646             : NS_DEFINE_NAMED_CID(NS_COMMANDLINE_CID);
     647             : 
     648             : static const mozilla::Module::CIDEntry kCommandLineCIDs[] = {
     649             :   { &kNS_COMMANDLINE_CID, false, nullptr, nsCommandLineConstructor },
     650             :   { nullptr }
     651             : };
     652             : 
     653             : static const mozilla::Module::ContractIDEntry kCommandLineContracts[] = {
     654             :   { "@mozilla.org/toolkit/command-line;1", &kNS_COMMANDLINE_CID },
     655             :   { nullptr }
     656             : };
     657             : 
     658             : static const mozilla::Module kCommandLineModule = {
     659             :   mozilla::Module::kVersion,
     660             :   kCommandLineCIDs,
     661             :   kCommandLineContracts
     662             : };
     663             : 
     664           9 : NSMODULE_DEFN(CommandLineModule) = &kCommandLineModule;

Generated by: LCOV version 1.13