diff --git a/netwerk/protocol/http/nsHttpHandler.cpp b/netwerk/protocol/http/nsHttpHandler.cpp index ed91f49584d2..9b7e9cfa2caf 100644 --- a/netwerk/protocol/http/nsHttpHandler.cpp +++ b/netwerk/protocol/http/nsHttpHandler.cpp @@ -1562,22 +1562,47 @@ nsHttpHandler::TimerCallback(nsITimer * aTimer, void * aClosure) thisObject->mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING; } +/** + * Currently, only regularizes the case of subtags. + */ static void -NormalizeLanguageTag(char *code) +CanonicalizeLanguageTag(char *languageTag) { - bool is_region = false; - while (*code != '\0') - { - if (*code == '-') { - is_region = true; + char *s = languageTag; + while (*s != '\0') { + *s = nsCRT::ToLower(*s); + s++; + } + + s = languageTag; + bool isFirst = true; + bool seenSingleton = false; + while (*s != '\0') { + char *subTagEnd = strchr(s, '-'); + if (subTagEnd == nullptr) { + subTagEnd = strchr(s, '\0'); + } + + if (isFirst) { + isFirst = false; + } else if (seenSingleton) { + // Do nothing } else { - if (is_region) { - *code = nsCRT::ToUpper(*code); - } else { - *code = nsCRT::ToLower(*code); + size_t subTagLength = subTagEnd - s; + if (subTagLength == 1) { + seenSingleton = true; + } else if (subTagLength == 2) { + *s = nsCRT::ToUpper(*s); + *(s + 1) = nsCRT::ToUpper(*(s + 1)); + } else if (subTagLength == 4) { + *s = nsCRT::ToUpper(*s); } } - code++; + + s = subTagEnd; + if (*s != '\0') { + s++; + } } } @@ -1636,7 +1661,7 @@ PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLangua *trim = '\0'; if (*token != '\0') { - NormalizeLanguageTag(token); + CanonicalizeLanguageTag(token); comma = count_n++ != 0 ? "," : ""; // delimiter if not first item uint32_t u = QVAL_TO_UINT(q); diff --git a/netwerk/test/unit/test_header_Accept-Language_case.js b/netwerk/test/unit/test_header_Accept-Language_case.js index f64e5cffaff7..2374ff1f8b72 100644 --- a/netwerk/test/unit/test_header_Accept-Language_case.js +++ b/netwerk/test/unit/test_header_Accept-Language_case.js @@ -8,6 +8,16 @@ function run_test() { let oldAcceptLangPref = intlPrefs.getCharPref("accept_languages"); let testData = [ + ["en", "en"], + ["ast", "ast"], + ["fr-ca", "fr-CA"], + ["zh-yue", "zh-yue"], + ["az-latn", "az-Latn"], + ["sl-nedis", "sl-nedis"], + ["zh-hant-hk", "zh-Hant-HK"], + ["ZH-HANT-HK", "zh-Hant-HK"], + ["en-us-x-priv", "en-US-x-priv"], + ["en-us-x-twain", "en-US-x-twain"], ["de, en-US, en", "de,en-US;q=0.7,en;q=0.3"], ["de,en-us,en", "de,en-US;q=0.7,en;q=0.3"], ["en-US, en", "en-US,en;q=0.5"],