Bug 278878: Send preference parsing errors to browser console. r=bsmedberg

MozReview-Commit-ID: 61mi71dZbO8

--HG--
extra : rebase_source : 87e32940aa557acd809ba0753fda08caf70ed0f9
This commit is contained in:
Milan Sreckovic 2016-04-22 15:35:01 -04:00
parent 9485b623a3
commit 779e30cf76
5 changed files with 79 additions and 8 deletions

View File

@ -219,6 +219,14 @@ AssertNotAlreadyCached(const char* aPrefType,
}
#endif
static void
ReportToConsole(const char* aMessage, int aLine, bool aError)
{
nsPrintfCString message("** Preference parsing %s (line %d) = %s **\n",
(aError ? "error" : "warning"), aLine, aMessage);
nsPrefBranch::ReportToConsole(NS_ConvertUTF8toUTF16(message.get()));
}
// Although this is a member of Preferences, it measures sPreferences and
// several other global structures.
/* static */ int64_t
@ -683,7 +691,7 @@ ReadExtensionPrefs(nsIFile *aFile)
uint32_t read;
PrefParseState ps;
PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr);
PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
while (NS_SUCCEEDED(rv = stream->Available(&avail)) && avail) {
rv = stream->Read(buffer, 4096, &read);
if (NS_FAILED(rv)) {
@ -997,7 +1005,7 @@ static nsresult openPrefFile(nsIFile* aFile)
return NS_ERROR_OUT_OF_MEMORY;
PrefParseState ps;
PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr);
PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
// Read is not guaranteed to return a buf the size of fileSize,
// but usually will.
@ -1179,7 +1187,7 @@ static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name)
NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE);
PrefParseState ps;
PREF_InitParseState(&ps, PREF_ReaderCallback, nullptr);
PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
PREF_ParseBuf(&ps, manifest, manifest.Length());
PREF_FinalizeParseState(&ps);

View File

