in src/parsers/manifestjson.js [262:413]
errorLookup(error) {
// This is the default message.
let baseObject = messages.JSON_INVALID;
// This is the default from webextension-manifest-schema, but it's not a
// super helpful error. We'll tidy it up a bit:
if (error && error.message) {
const lowerCaseMessage = error.message.toLowerCase();
if (lowerCaseMessage === 'must match a schema in anyof') {
// eslint-disable-next-line no-param-reassign
error.message = 'is not a valid key or has invalid extra properties';
}
}
const overrides = {
message: `"${error.instancePath || '/'}" ${error.message}`,
instancePath: error.instancePath,
};
if (error.keyword === SCHEMA_KEYWORDS.REQUIRED) {
baseObject = messages.MANIFEST_FIELD_REQUIRED;
} else if (error.keyword === SCHEMA_KEYWORDS.DEPRECATED) {
if (
Object.prototype.hasOwnProperty.call(
DEPRECATED_MANIFEST_PROPERTIES,
error.instancePath
)
) {
baseObject =
messages[DEPRECATED_MANIFEST_PROPERTIES[error.instancePath]];
if (baseObject === null) {
baseObject = messages.MANIFEST_FIELD_DEPRECATED;
}
let errorDescription = baseObject.description;
if (errorDescription === null) {
errorDescription = error.message;
}
// Set the description to the actual message from the schema
overrides.message = baseObject.message;
overrides.description = errorDescription;
}
// TODO(#2462): add a messages.MANIFEST_FIELD_DEPRECATED and ensure that deprecated
// properties are handled properly (e.g. we should also detect when the deprecated
// keyword is actually used to warn the developer of additional properties not
// explicitly defined in the schemas).
} else if (
error.keyword === SCHEMA_KEYWORDS.MIN_MANIFEST_VERSION ||
error.keyword === SCHEMA_KEYWORDS.MAX_MANIFEST_VERSION
) {
// Choose a different message for permissions unsupported with the
// add-on manifest_version.
if (PERMS_DATAPATH_REGEX.test(error.instancePath)) {
baseObject = messages.manifestPermissionUnsupported(error.data, error);
} else if (error.instancePath === '/applications') {
baseObject = messages.APPLICATIONS_INVALID;
} else {
baseObject = messages.manifestFieldUnsupported(
error.instancePath,
error
);
}
// Set the message and description from the one generated by the
// choosen message.
overrides.message = baseObject.message;
overrides.description = baseObject.description;
} else if (
error.instancePath.startsWith('/permissions') &&
error.keyword === SCHEMA_KEYWORDS.VALIDATE_PRIVILEGED_PERMISSIONS &&
error.params.privilegedPermissions
) {
if (this.isPrivilegedAddon) {
baseObject = error.params.privilegedPermissions.length
? messages.mozillaAddonsPermissionRequired(error)
: messages.privilegedFeaturesRequired(error);
} else {
baseObject = messages.manifestPermissionsPrivileged(error);
}
overrides.message = baseObject.message;
overrides.description = baseObject.description;
} else if (
error.instancePath.startsWith('/permissions') &&
typeof error.data !== 'undefined' &&
typeof error.data !== 'string'
) {
baseObject = messages.MANIFEST_BAD_PERMISSION;
overrides.message = `Permissions ${error.message}.`;
} else if (
error.instancePath.startsWith('/optional_permissions') &&
typeof error.data !== 'undefined' &&
typeof error.data !== 'string'
) {
baseObject = messages.MANIFEST_BAD_OPTIONAL_PERMISSION;
overrides.message = `Permissions ${error.message}.`;
} else if (
error.instancePath.startsWith('/host_permissions') &&
typeof error.data !== 'undefined' &&
typeof error.data !== 'string'
) {
baseObject = messages.MANIFEST_BAD_HOST_PERMISSION;
overrides.message = `Permissions ${error.message}.`;
} else if (error.keyword === SCHEMA_KEYWORDS.TYPE) {
baseObject = messages.MANIFEST_FIELD_INVALID;
} else if (error.keyword === SCHEMA_KEYWORDS.PRIVILEGED) {
baseObject = this.isPrivilegedAddon
? messages.mozillaAddonsPermissionRequired(error)
: messages.manifestFieldPrivileged(error);
overrides.message = baseObject.message;
overrides.description = baseObject.description;
}
// Arrays can be extremely verbose, this tries to make them a little
// more sane. Using a regex because there will likely be more as we
// expand the schema.
// Note that this works because the 2 regexps use similar patterns. We'll
// want to adjust this if they start to differ.
const match =
error.instancePath.match(PERMS_DATAPATH_REGEX) ||
error.instancePath.match(INSTALL_ORIGINS_DATAPATH_REGEX);
if (
match &&
baseObject.code !== messages.MANIFEST_BAD_PERMISSION.code &&
baseObject.code !== messages.MANIFEST_BAD_OPTIONAL_PERMISSION.code &&
baseObject.code !== messages.MANIFEST_BAD_HOST_PERMISSION.code &&
baseObject.code !== messages.MANIFEST_PERMISSION_UNSUPPORTED
) {
baseObject = messages[`MANIFEST_${match[1].toUpperCase()}`];
overrides.message = oneLine`/${match[1]}: Invalid ${match[1]}
"${error.data}" at ${match[2]}.`;
}
// Make sure we filter out warnings and errors code that should never be reported
// on manifest version 2 extensions.
const ignoredOnMV2 = [
messages.MANIFEST_HOST_PERMISSIONS.code,
messages.MANIFEST_BAD_HOST_PERMISSION.code,
];
if (
this.parsedJSON.manifest_version === 2 &&
ignoredOnMV2.includes(baseObject.code)
) {
return null;
}
return { ...baseObject, ...overrides };
}