gecko-dev/toolkit/components/commandlines/nsCommandLine.cpp
Gabriele Svelto 5dc21d568c Bug 1600545 - Remove useless inclusions of header files generated from IDL files in modules/, netwerk/, parser/, security/, startupcache/, storage/, toolkit/, tools/, uriloader/, widget/, xpcom/ and xpfe/ r=Ehsan
The inclusions were removed with the following very crude script and the
resulting breakage was fixed up by hand. The manual fixups did either
revert the changes done by the script, replace a generic header with a more
specific one or replace a header with a forward declaration.

find . -name "*.idl" | grep -v web-platform | grep -v third_party | while read path; do
    interfaces=$(grep "^\(class\|interface\).*:.*" "$path" | cut -d' ' -f2)
    if [ -n "$interfaces" ]; then
        if [[ "$interfaces" == *$'\n'* ]]; then
          regexp="\("
          for i in $interfaces; do regexp="$regexp$i\|"; done
          regexp="${regexp%%\\\|}\)"
        else
          regexp="$interfaces"
        fi
        interface=$(basename "$path")
        rg -l "#include.*${interface%%.idl}.h" . | while read path2; do
            hits=$(grep -v "#include.*${interface%%.idl}.h" "$path2" | grep -c "$regexp" )
            if [ $hits -eq 0 ]; then
                echo "Removing ${interface} from ${path2}"
                grep -v "#include.*${interface%%.idl}.h" "$path2" > "$path2".tmp
                mv -f "$path2".tmp "$path2"
            fi
        done
    fi
done

Differential Revision: https://phabricator.services.mozilla.com/D55444

--HG--
extra : moz-landing-system : lando
2019-12-06 09:17:57 +00:00

532 lines
13 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 "nsCommandLine.h"
#include "nsComponentManagerUtils.h"
#include "nsICategoryManager.h"
#include "nsICommandLineHandler.h"
#include "nsICommandLineValidator.h"
#include "nsIConsoleService.h"
#include "nsIClassInfoImpl.h"
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/SimpleEnumerator.h"
#include "nsNativeCharsetUtils.h"
#include "nsNetUtil.h"
#include "nsIFileProtocolHandler.h"
#include "nsIURI.h"
#include "nsUnicharUtils.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;
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::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_WIN)
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 "
u"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);
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;
}