@ -390,6 +390,17 @@ nsresult nsPrefBranch::CheckSanityOfStringLength(const char* aPrefName, const ui
return NS_OK;
}
/*static*/
void nsPrefBranch::ReportToConsole(const nsAString& aMessage)
{
nsresult rv;
nsCOMPtr<nsIConsoleService> console = do_GetService("@mozilla.org/consoleservice;1", &rv);
if (NS_FAILED(rv)) {
return;
}
nsAutoString message(aMessage);
console->LogStringMessage(message.get());
}
NS_IMETHODIMP nsPrefBranch::SetComplexValue(const char *aPrefName, const nsIID & aType, nsISupports *aValue)
{

View File

@ -196,6 +196,8 @@ public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
static void ReportToConsole(const nsAString& aMessage);
protected:
virtual ~nsPrefBranch();

View File

@ -97,6 +97,20 @@ pref_GrowBuf(PrefParseState *ps)
return true;
}
/**
* Report an error or a warning. If not specified, just dump to stderr.
*/
static void
pref_ReportParseProblem(PrefParseState& ps, const char* aMessage, int aLine, bool aError)
{
if (ps.reporter) {
ps.reporter(aMessage, aLine, aError);
} else {
printf_stderr("**** Preference parsing %s (line %d) = %s **\n",
(aError ? "error" : "warning"), aLine, aMessage);
}
}
/**
* pref_DoCallback
*
@ -119,6 +133,7 @@ pref_DoCallback(PrefParseState *ps)
break;
case PrefType::Int:
if ((ps->vb[0] == '-' || ps->vb[0] == '+') && ps->vb[1] == '\0') {
pref_ReportParseProblem(*ps, "invalid integer value", 0, true);
NS_WARNING("malformed integer value");
return false;
}
@ -136,11 +151,13 @@ pref_DoCallback(PrefParseState *ps)
}
void
PREF_InitParseState(PrefParseState *ps, PrefReader reader, void *closure)
PREF_InitParseState(PrefParseState *ps, PrefReader reader,
PrefParseErrorReporter reporter, void *closure)
{
memset(ps, 0, sizeof(*ps));
ps->reader = reader;
ps->closure = closure;
ps->reporter = reporter;
}
void
@ -179,9 +196,16 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
char udigit;
int state;
// The line number is currently only used for the error/warning reporting.
int lineNum = 0;
state = ps->state;
for (end = buf + bufLen; buf != end; ++buf) {
c = *buf;
if (c == '\r' || c == '\n' || c == 0x1A) {
lineNum ++;
}
switch (state) {
/* initial state */
case PREF_PARSE_INIT:
@ -228,6 +252,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
/* else wait for next char */
}
else {
pref_ReportParseProblem(*ps, "non-matching string", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -263,6 +288,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
state = PREF_PARSE_COMMENT_MAYBE_START;
}
else if (!isspace(c)) {
pref_ReportParseProblem(*ps, "need space, comment or quote", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -279,6 +305,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
state = PREF_PARSE_COMMENT_MAYBE_START;
}
else if (!isspace(c)) {
pref_ReportParseProblem(*ps, "need space, comment or comma", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -315,6 +342,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
state = PREF_PARSE_COMMENT_MAYBE_START;
}
else if (!isspace(c)) {
pref_ReportParseProblem(*ps, "need value, comment or space", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -336,6 +364,7 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
else if (isspace(c))
state = PREF_PARSE_UNTIL_CLOSE_PAREN;
else {
pref_ReportParseProblem(*ps, "while parsing integer", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -353,12 +382,13 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
break;
default:
/* pref file is malformed */
pref_ReportParseProblem(*ps, "while parsing comment", lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
break;
case PREF_PARSE_COMMENT_BLOCK:
if (c == '*')
if (c == '*')
state = PREF_PARSE_COMMENT_BLOCK_MAYBE_END;
break;
case PREF_PARSE_COMMENT_BLOCK_MAYBE_END:
@ -401,6 +431,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
state = PREF_PARSE_HEX_ESCAPE;
continue;
default:
pref_ReportParseProblem(*ps, "preserving unexpected JS escape sequence",
lineNum, false);
NS_WARNING("preserving unexpected JS escape sequence");
/* Invalid escape sequence so we do have to write more than
* one character. Grow line buffer if necessary... */
@ -423,6 +455,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
udigit = (c - 'a') + 10;
else {
/* bad escape sequence found, write out broken escape as-is */
pref_ReportParseProblem(*ps, "preserving invalid or incomplete hex escape",
lineNum, false);
NS_WARNING("preserving invalid or incomplete hex escape");
*ps->lbcur++ = '\\'; /* original escape slash */
if ((ps->lbcur + ps->esclen) >= ps->lbend && !pref_GrowBuf(ps))
@ -510,6 +544,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
state = PREF_PARSE_COMMENT_MAYBE_START;
}
else if (!isspace(c)) {
pref_ReportParseProblem(*ps, "need space, comment or open parentheses",
lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -522,6 +558,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
ps->nextstate = state; /* return here when done with comment */
state = PREF_PARSE_COMMENT_MAYBE_START;
} else if (!isspace(c)) {
pref_ReportParseProblem(*ps, "need space, comment or closing parentheses",
lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -540,6 +578,8 @@ PREF_ParseBuf(PrefParseState *ps, const char *buf, int bufLen)
state = PREF_PARSE_COMMENT_MAYBE_START;
}
else if (!isspace(c)) {
pref_ReportParseProblem(*ps, "need space, comment or semicolon",
lineNum, true);
NS_WARNING("malformed pref file");
return false;
}
@ -603,7 +643,7 @@ main(int argc, char **argv)
return -1;
}
PREF_InitParseState(&ps, pref_reader, nullptr);
PREF_InitParseState(&ps, pref_reader, nullptr, nullptr);
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0)
PREF_ParseBuf(&ps, buf, n);

View File

@ -36,9 +36,15 @@ typedef void (*PrefReader)(void *closure,
bool defPref,
bool stickyPref);
/**
* Report any errors or warnings we encounter during parsing.
*/
typedef void (*PrefParseErrorReporter)(const char* message, int line, bool error);
/* structure fields are private */
typedef struct PrefParseState {
PrefReader reader;
PrefParseErrorReporter reporter;
void *closure;
int state; /* PREF_PARSE_... */
int nextstate; /* sometimes used... */
@ -62,16 +68,20 @@ typedef struct PrefParseState {
* PREF_InitParseState
*
* Called to initialize a PrefParseState instance.
*
*
* @param ps
* PrefParseState instance.
* @param reader
* PrefReader callback function, which will be called once for each
* preference name value pair extracted.
* @param reporter
* PrefParseErrorReporter callback function, which will be called if we
* encounter any errors (stop) or warnings (continue) during parsing.
* @param closure
* PrefReader closure.
*/
void PREF_InitParseState(PrefParseState *ps, PrefReader reader, void *closure);
void PREF_InitParseState(PrefParseState *ps, PrefReader reader,
PrefParseErrorReporter reporter, void *closure);
/**
* PREF_FinalizeParseState