Bug 1454590 - Align overrideMIMEType with the XMLHttpRequest Standard. r?hsivonen
MozReview-Commit-ID: 5k34F96jRPX
new file mode 100644
--- /dev/null
+++ b/dom/base/MimeType.cpp
@@ -0,0 +1,256 @@
+#include "MimeType.h"
+#include "nsUnicharUtils.h"
+
+namespace {
+ static inline bool IsHTTPTokenPoint(const char16_t c) {
+ return c == '!' || c == '#' || c == '$' || c == '%' || c == '&' ||
+ c == '\'' || c == '*' || c == '+' || c == '-' || c == '.' ||
+ c == '^' || c == '_' || c == '`' || c == '|' || c == '~' ||
+ mozilla::IsAsciiAlphanumeric(c);
+ }
+
+ static inline bool IsHTTPQuotedStringTokenPoint(const char16_t c) {
+ return c == 0x9 || (c >= ' ' && c <= '~') || (c >= 0x80 && c <= 0xFF);
+ }
+}
+
+/* static */ mozilla::UniquePtr<MimeType>
+MimeType::Parse(const nsAString& aMimeType)
+{
+ // See https://mimesniff.spec.whatwg.org/#parsing-a-mime-type
+
+ // Steps 1-2
+ const char16_t* pos = aMimeType.BeginReading();
+ const char16_t* end = aMimeType.EndReading();
+ while (pos < end && mozilla::IsAsciiWhitespace(*pos)) {
+ ++pos;
+ }
+ if (pos == end) {
+ return nullptr;
+ }
+ while (end > pos && mozilla::IsAsciiWhitespace(*(end - 1))) {
+ --end;
+ }
+
+ // Steps 3-4
+ const char16_t* typeStart = pos;
+ while (pos < end && *pos != '/') {
+ if (!IsHTTPTokenPoint(*pos)) {
+ return nullptr;
+ }
+ ++pos;
+ }
+ const char16_t* typeEnd = pos;
+ if (typeStart == typeEnd) {
+ return nullptr;
+ }
+
+ // Step 5
+ if (pos == end) {
+ return nullptr;
+ }
+
+ // Step 6
+ ++pos;
+
+ // Step 7-9
+ const char16_t* subtypeStart = pos;
+ const char16_t* subtypeEnd = nullptr;
+ while (pos < end && *pos != ';') {
+ if (!IsHTTPTokenPoint(*pos)) {
+ // If we hit a whitespace, check that the rest of
+ // the subtype is whitespace, otherwise fail.
+ if (mozilla::IsAsciiWhitespace(*pos)) {
+ subtypeEnd = pos;
+ ++pos;
+ while (pos < end && *pos != ';') {
+ if (!mozilla::IsAsciiWhitespace(*pos)) {
+ return nullptr;
+ }
+ ++pos;
+ }
+ break;
+ } else {
+ return nullptr;
+ }
+ }
+ ++pos;
+ }
+ if (subtypeEnd == nullptr) {
+ subtypeEnd = pos;
+ }
+ if (subtypeStart == subtypeEnd) {
+ return nullptr;
+ }
+
+ // Step 10
+ nsString type;
+ nsString subtype;
+ for (const char16_t* c = typeStart; c < typeEnd; ++c) {
+ type.Append(ToLowerCaseASCII(*c));
+ }
+ for (const char16_t* c = subtypeStart; c < subtypeEnd; ++c) {
+ subtype.Append(ToLowerCaseASCII(*c));
+ }
+ mozilla::UniquePtr<MimeType> mimeType(mozilla::MakeUnique<MimeType>(type, subtype));
+
+ // Step 11
+ while (pos < end) {
+ // Step 11.1
+ ++pos;
+
+ // Step 11.2
+ while (pos < end && mozilla::IsAsciiWhitespace(*pos)) {
+ ++pos;
+ }
+
+ // Steps 11.3 and 11.4
+ nsString paramName;
+ bool paramNameHadInvalidChars = false;
+ while (pos < end && *pos != ';' && *pos != '=') {
+ if (!IsHTTPTokenPoint(*pos)) {
+ paramNameHadInvalidChars = true;
+ }
+ paramName.Append(ToLowerCaseASCII(*pos));
+ ++pos;
+ }
+
+ // Step 11.5
+ if (pos < end) {
+ if (*pos == ';') {
+ continue;
+ }
+ ++pos;
+ }
+
+ // Step 11.6
+ ParameterValue paramValue;
+ bool paramValueHadInvalidChars = false;
+
+ // Step 11.7
+ if (pos < end) {
+
+ // Step 11.7.1
+ if (*pos == '"') {
+
+ // Step 11.7.1.1
+ ++pos;
+
+ // Step 11.7.1.2
+ while (true) {
+
+ // Step 11.7.1.2.1
+ while (pos < end && *pos != '"' && *pos != '\\') {
+ if (!IsHTTPQuotedStringTokenPoint(*pos)) {
+ paramValueHadInvalidChars = true;
+ }
+ if (!IsHTTPTokenPoint(*pos)) {
+ paramValue.mRequiresQuoting = true;
+ }
+ paramValue.Append(*pos);
+ ++pos;
+ }
+
+ // Step 11.7.1.2.2
+ if (pos < end && *pos == '\\') {
+ // Step 11.7.1.2.2.1
+ ++pos;
+
+ // Step 11.7.1.2.2.2
+ if (pos < end) {
+ if (!IsHTTPQuotedStringTokenPoint(*pos)) {
+ paramValueHadInvalidChars = true;
+ }
+ if (!IsHTTPTokenPoint(*pos)) {
+ paramValue.mRequiresQuoting = true;
+ }
+ paramValue.Append(*pos);
+ ++pos;
+ continue;
+ }
+
+ // Step 11.7.1.2.2.3
+ paramValue.Append('\\');
+ paramValue.mRequiresQuoting = true;
+ break;
+ } else {
+ // Step 11.7.1.2.3
+ break;
+ }
+ }
+
+ // Step 11.7.1.3
+ while (pos < end && *pos != ';') {
+ ++pos;
+ }
+
+ } else {
+
+ const char16_t* paramValueStart = pos;
+
+ // Step 11.7.2.1
+ while (pos < end && *pos != ';') {
+ if (!IsHTTPQuotedStringTokenPoint(*pos)) {
+ paramValueHadInvalidChars = true;
+ }
+ if (!IsHTTPTokenPoint(*pos)) {
+ paramValue.mRequiresQuoting = true;
+ }
+ ++pos;
+ }
+
+ // Step 11.7.2.2
+ const char16_t* paramValueEnd = pos - 1;
+ while (paramValueEnd >= paramValueStart &&
+ mozilla::IsAsciiWhitespace(*paramValueEnd)) {
+ --paramValueEnd;
+ }
+
+ for (const char16_t* c = paramValueStart; c <= paramValueEnd; ++c) {
+ paramValue.Append(*c);
+ }
+ }
+
+ // Step 11.8
+ if (!paramName.IsEmpty() && !paramValue.IsEmpty() &&
+ !paramNameHadInvalidChars && !paramValueHadInvalidChars &&
+ !mimeType->mParameters.Get(paramName, ¶mValue)) {
+ mimeType->mParameters.Put(paramName, paramValue);
+ mimeType->mParameterNames.AppendElement(paramName);
+ }
+ }
+ }
+
+ return mimeType;
+}
+
+void
+MimeType::Serialize(nsAString& aOutput) const
+{
+ aOutput.Assign(mType);
+ aOutput.AppendLiteral("/");
+ aOutput.Append(mSubtype);
+ for (uint32_t i = 0; i < mParameterNames.Length(); i++) {
+ auto name = mParameterNames[i];
+ ParameterValue value;
+ mParameters.Get(name, &value);
+ aOutput.AppendLiteral(";");
+ aOutput.Append(name);
+ aOutput.AppendLiteral("=");
+ if (value.mRequiresQuoting) {
+ aOutput.AppendLiteral("\"");
+ const char16_t* vcur = value.BeginReading();
+ const char16_t* vend = value.EndReading();
+ while (vcur < vend) {
+ if (*vcur == '"' || *vcur == '\\') {
+ aOutput.AppendLiteral("\\");
+ }
+ aOutput.Append(*vcur);
+ vcur++;
+ }
+ aOutput.AppendLiteral("\"");
+ } else {
+ aOutput.Append(value);
+ }
+ }
+}
new file mode 100644
--- /dev/null
+++ b/dom/base/MimeType.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_dom_MimeType_h
+#define mozilla_dom_MimeType_h
+
+#include "mozilla/TextUtils.h"
+#include "mozilla/UniquePtr.h"
+#include "nsDataHashtable.h"
+#include "nsTArray.h"
+
+class MimeType final
+{
+private:
+ class ParameterValue : public nsString
+ {
+ public:
+ bool mRequiresQuoting;
+
+ ParameterValue()
+ : mRequiresQuoting(false)
+ {}
+ };
+
+ nsString mType;
+ nsString mSubtype;
+ nsDataHashtable<nsStringHashKey, ParameterValue> mParameters;
+ nsTArray<nsString> mParameterNames;
+
+public:
+ MimeType(const nsAString& aType, const nsAString& aSubtype)
+ : mType(aType), mSubtype(aSubtype)
+ {}
+
+ static mozilla::UniquePtr<MimeType> Parse(const nsAString& aStr);
+ void Serialize(nsAString& aStr) const;
+};
+
+#endif // mozilla_dom_MimeType_h
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -189,16 +189,17 @@ EXPORTS.mozilla.dom += [
'ImageTracker.h',
'IntlUtils.h',
'Link.h',
'Location.h',
'MessageBroadcaster.h',
'MessageListenerManager.h',
'MessageManagerGlobal.h',
'MessageSender.h',
+ 'MimeType.h',
'MozQueryInterface.h',
'NameSpaceConstants.h',
'Navigator.h',
'NodeInfo.h',
'NodeInfoInlines.h',
'NodeIterator.h',
'ParentProcessMessageManager.h',
'PlacesEvent.h',
@@ -283,16 +284,17 @@ UNIFIED_SOURCES += [
'InProcessTabChildMessageManager.cpp',
'IntlUtils.cpp',
'Link.cpp',
'Location.cpp',
'MessageBroadcaster.cpp',
'MessageListenerManager.cpp',
'MessageManagerGlobal.cpp',
'MessageSender.cpp',
+ 'MimeType.cpp',
'MozQueryInterface.cpp',
'Navigator.cpp',
'NodeInfo.cpp',
'NodeIterator.cpp',
'NodeUbiReporting.cpp',
'nsAttrValue.cpp',
'nsAttrValueOrString.cpp',
'nsCCUncollectableMarker.cpp',
new file mode 100644
--- /dev/null
+++ b/dom/base/test/gtest/TestMimeType.cpp
@@ -0,0 +1,708 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "gtest/gtest.h"
+
+#include "MimeType.h"
+#include "nsString.h"
+
+using mozilla::UniquePtr;
+
+TEST(MimeType, EmptyString)
+{
+ const auto in = NS_LITERAL_STRING("");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Empty string";
+}
+
+TEST(MimeType, JustWhitespace)
+{
+ const auto in = NS_LITERAL_STRING(" \t\r\n ");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Just whitespace";
+}
+
+TEST(MimeType, JustBackslash)
+{
+ const auto in = NS_LITERAL_STRING("\\");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Just backslash";
+}
+
+TEST(MimeType, JustForwardslash)
+{
+ const auto in = NS_LITERAL_STRING("/");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Just forward slash";
+}
+
+TEST(MimeType, MissingType1)
+{
+ const auto in = NS_LITERAL_STRING("/bogus");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Missing type #1";
+}
+
+TEST(MimeType, MissingType2)
+{
+ const auto in = NS_LITERAL_STRING(" \r\n\t/bogus");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Missing type #2";
+}
+
+TEST(MimeType, MissingSubtype1)
+{
+ const auto in = NS_LITERAL_STRING("bogus");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Missing subtype #1";
+}
+
+TEST(MimeType, MissingSubType2)
+{
+ const auto in = NS_LITERAL_STRING("bogus/");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Missing subtype #2";
+}
+
+TEST(MimeType, MissingSubType3)
+{
+ const auto in = NS_LITERAL_STRING("bogus;");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Missing subtype #3";
+}
+
+TEST(MimeType, MissingSubType4)
+{
+ const auto in = NS_LITERAL_STRING("bogus; \r\n\t");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Missing subtype #3";
+}
+
+TEST(MimeType, ExtraForwardSlash)
+{
+ const auto in = NS_LITERAL_STRING("bogus/bogus/;");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Extra forward slash";
+}
+
+TEST(MimeType, WhitespaceInType)
+{
+ const auto in = NS_LITERAL_STRING("t\re\nx\tt /html");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Type with whitespace";
+}
+
+TEST(MimeType, WhitespaceInSubtype)
+{
+ const auto in = NS_LITERAL_STRING("text/ h\rt\nm\tl");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Subtype with whitespace";
+}
+
+TEST(MimeType, NonAlphanumericMediaType1)
+{
+ const auto in = NS_LITERAL_STRING("</>");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Non-alphanumeric media type #1";
+}
+
+TEST(MimeType, NonAlphanumericMediaType2)
+{
+ const auto in = NS_LITERAL_STRING("(/)");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Non-alphanumeric media type #2";
+}
+
+TEST(MimeType, NonAlphanumericMediaType3)
+{
+ const auto in = NS_LITERAL_STRING("{/}");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Non-alphanumeric media type #3";
+}
+
+TEST(MimeType, NonAlphanumericMediaType4)
+{
+ const auto in = NS_LITERAL_STRING("\"/\"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Non-alphanumeric media type #4";
+}
+
+TEST(MimeType, NonAlphanumericMediaType5)
+{
+ const auto in = NS_LITERAL_STRING("\0/\0");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Non-alphanumeric media type #5";
+}
+
+TEST(MimeType, NonAlphanumericMediaType6)
+{
+ const auto in = NS_LITERAL_STRING("text/html(;doesnot=matter");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Non-alphanumeric media type #6";
+}
+
+TEST(MimeType, NonLatin1MediaType1)
+{
+ const auto in = NS_LITERAL_STRING("ÿ/ÿ");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Non-latin1 media type #1";
+}
+
+TEST(MimeType, NonLatin1MediaType2)
+{
+ const auto in = NS_LITERAL_STRING("\x0100/\x0100");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_FALSE(parsed) <<
+ "Non-latin1 media type #2";
+}
+
+TEST(MimeType, MultipleParameters)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=gbk;no=1;charset_=gbk_;yes=2");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.Equals(NS_LITERAL_STRING("text/html;charset=gbk;no=1;charset_=gbk_;yes=2"))) <<
+ "Multiple parameters";
+}
+
+TEST(MimeType, DuplicateParameter1)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=gbk;charset=windows-1255");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.Equals(NS_LITERAL_STRING("text/html;charset=gbk"))) <<
+ "Duplicate parameter #1";
+}
+
+TEST(MimeType, DuplicateParameter2)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=();charset=GBK");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.Equals(NS_LITERAL_STRING("text/html;charset=\"()\""))) <<
+ "Duplicate parameter #2";
+}
+
+TEST(MimeType, NonAlphanumericParametersAreQuoted)
+{
+ const auto in = NS_LITERAL_STRING("text/html;test=\x00FF\\;charset=gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.Equals(NS_LITERAL_STRING("text/html;test=\"\x00FF\\\\\";charset=gbk"))) <<
+ "Non-alphanumeric parameters are quoted";
+}
+
+TEST(MimeType, ParameterQuotedIfHasLeadingWhitespace1)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset= g\\\"bk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\" g\\\\\\\"bk\"")) <<
+ "Parameter is quoted if has leading whitespace #1";
+}
+
+TEST(MimeType, ParameterQuotedIfHasLeadingWhitespace2)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset= \"g\\bk\"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\" \\\"g\\\\bk\\\"\"")) <<
+ "Parameter is quoted if has leading whitespace #2";
+}
+
+TEST(MimeType, ParameterQuotedIfHasInternalWhitespace)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=g \\b\"k");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"g \\\\b\\\"k\"")) <<
+ "Parameter is quoted if has internal whitespace";
+}
+
+TEST(MimeType, ImproperlyQuotedParameter1)
+{
+ const auto in = NS_LITERAL_STRING("x/x;test=\"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("x/x")) <<
+ "Improperly-quoted parameter is handled properly #1";
+}
+
+TEST(MimeType, ImproperlyQuotedParameter2)
+{
+ const auto in = NS_LITERAL_STRING("x/x;test=\"\\");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("x/x;test=\"\\\\\"")) <<
+ "Improperly-quoted parameter is handled properly #2";
+}
+
+TEST(MimeType, NonLatin1ParameterIgnored)
+{
+ const auto in = NS_LITERAL_STRING("x/x;test=\xFFFD;x=x");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("x/x;x=x")) <<
+ "Non latin-1 parameters are ignored";
+}
+
+TEST(MimeType, ParameterIgnoredIfWhitespaceInName1)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset =gbk;charset=123");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=123")) <<
+ "Parameter ignored if whitespace in name #1";
+}
+
+TEST(MimeType, ParameterIgnoredIfWhitespaceInName2)
+{
+ const auto in = NS_LITERAL_STRING("text/html;cha rset =gbk;charset=123");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=123")) <<
+ "Parameter ignored if whitespace in name #2";
+}
+
+TEST(MimeType, WhitespaceTrimmed)
+{
+ const auto in = NS_LITERAL_STRING("\n\r\t text/plain\n\r\t ;\n\r\t charset=123\n\r\t ");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/plain;charset=123")) <<
+ "Whitespace appropriately ignored";
+}
+
+TEST(MimeType, WhitespaceOnlyParameterIgnored)
+{
+ const auto in = NS_LITERAL_STRING("x/x;x= \r\n\t");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("x/x")) <<
+ "Whitespace-only parameter is ignored";
+}
+
+TEST(MimeType, IncompleteParameterIgnored1)
+{
+ const auto in = NS_LITERAL_STRING("x/x;test");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("x/x")) <<
+ "Incomplete parameter is ignored #1";
+}
+
+TEST(MimeType, IncompleteParameterIgnored2)
+{
+ const auto in = NS_LITERAL_STRING("x/x;test=");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("x/x")) <<
+ "Incomplete parameter is ignored #2";
+}
+
+TEST(MimeType, IncompleteParameterIgnored3)
+{
+ const auto in = NS_LITERAL_STRING("x/x;test= \r\n\t");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("x/x")) <<
+ "Incomplete parameter is ignored #3";
+}
+
+TEST(MimeType, IncompleteParameterIgnored4)
+{
+ const auto in = NS_LITERAL_STRING("text/html;test;charset=gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Incomplete parameter is ignored #4";
+}
+
+TEST(MimeType, IncompleteParameterIgnored5)
+{
+ const auto in = NS_LITERAL_STRING("text/html;test=;charset=gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Incomplete parameter is ignored #5";
+}
+
+TEST(MimeType, EmptyParameterIgnored1)
+{
+ const auto in = NS_LITERAL_STRING("text/html ; ; charset=gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Empty parameter ignored #1";
+}
+
+TEST(MimeType, EmptyParameterIgnored2)
+{
+ const auto in = NS_LITERAL_STRING("text/html;;;;charset=gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Empty parameter ignored #2";
+}
+
+TEST(MimeType, InvalidParameterIgnored1)
+{
+ const auto in = NS_LITERAL_STRING("text/html;';charset=gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Invalid parameter ignored #1";
+}
+
+TEST(MimeType, InvalidParameterIgnored2)
+{
+ const auto in = NS_LITERAL_STRING("text/html;\";charset=gbk;=123; =321");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Invalid parameter ignored #2";
+}
+
+TEST(MimeType, InvalidParameterIgnored3)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset= \"\u007F;charset=GBK");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=GBK")) <<
+ "Invalid parameter ignored #3";
+}
+
+TEST(MimeType, InvalidParameterIgnored4)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\"\u007F;charset=foo\";charset=GBK;charset=");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=GBK")) <<
+ "Invalid parameter ignored #4";
+}
+
+TEST(MimeType, SingleQuotes1)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset='gbk'");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset='gbk'")) <<
+ "Single quotes handled properly #1";
+}
+
+TEST(MimeType, SingleQuotes2)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset='gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset='gbk")) <<
+ "Single quotes handled properly #2";
+}
+
+TEST(MimeType, SingleQuotes3)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=gbk'");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk'")) <<
+ "Single quotes handled properly #3";
+}
+
+TEST(MimeType, SingleQuotes4)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=';charset=GBK");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset='")) <<
+ "Single quotes handled properly #4";
+}
+
+TEST(MimeType, SingleQuotes5)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=''';charset=GBK");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset='''")) <<
+ "Single quotes handled properly #5";
+}
+
+TEST(MimeType, DoubleQuotes1)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\"gbk\"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Double quotes handled properly #1";
+}
+
+TEST(MimeType, DoubleQuotes2)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\"gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Double quotes handled properly #2";
+}
+
+TEST(MimeType, DoubleQuotes3)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=gbk\"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"gbk\\\"\"")) <<
+ "Double quotes handled properly #3";
+}
+
+TEST(MimeType, DoubleQuotes4)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\" gbk\"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\" gbk\"")) <<
+ "Double quotes handled properly #4";
+}
+
+TEST(MimeType, DoubleQuotes5)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\"gbk \"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"gbk \"")) <<
+ "Double quotes handled properly #5";
+}
+
+TEST(MimeType, DoubleQuotes6)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\"\\ gbk\"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\" gbk\"")) <<
+ "Double quotes handled properly #6";
+}
+
+TEST(MimeType, DoubleQuotes7)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\"\\g\\b\\k\"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Double quotes handled properly #7";
+}
+
+TEST(MimeType, DoubleQuotes8)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\"gbk\"x");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=gbk")) <<
+ "Double quotes handled properly #8";
+}
+
+TEST(MimeType, DoubleQuotes9)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\"\";charset=GBK");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=GBK")) <<
+ "Double quotes handled properly #9";
+}
+
+TEST(MimeType, DoubleQuotes10)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=\";charset=GBK");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\";charset=GBK\"")) <<
+ "Double quotes handled properly #10";
+}
+
+TEST(MimeType, UnexpectedCodePoints)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset={gbk}");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"{gbk}\"")) <<
+ "Unexpected code points handled properly";
+}
+
+TEST(MimeType, LongTypesSubtypesAccepted)
+{
+ const auto in = NS_LITERAL_STRING("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.Equals(in)) <<
+ "Long type/subtype accepted";
+}
+
+TEST(MimeType, LongParametersAccepted)
+{
+ const auto in = NS_LITERAL_STRING("text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.Equals(in)) <<
+ "Long parameters accepted";
+}
+
+TEST(MimeType, AllValidCharactersAccepted1)
+{
+ const auto in = NS_LITERAL_STRING("x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008A\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E\u009F\u00A0\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AD\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF\"");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.Equals(in)) <<
+ "All valid characters accepted #1";
+}
+
+TEST(MimeType, CaseNormalization1)
+{
+ const auto in = NS_LITERAL_STRING("TEXT/PLAIN;CHARSET=TEST");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/plain;charset=TEST")) <<
+ "Case normalized properly #1";
+}
+
+TEST(MimeType, CaseNormalization2)
+{
+ const auto in = NS_LITERAL_STRING("!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) <<
+ "Case normalized properly #2";
+}
+
+TEST(MimeType, LegacyCommentSyntax1)
+{
+ const auto in = NS_LITERAL_STRING("text/html;charset=gbk(");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;charset=\"gbk(\"")) <<
+ "Legacy comment syntax #1";
+}
+
+TEST(MimeType, LegacyCommentSyntax2)
+{
+ const auto in = NS_LITERAL_STRING("text/html;x=(;charset=gbk");
+ UniquePtr<MimeType> parsed = MimeType::Parse(in);
+ ASSERT_TRUE(parsed) << "Parsing succeeded";
+ nsAutoString out;
+ parsed->Serialize(out);
+ ASSERT_TRUE(out.EqualsLiteral("text/html;x=\"(\";charset=gbk")) <<
+ "Legacy comment syntax #2";
+}
--- a/dom/base/test/gtest/moz.build
+++ b/dom/base/test/gtest/moz.build
@@ -1,16 +1,17 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
UNIFIED_SOURCES += [
'TestContentUtils.cpp',
+ 'TestMimeType.cpp',
'TestPlainTextSerializer.cpp',
'TestXPathGenerator.cpp',
]
LOCAL_INCLUDES += [
'/dom/base'
]
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -2167,17 +2167,21 @@ XMLHttpRequestMainThread::OnStopRequest(
}
if (NS_SUCCEEDED(status) &&
mResponseType == XMLHttpRequestResponseType::Blob &&
!waitingForBlobCreation) {
// Smaller files may be written in cache map instead of separate files.
// Also, no-store response cannot be written in persistent cache.
nsAutoCString contentType;
- mChannel->GetContentType(contentType);
+ if (!mOverrideMimeType.IsEmpty()) {
+ contentType.Assign(NS_ConvertUTF16toUTF8(mOverrideMimeType));
+ } else {
+ mChannel->GetContentType(contentType);
+ }
// mBlobStorage can be null if the channel is non-file non-cacheable
// and if the response length is zero.
MaybeCreateBlobStorage();
mBlobStorage->GetBlobWhenReady(GetOwner(), contentType, this);
waitingForBlobCreation = true;
NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty");
@@ -3130,17 +3134,22 @@ XMLHttpRequestMainThread::OverrideMimeTy
NOT_CALLABLE_IN_SYNC_SEND_RV
if (mState == XMLHttpRequest_Binding::LOADING ||
mState == XMLHttpRequest_Binding::DONE) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_XHR_MUST_NOT_BE_LOADING_OR_DONE);
return;
}
- mOverrideMimeType = aMimeType;
+ UniquePtr<MimeType> parsed = MimeType::Parse(aMimeType);
+ if (parsed) {
+ parsed->Serialize(mOverrideMimeType);
+ } else {
+ mOverrideMimeType.AssignLiteral(APPLICATION_OCTET_STREAM);
+ }
}
bool
XMLHttpRequestMainThread::MozBackgroundRequest() const
{
return mFlagBackgroundRequest;
}
--- a/dom/xhr/XMLHttpRequestMainThread.h
+++ b/dom/xhr/XMLHttpRequestMainThread.h
@@ -34,16 +34,17 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/NotNull.h"
#include "mozilla/dom/MutableBlobStorage.h"
#include "mozilla/dom/BodyExtractor.h"
#include "mozilla/dom/ClientInfo.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FormData.h"
+#include "mozilla/dom/MimeType.h"
#include "mozilla/dom/PerformanceStorage.h"
#include "mozilla/dom/ServiceWorkerDescriptor.h"
#include "mozilla/dom/URLSearchParams.h"
#include "mozilla/dom/XMLHttpRequest.h"
#include "mozilla/dom/XMLHttpRequestBinding.h"
#include "mozilla/dom/XMLHttpRequestEventTarget.h"
#include "mozilla/dom/XMLHttpRequestString.h"
#include "mozilla/Encoding.h"
--- a/intl/unicharutil/util/nsUnicharUtils.cpp
+++ b/intl/unicharutil/util/nsUnicharUtils.cpp
@@ -54,16 +54,43 @@ ToLowerCase(nsAString& aString)
void
ToLowerCaseASCII(nsAString& aString)
{
char16_t *buf = aString.BeginWriting();
ToLowerCaseASCII(buf, buf, aString.Length());
}
+char
+ToLowerCaseASCII(char aChar)
+{
+ if (aChar >= 'A' && aChar <= 'Z') {
+ return aChar + 0x20;
+ }
+ return aChar;
+}
+
+char16_t
+ToLowerCaseASCII(char16_t aChar)
+{
+ if (aChar >= 'A' && aChar <= 'Z') {
+ return aChar + 0x20;
+ }
+ return aChar;
+}
+
+char32_t
+ToLowerCaseASCII(char32_t aChar)
+{
+ if (aChar >= 'A' && aChar <= 'Z') {
+ return aChar + 0x20;
+ }
+ return aChar;
+}
+
void
ToLowerCase(const nsAString& aSource,
nsAString& aDest)
{
const char16_t *in = aSource.BeginReading();
uint32_t len = aSource.Length();
aDest.SetLength(len);
--- a/intl/unicharutil/util/nsUnicharUtils.h
+++ b/intl/unicharutil/util/nsUnicharUtils.h
@@ -35,16 +35,20 @@ void ToUpperCase(const nsAString& aSourc
uint32_t ToLowerCase(uint32_t aChar);
uint32_t ToUpperCase(uint32_t aChar);
uint32_t ToTitleCase(uint32_t aChar);
void ToLowerCase(const char16_t *aIn, char16_t *aOut, uint32_t aLen);
void ToLowerCaseASCII(const char16_t *aIn, char16_t *aOut, uint32_t aLen);
void ToUpperCase(const char16_t *aIn, char16_t *aOut, uint32_t aLen);
+char ToLowerCaseASCII(const char aChar);
+char16_t ToLowerCaseASCII(const char16_t aChar);
+char32_t ToLowerCaseASCII(const char32_t aChar);
+
inline bool IsUpperCase(uint32_t c) {
return ToLowerCase(c) != c;
}
inline bool IsLowerCase(uint32_t c) {
return ToUpperCase(c) != c;
}
--- a/mfbt/TextUtils.h
+++ b/mfbt/TextUtils.h
@@ -43,16 +43,31 @@ constexpr bool
IsAscii(Char aChar)
{
using UnsignedChar = typename detail::MakeUnsignedChar<Char>::Type;
auto uc = static_cast<UnsignedChar>(aChar);
return uc < 0x80;
}
/**
+ * Returns true iff |aChar| matches Ascii Whitespace.
+ *
+ * This function is intended to match the Infra standard
+ * (https://infra.spec.whatwg.org/#ascii-whitespace)
+ */
+template<typename Char>
+constexpr bool
+IsAsciiWhitespace(Char aChar)
+{
+ using UnsignedChar = typename detail::MakeUnsignedChar<Char>::Type;
+ auto uc = static_cast<UnsignedChar>(aChar);
+ return uc == 0x9 || uc == 0xA || uc == 0xC || uc == 0xD || uc == 0x20;
+}
+
+/**
* Returns true iff |aChar| matches [a-z].
*
* This function is basically what you thought islower was, except its behavior
* doesn't depend on the user's current locale.
*/
template<typename Char>
constexpr bool
IsAsciiLowercaseAlpha(Char aChar)
deleted file mode 100644
--- a/testing/web-platform/meta/xhr/overridemimetype-blob.html.ini
+++ /dev/null
@@ -1,286 +0,0 @@
-[overridemimetype-blob.html]
- [Bogus MIME type should end up as application/octet-stream, 2]
- expected: FAIL
-
- [Bogus MIME type should end up as application/octet-stream, 3]
- expected: FAIL
-
- [Bogus MIME type should end up as application/octet-stream, 4]
- expected: FAIL
-
- [Bogus MIME type should end up as application/octet-stream, 5]
- expected: FAIL
-
- [Bogus MIME type should end up as application/octet-stream, 6]
- expected: FAIL
-
- [Bogus MIME type should end up as application/octet-stream, 7]
- expected: FAIL
-
- [Bogus MIME type should end up as application/octet-stream, 9]
- expected: FAIL
-
- [Valid MIME types need to be parsed and serialized 1]
- expected: FAIL
-
- [Valid MIME types need to be parsed and serialized 4]
- expected: FAIL
-
- [Valid MIME types need to be parsed and serialized 5]
- expected: FAIL
-
- [1) MIME types need to be parsed and serialized: text/html;charset=gbk]
- expected: FAIL
-
- [2) MIME types need to be parsed and serialized: TEXT/HTML;CHARSET=GBK]
- expected: FAIL
-
- [3) MIME types need to be parsed and serialized: text/html;charset=gbk(]
- expected: FAIL
-
- [4) MIME types need to be parsed and serialized: text/html;x=(;charset=gbk]
- expected: FAIL
-
- [5) MIME types need to be parsed and serialized: text/html;charset=gbk;charset=windows-1255]
- expected: FAIL
-
- [7) MIME types need to be parsed and serialized: text/html ;charset=gbk]
- expected: FAIL
-
- [8) MIME types need to be parsed and serialized: text/html; charset=gbk]
- expected: FAIL
-
- [9) MIME types need to be parsed and serialized: text/html;charset= gbk]
- expected: FAIL
-
- [10) MIME types need to be parsed and serialized: text/html;charset='gbk']
- expected: FAIL
-
- [11) MIME types need to be parsed and serialized: text/html;charset='gbk]
- expected: FAIL
-
- [12) MIME types need to be parsed and serialized: text/html;charset=gbk']
- expected: FAIL
-
- [13) MIME types need to be parsed and serialized: text/html;test;charset=gbk]
- expected: FAIL
-
- [14) MIME types need to be parsed and serialized: text/html;test=;charset=gbk]
- expected: FAIL
-
- [15) MIME types need to be parsed and serialized: text/html;';charset=gbk]
- expected: FAIL
-
- [16) MIME types need to be parsed and serialized: text/html;";charset=gbk]
- expected: FAIL
-
- [17) MIME types need to be parsed and serialized: text/html ; ; charset=gbk]
- expected: FAIL
-
- [18) MIME types need to be parsed and serialized: text/html;;;;charset=gbk]
- expected: FAIL
-
- [19) MIME types need to be parsed and serialized: text/html;charset="gbk"]
- expected: FAIL
-
- [20) MIME types need to be parsed and serialized: text/html;charset="gbk]
- expected: FAIL
-
- [21) MIME types need to be parsed and serialized: text/html;charset=gbk"]
- expected: FAIL
-
- [22) MIME types need to be parsed and serialized: text/html;charset=" gbk"]
- expected: FAIL
-
- [23) MIME types need to be parsed and serialized: text/html;charset="\\ gbk"]
- expected: FAIL
-
- [24) MIME types need to be parsed and serialized: text/html;charset="\\g\\b\\k"]
- expected: FAIL
-
- [25) MIME types need to be parsed and serialized: text/html;charset="gbk"x]
- expected: FAIL
-
- [26) MIME types need to be parsed and serialized: text/html;charset={gbk}]
- expected: FAIL
-
- [27) MIME types need to be parsed and serialized: text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk]
- expected: FAIL
-
- [29) MIME types need to be parsed and serialized: !#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]
- expected: FAIL
-
- [30) MIME types need to be parsed and serialized: x/x;x="\t !\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~
¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"]
- expected: FAIL
-
- [32) MIME types need to be parsed and serialized: x/x;test="\\]
- expected: FAIL
-
- [35) MIME types need to be parsed and serialized: text/html;test=ÿ;charset=gbk]
- expected: FAIL
-
- [36) MIME types need to be parsed and serialized: x/x;test=�;x=x]
- expected: FAIL
-
- [37) MIME types need to be parsed and serialized: ]
- expected: FAIL
-
- [39) MIME types need to be parsed and serialized: /]
- expected: FAIL
-
- [41) MIME types need to be parsed and serialized: bogus/]
- expected: FAIL
-
- [42) MIME types need to be parsed and serialized: bogus/ ]
- expected: FAIL
-
- [43) MIME types need to be parsed and serialized: bogus/bogus/;]
- expected: FAIL
-
- [44) MIME types need to be parsed and serialized: </>]
- expected: FAIL
-
- [46) MIME types need to be parsed and serialized: ÿ/ÿ]
- expected: FAIL
-
- [47) MIME types need to be parsed and serialized: text/html(;doesnot=matter]
- expected: FAIL
-
- [48) MIME types need to be parsed and serialized: {/}]
- expected: FAIL
-
- [49) MIME types need to be parsed and serialized: Ā/Ā]
- expected: FAIL
-
- [6) MIME types need to be parsed and serialized: text/html;charset=();charset=GBK]
- expected: FAIL
-
- [8) MIME types need to be parsed and serialized: text/html ;charset=gbk]
- expected: FAIL
-
- [9) MIME types need to be parsed and serialized: text/html; charset=gbk]
- expected: FAIL
-
- [10) MIME types need to be parsed and serialized: text/html;charset= gbk]
- expected: FAIL
-
- [11) MIME types need to be parsed and serialized: text/html;charset= "gbk"]
- expected: FAIL
-
- [12) MIME types need to be parsed and serialized: text/html;charset='gbk']
- expected: FAIL
-
- [13) MIME types need to be parsed and serialized: text/html;charset='gbk]
- expected: FAIL
-
- [14) MIME types need to be parsed and serialized: text/html;charset=gbk']
- expected: FAIL
-
- [15) MIME types need to be parsed and serialized: text/html;charset=';charset=GBK]
- expected: FAIL
-
- [16) MIME types need to be parsed and serialized: text/html;test;charset=gbk]
- expected: FAIL
-
- [17) MIME types need to be parsed and serialized: text/html;test=;charset=gbk]
- expected: FAIL
-
- [18) MIME types need to be parsed and serialized: text/html;';charset=gbk]
- expected: FAIL
-
- [19) MIME types need to be parsed and serialized: text/html;";charset=gbk]
- expected: FAIL
-
- [20) MIME types need to be parsed and serialized: text/html ; ; charset=gbk]
- expected: FAIL
-
- [21) MIME types need to be parsed and serialized: text/html;;;;charset=gbk]
- expected: FAIL
-
- [22) MIME types need to be parsed and serialized: text/html;charset= ";charset=GBK]
- expected: FAIL
-
- [23) MIME types need to be parsed and serialized: text/html;charset=";charset=foo";charset=GBK]
- expected: FAIL
-
- [24) MIME types need to be parsed and serialized: text/html;charset="gbk"]
- expected: FAIL
-
- [25) MIME types need to be parsed and serialized: text/html;charset="gbk]
- expected: FAIL
-
- [26) MIME types need to be parsed and serialized: text/html;charset=gbk"]
- expected: FAIL
-
- [27) MIME types need to be parsed and serialized: text/html;charset=" gbk"]
- expected: FAIL
-
- [28) MIME types need to be parsed and serialized: text/html;charset="gbk "]
- expected: FAIL
-
- [29) MIME types need to be parsed and serialized: text/html;charset="\\ gbk"]
- expected: FAIL
-
- [30) MIME types need to be parsed and serialized: text/html;charset="\\g\\b\\k"]
- expected: FAIL
-
- [31) MIME types need to be parsed and serialized: text/html;charset="gbk"x]
- expected: FAIL
-
- [32) MIME types need to be parsed and serialized: text/html;charset="";charset=GBK]
- expected: FAIL
-
- [33) MIME types need to be parsed and serialized: text/html;charset=";charset=GBK]
- expected: FAIL
-
- [34) MIME types need to be parsed and serialized: text/html;charset={gbk}]
- expected: FAIL
-
- [35) MIME types need to be parsed and serialized: text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk]
- expected: FAIL
-
- [37) MIME types need to be parsed and serialized: !#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]
- expected: FAIL
-
- [38) MIME types need to be parsed and serialized: x/x;x="\t !\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~
¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"]
- expected: FAIL
-
- [40) MIME types need to be parsed and serialized: x/x;test="\\]
- expected: FAIL
-
- [43) MIME types need to be parsed and serialized: text/html;test=ÿ;charset=gbk]
- expected: FAIL
-
- [44) MIME types need to be parsed and serialized: x/x;test=�;x=x]
- expected: FAIL
-
- [45) MIME types need to be parsed and serialized: ]
- expected: FAIL
-
- [47) MIME types need to be parsed and serialized: /]
- expected: FAIL
-
- [49) MIME types need to be parsed and serialized: bogus/]
- expected: FAIL
-
- [50) MIME types need to be parsed and serialized: bogus/ ]
- expected: FAIL
-
- [51) MIME types need to be parsed and serialized: bogus/bogus/;]
- expected: FAIL
-
- [52) MIME types need to be parsed and serialized: </>]
- expected: FAIL
-
- [54) MIME types need to be parsed and serialized: ÿ/ÿ]
- expected: FAIL
-
- [55) MIME types need to be parsed and serialized: text/html(;doesnot=matter]
- expected: FAIL
-
- [56) MIME types need to be parsed and serialized: {/}]
- expected: FAIL
-
- [57) MIME types need to be parsed and serialized: Ā/Ā]
- expected: FAIL
-