commit 79d87f543224b0e9d69a7520e25d9179d4f2c2bc Author: Alex Catarineu acat@torproject.org Date: Mon Nov 4 16:56:27 2019 +0000
Bug 1581537 - Avoid several browser language leaks r=smaug
Spoof dom/dom.properties, layout/xmlparser.properties, layout/MediaDocument.properties to en-US if needed.
Differential Revision: https://phabricator.services.mozilla.com/D46034
--HG-- extra : moz-landing-system : lando --- .../browser_misused_characters_in_strings.js | 6 +++ browser/installer/package-manifest.in | 3 ++ dom/base/Document.cpp | 8 ++- dom/base/Document.h | 5 ++ dom/base/nsContentUtils.cpp | 55 +++++++++++++++----- dom/base/nsContentUtils.h | 32 +++++++++++- dom/html/HTMLInputElement.cpp | 40 ++++++++------- dom/html/HTMLSelectElement.cpp | 4 +- dom/html/HTMLTextAreaElement.cpp | 18 +++---- dom/html/ImageDocument.cpp | 7 ++- dom/html/MediaDocument.cpp | 59 ++++++++++++++-------- dom/html/MediaDocument.h | 7 +++ dom/html/input/CheckableInputTypes.cpp | 11 ++-- dom/html/input/DateTimeInputTypes.cpp | 13 ++--- dom/html/input/FileInputType.cpp | 5 +- dom/html/input/InputType.cpp | 42 ++++++++------- dom/html/input/NumericInputTypes.cpp | 20 ++++---- dom/html/input/SingleLineTextInputTypes.cpp | 15 +++--- dom/locales/moz.build | 6 +++ layout/base/nsCSSFrameConstructor.cpp | 9 ++-- layout/forms/nsFileControlFrame.cpp | 4 +- layout/forms/nsGfxButtonControlFrame.cpp | 4 +- layout/generic/DetailsFrame.cpp | 6 +-- mobile/android/installer/package-manifest.in | 3 ++ parser/htmlparser/nsExpatDriver.cpp | 23 ++++++--- parser/htmlparser/nsParserMsgUtils.h | 3 ++ 26 files changed, 272 insertions(+), 136 deletions(-)
diff --git a/browser/base/content/test/static/browser_misused_characters_in_strings.js b/browser/base/content/test/static/browser_misused_characters_in_strings.js index 4b1d9a75d3bb..a9667b4feb96 100644 --- a/browser/base/content/test/static/browser_misused_characters_in_strings.js +++ b/browser/base/content/test/static/browser_misused_characters_in_strings.js @@ -99,6 +99,12 @@ let gWhitelist = [ key: "PatternAttributeCompileFailure", type: "single-quote", }, + // dom.properties is packaged twice so we need to have two exceptions for this string. + { + file: "dom.properties", + key: "PatternAttributeCompileFailure", + type: "single-quote", + }, { file: "netError.dtd", key: "inadequateSecurityError.longDesc", diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 1a2a24f9b5b9..1825397678d1 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -345,6 +345,9 @@ @RESPATH@/res/dtd/* @RESPATH@/res/language.properties @RESPATH@/res/locale/layout/HtmlForm.properties +@RESPATH@/res/locale/layout/MediaDocument.properties +@RESPATH@/res/locale/layout/xmlparser.properties +@RESPATH@/res/locale/dom/dom.properties #ifdef XP_MACOSX @RESPATH@/res/MainMenu.nib/ #endif diff --git a/dom/base/Document.cpp b/dom/base/Document.cpp index cdeabc4dc7b9..df9e7bd78e72 100644 --- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -3231,7 +3231,7 @@ bool Document::DocumentSupportsL10n(JSContext* aCx, JSObject* aObject) { }
void Document::LocalizationLinkAdded(Element* aLinkElement) { - if (!nsContentUtils::PrincipalAllowsL10n(NodePrincipal(), GetDocumentURI())) { + if (!AllowsL10n()) { return; }
@@ -3262,7 +3262,7 @@ void Document::LocalizationLinkAdded(Element* aLinkElement) { }
void Document::LocalizationLinkRemoved(Element* aLinkElement) { - if (!nsContentUtils::PrincipalAllowsL10n(NodePrincipal(), GetDocumentURI())) { + if (!AllowsL10n()) { return; }
@@ -3314,6 +3314,10 @@ void Document::InitialDocumentTranslationCompleted() { mPendingInitialTranslation = false; }
+bool Document::AllowsL10n() const { + return nsContentUtils::PrincipalAllowsL10n(NodePrincipal(), GetDocumentURI()); +} + bool Document::IsWebAnimationsEnabled(JSContext* aCx, JSObject* /*unused*/) { MOZ_ASSERT(NS_IsMainThread());
diff --git a/dom/base/Document.h b/dom/base/Document.h index e65bb95d94c9..9c338b0bb153 100644 --- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -3661,6 +3661,11 @@ class Document : public nsINode, */ virtual void InitialDocumentTranslationCompleted();
+ /** + * Returns whether the document allows localization. + */ + bool AllowsL10n() const; + protected: RefPtr<DocumentL10n> mDocumentL10n;
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 9c60c1befe1e..e75fd6c9af8b 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -3574,8 +3574,8 @@ static const char* gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT] = { "chrome://global/locale/mathml/mathml.properties", "chrome://global/locale/security/security.properties", "chrome://necko/locale/necko.properties", - "chrome://global/locale/layout/HtmlForm.properties", - "resource://gre/res/locale/layout/HtmlForm.properties"}; + "resource://gre/res/locale/layout/HtmlForm.properties", + "resource://gre/res/locale/dom/dom.properties"};
/* static */ nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) { @@ -3624,22 +3624,47 @@ void nsContentUtils::AsyncPrecreateStringBundles() { } }
-static bool SpoofLocaleEnglish() { +/* static */ +bool nsContentUtils::SpoofLocaleEnglish() { // 0 - will prompt // 1 - don't spoof // 2 - spoof return StaticPrefs::privacy_spoof_english() == 2; }
+static nsContentUtils::PropertiesFile GetMaybeSpoofedPropertiesFile( + nsContentUtils::PropertiesFile aFile, const char* aKey, + Document* aDocument) { + // When we spoof English, use en-US properties in strings that are accessible + // by content. + bool spoofLocale = nsContentUtils::SpoofLocaleEnglish() && + (!aDocument || !aDocument->AllowsL10n()); + if (spoofLocale) { + switch (aFile) { + case nsContentUtils::eFORMS_PROPERTIES: + return nsContentUtils::eFORMS_PROPERTIES_en_US; + case nsContentUtils::eDOM_PROPERTIES: + return nsContentUtils::eDOM_PROPERTIES_en_US; + default: + break; + } + } + return aFile; +} + +/* static */ +nsresult nsContentUtils::GetMaybeLocalizedString(PropertiesFile aFile, + const char* aKey, + Document* aDocument, + nsAString& aResult) { + return GetLocalizedString( + GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aResult); +} + /* static */ nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile, const char* aKey, nsAString& aResult) { - // When we spoof English, use en-US default strings in HTML forms. - if (aFile == eFORMS_PROPERTIES_MAYBESPOOF && SpoofLocaleEnglish()) { - aFile = eFORMS_PROPERTIES_en_US; - } - nsresult rv = EnsureStringBundle(aFile); NS_ENSURE_SUCCESS(rv, rv); nsIStringBundle* bundle = sStringBundles[aFile]; @@ -3647,16 +3672,20 @@ nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile, }
/* static */ +nsresult nsContentUtils::FormatMaybeLocalizedString( + PropertiesFile aFile, const char* aKey, Document* aDocument, + const char16_t** aParams, uint32_t aParamsLength, nsAString& aResult) { + return FormatLocalizedString( + GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aParams, + aParamsLength, aResult); +} + +/* static */ nsresult nsContentUtils::FormatLocalizedString(PropertiesFile aFile, const char* aKey, const char16_t** aParams, uint32_t aParamsLength, nsAString& aResult) { - // When we spoof English, use en-US default strings in HTML forms. - if (aFile == eFORMS_PROPERTIES_MAYBESPOOF && SpoofLocaleEnglish()) { - aFile = eFORMS_PROPERTIES_en_US; - } - nsresult rv = EnsureStringBundle(aFile); NS_ENSURE_SUCCESS(rv, rv); nsIStringBundle* bundle = sStringBundles[aFile]; diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index ee23a540871d..5b1eefef3854 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -1117,8 +1117,8 @@ class nsContentUtils { eMATHML_PROPERTIES, eSECURITY_PROPERTIES, eNECKO_PROPERTIES, - eFORMS_PROPERTIES_MAYBESPOOF, eFORMS_PROPERTIES_en_US, + eDOM_PROPERTIES_en_US, PropertiesFile_COUNT }; static nsresult ReportToConsole( @@ -1132,6 +1132,8 @@ class nsContentUtils {
static void LogMessageToConsole(const char* aMsg);
+ static bool SpoofLocaleEnglish(); + /** * Get the localized string named |aKey| in properties file |aFile|. */ @@ -1139,6 +1141,15 @@ class nsContentUtils { nsAString& aResult);
/** + * Same as GetLocalizedString, except that it might use en-US locale depending + * on SpoofLocaleEnglish() and whether the document is a built-in browser + * page. + */ + static nsresult GetMaybeLocalizedString(PropertiesFile aFile, + const char* aKey, Document* aDocument, + nsAString& aResult); + + /** * A helper function that parses a sandbox attribute (of an <iframe> or a CSP * directive) and converts it to the set of flags used internally. * @@ -1210,6 +1221,15 @@ class nsContentUtils { uint32_t aParamsLength, nsAString& aResult);
+ /** + * Same as FormatLocalizedString, except that it might use en-US locale + * depending on SpoofLocaleEnglish() and whether the document is a built-in + * browser page. + */ + static nsresult FormatMaybeLocalizedString( + PropertiesFile aFile, const char* aKey, Document* aDocument, + const char16_t** aParams, uint32_t aParamsLength, nsAString& aResult); + public: template <uint32_t N> static nsresult FormatLocalizedString(PropertiesFile aFile, const char* aKey, @@ -1218,6 +1238,16 @@ class nsContentUtils { return FormatLocalizedString(aFile, aKey, aParams, N, aResult); }
+ template <uint32_t N> + static nsresult FormatMaybeLocalizedString(PropertiesFile aFile, + const char* aKey, + Document* aDocument, + const char16_t* (&aParams)[N], + nsAString& aResult) { + return FormatMaybeLocalizedString(aFile, aKey, aDocument, aParams, N, + aResult); + } + /** * Fill (with the parameters given) the localized string named |aKey| in * properties file |aFile| consuming an nsTArray of nsString parameters rather diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index dd0365a7646c..3217c78a2757 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -725,15 +725,16 @@ nsresult HTMLInputElement::InitFilePicker(FilePickerType aType) { nsAutoString title; nsAutoString okButtonLabel; if (aType == FILE_PICKER_DIRECTORY) { - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "DirectoryUpload", title); + nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + "DirectoryUpload", OwnerDoc(), + title);
- nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, - "DirectoryPickerOkButtonLabel", okButtonLabel); + nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + "DirectoryPickerOkButtonLabel", + OwnerDoc(), okButtonLabel); } else { - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "FileUpload", title); + nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + "FileUpload", OwnerDoc(), title); }
nsCOMPtr<nsIFilePicker> filePicker = @@ -2339,24 +2340,25 @@ void HTMLInputElement::GetDisplayFileName(nsAString& aValue) const { if ((IsDirPickerEnabled() && Allowdirs()) || (StaticPrefs::dom_webkitBlink_dirPicker_enabled() && HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory))) { - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "NoDirSelected", value); + nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + "NoDirSelected", OwnerDoc(), + value); } else if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) { - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "NoFilesSelected", - value); + nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + "NoFilesSelected", OwnerDoc(), + value); } else { - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "NoFileSelected", - value); + nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + "NoFileSelected", OwnerDoc(), + value); } } else { nsString count; count.AppendInt(int(mFileData->mFilesOrDirectories.Length()));
const char16_t* params[] = {count.get()}; - nsContentUtils::FormatLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "XFilesSelected", params, + nsContentUtils::FormatMaybeLocalizedString( + nsContentUtils::eFORMS_PROPERTIES, "XFilesSelected", OwnerDoc(), params, value); }
@@ -5828,8 +5830,8 @@ HTMLInputElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission) { !HasAttr(kNameSpaceID_None, nsGkAtoms::value)) { // Get our default value, which is the same as our default label nsAutoString defaultValue; - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "Submit", defaultValue); + nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + "Submit", OwnerDoc(), defaultValue); value = defaultValue; }
diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp index 76f21db23b31..a7a93468af02 100644 --- a/dom/html/HTMLSelectElement.cpp +++ b/dom/html/HTMLSelectElement.cpp @@ -1538,9 +1538,9 @@ nsresult HTMLSelectElement::GetValidationMessage(nsAString& aValidationMessage, switch (aType) { case VALIDITY_STATE_VALUE_MISSING: { nsAutoString message; - nsresult rv = nsContentUtils::GetLocalizedString( + nsresult rv = nsContentUtils::GetMaybeLocalizedString( nsContentUtils::eDOM_PROPERTIES, "FormValidationSelectMissing", - message); + OwnerDoc(), message); aValidationMessage = message; return rv; } diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp index 0d1ba35c8b59..5a5a81545142 100644 --- a/dom/html/HTMLTextAreaElement.cpp +++ b/dom/html/HTMLTextAreaElement.cpp @@ -1000,9 +1000,9 @@ nsresult HTMLTextAreaElement::GetValidationMessage( strTextLength.AppendInt(textLength);
const char16_t* params[] = {strMaxLength.get(), strTextLength.get()}; - rv = nsContentUtils::FormatLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooLong", params, - message); + rv = nsContentUtils::FormatMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooLong", + OwnerDoc(), params, message); aValidationMessage = message; } break; case VALIDITY_STATE_TOO_SHORT: { @@ -1016,16 +1016,16 @@ nsresult HTMLTextAreaElement::GetValidationMessage( strTextLength.AppendInt(textLength);
const char16_t* params[] = {strMinLength.get(), strTextLength.get()}; - rv = nsContentUtils::FormatLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooShort", params, - message); + rv = nsContentUtils::FormatMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooShort", + OwnerDoc(), params, message); aValidationMessage = message; } break; case VALIDITY_STATE_VALUE_MISSING: { nsAutoString message; - rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, - "FormValidationValueMissing", - message); + rv = nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationValueMissing", + OwnerDoc(), message); aValidationMessage = message; } break; default: diff --git a/dom/html/ImageDocument.cpp b/dom/html/ImageDocument.cpp index 87b70961a386..2de785f5fb51 100644 --- a/dom/html/ImageDocument.cpp +++ b/dom/html/ImageDocument.cpp @@ -577,14 +577,13 @@ nsresult ImageDocument::OnLoadComplete(imgIRequest* aRequest, UpdateTitleAndCharset();
// mImageContent can be null if the document is already destroyed - if (NS_FAILED(aStatus) && mStringBundle && mImageContent) { + if (NS_FAILED(aStatus) && mImageContent) { nsAutoCString src; mDocumentURI->GetSpec(src); NS_ConvertUTF8toUTF16 srcString(src); const char16_t* formatString[] = {srcString.get()}; nsAutoString errorMsg; - mStringBundle->FormatStringFromName("InvalidImage", formatString, 1, - errorMsg); + FormatStringFromName("InvalidImage", formatString, 1, errorMsg);
mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::alt, errorMsg, false); } @@ -788,7 +787,7 @@ void ImageDocument::UpdateTitleAndCharset() { ratioStr.AppendInt(NSToCoordFloor(GetRatio() * 100));
const char16_t* formatString[1] = {ratioStr.get()}; - mStringBundle->FormatStringFromName("ScaledImage", formatString, 1, status); + FormatStringFromName("ScaledImage", formatString, 1, status); }
static const char* const formatNames[4] = { diff --git a/dom/html/MediaDocument.cpp b/dom/html/MediaDocument.cpp index 196adddc0f38..48d209d67b11 100644 --- a/dom/html/MediaDocument.cpp +++ b/dom/html/MediaDocument.cpp @@ -121,14 +121,6 @@ nsresult MediaDocument::Init() { nsresult rv = nsHTMLDocument::Init(); NS_ENSURE_SUCCESS(rv, rv);
- // Create a bundle for the localization - nsCOMPtr<nsIStringBundleService> stringService = - mozilla::services::GetStringBundleService(); - if (stringService) { - stringService->CreateBundle(NSMEDIADOCUMENT_PROPERTIES_URI, - getter_AddRefs(mStringBundle)); - } - mIsSyntheticDocument = true;
return NS_OK; @@ -327,6 +319,38 @@ nsresult MediaDocument::LinkScript(const nsAString& aScript) { return head->AppendChildTo(script, false); }
+void MediaDocument::FormatStringFromName(const char* aName, + const char16_t** aParams, + uint32_t aLength, nsAString& aResult) { + bool spoofLocale = nsContentUtils::SpoofLocaleEnglish() && !AllowsL10n(); + if (!spoofLocale) { + if (!mStringBundle) { + nsCOMPtr<nsIStringBundleService> stringService = + mozilla::services::GetStringBundleService(); + if (stringService) { + stringService->CreateBundle(NSMEDIADOCUMENT_PROPERTIES_URI, + getter_AddRefs(mStringBundle)); + } + } + if (mStringBundle) { + mStringBundle->FormatStringFromName(aName, aParams, aLength, aResult); + } + } else { + if (!mStringBundleEnglish) { + nsCOMPtr<nsIStringBundleService> stringService = + mozilla::services::GetStringBundleService(); + if (stringService) { + stringService->CreateBundle(NSMEDIADOCUMENT_PROPERTIES_URI_en_US, + getter_AddRefs(mStringBundleEnglish)); + } + } + if (mStringBundleEnglish) { + mStringBundleEnglish->FormatStringFromName(aName, aParams, aLength, + aResult); + } + } +} + void MediaDocument::UpdateTitleAndCharset(const nsACString& aTypeStr, nsIChannel* aChannel, const char* const* aFormatNames, @@ -338,7 +362,6 @@ void MediaDocument::UpdateTitleAndCharset(const nsACString& aTypeStr, NS_ConvertASCIItoUTF16 typeStr(aTypeStr); nsAutoString title;
- if (mStringBundle) { // if we got a valid size (not all media have a size) if (aWidth != 0 && aHeight != 0) { nsAutoString widthStr; @@ -349,27 +372,24 @@ void MediaDocument::UpdateTitleAndCharset(const nsACString& aTypeStr, if (!fileStr.IsEmpty()) { const char16_t* formatStrings[4] = {fileStr.get(), typeStr.get(), widthStr.get(), heightStr.get()}; - mStringBundle->FormatStringFromName(aFormatNames[eWithDimAndFile], - formatStrings, 4, title); + FormatStringFromName(aFormatNames[eWithDimAndFile], formatStrings, 4, + title); } else { const char16_t* formatStrings[3] = {typeStr.get(), widthStr.get(), heightStr.get()}; - mStringBundle->FormatStringFromName(aFormatNames[eWithDim], - formatStrings, 3, title); + FormatStringFromName(aFormatNames[eWithDim], formatStrings, 3, title); } } else { // If we got a filename, display it if (!fileStr.IsEmpty()) { const char16_t* formatStrings[2] = {fileStr.get(), typeStr.get()}; - mStringBundle->FormatStringFromName(aFormatNames[eWithFile], - formatStrings, 2, title); + FormatStringFromName(aFormatNames[eWithFile], formatStrings, 2, title); } else { const char16_t* formatStrings[1] = {typeStr.get()}; - mStringBundle->FormatStringFromName(aFormatNames[eWithNoInfo], - formatStrings, 1, title); + FormatStringFromName(aFormatNames[eWithNoInfo], formatStrings, 1, + title); } } - }
// set it on the document if (aStatus.IsEmpty()) { @@ -379,8 +399,7 @@ void MediaDocument::UpdateTitleAndCharset(const nsACString& aTypeStr, nsAutoString titleWithStatus; const nsPromiseFlatString& status = PromiseFlatString(aStatus); const char16_t* formatStrings[2] = {title.get(), status.get()}; - mStringBundle->FormatStringFromName("TitleWithStatus", formatStrings, 2, - titleWithStatus); + FormatStringFromName("TitleWithStatus", formatStrings, 2, titleWithStatus); IgnoredErrorResult ignored; SetTitle(titleWithStatus, ignored); } diff --git a/dom/html/MediaDocument.h b/dom/html/MediaDocument.h index e11fd2ec8551..9c295e70d85f 100644 --- a/dom/html/MediaDocument.h +++ b/dom/html/MediaDocument.h @@ -16,6 +16,9 @@ #define NSMEDIADOCUMENT_PROPERTIES_URI \ "chrome://global/locale/layout/MediaDocument.properties"
+#define NSMEDIADOCUMENT_PROPERTIES_URI_en_US \ + "resource://gre/res/locale/layout/MediaDocument.properties" + namespace mozilla { namespace dom {
@@ -60,6 +63,9 @@ class MediaDocument : public nsHTMLDocument { nsresult LinkStylesheet(const nsAString& aStylesheet); nsresult LinkScript(const nsAString& aScript);
+ void FormatStringFromName(const char* aName, const char16_t** aParams, + uint32_t aLength, nsAString& aResult); + // |aFormatNames[]| needs to have four elements in the following order: // a format name with neither dimension nor file, a format name with // filename but w/o dimension, a format name with dimension but w/o filename, @@ -77,6 +83,7 @@ class MediaDocument : public nsHTMLDocument { const nsAString& aStatus = EmptyString());
nsCOMPtr<nsIStringBundle> mStringBundle; + nsCOMPtr<nsIStringBundle> mStringBundleEnglish; static const char* const sFormatNames[4];
private: diff --git a/dom/html/input/CheckableInputTypes.cpp b/dom/html/input/CheckableInputTypes.cpp index f55000c766ea..c564c36b884a 100644 --- a/dom/html/input/CheckableInputTypes.cpp +++ b/dom/html/input/CheckableInputTypes.cpp @@ -23,14 +23,15 @@ bool CheckboxInputType::IsValueMissing() const { }
nsresult CheckboxInputType::GetValueMissingMessage(nsAString& aMessage) { - return nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, - "FormValidationCheckboxMissing", - aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationCheckboxMissing", + mInputElement->OwnerDoc(), aMessage); }
/* input type=radio */
nsresult RadioInputType::GetValueMissingMessage(nsAString& aMessage) { - return nsContentUtils::GetLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationRadioMissing", aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationRadioMissing", + mInputElement->OwnerDoc(), aMessage); } diff --git a/dom/html/input/DateTimeInputTypes.cpp b/dom/html/input/DateTimeInputTypes.cpp index 11dfc9e541b9..6d87313907f4 100644 --- a/dom/html/input/DateTimeInputTypes.cpp +++ b/dom/html/input/DateTimeInputTypes.cpp @@ -137,9 +137,9 @@ nsresult DateTimeInputTypeBase::GetRangeOverflowMessage(nsAString& aMessage) { mInputElement->GetAttr(kNameSpaceID_None, nsGkAtoms::max, maxStr);
const char16_t* params[] = {maxStr.get()}; - return nsContentUtils::FormatLocalizedString( + return nsContentUtils::FormatMaybeLocalizedString( nsContentUtils::eDOM_PROPERTIES, "FormValidationDateTimeRangeOverflow", - params, aMessage); + mInputElement->OwnerDoc(), params, aMessage); }
nsresult DateTimeInputTypeBase::GetRangeUnderflowMessage(nsAString& aMessage) { @@ -147,9 +147,9 @@ nsresult DateTimeInputTypeBase::GetRangeUnderflowMessage(nsAString& aMessage) { mInputElement->GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
const char16_t* params[] = {minStr.get()}; - return nsContentUtils::FormatLocalizedString( + return nsContentUtils::FormatMaybeLocalizedString( nsContentUtils::eDOM_PROPERTIES, "FormValidationDateTimeRangeUnderflow", - params, aMessage); + mInputElement->OwnerDoc(), params, aMessage); }
nsresult DateTimeInputTypeBase::MinMaxStepAttrChanged() { @@ -193,8 +193,9 @@ nsresult DateInputType::GetBadInputMessage(nsAString& aMessage) { return NS_ERROR_UNEXPECTED; }
- return nsContentUtils::GetLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidDate", aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidDate", + mInputElement->OwnerDoc(), aMessage); }
bool DateInputType::ConvertStringToNumber( diff --git a/dom/html/input/FileInputType.cpp b/dom/html/input/FileInputType.cpp index 2536a875b2ca..856684080825 100644 --- a/dom/html/input/FileInputType.cpp +++ b/dom/html/input/FileInputType.cpp @@ -21,6 +21,7 @@ bool FileInputType::IsValueMissing() const { }
nsresult FileInputType::GetValueMissingMessage(nsAString& aMessage) { - return nsContentUtils::GetLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationFileMissing", aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationFileMissing", + mInputElement->OwnerDoc(), aMessage); } diff --git a/dom/html/input/InputType.cpp b/dom/html/input/InputType.cpp index 210daeafad14..51dbe9b93527 100644 --- a/dom/html/input/InputType.cpp +++ b/dom/html/input/InputType.cpp @@ -166,9 +166,9 @@ nsresult InputType::GetValidationMessage( strTextLength.AppendInt(textLength);
const char16_t* params[] = {strMaxLength.get(), strTextLength.get()}; - rv = nsContentUtils::FormatLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooLong", params, - message); + rv = nsContentUtils::FormatMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooLong", + mInputElement->OwnerDoc(), params, message); aValidationMessage = message; break; } @@ -184,9 +184,9 @@ nsresult InputType::GetValidationMessage( strTextLength.AppendInt(textLength);
const char16_t* params[] = {strMinLength.get(), strTextLength.get()}; - rv = nsContentUtils::FormatLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooShort", params, - message); + rv = nsContentUtils::FormatMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationTextTooShort", + mInputElement->OwnerDoc(), params, message);
aValidationMessage = message; break; @@ -216,9 +216,9 @@ nsresult InputType::GetValidationMessage( nsAutoString title; mInputElement->GetAttr(kNameSpaceID_None, nsGkAtoms::title, title); if (title.IsEmpty()) { - rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, - "FormValidationPatternMismatch", - message); + rv = nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationPatternMismatch", + mInputElement->OwnerDoc(), message); } else { if (title.Length() > nsIConstraintValidation::sContentSpecifiedMaxLengthMessage) { @@ -226,9 +226,10 @@ nsresult InputType::GetValidationMessage( nsIConstraintValidation::sContentSpecifiedMaxLengthMessage); } const char16_t* params[] = {title.get()}; - rv = nsContentUtils::FormatLocalizedString( + rv = nsContentUtils::FormatMaybeLocalizedString( nsContentUtils::eDOM_PROPERTIES, - "FormValidationPatternMismatchWithTitle", params, message); + "FormValidationPatternMismatchWithTitle", mInputElement->OwnerDoc(), + params, message); } aValidationMessage = message; break; @@ -278,23 +279,25 @@ nsresult InputType::GetValidationMessage(
if (valueLowStr.Equals(valueHighStr)) { const char16_t* params[] = {valueLowStr.get()}; - rv = nsContentUtils::FormatLocalizedString( + rv = nsContentUtils::FormatMaybeLocalizedString( nsContentUtils::eDOM_PROPERTIES, - "FormValidationStepMismatchOneValue", params, message); + "FormValidationStepMismatchOneValue", mInputElement->OwnerDoc(), + params, message); } else { const char16_t* params[] = {valueLowStr.get(), valueHighStr.get()}; - rv = nsContentUtils::FormatLocalizedString( + rv = nsContentUtils::FormatMaybeLocalizedString( nsContentUtils::eDOM_PROPERTIES, "FormValidationStepMismatch", - params, message); + mInputElement->OwnerDoc(), params, message); } } else { nsAutoString valueLowStr; ConvertNumberToString(valueLow, valueLowStr);
const char16_t* params[] = {valueLowStr.get()}; - rv = nsContentUtils::FormatLocalizedString( + rv = nsContentUtils::FormatMaybeLocalizedString( nsContentUtils::eDOM_PROPERTIES, - "FormValidationStepMismatchOneValue", params, message); + "FormValidationStepMismatchOneValue", mInputElement->OwnerDoc(), + params, message); }
aValidationMessage = message; @@ -318,8 +321,9 @@ nsresult InputType::GetValidationMessage( }
nsresult InputType::GetValueMissingMessage(nsAString& aMessage) { - return nsContentUtils::GetLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationValueMissing", aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationValueMissing", + mInputElement->OwnerDoc(), aMessage); }
nsresult InputType::GetTypeMismatchMessage(nsAString& aMessage) { diff --git a/dom/html/input/NumericInputTypes.cpp b/dom/html/input/NumericInputTypes.cpp index 6332e028c17e..9770ccd416b1 100644 --- a/dom/html/input/NumericInputTypes.cpp +++ b/dom/html/input/NumericInputTypes.cpp @@ -72,9 +72,9 @@ nsresult NumericInputTypeBase::GetRangeOverflowMessage(nsAString& aMessage) { MOZ_ASSERT(ok, "buf not big enough");
const char16_t* params[] = {maxStr.get()}; - return nsContentUtils::FormatLocalizedString( + return nsContentUtils::FormatMaybeLocalizedString( nsContentUtils::eDOM_PROPERTIES, "FormValidationNumberRangeOverflow", - params, aMessage); + mInputElement->OwnerDoc(), params, aMessage); }
nsresult NumericInputTypeBase::GetRangeUnderflowMessage(nsAString& aMessage) { @@ -89,9 +89,9 @@ nsresult NumericInputTypeBase::GetRangeUnderflowMessage(nsAString& aMessage) { MOZ_ASSERT(ok, "buf not big enough");
const char16_t* params[] = {minStr.get()}; - return nsContentUtils::FormatLocalizedString( + return nsContentUtils::FormatMaybeLocalizedString( nsContentUtils::eDOM_PROPERTIES, "FormValidationNumberRangeUnderflow", - params, aMessage); + mInputElement->OwnerDoc(), params, aMessage); }
bool NumericInputTypeBase::ConvertStringToNumber( @@ -150,15 +150,15 @@ bool NumberInputType::HasBadInput() const { }
nsresult NumberInputType::GetValueMissingMessage(nsAString& aMessage) { - return nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, - "FormValidationBadInputNumber", - aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationBadInputNumber", + mInputElement->OwnerDoc(), aMessage); }
nsresult NumberInputType::GetBadInputMessage(nsAString& aMessage) { - return nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES, - "FormValidationBadInputNumber", - aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationBadInputNumber", + mInputElement->OwnerDoc(), aMessage); }
bool NumberInputType::IsMutable() const { diff --git a/dom/html/input/SingleLineTextInputTypes.cpp b/dom/html/input/SingleLineTextInputTypes.cpp index 15cbe65a1941..090de7466fae 100644 --- a/dom/html/input/SingleLineTextInputTypes.cpp +++ b/dom/html/input/SingleLineTextInputTypes.cpp @@ -116,8 +116,9 @@ bool URLInputType::HasTypeMismatch() const { }
nsresult URLInputType::GetTypeMismatchMessage(nsAString& aMessage) { - return nsContentUtils::GetLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidURL", aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidURL", + mInputElement->OwnerDoc(), aMessage); }
/* input type=email */ @@ -154,13 +155,15 @@ bool EmailInputType::HasBadInput() const { }
nsresult EmailInputType::GetTypeMismatchMessage(nsAString& aMessage) { - return nsContentUtils::GetLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidEmail", aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidEmail", + mInputElement->OwnerDoc(), aMessage); }
nsresult EmailInputType::GetBadInputMessage(nsAString& aMessage) { - return nsContentUtils::GetLocalizedString( - nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidEmail", aMessage); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eDOM_PROPERTIES, "FormValidationInvalidEmail", + mInputElement->OwnerDoc(), aMessage); }
/* static */ diff --git a/dom/locales/moz.build b/dom/locales/moz.build index b2bcd271de7c..51f4b88ccd47 100644 --- a/dom/locales/moz.build +++ b/dom/locales/moz.build @@ -62,4 +62,10 @@ JAR_MANIFESTS += ['jar.mn']
RESOURCE_FILES.locale.layout += [ 'en-US/chrome/layout/HtmlForm.properties', + 'en-US/chrome/layout/MediaDocument.properties', + 'en-US/chrome/layout/xmlparser.properties', +] + +RESOURCE_FILES.locale.dom += [ + 'en-US/chrome/dom/dom.properties', ] diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 7a5a96d1769a..491274c9b2a6 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1654,8 +1654,8 @@ already_AddRefed<nsIContent> nsCSSFrameConstructor::CreateGeneratedContent( }
nsAutoString temp; - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "Submit", temp); + nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eFORMS_PROPERTIES, "Submit", mDocument, temp); return CreateGenConTextNode(aState, temp, nullptr, nullptr); }
@@ -7899,8 +7899,9 @@ void nsCSSFrameConstructor::GetAlternateTextFor(Element* aElement, nsAtom* aTag,
// If there's no "value" attribute either, then use the localized string for // "Submit" as the alternate text. - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "Submit", aAltText); + nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + "Submit", aElement->OwnerDoc(), + aAltText); } }
diff --git a/layout/forms/nsFileControlFrame.cpp b/layout/forms/nsFileControlFrame.cpp index 9be30011aa8e..8da00f76dcea 100644 --- a/layout/forms/nsFileControlFrame.cpp +++ b/layout/forms/nsFileControlFrame.cpp @@ -215,8 +215,8 @@ static already_AddRefed<Element> MakeAnonButton(Document* aDoc,
// Set the file picking button text depending on the current locale. nsAutoString buttonTxt; - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, labelKey, buttonTxt); + nsContentUtils::GetMaybeLocalizedString(nsContentUtils::eFORMS_PROPERTIES, + labelKey, aDoc, buttonTxt);
// Set the browse button text. It's a bit of a pain to do because we want to // make sure we are not notifying. diff --git a/layout/forms/nsGfxButtonControlFrame.cpp b/layout/forms/nsGfxButtonControlFrame.cpp index 03186ef7bf54..fa4219a5308f 100644 --- a/layout/forms/nsGfxButtonControlFrame.cpp +++ b/layout/forms/nsGfxButtonControlFrame.cpp @@ -88,8 +88,8 @@ nsresult nsGfxButtonControlFrame::GetDefaultLabel(nsAString& aString) const { return NS_OK; }
- return nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, prop, aString); + return nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eFORMS_PROPERTIES, prop, mContent->OwnerDoc(), aString); }
nsresult nsGfxButtonControlFrame::GetLabel(nsString& aLabel) { diff --git a/layout/generic/DetailsFrame.cpp b/layout/generic/DetailsFrame.cpp index e1a9f0c70b2b..20f93b2f328f 100644 --- a/layout/generic/DetailsFrame.cpp +++ b/layout/generic/DetailsFrame.cpp @@ -98,9 +98,9 @@ nsresult DetailsFrame::CreateAnonymousContent( mDefaultSummary = new HTMLSummaryElement(nodeInfo.forget());
nsAutoString defaultSummaryText; - nsContentUtils::GetLocalizedString( - nsContentUtils::eFORMS_PROPERTIES_MAYBESPOOF, "DefaultSummary", - defaultSummaryText); + nsContentUtils::GetMaybeLocalizedString( + nsContentUtils::eFORMS_PROPERTIES, "DefaultSummary", + GetContent()->OwnerDoc(), defaultSummaryText); RefPtr<nsTextNode> description = new nsTextNode(nodeInfoManager); description->SetText(defaultSummaryText, false); mDefaultSummary->AppendChildTo(description, false); diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index 2002a894fc51..33e0175a624e 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -203,6 +203,9 @@ @BINPATH@/res/dtd/* @BINPATH@/res/language.properties @BINPATH@/res/locale/layout/HtmlForm.properties +@BINPATH@/res/locale/layout/MediaDocument.properties +@BINPATH@/res/locale/layout/xmlparser.properties +@BINPATH@/res/locale/dom/dom.properties
#ifndef MOZ_ANDROID_EXCLUDE_FONTS @BINPATH@/res/fonts/* diff --git a/parser/htmlparser/nsExpatDriver.cpp b/parser/htmlparser/nsExpatDriver.cpp index 73a0e65328f0..0c35f87bc321 100644 --- a/parser/htmlparser/nsExpatDriver.cpp +++ b/parser/htmlparser/nsExpatDriver.cpp @@ -673,12 +673,13 @@ static nsresult CreateErrorText(const char16_t* aDescription, const char16_t* aSourceURL, const uint32_t aLineNumber, const uint32_t aColNumber, - nsString& aErrorString) { + nsString& aErrorString, bool spoofEnglish) { aErrorString.Truncate();
nsAutoString msg; nsresult rv = nsParserMsgUtils::GetLocalizedStringByName( - XMLPARSER_PROPERTIES, "XMLParsingError", msg); + spoofEnglish ? XMLPARSER_PROPERTIES_en_US : XMLPARSER_PROPERTIES, + "XMLParsingError", msg); NS_ENSURE_SUCCESS(rv, rv);
// XML Parsing Error: %1$S\nLocation: %2$S\nLine Number %3$u, Column %4$u: @@ -719,8 +720,15 @@ nsresult nsExpatDriver::HandleError() { // Map Expat error code to an error string // XXX Deal with error returns. nsAutoString description; - nsParserMsgUtils::GetLocalizedStringByID(XMLPARSER_PROPERTIES, code, - description); + nsCOMPtr<Document> doc; + if (mOriginalSink) { + doc = do_QueryInterface(mOriginalSink->GetTarget()); + } + bool spoofEnglish = + nsContentUtils::SpoofLocaleEnglish() && (!doc || !doc->AllowsL10n()); + nsParserMsgUtils::GetLocalizedStringByID( + spoofEnglish ? XMLPARSER_PROPERTIES_en_US : XMLPARSER_PROPERTIES, code, + description);
if (code == XML_ERROR_TAG_MISMATCH) { /** @@ -756,8 +764,9 @@ nsresult nsExpatDriver::HandleError() { tagName.Append(nameStart, (nameEnd ? nameEnd : pos) - nameStart);
nsAutoString msg; - nsParserMsgUtils::GetLocalizedStringByName(XMLPARSER_PROPERTIES, "Expected", - msg); + nsParserMsgUtils::GetLocalizedStringByName( + spoofEnglish ? XMLPARSER_PROPERTIES_en_US : XMLPARSER_PROPERTIES, + "Expected", msg);
// . Expected: </%S>. nsAutoString message; @@ -771,7 +780,7 @@ nsresult nsExpatDriver::HandleError() {
nsAutoString errorText; CreateErrorText(description.get(), XML_GetBase(mExpatParser), lineNumber, - colNumber, errorText); + colNumber, errorText, spoofEnglish);
nsAutoString sourceText(mLastLine); AppendErrorPointer(colNumber, mLastLine.get(), sourceText); diff --git a/parser/htmlparser/nsParserMsgUtils.h b/parser/htmlparser/nsParserMsgUtils.h index b4ec4784d65f..3645610385c1 100644 --- a/parser/htmlparser/nsParserMsgUtils.h +++ b/parser/htmlparser/nsParserMsgUtils.h @@ -11,6 +11,9 @@ #define XMLPARSER_PROPERTIES \ "chrome://global/locale/layout/xmlparser.properties"
+#define XMLPARSER_PROPERTIES_en_US \ + "resource://gre/res/locale/layout/xmlparser.properties" + class nsParserMsgUtils { nsParserMsgUtils(); // Currently this is not meant to be created, use the // static methods
tbb-commits@lists.torproject.org