1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/commandlines/nsCommandLine.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,658 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsICommandLineRunner.h" 1.9 + 1.10 +#include "nsICategoryManager.h" 1.11 +#include "nsICommandLineHandler.h" 1.12 +#include "nsICommandLineValidator.h" 1.13 +#include "nsIConsoleService.h" 1.14 +#include "nsIClassInfoImpl.h" 1.15 +#include "nsIDOMWindow.h" 1.16 +#include "nsIFile.h" 1.17 +#include "nsISimpleEnumerator.h" 1.18 +#include "nsIStringEnumerator.h" 1.19 + 1.20 +#include "nsCOMPtr.h" 1.21 +#include "mozilla/ModuleUtils.h" 1.22 +#include "nsISupportsImpl.h" 1.23 +#include "nsNativeCharsetUtils.h" 1.24 +#include "nsNetUtil.h" 1.25 +#include "nsUnicharUtils.h" 1.26 +#include "nsTArray.h" 1.27 +#include "nsTextFormatter.h" 1.28 +#include "nsXPCOMCID.h" 1.29 +#include "plstr.h" 1.30 +#include "mozilla/Attributes.h" 1.31 + 1.32 +#ifdef MOZ_WIDGET_COCOA 1.33 +#include <CoreFoundation/CoreFoundation.h> 1.34 +#include "nsILocalFileMac.h" 1.35 +#elif defined(XP_WIN) 1.36 +#include <windows.h> 1.37 +#include <shlobj.h> 1.38 +#elif defined(XP_UNIX) 1.39 +#include <unistd.h> 1.40 +#endif 1.41 + 1.42 +#ifdef DEBUG_bsmedberg 1.43 +#define DEBUG_COMMANDLINE 1.44 +#endif 1.45 + 1.46 +#define NS_COMMANDLINE_CID \ 1.47 + { 0x23bcc750, 0xdc20, 0x460b, { 0xb2, 0xd4, 0x74, 0xd8, 0xf5, 0x8d, 0x36, 0x15 } } 1.48 + 1.49 +class nsCommandLine MOZ_FINAL : public nsICommandLineRunner 1.50 +{ 1.51 +public: 1.52 + NS_DECL_ISUPPORTS 1.53 + NS_DECL_NSICOMMANDLINE 1.54 + NS_DECL_NSICOMMANDLINERUNNER 1.55 + 1.56 + nsCommandLine(); 1.57 + 1.58 +protected: 1.59 + ~nsCommandLine() { } 1.60 + 1.61 + typedef nsresult (*EnumerateHandlersCallback)(nsICommandLineHandler* aHandler, 1.62 + nsICommandLine* aThis, 1.63 + void *aClosure); 1.64 + typedef nsresult (*EnumerateValidatorsCallback)(nsICommandLineValidator* aValidator, 1.65 + nsICommandLine* aThis, 1.66 + void *aClosure); 1.67 + 1.68 + void appendArg(const char* arg); 1.69 + void resolveShortcutURL(nsIFile* aFile, nsACString& outURL); 1.70 + nsresult EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure); 1.71 + nsresult EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure); 1.72 + 1.73 + nsTArray<nsString> mArgs; 1.74 + uint32_t mState; 1.75 + nsCOMPtr<nsIFile> mWorkingDir; 1.76 + nsCOMPtr<nsIDOMWindow> mWindowContext; 1.77 + bool mPreventDefault; 1.78 +}; 1.79 + 1.80 +nsCommandLine::nsCommandLine() : 1.81 + mState(STATE_INITIAL_LAUNCH), 1.82 + mPreventDefault(false) 1.83 +{ 1.84 + 1.85 +} 1.86 + 1.87 + 1.88 +NS_IMPL_CLASSINFO(nsCommandLine, nullptr, 0, NS_COMMANDLINE_CID) 1.89 +NS_IMPL_ISUPPORTS_CI(nsCommandLine, 1.90 + nsICommandLine, 1.91 + nsICommandLineRunner) 1.92 + 1.93 +NS_IMETHODIMP 1.94 +nsCommandLine::GetLength(int32_t *aResult) 1.95 +{ 1.96 + *aResult = int32_t(mArgs.Length()); 1.97 + return NS_OK; 1.98 +} 1.99 + 1.100 +NS_IMETHODIMP 1.101 +nsCommandLine::GetArgument(int32_t aIndex, nsAString& aResult) 1.102 +{ 1.103 + NS_ENSURE_ARG_MIN(aIndex, 0); 1.104 + NS_ENSURE_ARG_MAX(aIndex, int32_t(mArgs.Length() - 1)); 1.105 + 1.106 + aResult = mArgs[aIndex]; 1.107 + return NS_OK; 1.108 +} 1.109 + 1.110 +NS_IMETHODIMP 1.111 +nsCommandLine::FindFlag(const nsAString& aFlag, bool aCaseSensitive, int32_t *aResult) 1.112 +{ 1.113 + NS_ENSURE_ARG(!aFlag.IsEmpty()); 1.114 + 1.115 + nsDefaultStringComparator caseCmp; 1.116 + nsCaseInsensitiveStringComparator caseICmp; 1.117 + nsStringComparator& c = aCaseSensitive ? 1.118 + static_cast<nsStringComparator&>(caseCmp) : 1.119 + static_cast<nsStringComparator&>(caseICmp); 1.120 + 1.121 + for (uint32_t f = 0; f < mArgs.Length(); f++) { 1.122 + const nsString &arg = mArgs[f]; 1.123 + 1.124 + if (arg.Length() >= 2 && arg.First() == char16_t('-')) { 1.125 + if (aFlag.Equals(Substring(arg, 1), c)) { 1.126 + *aResult = f; 1.127 + return NS_OK; 1.128 + } 1.129 + } 1.130 + } 1.131 + 1.132 + *aResult = -1; 1.133 + return NS_OK; 1.134 +} 1.135 + 1.136 +NS_IMETHODIMP 1.137 +nsCommandLine::RemoveArguments(int32_t aStart, int32_t aEnd) 1.138 +{ 1.139 + NS_ENSURE_ARG_MIN(aStart, 0); 1.140 + NS_ENSURE_ARG_MAX(uint32_t(aEnd) + 1, mArgs.Length()); 1.141 + 1.142 + for (int32_t i = aEnd; i >= aStart; --i) { 1.143 + mArgs.RemoveElementAt(i); 1.144 + } 1.145 + 1.146 + return NS_OK; 1.147 +} 1.148 + 1.149 +NS_IMETHODIMP 1.150 +nsCommandLine::HandleFlag(const nsAString& aFlag, bool aCaseSensitive, 1.151 + bool *aResult) 1.152 +{ 1.153 + nsresult rv; 1.154 + 1.155 + int32_t found; 1.156 + rv = FindFlag(aFlag, aCaseSensitive, &found); 1.157 + NS_ENSURE_SUCCESS(rv, rv); 1.158 + 1.159 + if (found == -1) { 1.160 + *aResult = false; 1.161 + return NS_OK; 1.162 + } 1.163 + 1.164 + *aResult = true; 1.165 + RemoveArguments(found, found); 1.166 + 1.167 + return NS_OK; 1.168 +} 1.169 + 1.170 +NS_IMETHODIMP 1.171 +nsCommandLine::HandleFlagWithParam(const nsAString& aFlag, bool aCaseSensitive, 1.172 + nsAString& aResult) 1.173 +{ 1.174 + nsresult rv; 1.175 + 1.176 + int32_t found; 1.177 + rv = FindFlag(aFlag, aCaseSensitive, &found); 1.178 + NS_ENSURE_SUCCESS(rv, rv); 1.179 + 1.180 + if (found == -1) { 1.181 + aResult.SetIsVoid(true); 1.182 + return NS_OK; 1.183 + } 1.184 + 1.185 + if (found == int32_t(mArgs.Length()) - 1) { 1.186 + return NS_ERROR_INVALID_ARG; 1.187 + } 1.188 + 1.189 + ++found; 1.190 + 1.191 + if (mArgs[found].First() == '-') { 1.192 + return NS_ERROR_INVALID_ARG; 1.193 + } 1.194 + 1.195 + aResult = mArgs[found]; 1.196 + RemoveArguments(found - 1, found); 1.197 + 1.198 + return NS_OK; 1.199 +} 1.200 + 1.201 +NS_IMETHODIMP 1.202 +nsCommandLine::GetState(uint32_t *aResult) 1.203 +{ 1.204 + *aResult = mState; 1.205 + return NS_OK; 1.206 +} 1.207 + 1.208 +NS_IMETHODIMP 1.209 +nsCommandLine::GetPreventDefault(bool *aResult) 1.210 +{ 1.211 + *aResult = mPreventDefault; 1.212 + return NS_OK; 1.213 +} 1.214 + 1.215 +NS_IMETHODIMP 1.216 +nsCommandLine::SetPreventDefault(bool aValue) 1.217 +{ 1.218 + mPreventDefault = aValue; 1.219 + return NS_OK; 1.220 +} 1.221 + 1.222 +NS_IMETHODIMP 1.223 +nsCommandLine::GetWorkingDirectory(nsIFile* *aResult) 1.224 +{ 1.225 + NS_ENSURE_TRUE(mWorkingDir, NS_ERROR_NOT_INITIALIZED); 1.226 + 1.227 + NS_ADDREF(*aResult = mWorkingDir); 1.228 + return NS_OK; 1.229 +} 1.230 + 1.231 +NS_IMETHODIMP 1.232 +nsCommandLine::GetWindowContext(nsIDOMWindow* *aResult) 1.233 +{ 1.234 + NS_IF_ADDREF(*aResult = mWindowContext); 1.235 + return NS_OK; 1.236 +} 1.237 + 1.238 +NS_IMETHODIMP 1.239 +nsCommandLine::SetWindowContext(nsIDOMWindow* aValue) 1.240 +{ 1.241 + mWindowContext = aValue; 1.242 + return NS_OK; 1.243 +} 1.244 + 1.245 +NS_IMETHODIMP 1.246 +nsCommandLine::ResolveFile(const nsAString& aArgument, nsIFile* *aResult) 1.247 +{ 1.248 + NS_ENSURE_TRUE(mWorkingDir, NS_ERROR_NOT_INITIALIZED); 1.249 + 1.250 + // This is some seriously screwed-up code. nsIFile.appendRelativeNativePath 1.251 + // explicitly does not accept .. or . path parts, but that is exactly what we 1.252 + // need here. So we hack around it. 1.253 + 1.254 + nsresult rv; 1.255 + 1.256 +#if defined(MOZ_WIDGET_COCOA) 1.257 + nsCOMPtr<nsILocalFileMac> lfm (do_QueryInterface(mWorkingDir)); 1.258 + NS_ENSURE_TRUE(lfm, NS_ERROR_NO_INTERFACE); 1.259 + 1.260 + nsCOMPtr<nsILocalFileMac> newfile (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID)); 1.261 + NS_ENSURE_TRUE(newfile, NS_ERROR_OUT_OF_MEMORY); 1.262 + 1.263 + CFURLRef baseurl; 1.264 + rv = lfm->GetCFURL(&baseurl); 1.265 + NS_ENSURE_SUCCESS(rv, rv); 1.266 + 1.267 + nsAutoCString path; 1.268 + NS_CopyUnicodeToNative(aArgument, path); 1.269 + 1.270 + CFURLRef newurl = 1.271 + CFURLCreateFromFileSystemRepresentationRelativeToBase(nullptr, (const UInt8*) path.get(), 1.272 + path.Length(), 1.273 + true, baseurl); 1.274 + 1.275 + CFRelease(baseurl); 1.276 + 1.277 + rv = newfile->InitWithCFURL(newurl); 1.278 + CFRelease(newurl); 1.279 + if (NS_FAILED(rv)) return rv; 1.280 + 1.281 + NS_ADDREF(*aResult = newfile); 1.282 + return NS_OK; 1.283 + 1.284 +#elif defined(XP_UNIX) 1.285 + nsCOMPtr<nsIFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID)); 1.286 + NS_ENSURE_TRUE(lf, NS_ERROR_OUT_OF_MEMORY); 1.287 + 1.288 + if (aArgument.First() == '/') { 1.289 + // absolute path 1.290 + rv = lf->InitWithPath(aArgument); 1.291 + if (NS_FAILED(rv)) return rv; 1.292 + 1.293 + NS_ADDREF(*aResult = lf); 1.294 + return NS_OK; 1.295 + } 1.296 + 1.297 + nsAutoCString nativeArg; 1.298 + NS_CopyUnicodeToNative(aArgument, nativeArg); 1.299 + 1.300 + nsAutoCString newpath; 1.301 + mWorkingDir->GetNativePath(newpath); 1.302 + 1.303 + newpath.Append('/'); 1.304 + newpath.Append(nativeArg); 1.305 + 1.306 + rv = lf->InitWithNativePath(newpath); 1.307 + if (NS_FAILED(rv)) return rv; 1.308 + 1.309 + rv = lf->Normalize(); 1.310 + if (NS_FAILED(rv)) return rv; 1.311 + 1.312 + NS_ADDREF(*aResult = lf); 1.313 + return NS_OK; 1.314 + 1.315 +#elif defined(XP_WIN32) 1.316 + nsCOMPtr<nsIFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID)); 1.317 + NS_ENSURE_TRUE(lf, NS_ERROR_OUT_OF_MEMORY); 1.318 + 1.319 + rv = lf->InitWithPath(aArgument); 1.320 + if (NS_FAILED(rv)) { 1.321 + // If it's a relative path, the Init is *going* to fail. We use string magic and 1.322 + // win32 _fullpath. Note that paths of the form "\Relative\To\CurDrive" are 1.323 + // going to fail, and I haven't figured out a way to work around this without 1.324 + // the PathCombine() function, which is not available in plain win95/nt4 1.325 + 1.326 + nsAutoString fullPath; 1.327 + mWorkingDir->GetPath(fullPath); 1.328 + 1.329 + fullPath.Append('\\'); 1.330 + fullPath.Append(aArgument); 1.331 + 1.332 + WCHAR pathBuf[MAX_PATH]; 1.333 + if (!_wfullpath(pathBuf, fullPath.get(), MAX_PATH)) 1.334 + return NS_ERROR_FAILURE; 1.335 + 1.336 + rv = lf->InitWithPath(nsDependentString(pathBuf)); 1.337 + if (NS_FAILED(rv)) return rv; 1.338 + } 1.339 + NS_ADDREF(*aResult = lf); 1.340 + return NS_OK; 1.341 + 1.342 +#else 1.343 +#error Need platform-specific logic here. 1.344 +#endif 1.345 +} 1.346 + 1.347 +NS_IMETHODIMP 1.348 +nsCommandLine::ResolveURI(const nsAString& aArgument, nsIURI* *aResult) 1.349 +{ 1.350 + nsresult rv; 1.351 + 1.352 + // First, we try to init the argument as an absolute file path. If this doesn't 1.353 + // work, it is an absolute or relative URI. 1.354 + 1.355 + nsCOMPtr<nsIIOService> io = do_GetIOService(); 1.356 + NS_ENSURE_TRUE(io, NS_ERROR_OUT_OF_MEMORY); 1.357 + 1.358 + nsCOMPtr<nsIURI> workingDirURI; 1.359 + if (mWorkingDir) { 1.360 + io->NewFileURI(mWorkingDir, getter_AddRefs(workingDirURI)); 1.361 + } 1.362 + 1.363 + nsCOMPtr<nsIFile> lf (do_CreateInstance(NS_LOCAL_FILE_CONTRACTID)); 1.364 + rv = lf->InitWithPath(aArgument); 1.365 + if (NS_SUCCEEDED(rv)) { 1.366 + lf->Normalize(); 1.367 + nsAutoCString url; 1.368 + // Try to resolve the url for .url files. 1.369 + resolveShortcutURL(lf, url); 1.370 + if (!url.IsEmpty()) { 1.371 + return io->NewURI(url, 1.372 + nullptr, 1.373 + workingDirURI, 1.374 + aResult); 1.375 + } 1.376 + 1.377 + return io->NewFileURI(lf, aResult); 1.378 + } 1.379 + 1.380 + return io->NewURI(NS_ConvertUTF16toUTF8(aArgument), 1.381 + nullptr, 1.382 + workingDirURI, 1.383 + aResult); 1.384 +} 1.385 + 1.386 +void 1.387 +nsCommandLine::appendArg(const char* arg) 1.388 +{ 1.389 +#ifdef DEBUG_COMMANDLINE 1.390 + printf("Adding XP arg: %s\n", arg); 1.391 +#endif 1.392 + 1.393 + nsAutoString warg; 1.394 +#ifdef XP_WIN 1.395 + CopyUTF8toUTF16(nsDependentCString(arg), warg); 1.396 +#else 1.397 + NS_CopyNativeToUnicode(nsDependentCString(arg), warg); 1.398 +#endif 1.399 + 1.400 + mArgs.AppendElement(warg); 1.401 +} 1.402 + 1.403 +void 1.404 +nsCommandLine::resolveShortcutURL(nsIFile* aFile, nsACString& outURL) 1.405 +{ 1.406 + nsCOMPtr<nsIFileProtocolHandler> fph; 1.407 + nsresult rv = NS_GetFileProtocolHandler(getter_AddRefs(fph)); 1.408 + if (NS_FAILED(rv)) 1.409 + return; 1.410 + 1.411 + nsCOMPtr<nsIURI> uri; 1.412 + rv = fph->ReadURLFile(aFile, getter_AddRefs(uri)); 1.413 + if (NS_FAILED(rv)) 1.414 + return; 1.415 + 1.416 + uri->GetSpec(outURL); 1.417 +} 1.418 + 1.419 +NS_IMETHODIMP 1.420 +nsCommandLine::Init(int32_t argc, const char* const* argv, nsIFile* aWorkingDir, 1.421 + uint32_t aState) 1.422 +{ 1.423 + NS_ENSURE_ARG_MAX(aState, 2); 1.424 + 1.425 + int32_t i; 1.426 + 1.427 + mWorkingDir = aWorkingDir; 1.428 + 1.429 + // skip argv[0], we don't want it 1.430 + for (i = 1; i < argc; ++i) { 1.431 + const char* curarg = argv[i]; 1.432 + 1.433 +#ifdef DEBUG_COMMANDLINE 1.434 + printf("Testing native arg %i: '%s'\n", i, curarg); 1.435 +#endif 1.436 +#if defined(XP_WIN) 1.437 + if (*curarg == '/') { 1.438 + char* dup = PL_strdup(curarg); 1.439 + if (!dup) return NS_ERROR_OUT_OF_MEMORY; 1.440 + 1.441 + *dup = '-'; 1.442 + char* colon = PL_strchr(dup, ':'); 1.443 + if (colon) { 1.444 + *colon = '\0'; 1.445 + appendArg(dup); 1.446 + appendArg(colon+1); 1.447 + } else { 1.448 + appendArg(dup); 1.449 + } 1.450 + PL_strfree(dup); 1.451 + continue; 1.452 + } 1.453 +#endif 1.454 +#ifdef XP_UNIX 1.455 + if (*curarg == '-' && 1.456 + *(curarg+1) == '-') { 1.457 + ++curarg; 1.458 + 1.459 + char* dup = PL_strdup(curarg); 1.460 + if (!dup) return NS_ERROR_OUT_OF_MEMORY; 1.461 + 1.462 + char* eq = PL_strchr(dup, '='); 1.463 + if (eq) { 1.464 + *eq = '\0'; 1.465 + appendArg(dup); 1.466 + appendArg(eq + 1); 1.467 + } else { 1.468 + appendArg(dup); 1.469 + } 1.470 + PL_strfree(dup); 1.471 + continue; 1.472 + } 1.473 +#endif 1.474 + 1.475 + appendArg(curarg); 1.476 + } 1.477 + 1.478 + mState = aState; 1.479 + 1.480 + return NS_OK; 1.481 +} 1.482 + 1.483 +static void 1.484 +LogConsoleMessage(const char16_t* fmt, ...) 1.485 +{ 1.486 + va_list args; 1.487 + va_start(args, fmt); 1.488 + char16_t* msg = nsTextFormatter::vsmprintf(fmt, args); 1.489 + va_end(args); 1.490 + 1.491 + nsCOMPtr<nsIConsoleService> cs = do_GetService("@mozilla.org/consoleservice;1"); 1.492 + if (cs) 1.493 + cs->LogStringMessage(msg); 1.494 + 1.495 + NS_Free(msg); 1.496 +} 1.497 + 1.498 +nsresult 1.499 +nsCommandLine::EnumerateHandlers(EnumerateHandlersCallback aCallback, void *aClosure) 1.500 +{ 1.501 + nsresult rv; 1.502 + 1.503 + nsCOMPtr<nsICategoryManager> catman 1.504 + (do_GetService(NS_CATEGORYMANAGER_CONTRACTID)); 1.505 + NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED); 1.506 + 1.507 + nsCOMPtr<nsISimpleEnumerator> entenum; 1.508 + rv = catman->EnumerateCategory("command-line-handler", 1.509 + getter_AddRefs(entenum)); 1.510 + NS_ENSURE_SUCCESS(rv, rv); 1.511 + 1.512 + nsCOMPtr<nsIUTF8StringEnumerator> strenum (do_QueryInterface(entenum)); 1.513 + NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED); 1.514 + 1.515 + nsAutoCString entry; 1.516 + bool hasMore; 1.517 + while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) { 1.518 + strenum->GetNext(entry); 1.519 + 1.520 + nsCString contractID; 1.521 + rv = catman->GetCategoryEntry("command-line-handler", 1.522 + entry.get(), 1.523 + getter_Copies(contractID)); 1.524 + if (NS_FAILED(rv)) 1.525 + continue; 1.526 + 1.527 + nsCOMPtr<nsICommandLineHandler> clh(do_GetService(contractID.get())); 1.528 + if (!clh) { 1.529 + LogConsoleMessage(MOZ_UTF16("Contract ID '%s' was registered as a command line handler for entry '%s', but could not be created."), 1.530 + contractID.get(), entry.get()); 1.531 + continue; 1.532 + } 1.533 + 1.534 + rv = (aCallback)(clh, this, aClosure); 1.535 + if (rv == NS_ERROR_ABORT) 1.536 + break; 1.537 + 1.538 + rv = NS_OK; 1.539 + } 1.540 + 1.541 + return rv; 1.542 +} 1.543 + 1.544 +nsresult 1.545 +nsCommandLine::EnumerateValidators(EnumerateValidatorsCallback aCallback, void *aClosure) 1.546 +{ 1.547 + nsresult rv; 1.548 + 1.549 + nsCOMPtr<nsICategoryManager> catman 1.550 + (do_GetService(NS_CATEGORYMANAGER_CONTRACTID)); 1.551 + NS_ENSURE_TRUE(catman, NS_ERROR_UNEXPECTED); 1.552 + 1.553 + nsCOMPtr<nsISimpleEnumerator> entenum; 1.554 + rv = catman->EnumerateCategory("command-line-validator", 1.555 + getter_AddRefs(entenum)); 1.556 + NS_ENSURE_SUCCESS(rv, rv); 1.557 + 1.558 + nsCOMPtr<nsIUTF8StringEnumerator> strenum (do_QueryInterface(entenum)); 1.559 + NS_ENSURE_TRUE(strenum, NS_ERROR_UNEXPECTED); 1.560 + 1.561 + nsAutoCString entry; 1.562 + bool hasMore; 1.563 + while (NS_SUCCEEDED(strenum->HasMore(&hasMore)) && hasMore) { 1.564 + strenum->GetNext(entry); 1.565 + 1.566 + nsXPIDLCString contractID; 1.567 + rv = catman->GetCategoryEntry("command-line-validator", 1.568 + entry.get(), 1.569 + getter_Copies(contractID)); 1.570 + if (!contractID) 1.571 + continue; 1.572 + 1.573 + nsCOMPtr<nsICommandLineValidator> clv(do_GetService(contractID.get())); 1.574 + if (!clv) 1.575 + continue; 1.576 + 1.577 + rv = (aCallback)(clv, this, aClosure); 1.578 + if (rv == NS_ERROR_ABORT) 1.579 + break; 1.580 + 1.581 + rv = NS_OK; 1.582 + } 1.583 + 1.584 + return rv; 1.585 +} 1.586 + 1.587 +static nsresult 1.588 +EnumValidate(nsICommandLineValidator* aValidator, nsICommandLine* aThis, void*) 1.589 +{ 1.590 + return aValidator->Validate(aThis); 1.591 +} 1.592 + 1.593 +static nsresult 1.594 +EnumRun(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void*) 1.595 +{ 1.596 + return aHandler->Handle(aThis); 1.597 +} 1.598 + 1.599 +NS_IMETHODIMP 1.600 +nsCommandLine::Run() 1.601 +{ 1.602 + nsresult rv; 1.603 + 1.604 + rv = EnumerateValidators(EnumValidate, nullptr); 1.605 + if (rv == NS_ERROR_ABORT) 1.606 + return rv; 1.607 + 1.608 + rv = EnumerateHandlers(EnumRun, nullptr); 1.609 + if (rv == NS_ERROR_ABORT) 1.610 + return rv; 1.611 + 1.612 + return NS_OK; 1.613 +} 1.614 + 1.615 +static nsresult 1.616 +EnumHelp(nsICommandLineHandler* aHandler, nsICommandLine* aThis, void* aClosure) 1.617 +{ 1.618 + nsresult rv; 1.619 + 1.620 + nsCString text; 1.621 + rv = aHandler->GetHelpInfo(text); 1.622 + if (NS_SUCCEEDED(rv)) { 1.623 + NS_ASSERTION(text.Length() == 0 || text.Last() == '\n', 1.624 + "Help text from command line handlers should end in a newline."); 1.625 + 1.626 + nsACString* totalText = reinterpret_cast<nsACString*>(aClosure); 1.627 + totalText->Append(text); 1.628 + } 1.629 + 1.630 + return NS_OK; 1.631 +} 1.632 + 1.633 +NS_IMETHODIMP 1.634 +nsCommandLine::GetHelpText(nsACString& aResult) 1.635 +{ 1.636 + EnumerateHandlers(EnumHelp, &aResult); 1.637 + 1.638 + return NS_OK; 1.639 +} 1.640 + 1.641 +NS_GENERIC_FACTORY_CONSTRUCTOR(nsCommandLine) 1.642 + 1.643 +NS_DEFINE_NAMED_CID(NS_COMMANDLINE_CID); 1.644 + 1.645 +static const mozilla::Module::CIDEntry kCommandLineCIDs[] = { 1.646 + { &kNS_COMMANDLINE_CID, false, nullptr, nsCommandLineConstructor }, 1.647 + { nullptr } 1.648 +}; 1.649 + 1.650 +static const mozilla::Module::ContractIDEntry kCommandLineContracts[] = { 1.651 + { "@mozilla.org/toolkit/command-line;1", &kNS_COMMANDLINE_CID }, 1.652 + { nullptr } 1.653 +}; 1.654 + 1.655 +static const mozilla::Module kCommandLineModule = { 1.656 + mozilla::Module::kVersion, 1.657 + kCommandLineCIDs, 1.658 + kCommandLineContracts 1.659 +}; 1.660 + 1.661 +NSMODULE_DEFN(CommandLineModule) = &kCommandLineModule;